RIFF AVI RLE 不同于 GDI RLE

RIFF AVI RLE different to GDI RLE

我有一个基本的 RIFF AVI,是在 1990 年代早期制作的,我很想用原生 VB/C# 代码制作一个基本的视频播放器。根据 header,它使用旧的 MS RLE 编解码器。 AVI 中的位图 header 表示它是 RLE8 压缩的。

  1. 这是将原始 'xxdc' 压缩数据写入位图的结果,该位图从头开始创建并在 Windows 照片查看器
  2. 中打开
  3. 使用 VirtualDub 提取的同一帧
  4. 下面的代码解压缩 RLE8 位图

问题是下面的代码和 Windows 做同样的事情,部分丢失导致我从旧的 VirtualDub blog post 得到以下内容;

(GDI's RLE isn't the same as AVI's RLE)".

问题是我找不到区别:(。我在互联网上找不到任何资源,在 MSDN 上也找不到任何 material。

我从 http://dirkbertels.net/computing/bitmap_decompression.php 移植了一个 RLE8 解压缩示例到 VB(为简洁起见省略了位图结构)。这是一种享受。问题是使用 RLE8 的 AVI 帧无法正常工作。

        Dim firstByte As Byte
        Dim secondByte As Byte
        Dim currX As UInteger = 0
        Dim currY As UInteger = 0
        Dim i As UInteger

        Do
            firstByte = br.ReadByte
            If 0 <> firstByte Then
                ' Encoded Mode
                secondByte = br.ReadByte
                For i = 0 To firstByte - 1
                    frame.SetPixel(currX, currY, _bitmap.biClut(secondByte))
                    currX += 1
                Next i
            Else
                ' Absolute Mode
                firstByte = br.ReadByte ' store next byte
                Select Case firstByte
                    Case 0 ' new line
                        currX = 0
                        currY += 1 ' move cursor to beginning of next line
                    Case 1 ' end of bitmap
                        Exit Do
                    Case 2 ' delta = goto X and Y
                        currX += CInt(br.ReadByte) ' read byte and add value to x value
                        currY += CInt(br.ReadByte) ' read byte and add value to y value
                    Case Else
                        For i = 0 To firstByte - 1
                            secondByte = br.ReadByte
                            frame.SetPixel(currX, currY, _bitmap.biClut(secondByte))
                            currX += 1
                        Next i
                        'If 0 <> (firstByte And &H1) Then
                        '    br.ReadByte()
                        'End If
                        If firstByte And &H1 Then ' if the run doesn't end on a word boundary,
                            br.ReadByte()
                        End If
                End Select
            End If
        Loop

我现在不知道 VirtualDub、FFMPEG 和其他人如何在不使用旧的 MSRLE.DLL 编解码器的情况下做到这一点...有人有什么想法吗?

我找到了解决方案,所以我会在这里回答,以便像我这样的人有一个起点。

帧数据解压正确。问题是我没有正确遵循 RIFF AVI 规范。对于我的视频,每一帧都比前一帧解压缩。