2

AVI ムービーを作成する Delphi 6 アプリケーションがあります。圧縮されていないビデオ フレームを含む AVI ファイルを書き込めるようになりました。圧縮ビデオ ストリームを作成しようとすると、AVIStreamSetFormat() を呼び出すと、AVIERR_MEMORY エラーが発生します。

hr := AVIStreamSetFormat(
        FAvi_.thePsCompressed, 
        0, 
        @dsBmih, 
        dsBmih.biSize + dsBmih.biClrUsed * sizeof(RGBQUAD));

このエラーが発生するのはなぜですか? また、修正するにはどうすればよいですか?

AVISaveOptions() への呼び出しを使用して、Radius コンプレッサーで Cinepak コードを選択した後の圧縮オプション データ構造の内容を次に示します。別のコンプレッサーを選択して、エラーが発生することに注意してください。

fccType: 0
fccHandler: 1684633187
dwKeyFrameEvery: 0
dwQuality: 8800
dwBytesPerSecond: 0
dwFlags: 8
lpFormat: nil
cbFormat: 0
lpParms: nil
cbParms: 4
dwInterleaveEvery: 0

TBitmapHeaderInfo データ構造の内容は次のとおりです。

biSize: 40
biWidth: 320
biHeight: -240
biPlanes: 1
biBitcount: 32
biCompression: 0
biSizeImage: 307200
biXPelsPerMeter: 0
biYPelsPerMeter: 0
biClrUsed: 0
biClrImportant: 0

AVIStreamSetFormat() への呼び出しを含むメソッドは次のとおりです。

function TAviWriterWithCompression.compressionDirect(
                                opts: PAVICOMPRESSOPTIONS;
                                bShowDialog: boolean;
                                hparent: HWND;
                                dsBmih: TBitmapInfoHeader;
                                sizeImage: integer;
                                DIBValues: Pointer;
                                framesPerSecond: integer): HRESULT;
var
    lastErr: string;
    hr: HRESULT;
    myopts: TAVICOMPRESSOPTIONS;
    aopts: array[0..0] of PAVICOMPRESSOPTIONS;
    res: Bool;
begin
    if not FIsVirginFile then
    begin
        // The output file already has at least one audio or video frame so
        //  setting or changing the compression format is not allowed.
        Result := LongInt(AVIERR_ERROR);

        // =========================== EXIT POINT ==============
        exit;
    end; // if not Assigned(FAvi_) then

    if not Assigned(FAvi_) then
    begin
        Result := LongInt(AVIERR_BADHANDLE);

        // =========================== EXIT POINT ==============
        exit;
    end; // if not Assigned(FAvi_) then

    // Check the utility object for an error.
    if (FAvi_.iserr) then
    begin
        Result := LongInt(AVIERR_ERROR);
        // =========================== EXIT POINT ==============
        exit;
    end; // if (FAvi_.iserr) then

    // Make sure the compressor has not already been selected.
    if Assigned(FAvi_.thePsCompressed) then
    begin
        Result := LongInt(AVIERR_COMPRESSOR);
        // =========================== EXIT POINT ==============
        exit;
    end; // if (FAvi_.iserr) then

    // create the stream, if it wasn't there before
    if not Assigned(FAvi_.thePs) then
    begin
        hr := createVideoStream(dsBmih, framesPerSecond);

        if hr <> AVIERR_OK then
        begin
            Result := hr;

            // Set the error flag in our utility object.
            FAvi_.iserr := true;

            // =========================== EXIT POINT ==============
            exit;
        end; // if hr <> AVIERR_OK then
    end; // if not Assigned(FAvi_.thePs) then

    // set the compression, prompting dialog if necessary
    if not Assigned(FAvi_.thePsCompressed) then
    begin
        ZeroMemory(@myopts, sizeof(myopts));

        if Assigned(opts) then
            // Use the provided compressor options
            aopts[0] := opts
        else
            // Use our initialized (empty) variable.
            aopts[0] := @myopts;

        // Does the caller want to show the compressor dialog box?
        if (bShowDialog) then
        begin
            res := AVISaveOptions(hparent, 0, 1, FAvi_.thePs, aopts[0]);

            if not res then
            begin
                AVISaveOptionsFree(1, aopts[0]);

                // Set the error flag.
                FAvi_.iserr := true;

                Result := LongInt(AVIERR_USERABORT);

                // =========================== EXIT POINT ==============
                exit;
            end; // if res = 0 then
        end; // if (bShowDialog) then

        hr := AVIMakeCompressedStream(FAvi_.thePsCompressed, FAvi_.thePs, aopts[0], nil);

        if hr <> AVIERR_OK then
        begin
            Result := hr;

            // Set the error flag in our utility object.
            FAvi_.iserr := true;

            // =========================== EXIT POINT ==============
            exit;
        end; // if hr <> AVIERR_OK then

        AVISaveOptionsFree(1, aopts[0]);
        postDiagMsg('Avi::compression after AVISaveOptionsFree()');

        // >>>> This is where I get the AVIERR_MEMORY error.
        hr := AVIStreamSetFormat(FAvi_.thePsCompressed, 0, @dsBmih, dsBmih.biSize + dsBmih.biClrUsed * sizeof(RGBQUAD));

        if hr <> AVIERR_OK then
        begin
            Result := hr;

            // Set the error flag in our utility object.
            FAvi_.iserr := true;

            // =========================== EXIT POINT ==============
            exit;
        end; // if hr <> AVIERR_OK then
    end; // if not Assigned(FAvi_.thePsCompressed) then

    Result := AVIERR_OK;
end;
4

1 に答える 1

3

biHeight構造体の負の値が原因である可能性があります。これはTBitmapHeaderInfo、DIB セクションに格納されているビット値が垂直方向に反転したイメージを表すことを意味します。

一部のコーデックでは、これを解決できない場合があります。そのため、画像ヘッダーのサイズとビット深度が、選択したビデオ ストリーム コンプレッサーで処理できることを確認してください。サポートされている画像形式のみを使用する必要があり、コーデックが反転画像をサポートしていない場合は、DIB 画像データを反転し、画像ヘッダーを自分で手動で変更する必要があります。

于 2012-05-03T14:30:55.213 に答える