[FFmpeg-devel] [PATCH 2/3] avformat: remove more unneeded avio_flush() calls
Martin Storsjö
martin at martin.st
Fri Jan 3 23:28:15 EET 2020
On Fri, 3 Jan 2020, Marton Balint wrote:
> On Fri, 3 Jan 2020, Martin Storsjö wrote:
>
>> On Fri, 3 Jan 2020, Marton Balint wrote:
>>
>>> Throughout libavformat there are lots of avio_flush() calls which are
>> unneeded:
>>> - Instances found at the end of write_header, write_packet and
>> write_trailer
>>> callbacks. These are handled by the generic code in libavformat/mux.c.
>>
>> They are only handled by the generic code, if the flush_packets flag is
>> set. If it isn't, and the flush was there for a reason (I'm sure not all
>> of them are, but I'm also quite sure a few of them are there for very
>> specific reasons), things will now break.
>
> For write_packet, you are right, it removes the explicit flush and fall
> backs to the default behaviour of the flush_packets flag, which is to
> flush if the output is streamed, and not flush otherwise. Can you a think
> of a case which breaks when the output is not streamed?
Hmm, not really
> For write_header there is an explicit flush in avio_write_marker if the
> marker type is AVIO_DATA_MARKER_HEADER and if the type is different to the
> existing marker, so it should not make a difference.
Ah, I overlooked that - then it might be fine.
>>
>> One such case that you're removing comes from
>> 8ad5124b7ecf7f727724e270a7b4bb8c7bcbf6a4 which was added for a specific
>> reason.
>
> I guess this predates your avio_write_marker addition.
Yeah, I guess so.
>>
>>> - Instances in the middle of write_header and write_trailer which are
>>> redundant or are present becuase avio_flush() used to be required before
>>> doing a seekback. That is no longer the case, aviobuf code does the flush
>>> automatically on seek.
>>
>> It's not necessarily about flushing before doing seekback, it's also about
>> ensuring that seekback can be done within the current buffer.
>>
>> For streaming output (where we can't seek back once data has been
>> flushed), it's cruicial to flush _before_ a point you want to seek to.
>> Consider if we have a 32k avio buffer, and it's filled up to 30k at the
>> moment. We're going to write a 8k structure which requires seeks back and
>> forth. If we remove the pre-write-flush, we'll write 2k of data, flush it
>> out, and later seeks to the beginning of this block will fail.
>>
>> If we explicitly flush before starting to write one block where we know
>> we'll need to seek to, we maximize the chances of it working. (If we need
>> to seek across a larger area than the avio buffer, then it still won't
>> work of course.)
>>
>> I didn't check yet all of the ones you are removing, but I'd say at least
>> that movenc.c has cases of intentional flushing in this style.
>
> Ok, this can be a problem indeed. A proper solution would be to use a
> dynbuf in these cases if streaming is of importance because it is wrong to
> assume any particular output buffer size in a muxer and rely on this
> behaviour.
Yes, that would be better indeed. For the case with movenc, I think I
think I might have taken this route in order to reduce the amount of
needed refactoring as this method felt good enough for the cases at hand
at the time.
>>> So this patch removes those cases. Removing explicit avio_flush() calls
>> helps
>>> us to buffer more data and avoid flushing the IO context too often which
>> causes
>>> reduced IO throughput for non-streamed file output.
>>
>> So if you're arguing that some can be removed because the generic code in
>> mux.c does the same (although it only does so if a nondefault flag is
>> set?), this benefit can only be attributed to the other ones, that are
>> removed from the middle of functions.
>
> Yes. I will rework the patchset, sepearte the cases better and maybe keep
> the ones in the middle write_header/write_trailer for now.
Awesome, that'd make me more comfortable with it!
// Martin
More information about the ffmpeg-devel
mailing list