1

我编写了一个创建 MJPEG 文件的 Delphi 程序,该文件的长度可以达到几 GB。JPG 是使用 DSPack 从 DirectX 相机中获取的。该部分工作正常,并以以下格式创建 JPG 图像文件:

FF D8 ....(图像数据)... FF D9 FF D8 ....(图像数据)... FF D9 FF D8 等

FF D8 标记 JPG 的开始,FF D9 标记结束。每个 JPG 大小约为 21KB。

现在,我正在尝试编写一个匹配的 MJPEG 播放器。

在表单的 FormCreate 过程中,我创建了一个 FileStream 并显示了第一个正常工作的 JPG:

procedure TForm1.FormCreate(Sender: TObject);
var
  b: Array[0..1] of Byte;
  jpg: TJPEGImage;
begin
 :
 :
   MemoryStream:= TMemoryStream.Create;
   jpg:= TJPEGImage.Create;

   MJPEGStream:= TFileStream.Create(MJPEGFileName, fmOpenRead);

   MJPEGStream.Position:= 0;

   repeat                                   
      MJPEGStream.Read(b[0], 2);            // Find end of first jpg
      MemoryStream.Write(b[0], 2);          // and write to memory
   until (b[0] = $FF) and (b[1] = $D9);

   MemoryStream.Position:= 0;
   jpg.LoadFromStream(memoryStream);
   Image1.Picture.Assign(jpg);
   MemoryStream.Free;
   jpg.Free;
end;

我将 FileStream 保持打开状态,因此希望它的 Position 指针被保留。我在表格上有一个按钮,目的是一次慢跑转发一个 JPG,但是,虽然第一个“慢跑”推进了一个 JPG,但随后的慢跑推进了随机次数。这是程序:

procedure TForm1.btnJogForwardClick(Sender: TObject);
var
   b: Array[0..1] of Byte;
   jpg: TJPEGImage;

begin
    MemoryStream:= TMemoryStream.Create;
    try
       repeat
          MJPEGStream.Read(b[0], 2);
          MemoryStream.Write(b[0], 2);
       until ((b[0] = $FF) and (b[1] = $D9));

       MemoryStream.Position:= 0;
       jpg:= TJPEGImage.Create;
       try
         try
           jpg.LoadFromStream(MemoryStream);
           Image1.Picture.Assign(jpg);
         except
         end;
       finally
         jpg.Free;
       end;
    finally
       MemoryStream.Free;
  end;

我检查了第 3 方 MJPEG 播放器,它能够逐帧慢跑,所以我知道 MJPEG 文件没问题。任何关于为什么我的程序没有逐帧统一执行的建议将不胜感激。

谢谢,约翰。

4

1 回答 1

1

感谢您的意见和建议。我想我已经设法对其进行了排序。

const
  JPGSizeMax = 100000;

procedure TForm1.FormCreate(Sender: TObject);
var
   b: Array[0..JPGSizeMax] of Byte;
 :
 :
begin
 :
 :
MJPEGStream:= TFileStream.Create(MJPEGFileName, fmOpenRead);
MJPEGStream.Position:= 0;

MJPEGStream.Read(b[0], JPGSizeMax);
for i:= 0 to JPGSizeMax do
begin
   if (b[i] = $D9) and (b[i-1] = $FF) then
   begin
     Count:= i;
     break;
   end;
end;

MemoryStream.Write(b[0], Count);
FilePosition:= Count + 1;

MemoryStream.Position:= 0;
jpg.LoadFromStream(memoryStream);
Image1.Picture.Assign(jpg);

MemoryStream.Free;
jpg.Free;

结尾;

Jog 按钮的过程大致相同:

MJPEGStream.Position:= FilePosition;

MJPEGStream.Read(b[0], JPGSizeMax);
for i:= 0 to JPGSizeMax do
begin
   if (b[i] = $D9) and (b[i-1] = $FF) then
   begin
     Count:= i;
     break;
   end;
end;

  memoryStream.Write(b[0], Count);
  FilePosition:= FilePosition + count + 1;

// etc

再次感谢您为我指明正确的方向。

约翰。

于 2016-04-29T19:50:13.560 回答