I have a raw H.264 video stream (which starts with hex 00 00 01 FC ...
, a 3-byte start code followed by a NAL unit). ffmpeg
can process it but it really doesn't want to...
Let's test
Let's say the filename is avcfile.raw
and I want to wrap this video into a container.
> ffmpeg -i avcfile.raw -c copy out.mp4
...
avcfile.raw: Invalid data found when processing input
Let's rename the file to avcfile.h264
> ffmpeg -i avcfile.h264 -c copy out.mp4
...
Output file #0 (out.mp4):
Output stream #0:0 (video): 230 packets muxed (77103 bytes);
Total: 230 packets (77103 bytes) muxed
It magically works!
So how do I convince ffmpeg
to process my file without renaming it to an .h264
extenstion?
I've tried all these arguments to no avail: -f h264 -err_detect ignore_err -flags +global_header
. Isn't the whole purpose of -f
to do what I'm asking?
Why I need this
The ultimate goal is to pipe the raw H264 stream to ffmpeg
from stdout, like so:
somenetworkstreamer | ffmpeg -i pipe: -f h264 -c copy out.mp4
...and there lies the problem - I cannot give an unnamed pipe an .h264
extension!
Any ideas? Does ffmpeg
have some other "force format" switch I don't know about? Can I append some magic bytes to the start of my stream?
Some -loglevel debug output
When it works (e.g. ffmpeg -i file.h264 -
)
Splitting the commandline.
Reading option '-i' ... matched as input url with argument 'file.h264'.
Reading option '-c' ... matched as option 'c' (codec name) with argument 'copy'.
...
Reading option 'out.mp4' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option loglevel (set logging level) with argument debug.
Successfully parsed a group of options.
Parsing a group of options: input url file.h264.
Successfully parsed a group of options.
Opening an input file: teste.h264.
[NULL @ 0x871230] Opening 'teste.h264' for reading
[file @ 0x8719c0] Setting default whitelist 'file,crypto'
[h264 @ 0x871230] Format h264 detected only with low score of 1, misdetection possible!
[h264 @ 0x871230] Before avformat_find_stream_info() pos: 0 bytes read:77103 seeks:0 nb_streams:1
[AVBSFContext @ 0x878350] Invalid NAL unit 0, skipping.
[AVBSFContext @ 0x878350] nal_unit_type: 7(SPS), nal_ref_idc: 1
[AVBSFContext @ 0x878350] nal_unit_type: 8(PPS), nal_ref_idc: 1
[AVBSFContext @ 0x878350] nal_unit_type: 5(IDR), nal_ref_idc: 1
[AVBSFContext @ 0x878350] Invalid NAL unit 0, skipping.
[h264 @ 0x872430] Invalid NAL unit 0, skipping.
[h264 @ 0x872430] nal_unit_type: 7(SPS), nal_ref_idc: 1
[h264 @ 0x872430] nal_unit_type: 8(PPS), nal_ref_idc: 1
[h264 @ 0x872430] nal_unit_type: 5(IDR), nal_ref_idc: 1
[h264 @ 0x872430] Invalid NAL unit 0, skipping.
[h264 @ 0x872430] Format yuv420p chosen by get_format().
[h264 @ 0x872430] Reinit context to 1920x1088, pix_fmt: yuv420p
[h264 @ 0x872430] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 1
[h264 @ 0x872430] Invalid NAL unit 8, skipping.
...
Input #0, h264, from 'file.h264':
Duration: N/A, bitrate: N/A
Stream #0:0, 64, 1/1200000: Video: h264 (Main), 1 reference frame, yuv420p(progressive, left), 1920x1080 (1920x1088), 0/1, 12.17 fps, 12 tbr, 1200k tbn, 24 tbc
Successfully opened the file.
Parsing a group of options: output url out.mp4.
Applying option c (codec name) with argument copy.
Successfully parsed a group of options.
Opening an output file: out.mp4.
[file @ 0x9620f0] Setting default whitelist 'file,crypto'
Successfully opened the file.
Output #0, mp4, to 'out.mp4':
Metadata:
encoder : Lavf58.20.100
Stream #0:0, 0, 1/1200000: Video: h264 (Main), 1 reference frame (avc1 / 0x31637661), yuv420p(progressive, left), 1920x1080 (0x0), 0/1, q=2-31, 12.17 fps, 12 tbr, 1200k tbn, 1200k tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
[mp4 @ 0x8760d0] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
No more output streams to write to, finishing.
frame= 230 fps=0.0 q=-1.0 Lsize= 79kB time=00:00:18.90 bitrate= 34.1kbits/s speed= 945x
video:75kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 4.431734%
Input file #0 (file.h264):
Input stream #0:0 (video): 230 packets read (77103 bytes);
Total: 230 packets (77103 bytes) demuxed
Output file #0 (out.mp4):
Output stream #0:0 (video): 230 packets muxed (77103 bytes);
Total: 230 packets (77103 bytes) muxed
0 frames successfully decoded, 0 decoding errors
When it doesn't (e.g. ffmpeg -i file.raw -
)
Splitting the commandline.
Reading option '-i' ... matched as input url with argument 'file.raw'.
Reading option '-c' ... matched as option 'c' (codec name) with argument 'copy'.
Reading option '-err_detect' ...Routing option err_detect to both codec and muxer layer
matched as AVOption 'err_detect' with argument 'ignore_err'.
Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument 'debug'.
Reading option '-flags' ... matched as AVOption 'flags' with argument '+global_header'.
Reading option '-f' ... matched as option 'f' (force format) with argument 'h264'.
Reading option '-c' ... matched as option 'c' (codec name) with argument 'copy'.
Reading option 'out.mp4' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option loglevel (set logging level) with argument debug.
Successfully parsed a group of options.
Parsing a group of options: input url file.raw.
Successfully parsed a group of options.
Opening an input file: file.raw.
[NULL @ 0x201f270] Opening 'file.raw' for reading
[file @ 0x201fa00] Setting default whitelist 'file,crypto'
[AVIOContext @ 0x2027bd0] Statistics: 77108 bytes read, 0 seeks
file.raw: Invalid data found when processing input
Yeah, you didn't even try to invoke H264...
Versions
I've tried this with ffmpeg 4.1.6 and 4.3.2