1

長さが数 GB になる MJPEG ファイルを作成する Delphi プログラムを作成しました。JPG は、DSPack を使用して DirectX カメラから取得されます。その部分は正常に機能し、次の形式で JPG 画像のファイルを作成します。

FF D8 ....(画像データ)... FF D9 FF D8 ....(画像データ)... FF D9 FF D8 etc

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 ポインターが保持されます。フォームにボタンがあり、一度に 1 つの JPG をジョグすることを意図していますが、最初の「ジョグ」は 1 つの 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;

サードパーティの 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 に答える