3

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

1 Answer 1

3

Oh, that's right - all input-related arguments need to go before the input argument with ffmpeg.

The documentation states:

As a general rule, options are applied to the next specified file. Therefore, order is important, and you can have the same option on the command line multiple times. Each occurrence is then applied to the next input or output file. Exceptions from this rule are the global options (e.g. verbosity level), which should be specified first.

This works:

ffmpeg -f h264 -i avcfile.h264 -c copy out.mp4

somenetworkstreamer | ffmpeg -f h264 -i pipe: -c copy out.mp4

1
  • I have another question like this. I wanna an h264 file output to pipe, but my command can not work. ffmpeg -f mjpeg -i http://127.0.0.1:20000/ -r 120 -f h264 -max_delay 1 -s 390x844 -c:v libx264 -tune zerolatency -b:v 600k -
    – caimaoy
    Jan 6 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.