[FFmpeg-devel] [PATCH] avformat/mpegts: use a buffer pool for PES payloads
James Almer
jamrial at gmail.com
Fri Apr 3 20:46:02 EEST 2020
On 4/2/2020 4:54 PM, Marton Balint wrote:
>
>
> On Thu, 2 Apr 2020, James Almer wrote:
>
>> On 4/2/2020 3:49 PM, Marton Balint wrote:
>>>
>>>
>>> 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.
>>
>> I don't think that's possible, or worth trying. There's currently no way
>> to query the amount of buffers in a given pool, and definitely no way to
>> know what buffers will be returned to a pool once all their references
>> are freed, other than keeping track of them within the muxer.
>
> I meant something like this:
>
> required_size = pes->total_size + AV_INPUT_BUFFER_PADDING;
> index = av_log2(requred_size);
> if (!ts->pools[index]) {
> pool_size = FFMIN(MAX_PES_PAYLOAD + AV_INPUT_BUFFER_PADDING, 2 <<
> index);
> ts->pools[index] = av_buffer_pool_init(pool_size);
> }
> pes->buffer = av_buffer_pool_get(ts->pool[index]);
Ah, you meant several pools. Seems a bit too convoluted for what
ultimately is a relatively small gain...
>
>
>>
>> I'll try limiting the usage of the pool to unbound packets only, but i
>> suspect it will not make much of a difference compared to no pool usage
>> at all.
>
> Yeah, I expect this outcome as well.
So in the end it did make a difference, at least for these samples. Not
sure how often unbound PES payloads happen in mpegts, since i don't have
other samples at hand to test and bench, so i'm inclined to either do it
this way, or just drop the patch.
>
> Regards,
> Marton
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
More information about the ffmpeg-devel
mailing list