18

I'm having trouble writing h264 video with OpenCV 3 via FFmpeg ("'X','2','6','4'" FOURCC). I've seen all the related posts so far on SO, but nothing helps. Code:

cv::VideoWriter writer(output_path.string(),    CV_FOURCC('X','2','6','4'), 60, frame_size);

Output:

OpenCV: FFMPEG: tag 0x34363258/'X264' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000021/'!???'

The resulting video is extremely small (byte-wise) and unreadable. Setting the four_cc to -1 results in "unknown tag" from FFmpeg, I don't get any prompt to choose codec as others suggested.

The OpenCV 3 doc states:

FFMPEG backend with MP4 container natively uses other values as fourcc code: see ObjectType, so you may receive a warning message from OpenCV about fourcc code conversion.

That page they refrence doesn't have h264 / x264 listed, and I'm not sure how to interpret that statement, since earlier SO posts seem to all list X.2.6.4 as the appropriate code. Using H.2.6.4 actually gives identical output.

Any suggestions / workarounds?

P.S. the ffmpeg is most up-to-date from Ubuntu maintainers, it lists that it was configured with --enable-libx264

EDIT: I tried to use the mkv container instead of mp4. The warning about tag not being supported went away, but the resulting video is still unreadable.

Community
  • 1
  • 1
Greg Kramida
  • 4,064
  • 5
  • 30
  • 46
  • 1
    I can't tell how to solve this, but `VideoWriter` is not much powerful. You probably need to save your video with some working format, and then convert to H264 with ffmpeg. – Miki Dec 01 '15 at 16:01
  • @Miki if you know a way to convert opencv matrices properly into x264_picture_t to use x264 directly, that might work. I've tried converting to YUV_I420 and manually setting fields of x264_picture_t, but so far failed. – Greg Kramida Dec 01 '15 at 17:06

3 Answers3

11

I think your finding here is key:

FFMPEG backend with MP4 container natively uses other values as fourcc code: see ObjectType, so you may receive a warning message from OpenCV about fourcc code conversion.

The mp4 tag values implemented for ffmpeg confirm this, and are in the ff_mp4_obj_type[], in isom.c. The code in OpenCV's cap_ffmpeg_impl.hpp likely needs to be updated to support this. I poked around for an hour or two, realized it was non-trivial, and bailed.

One work-around is to output to an .avi file. There are numerous examples of people having trouble with OpenCV and mp4, and being told to use .mov or .avi. (Here's one.)

@Greg Kramida: setting isColor = false did not help for me: the message remained, and my output file became only ~48 bytes. According to the documentation it is a Windows flag -- whatever it is doing for me on Linux, it isn't good.

Did you confirm that you could generate x264 with ffmpeg, by itself?

After confirming that libx264 has value 0x21 when I invoke this on the command line:

ffmpeg -i x264-input.mp4 -vcodec libx264 -f mp4 x264-output.mp4

I decided to use 0x21 directly into VideoWriter.open(). That generates a valid and interpretable video file.

For reference, my software is ffmpeg 3.0:

ffmpeg -version
ffmpeg version 3.0 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 4.9.2 (Debian 4.9.2-10)
configuration: --enable-libx264 --enable-gpl --prefix=/usr/local --enable-shared --cc=`gcc -fPIC` --enable-libfdk-aac --enable-libx265 --enable-nonfree --enable-libmp3lame
libavutil      55. 17.103 / 55. 17.103
libavcodec     57. 24.102 / 57. 24.102
libavformat    57. 25.100 / 57. 25.100
libavdevice    57.  0.101 / 57.  0.101
libavfilter     6. 31.100 /  6. 31.100
libswscale      4.  0.100 /  4.  0.100
libswresample   2.  0.101 /  2.  0.101
libpostproc    54.  0.100 / 54.  0.100

And OpenCV 3.1.0 configured with:

cmake \
    -D WITH_IPP=ON \
    -D INSTALL_CREATE_DISTRIB=ON \
    -D CMAKE_BUILD_TYPE=Release \
    -D CMAKE_INSTALL_PREFIX=/usr/local ..

x264 is the libx264-142:amd64 release for Debian Jessie.

Jameson
  • 6,400
  • 6
  • 32
  • 53
  • 1
    This is interesting. I am also on Linux, and setting the ```isColor``` flag to false made all the difference for me. Whatever is the issue you're having, it's obviously different from mine, so, if you're still interested in direct mp4 output from OpenCV, I suggest you post a separate question describing your issue, referencing this one. I also suggest we take this conversation to a private chat to stick to the preferred QA format of SO. I can provide my compile flags there. – Greg Kramida Feb 19 '16 at 15:17
8

The problem had nothing to do with the displayed warning. I was trying to write single-channel images, while the VideoWriter was expecting a 3-channel color image (default value of isColor, the 5-th argument to VideoWriter's constructor, is "true"). The solution was setting isColor to false.

Greg Kramida
  • 4,064
  • 5
  • 30
  • 46
  • 1
    When down-voting, please consider explaining down-vote to help improve the answer. – Greg Kramida Feb 18 '16 at 15:29
  • This answer is a couple years old, but I'm struggeling with the same problem. I'm on OSX using OpenCV 3.2.0 and ffmpeg compiled with `openh264`. For me setting the 5th argument to either `True` or `False` or leaving it out doesn't make any difference. Any other ideas how I could debug this? – kramer65 May 15 '17 at 17:57
  • @kramer65, I would highly recommend posting a separate issue about this, and referencing this one, saying that this one is not the problem you're having (i.e. the isColor flag doesn't make a difference). The only suggestion I have -- try both X264 and H264 codes. Also, on Linux, libx264 development library needed to be installed, not openh264... I don't know if there's a package of that for OSX. – Greg Kramida May 15 '17 at 21:54
5

The problem on OpenCV which message is:

OpenCV: FFMPEG: tag 0x34363248/'H264' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000021/'!???'

It is produced by definitions of CV_FOURCC('H','2','6','4') this value do not corresponds with the value defined on isom.c

{ AV_CODEC_ID_H264 , 0x21 }

Then defining fourcc as 0x21 cv::VideoWriter works smooth,

cv::VideoWriter VF;
VF.open(filename,0x21,fps,frameSize,true);

as Jameson comments above,

"I decided to use 0x21 directly into VideoWriter.open(). That generates a valid and interpretable video file."

  • Opencv's way of conversion on FOURCC isn't compatable with FFMPEG. Correct way is to hardcode 0x21! Worked for me! – Menilik Belay Woldeyes May 23 '19 at 08:54
  • I dont really get why, the debug message says "fallback to use tag 0x21", so shouldnt the fallback be the same as a hardcoded 0x21 tag? – Jodo Jan 05 '20 at 09:02