GNOME Bugzilla – Bug 766618
mpegtsmux, high overhead for a small aac bitrate
Last modified: 2018-11-03 13:51:37 UTC
I am facing an issue with the following pipeline : audiotestsrc num-buffers=100000 ! audio/x-raw,channels=2 ! voaacenc bitrate=32000 ! mpegtsmux ! filesink location=test.ts The tsdemux generate a stream with a huge bitrate compared to other containers, such as mp4mux : audiotestsrc num-buffers=100000 ! audio/x-raw,channels=2 ! voaacenc bitrate=32000 ! mp4mux ! filesink location=test.mp4 $ ls -lh test.* -rw-r--r-- 1 vincent vincent 9.6M May 18 10:56 test.mp4 -rw-r--r-- 1 vincent vincent 26M May 18 10:57 test.ts I think there is a misconfiguration somewhere which leads the demux to create very small chunk with many headers. I also noticed we can reduce the size of the ts file with libav : $ avconv -i test.ts -codec copy test2.ts $ ls -lh *.ts -rw-r--r-- 1 vincent vincent 26M May 18 10:57 test.ts -rw-r--r-- 1 vincent vincent 9.8M May 18 11:03 test2.ts The problem is most likely that we don't combine multiple AAC packets into a single PES packet, and thus have a lot of overhead for each of them. ffmpeg does this for audio at least if I remember the muxer code correctly.
As I understand how the muxer works in ffmpeg, we must fill the PES payload with an aggregation of full audio frames. I am able to do it in an element upstream, but I don't really understand how to do it inside the mpegtsmux. Any advice about this point ? static GstFlowReturn gst_audio_pes_assembler_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstAudioPesAssembler *filter = GST_AUDIOPESASSEMBLER (parent); GstFlowReturn ret = GST_FLOW_OK; GstBuffer* out; gsize avail; avail = gst_adapter_available(filter->adapter); if (avail + gst_buffer_get_size(buf) > 2930) { out = gst_adapter_take_buffer_fast(filter->adapter, avail); ret = gst_pad_push (filter->srcpad, out); } gst_adapter_push(filter->adapter, buf); return ret; } -- vincent.
For Opus and AAC there is already this preparation function. You could hook around the call to those and after them (or before?) accumulate full frames in an adapter, and only pass an actual buffer onwards once enough has accumulated.
Problem is that this adds latency so should probably not be done if upstream is live? Or we should hide it behind a property.
Ok, I can store a GstAdapter into MpegTsPadData::prepare_data, and then use it into mpegtsmux_prepare_aac. This algorithm comes from libav : libav/libavformat/mpegtsenc.c:1143 1) In libav/libavformat/mpegtsenc.c:1143, the latency is taken into accound via a max_delay parameter : """ if (ts_st->payload_size + size > ts->pes_payload_size || (dts != AV_NOPTS_VALUE && ts_st->payload_dts != AV_NOPTS_VALUE && av_compare_ts(dts - ts_st->payload_dts, st->time_base, s->max_delay, AV_TIME_BASE_Q) >= 0)) { """ -> may be we could implement the same solution in mpegtsmux ? (e.g: add a "max-delay" property). 2) libav does not only aggregates AAC frames, but frames for all audio media, do you think mpegtsmux should do the same ?
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/392.