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.
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
.
User contributions licensed under CC BY-SA 3.0