[FFmpeg-devel] [RFC] Sending H.264 stream to multiple containers

Stefano Sabatini stefasab at gmail.com
Tue Jul 16 12:38:19 CEST 2013


On date Monday 2013-07-15 19:47:07 +0800, Peng encoded:
> >If I create and MP4 file, I can remux it with: ffmpeg -i in.mp4 -c
> >copy -bsf:v h264_mp4toannexb out.ts thus my expectation is that
> >the h264_mp4toannexb filter should be able to add the packet
> >header when doing:ffmpeg -i INPUT -map 0 -flags +global_header
> >-c:v libx264 -c:a libvo_aacenc -bsf:v h264_mp4toannexb out.ts
> >which is not the case since this will result in an error when
> >parsing the header.
> 

> It is reasonable to expect the filter to put the header back.

> However, the problem is that '-flags +global_header -c:v ' libx264'
> does not give you MP4-compliant stream, instead it gives you normal
> Annex B stream without repeated headers before every key frame,
> which h264_mp4toannexb does not deal with.

You stand correct.

So what I discovered is this: the x264 encoder (or better, our
wrapper) always creates an Annex B bitstream, but the movenc muxer
will convert the packets to AVCC format before muxing.

If flags +global_header is set, libx264 will store the (Annex B)
extradata in the codec context extradata, otherwise it will store it
directly in the packets (if x4->params->b_repeat_headers is set).

When an MP4 -> TS copy is done, the bitstream is in MP4 format and
needs to be converted to Annex B format:
ffmpeg -i in.mp4 -c copy -bsf:v h264_mp4toannexb out.ts

but when I do:
ffmpeg -i INPUT -map 0 -flags +global_header -c:v libx264 -c:a libvo_aacenc -bsf:v h264_mp4toannexb out.ts

what's happening is that a global header is stored in the extradata by
the x264 wrapper, no header is put in the packet header, but the
generated stream is in the Annex B format (which is the only one
generated by the x264 wrapper) and thus is not accepted by the filter.

The solution I found is the following:
ffmpeg -i INPUT -map 0 -flags +global_header -c:v libx264 -bsf:v dump_extra -y out.ts

This tells the encoder to write the extradata, but at the same time
will not write the generated metadata in the packet headers, which is
obviated with the use of the dump_extra filter (which just takes the
extradata - in this case the Annex B header generated by the libx264
wrapper - and dump it at the beginning of each packet).

This translates into the tee command:
ffmpeg -i INPUT -map 0 -flags +global_header -c:v libx264 -c:a aac -strict experimental -t 10 -f tee -tee_bsfs "dump_extra:v" "out.ts|[movflags=+faststart]out.mp4" -loglevel verbose

which allows to generate valid MP4 and MPEG-TS output at the same
time.

I'll send some documentation patches to make more apparent this
scenario in a while.

[...]

Thank you for the heads up which led me to find a solution to this
problem! :)
-- 
FFmpeg = Freak and Furious Miracolous Philosofic Exciting Ghost


More information about the ffmpeg-devel mailing list