Home > Blockchain >  FFMPEG Video Corrupt When Not Perfect Square
FFMPEG Video Corrupt When Not Perfect Square

Time:04-24

I am writing frames from OpenCV using the following method. These code works totally fine when using a perfectly square resolution like 1000x1000 or 500x500, but when trying to do 1920x1200 or any other rectangular resolution, the written MP4 contains what is seen in the attached image. The MP4 file plays that still frame for the exact number of excepted seconds.

What could possibly be causing this kind of behavior?

  • The camera width and height match the output resolution
  • What is seen in the attachment is actually a frame from the camera, its just corrupted in the way seen.
  • File size matches excpected output roughly
process = sp.Popen(shlex.split(f'ffmpeg -y -hide_banner -loglevel error
 -s {fwidth}x{fheight} -pixel_format bgr24 -f rawvideo 
-r {self.fps} -i pipe: -vcodec libx265 -pix_fmt yuv420p 
-crf 24 {filename}'), stdin=sp.PIPE)

for frame in frameList:
    process.stdin.write(frame.tobytes())

# Close and flush stdin
process.stdin.close()

# Wait for sub-process to finish
process.wait()

# Terminate the sub-process
process.terminate()

enter image description here

Attached is the ffprobe log

ffprobe version 3.4.8-0ubuntu0.2 Copyright (c) 2007-2020 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04)
  configuration: --prefix=/usr --extra-version=0ubuntu0.2 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
  WARNING: library configuration mismatch
  avcodec     configuration: --prefix=/usr --extra-version=0ubuntu0.2 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared --enable-version3 --disable-doc --disable-programs --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libtesseract --enable-libvo_amrwbenc
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libavresample   3.  7.  0 /  3.  7.  0
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/var/www/html/students/RH-PITCH_VIDEO.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf57.83.100
  Duration: 00:00:03.13, start: 0.000000, bitrate: 452 kb/s
    Stream #0:0(und): Video: hevc (Main) (hev1 / 0x31766568), yuv420p(tv, progressive), 1200x1100, 432 kb/s, 160 fps, 160 tbr, 10240 tbn, 160 tbc (default)
    Metadata:
      handler_name    : VideoHandler

CodePudding user response:

The described behavior definitely points to piping the frame data in a wrong order.

Given a (row-)contiguous numpy array (i.e., a C-ordered array), np.uint8 RGB24/BGR24 frame should be stored so frame.shape = (height, width, ncomp=3). If the ordering is not correct, use np.transpose to reorder the array dimensions.

Meanwhile, FFmpeg's size input option is specified as -s widthxheight. So first make sure the width and height matches the frame shape.

If your frame dimension is correct, then it is likely that your numpy array is formatted in Fortran order, or column contiguous order. For this representation, the correct shape is ncomp x width x height. Sending a height x width x ncomp array to the ffmpeg's stdin pipe also screws up the image. For this, an easy fix is to use frame.tobytes('C') to reorder the bytes.

In any case, it would be the most efficient to fix the dimension issues upstream so frame is produced in the correct shape for the FFmpeg.

  • Related