[FFmpeg-devel] [PATCH] avformat/mpegts: use a buffer pool for PES payloads

Marton Balint cus at passwd.hu
Thu Apr 2 21:49:13 EEST 2020



On Thu, 2 Apr 2020, James Almer wrote:

> On 4/2/2020 3:27 PM, Marton Balint wrote:
>> 
>> 
>> On Thu, 2 Apr 2020, Marton Balint wrote:
>> 
>>>
>>>
>>> On Thu, 2 Apr 2020, James Almer wrote:
>>>
>>>> On 3/29/2020 6:07 PM, James Almer wrote:
>>>>> This produces a small speed up in demuxing
>>>>>
>>>>> Signed-off-by: James Almer <jamrial at gmail.com>
>>>>> ---
>>>>>  libavformat/mpegts.c | 20 ++++++++++++++++----
>>>>>  1 file changed, 16 insertions(+), 4 deletions(-)
>>>>>
>>>>> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
>>>>> index 7f56bacb2c..7746a524c4 100644
>>>>> --- a/libavformat/mpegts.c
>>>>> +++ b/libavformat/mpegts.c
>>>>> @@ -157,6 +157,8 @@ struct MpegTSContext {
>>>>>      int resync_size;
>>>>>      int merge_pmt_versions;
>>>>>
>>>>> +    AVBufferPool *pool;
>>>>> +
>>>>>      /******************************************/
>>>>>      /* private mpegts data */
>>>>>      /* scan context */
>>>>> @@ -1177,8 +1179,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
>>>>>                          pes->total_size = MAX_PES_PAYLOAD;
>>>>>
>>>>>                      /* allocate pes buffer */
>>>>> -                    pes->buffer = av_buffer_alloc(pes->total_size +
>>>>> - 
>>> AV_INPUT_BUFFER_PADDING_SIZE);
>>>>> +                    pes->buffer = av_buffer_pool_get(ts->pool);
>>>>>                      if (!pes->buffer)
>>>>>                          return AVERROR(ENOMEM);
>>>>>
>>>>> @@ -1351,8 +1352,7 @@ skip:
>>>>>                      if (ret < 0)
>>>>>                          return ret;
>>>>>                      pes->total_size = MAX_PES_PAYLOAD;
>>>>> -                    pes->buffer = av_buffer_alloc(pes->total_size +
>>>>> - 
>>> AV_INPUT_BUFFER_PADDING_SIZE);
>>>>> +                    pes->buffer = av_buffer_pool_get(ts->pool);
>>>>>                      if (!pes->buffer)
>>>>>                          return AVERROR(ENOMEM);
>>>>>                      ts->stop_parse = 1;
>>>>> @@ -3032,6 +3032,10 @@ static int mpegts_read_header(AVFormatContext
>>>>> *s)
>>>>>      ts->stream     = s;
>>>>>      ts->auto_guess = 0;
>>>>>
>>>>> +    ts->pool = av_buffer_pool_init(MAX_PES_PAYLOAD + 
>>> AV_INPUT_BUFFER_PADDING_SIZE, NULL);
>>>>> +    if (!ts->pool)
>>>>> +        return AVERROR(ENOMEM);
>>>>> +
>>>>>      if (s->iformat == &ff_mpegts_demuxer) {
>>>>>          /* normal demux */
>>>>>
>>>>> @@ -3200,6 +3204,8 @@ static void mpegts_free(MpegTSContext *ts)
>>>>>
>>>>>      clear_programs(ts);
>>>>>
>>>>> +    av_buffer_pool_uninit(&ts->pool);
>>>>> +
>>>>>      for (i = 0; i < NB_PID_MAX; i++)
>>>>>          if (ts->pids[i])
>>>>>              mpegts_close_filter(ts, ts->pids[i]);
>>>>> @@ -3295,6 +3301,12 @@ MpegTSContext 
>>> *avpriv_mpegts_parse_open(AVFormatContext *s)
>>>>>      ts->stream = s;
>>>>>      ts->auto_guess = 1;
>>>>>
>>>>> +    ts->pool = av_buffer_pool_init(MAX_PES_PAYLOAD + 
>>> AV_INPUT_BUFFER_PADDING_SIZE, NULL);
>>>>> +    if (!ts->pool) {
>>>>> +        av_free(ts);
>>>>> +        return NULL;
>>>>> +    }
>>>>> +
>>>>>      mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1);
>>>>>      mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1);
>>>>>      mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1);
>>>>
>>>> Will apply soon if no one objects.
>>>
>>> LGTM.
>> 
>> On second thought aint this going to waste too much memory on small
>> packets? If packets are queued somewhere it can make a huge difference
>> if every buffer is 200kb...
>> 
>> Does the speedup goes away if only unbound packets make use of the
>> buffer pool?
>> 
>> Thanks,
>> Marton
>
> I tried these two LG 4k HDR sample videos, and the pool was never bigger
> than 3 to 5 buffers for the entire demuxing process.

That is the case if there is no packet buffering, like in ffmpeg using a 
single input. But in ffplay or a lot of other apps packets are 
pre-buffered to remove the latency of the source media. An app could have 
assumed that if it buffers 1 MB of packets it will not consume a lot more 
than 1 MB of memory.

>
> I'll bench again with your suggestion, but i don't think it will be a
> problem even as is.

Maybe we should create log2(MAX_PACKET_SIZE) number of buffer pools 
instead? In that case the memory wasted is at most 100%... Still not very 
good, but a lot more acceptable.

Regards,
Marton


More information about the ffmpeg-devel mailing list