marksfink / cfenc

Command-line Cineform encoder/transcoder for Linux and Mac.
GNU Lesser General Public License v3.0
8 stars 2 forks source link

Since when SOWT audio format is not compatibe with MOV container? #2

Open bouncyball-git opened 4 years ago

bouncyball-git commented 4 years ago

Hi, Thank you for this long awaited tool!

I'm converting AVI (v210, PCM) to MOV and experiencing output written at the end of the message (related lines made bold).

Yes I've read your comment:

If the target file format does not support the audio codec, it throws an error and fails. This is because it copies all streams other than video. This can happen when going from MOV to AVI or vice versa

But 'sowt' is perfectly compatible (IT IS apple's fourcc actually) with MOV. Transcoding runs smoothly from AVI to AVI or from MOV to MOV. Also, remuxing (just copying streams) from AVI to MOV with ffmpeg completes w/o errors.

Can you help me resolve this issue?

$ ./cfenc -i M12-1335.avi M12-1335.MOV cfenc version 0.1 -- Cineform encoder/transcoder libavformat 58. 48.100 libavcodec 58. 94.100 libavutil 56. 55.100 libswscale 5. 8.100 libCFHDCodec 10. 0. 2

[avi @ 0x564e1c07ff00] Stream #0: not enough frames to estimate rate; consider increasing probesize Input #0, avi, from 'M12-1335.avi': Metadata: encoder : Lavf58.29.100 Duration: 00:00:32.87, start: 0.000000, bitrate: 1062171 kb/s Stream #0:0: Video: v210 (v210 / 0x30313276), yuv422p10le, 1920x1080 [SAR 1:1 DAR 16:9], 1061969 kb/s, 23.98 fps, 23.98 tbr, 23.98 tbn, 23.98 tbc Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s Guessed channel layout for stream #0:1: stereo [mov @ 0x564e1c09f240] Tag [1][0][0][0] incompatible with output codec id '65536' (sowt) open_output: avformat_write_header failed: Invalid data found when processing input

marksfink commented 4 years ago

Hi bouncyball-git, that error is coming from the avformat library, not cfenc as such. And I have had similar issues. Try using ffmpeg to remux the file from avi to mov. Does it change the audio format at all?

If not, then could you post a sample file? I'll download and see if I can figure it out.

bouncyball-git commented 4 years ago

Hi marksfink, thanks for reply.

This is the ffprobe output for original AVI and remuxed MOV with ffmpeg:

$ ffprobe M12-1329.avi Input #0, avi, from 'M12-1329.avi': Metadata: encoder : Lavf58.48.100 Duration: 00:00:04.17, start: 0.000000, bitrate: 1062193 kb/s Stream #0:0: Video: v210 (v210 / 0x30313276), yuv422p10le, 1920x1080, 1071334 kb/s, 23.98 fps, 23.98 tbr, 23.98 tbn, 23.98 tbc Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s

$ ffprobe M12-1329.mov Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'M12-1329.mov': Metadata: major_brand : qt
minor_version : 512 compatible_brands: qt
encoder : Lavf58.48.100 Duration: 00:00:04.18, start: 0.000000, bitrate: 1059330 kb/s Stream #0:0: Video: v210 (v210 / 0x30313276), yuv422p10le, 1920x1080, 1060621 kb/s, 23.98 fps, 23.98 tbr, 11988 tbn, 11988 tbc (default) Metadata: handler_name : VideoHandler Stream #0:1: Audio: pcm_s16le (sowt / 0x74776F73), 48000 Hz, stereo, s16, 1536 kb/s (default) Metadata: handler_name : SoundHandler

The streams are identical except for mov container apple calls it s16le == sowt (and s16be == twos) (signed 16bit little/big endian)

regards bb

P.S. If needed I will share the orig avi

bouncyball-git commented 4 years ago

Here is the sample: Link

marksfink commented 4 years ago

I looked at your sample. I have a debug build of FFmpeg that I use to look at exactly what FFmpeg does, line by line as it executes. In your case, it changes the codec tag when you copy the audio track in your file, going from avi to mov, without otherwise modifying the stream. You can see it in the output you posted: in the avi file, the codec tag is 1 (and it shows up that way in decimal format when debugging); as it proceeds, it changes it to 0x74476F73 for the mov file. Same codec, same characteristics, but that tag matters. In contrast, cfenc just copies everything as-is including the codec tag, and so it fails in this case. I would have to add the extra intelligence that FFmpeg has to change the codec tag for cases like this.

I'll be honest: it's not high on my list of priorities right now. Particularly because you can remux with FFmpeg first, then run it through cfenc for the Cineform piece. Which I recognize is an extra step and a bother.

I suspect that cfenc will almost always fail when copying audio from avi to mov and vice versa. It will be ok when keeping the same file container.

bouncyball-git commented 4 years ago

Thank you for your comprehensive answer. Now I understand the issue.

I'm one of the developers of mlvapp and wanted to include cfenc into our encoding chain alongside with ffmpeg. However the pipe input in cfenc does not work as it works in ffmped (e.g. "-i -"). If I open pipe for /dev/stdin in linux it works. Besides we do audio separately and wav is fed to ffmpeg as a second input in addition to raw video pipe.

Can I just use your cpp code to implement it directly into mlvapp?

regards bb

marksfink commented 4 years ago

Actually, it would be an easy adjustment to support "-i -". I'll add it in. In any case, feel free to use the code how you like. I don't mind.

bouncyball-git commented 4 years ago

Thanks :)

bouncyball-git commented 4 years ago

One more question.

Lets assume input video depth is more than 8bit (RGB48) and we want to encode to cineform 422 yuv 10bit. Is it absolutly necessary to encode to v210 first and then feed to cineform encoder? Or does cineform encoder do conversion/scaling itself when feeding RGB directly?

marksfink commented 4 years ago

Yes, the Cineform encoder would take RGB48 and convert to v210 when encoding to YUV. The challenge (when writing cfenc) is that the Cineform encoder only accepts certain input formats (RGB48 happens to be one). So to "normalize" the input, I convert anything more than 8-bit to v210 for YUV (and to RGB48 for RGB) because the Cineform encoder accepts those two formats and it will convert to those formats anyway, so we're not wasting or adding cycles. Of course if the video is already v210 or RGB48 and you are not changing color spaces, then we just pass it through. Plus I can control the coefficients used for the conversion. And on that note cfenc currently supports Rec601 and Rec709 because that's what I use. But it occurred to me that I could add Rec2020 -- and I probably will add Rec2020 because it is easy to do. In contrast, the Cineform encoder limits you to Rec601 and Rec709. cfenc sets the Cineform encoder flag to Rec601 and/or 709 but I'm not sure it matters since cfenc uses swscale (FFmpeg) for the conversions; my thought is that the setting may affect how the video is decoded later, but I'm not sure on that.

marksfink commented 4 years ago

Actually, there's no chance of passing through v210 with FFmpeg. 10-bit YUV is always planar with FFmpeg. And, for reasons unbeknownst to me, it does not treat v210 as a pixel format (which it is). Rather, it treats it as a codec. And we must create an encoder for it. All a giant pita for our purposes with Cineform. Probably more detail than you care about. In any case, when using FFmpeg libraries, the only two formats that will pass through to the Cineform encoder are RGB48 and YUYV.

marksfink commented 4 years ago

Just committed an update that supports "-i -" and BT.2020 coefficients. Easy-peasy.

bouncyball-git commented 4 years ago

Thank you!

marksfink commented 4 years ago

So my previous comments got me thinking and I reviewed things. I realized it is easy to passthrough v210; I think I must have got wrapped up in other details when initially writing it. Plus you provided a test video using v210, so testing was easy. Thanks for that! Anyhow, new commit that passes through v210.

bouncyball-git commented 4 years ago

Yes I saw it, thanks.