1

I am using ffmpeg to transcode videos into a specific AVI format using ffmpeg.exe -i "Input.ext" -y -vcodec rawvideo -pix_fmt rgb555le -an -map_metadata -1 TEST_ENCODE.avi. The resulting AVI is an input for a legacy command-line program that is no longer supported. Unfortunately, this program is unable to read AVIs produced by ffmpeg despite being in the proper format and using the proper encoding. After days of analysis and debugging, I have finally identified the issue. ffmpeg is encoding the bitmap frames in the AVI with a negative height, indicating a top down scanline order. My other program, however, requires a positive height with the more traditional bottom up scanline order. Is it possible to force ffmpeg to use a positive height (bottom up scanline order) for the frames?

Edit: Even when turning the verbosity as high as possible, I haven't been able to get ffmpeg to report enough detail to catch this generally insignificant detail of the encoding, but since I was asked for the logs I'll provide them.

WORKS_IN_LEGACY_APP:

D:\AutoHotkey Scripts\PS Gui v4\!OutputDest>"D:\Program Files\ffmpeg\bin\ffmpeg.exe" -v 9 -loglevel 99 -i TEST_COPY.avi
ffmpeg version git-2020-06-17-0b3bd00 Copyright (c) 2000-2020 the FFmpeg developers
  built with gcc 9.3.1 (GCC) 20200523
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libsrt --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --disable-w32threads --enable-libmfx --enable-ffnvcodec --enable-cuda-llvm --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt --enable-amf
  libavutil      56. 55.100 / 56. 55.100
  libavcodec     58. 92.100 / 58. 92.100
  libavformat    58. 46.101 / 58. 46.101
  libavdevice    58. 11.100 / 58. 11.100
  libavfilter     7. 86.100 /  7. 86.100
  libswscale      5.  8.100 /  5.  8.100
  libswresample   3.  8.100 /  3.  8.100
  libpostproc    55.  8.100 / 55.  8.100
Splitting the commandline.
Reading option '-v' ... matched as option 'v' (set logging level) with argument '9'.
Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument '99'.
Reading option '-i' ... matched as input url with argument 'TEST_COPY.avi'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument 9.
Successfully parsed a group of options.
Parsing a group of options: input url TEST_COPY.avi.
Successfully parsed a group of options.
Opening an input file: TEST_COPY.avi.
[NULL @ 000002d12df7bf80] Opening 'TEST_COPY.avi' for reading
[file @ 000002d12df7c880] Setting default whitelist 'file,crypto,data'
Probing avi score:100 size:2048
[avi @ 000002d12df7bf80] Format avi probed with size=2048 and score=100
[avi @ 000002d12df7d300] use odml:1
[avi @ 000002d12df7bf80] pos:14 tag: tag=LIST size=0x11ec
[avi @ 000002d12df7bf80] pos:18 list: tag=hdrl size=0x0
[avi @ 000002d12df7bf80] pos:20 tag: tag=avih size=0x38
[avi @ 000002d12df7bf80] pos:60 tag: tag=LIST size=0x1094
[avi @ 000002d12df7bf80] pos:64 list: tag=strl size=0x0
[avi @ 000002d12df7bf80] pos:6C tag: tag=strh size=0x38
[avi @ 000002d12df7bf80] pos:74 strh: tag=vids size=0xffffffff
[avi @ 000002d12df7bf80] 125000 8341 0
[avi @ 000002d12df7bf80] pos:AC tag: tag=strf size=0x28
[avi @ 000002d12df7bf80] pos:D4 video: tag=[0][0][0][0] size=0x0
[avi @ 000002d12df7bf80] pos:DC tag: tag=JUNK size=0x1018
[avi @ 000002d12df7bf80] pos:10FC tag: tag=JUNK size=0x104
[avi @ 000002d12df7bf80] pos:1208 tag: tag=LIST size=0x1a
[avi @ 000002d12df7bf80] pos:120C list: tag=INFO size=0x0
[avi @ 000002d12df7bf80] pos:122A tag: tag=JUNK size=0x3f8
[avi @ 000002d12df7bf80] pos:162A tag: tag=LIST size=0x4268644
[avi @ 000002d12df7bf80] pos:162E list: tag=movi size=0x0
[avi @ 000002d12df7bf80] movi end=4269c6e
[avi @ 000002d12df7bf80] movi_end=0x4269c6e
[avi @ 000002d12df7bf80] 0: tag=0x63643030 flags=0x10 pos=0x4 len=348160/348160 cum_len=0
[avi @ 000002d12df7bf80] 1: tag=0x63643030 flags=0x10 pos=0x5500c len=348160/348160 cum_len=1
[avi @ 000002d12df7bf80] 2: tag=0x63643030 flags=0x10 pos=0xaa014 len=348160/348160 cum_len=2
[A bunch more of these, truncated due to size.]
[avi @ 000002d12df7bf80] 198: tag=0x63643030 flags=0x10 pos=0x41be634 len=348160/348160 cum_len=198
[avi @ 000002d12df7bf80] 199: tag=0x63643030 flags=0x10 pos=0x421363c len=348160/348160 cum_len=199
[avi @ 000002d12df7bf80] Before avformat_find_stream_info() pos: 5678 bytes read:104712 seeks:4 nb_streams:1
[avi @ 000002d12df7bf80] parser not found for codec rawvideo, packets or times may be invalid.
    Last message repeated 1 times
[avi @ 000002d12df7bf80] All info found
[avi @ 000002d12df7bf80] stream 0: start_time: 0 duration: 13.3456
[avi @ 000002d12df7bf80] format: start_time: 0 duration: 13.3456 (estimate from stream) bitrate=41747 kb/s
[avi @ 000002d12df7bf80] After avformat_find_stream_info() pos: 353846 bytes read:420112 seeks:4 frames:1
Input #0, avi, from 'TEST_COPY.avi':
  Metadata:
    encoder         : Lavf58.46.101
  Duration: 00:00:13.35, start: 0.000000, bitrate: 41747 kb/s
    Stream #0:0, 1, 8341/125000: Video: rawvideo, 1 reference frame, rgb555le, 640x272, 0/1, 41950 kb/s, 14.99 fps, 14.99 tbr, 14.99 tbn, 14.99 tbc
Successfully opened the file.
At least one output file must be specified
[AVIOContext @ 000002d12df85340] Statistics: 420112 bytes read, 4 seeks

TEST_ENCODE (Doesn't Work):

D:\AutoHotkey Scripts\PS Gui v4\!OutputDest>"D:\Program Files\ffmpeg\bin\ffmpeg.exe" -v 9 -loglevel 99 -i TEST_ENCODE.avi
ffmpeg version git-2020-06-17-0b3bd00 Copyright (c) 2000-2020 the FFmpeg developers
  built with gcc 9.3.1 (GCC) 20200523
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libsrt --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --disable-w32threads --enable-libmfx --enable-ffnvcodec --enable-cuda-llvm --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt --enable-amf
  libavutil      56. 55.100 / 56. 55.100
  libavcodec     58. 92.100 / 58. 92.100
  libavformat    58. 46.101 / 58. 46.101
  libavdevice    58. 11.100 / 58. 11.100
  libavfilter     7. 86.100 /  7. 86.100
  libswscale      5.  8.100 /  5.  8.100
  libswresample   3.  8.100 /  3.  8.100
  libpostproc    55.  8.100 / 55.  8.100
Splitting the commandline.
Reading option '-v' ... matched as option 'v' (set logging level) with argument '9'.
Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument '99'.
Reading option '-i' ... matched as input url with argument 'TEST_ENCODE.avi'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument 9.
Successfully parsed a group of options.
Parsing a group of options: input url TEST_ENCODE.avi.
Successfully parsed a group of options.
Opening an input file: TEST_ENCODE.avi.
[NULL @ 000002c07a68bf80] Opening 'TEST_ENCODE.avi' for reading
[file @ 000002c07a68c880] Setting default whitelist 'file,crypto,data'
Probing avi score:100 size:2048
[avi @ 000002c07a68bf80] Format avi probed with size=2048 and score=100
[avi @ 000002c07a68d300] use odml:1
[avi @ 000002c07a68bf80] pos:14 tag: tag=LIST size=0x11ec
[avi @ 000002c07a68bf80] pos:18 list: tag=hdrl size=0x0
[avi @ 000002c07a68bf80] pos:20 tag: tag=avih size=0x38
[avi @ 000002c07a68bf80] pos:60 tag: tag=LIST size=0x1094
[avi @ 000002c07a68bf80] pos:64 list: tag=strl size=0x0
[avi @ 000002c07a68bf80] pos:6C tag: tag=strh size=0x38
[avi @ 000002c07a68bf80] pos:74 strh: tag=vids size=0xffffffff
[avi @ 000002c07a68bf80] 125000 8341 0
[avi @ 000002c07a68bf80] pos:AC tag: tag=strf size=0x28
[avi @ 000002c07a68bf80] pos:D4 video: tag=[0][0][0][0] size=0x0
[avi @ 000002c07a68bf80] pos:DC tag: tag=JUNK size=0x1018
[avi @ 000002c07a68bf80] pos:10FC tag: tag=JUNK size=0x104
[avi @ 000002c07a68bf80] pos:1208 tag: tag=LIST size=0x1a
[avi @ 000002c07a68bf80] pos:120C list: tag=INFO size=0x0
[avi @ 000002c07a68bf80] pos:122A tag: tag=JUNK size=0x3f8
[avi @ 000002c07a68bf80] pos:162A tag: tag=LIST size=0x4268644
[avi @ 000002c07a68bf80] pos:162E list: tag=movi size=0x0
[avi @ 000002c07a68bf80] movi end=4269c6e
[avi @ 000002c07a68bf80] movi_end=0x4269c6e
[avi @ 000002c07a68bf80] 0: tag=0x63643030 flags=0x10 pos=0x4 len=348160/348160 cum_len=0
[avi @ 000002c07a68bf80] 1: tag=0x63643030 flags=0x10 pos=0x5500c len=348160/348160 cum_len=1
[avi @ 000002c07a68bf80] 2: tag=0x63643030 flags=0x10 pos=0xaa014 len=348160/348160 cum_len=2
[A bunch more of these, truncated due to size.]
[avi @ 000002c07a68bf80] 198: tag=0x63643030 flags=0x10 pos=0x41be634 len=348160/348160 cum_len=198
[avi @ 000002c07a68bf80] 199: tag=0x63643030 flags=0x10 pos=0x421363c len=348160/348160 cum_len=199
[avi @ 000002c07a68bf80] Before avformat_find_stream_info() pos: 5678 bytes read:104712 seeks:4 nb_streams:1
[avi @ 000002c07a68bf80] parser not found for codec rawvideo, packets or times may be invalid.
    Last message repeated 1 times
[avi @ 000002c07a68bf80] All info found
[avi @ 000002c07a68bf80] stream 0: start_time: 0 duration: 13.3456
[avi @ 000002c07a68bf80] format: start_time: 0 duration: 13.3456 (estimate from stream) bitrate=41747 kb/s
[avi @ 000002c07a68bf80] After avformat_find_stream_info() pos: 353846 bytes read:420112 seeks:4 frames:1
Input #0, avi, from 'TEST_ENCODE.avi':
  Metadata:
    encoder         : Lavf58.46.101
  Duration: 00:00:13.35, start: 0.000000, bitrate: 41747 kb/s
    Stream #0:0, 1, 8341/125000: Video: rawvideo, 1 reference frame, rgb555le, 640x272, 0/1, 41950 kb/s, 14.99 fps, 14.99 tbr, 14.99 tbn, 14.99 tbc
Successfully opened the file.
At least one output file must be specified
[AVIOContext @ 000002c07a695340] Statistics: 420112 bytes read, 4 seeks

As you can see, ffmpeg loads the "strf" chunk but doesn't report what each of the fields in the Bitmap Header are. To get that info, I found a nifty little program called VidTrace (http://www.jmcgowan.com/aviauthor.html#VidTrace)

WORKS_IN_LEGACY_APP:

D:\AutoHotkey Scripts\PS Gui v4\!OutputDest>vidtrace.exe TEST_COPY.avi
RIFF (69642478) AVI
 LIST (4588) hdrl
  avih (56)
   Microseconds Per Frame: 66728
    14.986213 Frames Per Second
   Maximum Bytes Per Second: 5243818
   Pad to Multiples of This Size: 0
   Flags DWORD (hex): 910
    FLAG: (AVIF_HASINDEX)  AVI File Has 'idx1' chunk
    FLAG: (AVIF_ISINTERLEAVED)  AVI File is Interleaved
    FLAG: (AVIF_TRUSTCKTYPE)  Use Chunk Type to Find Key Frames
   Total Frames: 200
   Initial Frames: 0
   Number of Streams: 1
   Suggested Buffer Size: 1048576
   Width in Pixels: 640
   Height in Pixels: 272
   Scale (MAY BE UNUSED): 0
   Rate (MAY BE UNUSED): 0
    Samples Per Second (MAY BE UNUSED): 0
   Start of AVI File (MAY BE UNUSED): 0
   Length of AVI File (MAY BE UNUSED): 0
  LIST (4244) strl
   strh (56)
    Stream Type (Four Character Code): 'vids'
     'vids' is Four Character Code for Video Stream
    Installable Compressor (Four Character Code): ''
     '' is Four Character Code for Uncompressed DIB
    Flags (hex): 0
    Priority (MAY BE UNUSED) (hex): 0
    Language Code (MAY BE UNUSED) (hex): 0
    Initial Frames: 0
    Scale: 8341
    Rate: 125000
    Start: 0
    Length: 200
    Suggested Buffer Size: 348160
    Quality: 4294967295
    Sample Size: 0
    Frame - 16 bit RECT takes 8 bytes (MAY BE UNUSED): Top: 0 Bottom: 272 Left: 0 Right: 640
    Note on Frame: In 16 bit Windows, the RECT structure is
    Note on Frame: four (4) 16 bit integers, a total of 8 bytes.
    Note on Frame: Some AVI use a 16 bit RECT for Frame.
    Note on Frame: Others use a 32 bit RECT, a total of 16 bytes.
   strf (40)
    Windows Bitmap Header
    Number of Bytes Required by Bitmap Structure: 40
    Width of Bitmap in Pixels: 640
    Height of Bitmap in Pixels: 272
    Number of Planes: 1
    Number of Bits Per Pixel (1,4,8,16,24, or 32): 16
    Compression Mode (hex): 0
     COMPRESSION: Uncompressed RGB Format
    Size of Image in Bytes: 348160
    Horizontal Resolution in Pixels per Meter: 0
    Vertical Resolution in Pixels per Meter: 0
    Number of Color Indices Actually Used by the Bitmap: 0
    Number of Color Indices Considered Important to Display Bitmap: 0
   JUNK (4120)
  JUNK (260)
 LIST (26) INFO
  ISFT (14)
 JUNK (1016)
 LIST (69633604) movi
  00dc (348160)
  00dc (348160)
  00dc (348160)
  00dc (348160)
  [A bunch more of these, truncated due to size.]
  00dc (348160)
 idx1 (3200)

TEST_ENCODE (Doesn't Work):

D:\AutoHotkey Scripts\PS Gui v4\!OutputDest>vidtrace.exe TEST_ENCODE.avi
RIFF (69642478) AVI
 LIST (4588) hdrl
  avih (56)
   Microseconds Per Frame: 66728
    14.986213 Frames Per Second
   Maximum Bytes Per Second: 4891499
   Pad to Multiples of This Size: 0
   Flags DWORD (hex): 910
    FLAG: (AVIF_HASINDEX)  AVI File Has 'idx1' chunk
    FLAG: (AVIF_ISINTERLEAVED)  AVI File is Interleaved
    FLAG: (AVIF_TRUSTCKTYPE)  Use Chunk Type to Find Key Frames
   Total Frames: 200
   Initial Frames: 0
   Number of Streams: 1
   Suggested Buffer Size: 1048576
   Width in Pixels: 640
   Height in Pixels: 272
   Scale (MAY BE UNUSED): 0
   Rate (MAY BE UNUSED): 0
    Samples Per Second (MAY BE UNUSED): 0
   Start of AVI File (MAY BE UNUSED): 0
   Length of AVI File (MAY BE UNUSED): 0
  LIST (4244) strl
   strh (56)
    Stream Type (Four Character Code): 'vids'
     'vids' is Four Character Code for Video Stream
    Installable Compressor (Four Character Code): ''
     '' is Four Character Code for Uncompressed DIB
    Flags (hex): 0
    Priority (MAY BE UNUSED) (hex): 0
    Language Code (MAY BE UNUSED) (hex): 0
    Initial Frames: 0
    Scale: 8341
    Rate: 125000
    Start: 0
    Length: 200
    Suggested Buffer Size: 348160
    Quality: 4294967295
    Sample Size: 0
    Frame - 16 bit RECT takes 8 bytes (MAY BE UNUSED): Top: 0 Bottom: 272 Left: 0 Right: 640
    Note on Frame: In 16 bit Windows, the RECT structure is
    Note on Frame: four (4) 16 bit integers, a total of 8 bytes.
    Note on Frame: Some AVI use a 16 bit RECT for Frame.
    Note on Frame: Others use a 32 bit RECT, a total of 16 bytes.
   strf (40)
    Windows Bitmap Header
    Number of Bytes Required by Bitmap Structure: 40
    Width of Bitmap in Pixels: 640
    Height of Bitmap in Pixels: -272
    Number of Planes: 1
    Number of Bits Per Pixel (1,4,8,16,24, or 32): 16
    Compression Mode (hex): 0
     COMPRESSION: Uncompressed RGB Format
    Size of Image in Bytes: 348160
    Horizontal Resolution in Pixels per Meter: 0
    Vertical Resolution in Pixels per Meter: 0
    Number of Color Indices Actually Used by the Bitmap: 0
    Number of Color Indices Considered Important to Display Bitmap: 0
   JUNK (4120)
  JUNK (260)
 LIST (26) INFO
  ISFT (14)
 JUNK (1016)
 LIST (69633604) movi
  00dc (348160)
  00dc (348160)
  00dc (348160)
  00dc (348160)
  [A bunch more of these, truncated due to size.]
  00dc (348160)
 idx1 (3200)

Note the different sign on the value of "Height of Bitmap in Pixels" in the "strf" chunk.

I added -vf vflip to ffmpeg when encoding to invert the scanlines, and then I manually edited the bitmap height to be positive with a hex editor. After doing this, my legacy program works properly, proving the negative height is the sole cause of my issues.

23
  • Not clear what this means - what is 'negative height' and where is this identified? Note that rawvideo is, as the name suggests, just a raw dump of pixel values so the frame data itself has no technical concept of row ordering. At most this will produce an incorrectly oriented image rather than prevent decoding. This is probably a metadata issue. Share the full log of ffmpeg -i TEST_ENCODE.avi and of ffmpeg -i WORKS_IN_LEGACY_APP.avi
    – Gyan
    Jun 22, 2020 at 8:43
  • While your statement may sometimes be true, it is not the case here. The original Windows AVI format (docs.microsoft.com/en-us/windows/win32/directshow/…) is just a bunch of Device Independent Bitmaps (DIB) put together, optionally interleaved with audio. These bitmaps share a common BITMAPINFO Header (docs.microsoft.com/en-us/windows/win32/api/wingdi/…). This bitmap header is located in the "strf" chunk in the RIFF container, and the third field is "biHeight" which can be positive or negative depending on the scanline ordering.
    – Sam.
    Jun 22, 2020 at 19:01
  • Updated OP with logs and proof of my claims.
    – Sam.
    Jun 22, 2020 at 19:12
  • So it was a metadata issue. ffmpeg's rawvideo encoder has no concept of negative height - it always writes rows top down.
    – Gyan
    Jun 22, 2020 at 19:38
  • That may be the case, but at some level ffmpeg is aware that bottom-up ordering is the standard for bitmaps because a) it properly reads in both bottom-up positive height data and top-down negative height data, and b) knows to make the height negative when the rawvideo encoder outputs top-down data. Perhaps that happens at the muxing/demuxing level instead of the encoding/decoding level (I find the nuances of what gets put into which box here a bit unclear), but none of this answers my original question: How to make ffmpeg output an AVI with bottom-up scanline ordering and positive height?
    – Sam.
    Jun 22, 2020 at 23:06

1 Answer 1

0

ffmpeg needed to be updated to be able to produce rawvideo AVI video frames with a positive height and bottom up scanline order. The solution is now to use the commands -vf vflip -flipped_raw_rgb 1.

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.