Log in

View Full Version : should I use ffmpeg for x264 or just pipe?


seandarcy
15th May 2011, 03:35
With your help, I've been working on encoding a bunch of dv files.

Here's my script:

ffmpeg -i in.dv -an -vf "yadif=1:0,hqdn3d" -r 60000/1001 \
-vcodec libx264 -preset slower -tune film -crf 17 $1.m4v
ffmpeg -i in.dv -vn -acodec copy -f wav - | neroAacEnc -q 0.3 -ignorelength -if - -of $1.m4a
MP4Box -hint -add $1.m4v -add $1.m4a -new $1.mp4
rm -f $1.m4*

Should I just use ffmpeg to pipe -pix-fmt yuv420p16be output, and run x264 directly? Just like I do with the audio.

sean

Selur
15th May 2011, 04:46
Personally I use ffmpeg/mencoder to decode and then pipe x264 simply because it a lot more hassle to update (compile) ffmpeg each time x264 is updated (unless you are happy with the updates provided by you distro maintainer) than to just update x264.
Quality and speed wise it shouldn't really make a difference assuming your external and internal (in ffmpeg) x264 versions are the same.

Cu Selur

seandarcy
15th May 2011, 17:19
So this should generate the same output as my existing script??

ffmpeg -i in.dv -an -vf "yadif=1:0,hqdn3d" -r 60000/1001 \
-pix_fmt yuv420p -f yuv4mpegpipe - |
x264 --input-res 720x480 --fps 60000/1001 \
--preset slower --tune film --crf 17 -o out.m4v -

It seems to work. But is this correct, or the best way?

This would be great. Then I could use x264 options natively, without having to figure out the ffmpeg<>x264 mappings.

Also, if I don't specify --input-res and --fps x264 fails, with an error message about raw input. From the help, it would seem that they are not needed for yuv4mpeg input. Is it needed here because it's a pipe?

sean

LoRd_MuldeR
15th May 2011, 17:36
For raw YUV data you have to specify the input resolution and the FPS, because there is no way to get these parameters from the "raw" pixel data.

However the YUV4MPEG format has a small header with exactly that information, so I think it should not be needed to specify the input resolution or FPS when YUV4MPEG is used.

This should work with pipes as well as with files, but x264 has to know the input is YUV4MPEG. Try adding "--demuxer y4m" to the x264 part of your command-line...

MasterNobody
15th May 2011, 17:37
Also, if I don't specify --input-res and --fps x264 fails, with an error message about raw input. From the help, it would seem that they are not needed for yuv4mpeg input. Is it needed here because it's a pipe?

sean
You didn't specified --demuxer y4m

seandarcy
15th May 2011, 19:22
yup, --demuxer y4m worked like a charm.

But the output is _way_ different from using ffmpeg directly.

Using the piped input,

ffmpeg -i in.dv -an -vf "yadif=1:0,hqdn3d" -r 60000/1001 \
-pix_fmt yuv420p -f yuv4mpegpipe - |
x264 --input-res 720x480 --fps 60000/1001 \
--preset slower --tune film --crf 17 -o out.m4v -

I get a 1.65 gig file:

1645920794 May 15 13:09 out.m4v


But using

ffmpeg -i in.dv -an -vcodec libx264 -preset slower -tune film \
-vf "yadif=1:0,hqdn3d" -r 60000/1001 -crf 15 JulyPlay.m4v

I got a 700meg file:

697669397 May 7 20:57 JulyPlay.mp4

And this is after it's been muxed with the audio! And a little lower crf.

Puzzled.

sean

LoRd_MuldeR
15th May 2011, 19:29
It's probably because FFmpeg uses quite different settings than the x264 CLI encoder.

With tools like MediaInfo (http://mediainfo.sourceforge.net/en) or Avinaptic (http://www.videohelp.com/tools/avinaptic) you can extract the complete x264 settings that have actually been used from the encoded file - because x264 writes its settings as custom SEI to the bitstream.

Therefore I would suggest you carefully compare the exact settings of both files! It is also possible that your FFmpeg build uses a different version of x264, which can make a big difference...

(In the history of x264 there often have been changes that re-defined the CRF scale, so CRF values generally are not comparable between different versions of x264)

seandarcy
15th May 2011, 21:02
You didn't specified --demuxer y4m

I told you it worked, but it doesn't!
x264 --demuxer y4m --preset slower --tune film --bitrate 1200 -o out3.m4v -
..........
[yadif @ 0xe12ec0] mode:1 parity:0
[hqdn3d @ 0xe0db40] ls:4.000000 cs:3.000000 lt:6.000000 ct:4.500000
[hqdn3d @ 0xe0db40] auto-inserting filter 'auto-inserted scaler 0' between the filter 'Parsed filter 0 yadif' and the filter 'Parsed filter 1 hqdn3d'
[scale @ 0xe0e380] w:720 h:480 fmt:yuv411p -> w:720 h:480 fmt:yuv420p flags:0xa0000004
Output #0, yuv4mpegpipe, to 'pipe:':
Metadata:
encoder : Lavf53.0.3
Stream #0.0: Video: rawvideo, yuv420p, 720x480 [PAR 8:9 DAR 4:3], q=2-31, 200 kb/s, 90k tbn, 59.94 tbc
Stream mapping:
Stream #0.0 -> #0.0
Press [q] to stop encoding
y4m [info]: 720x480i 8:9 @ 60000/1001 fps (cfr)
x264 [warning]: input appears to be interlaced, enabling bff interlaced mode.
If you want otherwise, use --no-interlaced or --tff

So ffmpeg thinks it's generating yuv420p, but x264 is seeing 720x480i !

An ffmpeg bug? x264? or did I screw up somehow?

LoRd_MuldeR
15th May 2011, 21:29
I think "420p" refers to "YUV 4:2:0, progressive". That is perfectly fine as input for x264 and it doesn't say anything about the resolution.
http://en.wikipedia.org/wiki/Chroma_subsampling#Sampling_systems_and_ratios

If however you used a deinterlacing filter, such as Yadif, on the FFmpeg side, then x264 definitely shouldn't encode the result as interlaced!
So in this particular case you should follow x264's suggestion and add the "--no-interlaced" parameter...

J_Darnley
15th May 2011, 22:12
I think "420p" refers to "YUV 4:2:0, progressive".

Planar, not progressive. And if yuv420i existed, it would be interleaved not interlaced. This has no bearing on the content of the image, only how it is stored in memory.

LoRd_MuldeR
15th May 2011, 23:09
Thanks for the correction. Still I think the video is also progressive, as he has applied Yadif. So using "--no-interlaced" is advisable here.

Chikuzen
16th May 2011, 03:16
no.
YUV4MPEG2 stream header has I-tag(interlaced flag), and x264cli's y4m demuxer can parse it(see x264/input/y4m.c (https://github.com/DarkShikari/x264-devel/blob/master/input/y4m.c#L118-L137)).
"--no-interlaced" need not be used.

kemuri-_9
16th May 2011, 04:04
no.
YUV4MPEG2 stream header has I-tag(interlaced flag), and x264cli's y4m demuxer can parse it(see x264/input/y4m.c (https://github.com/DarkShikari/x264-devel/blob/master/input/y4m.c#L118-L137)).
"--no-interlaced" need not be used.

you're missing the point:
x264cli is reading the interlaced flag off the input y4m header which is being incorrectly generated by ffmpeg (saying it's interlaced even after being deinterlaced by yadif).
so --no-interlaced is required to override x264cli's detection here.

Chikuzen
16th May 2011, 04:34
yeah, ffmpeg output incorrect y4m header.
y4m header that exported from ffmpeg is always 'Ip'.
thus "--no-interlaced" is not required:p

LoRd_MuldeR
16th May 2011, 06:36
yeah, ffmpeg output incorrect y4m header.
y4m header that exported from ffmpeg is always 'Ip'.
thus "--no-interlaced" is not required:p

It's obvious from seandarcy's post (http://forum.doom9.org/showpost.php?p=1501188&postcount=8) that he gets progressive output from FFmpeg (he explicitely applies a deinterlace filter) and that x264 still thinks the input is interlaced (and therefore enables interlaced encoding). Thus "--no-interlaced" is required in this particular case, I think...

Chikuzen
16th May 2011, 07:25
umm
sorry, it's my misunderstanding.