0

libavcodec を使用してビデオをトランスコードしようとしています。大きなビデオ ファイル (1 時間以上) をトランスコードすると、avcodec_encode_video で大量のメモリ リークが発生します。私はそれをデバッグしようとしましたが、さまざまなビデオファイルでさまざまな機能がリークを生成し、それについて少し混乱しました:)。ここで、QTメモリリークを伴うFFMPEGは私が抱えている問題と同じですが、その人がどのように解決したのかわかりません。QtFFmpegwrapper は、私と同じことをしているようです (または、何かを見逃していました)。

私の方法はもっと低いです。aFrame と aPacket は av_free と av_free_packet で外に出しました。

int
Videocut::encode(
AVStream *anOutputStream,
AVFrame *aFrame,
AVPacket *aPacket
)
{
AVCodecContext *outputCodec = anOutputStream->codec;

if (!anOutputStream ||
    !aFrame ||
    !aPacket)
{
    return 1;
    /* NOTREACHED */
}

uint8_t * buffer = (uint8_t *)malloc(
    sizeof(uint8_t) * _DefaultEncodeBufferSize
    );

    if (NULL == buffer) {
        return 2;
        /* NOTREACHED */
}

int packetSize = avcodec_encode_video(
    outputCodec,
        buffer,
        _DefaultEncodeBufferSize,
        aFrame
    );

if (packetSize < 0) {
    free(buffer);
    return 1;
    /* NOTREACHED */
}

aPacket->data = buffer;
aPacket->size = packetSize;

return 0;
}
4

1 に答える 1

1

最初のステップは、可能であれば、Linux ボックスの Valgrind で問題を再現することです。

通常、ffmpeg エンコーダーとデコーダーは動的にメモリを割り当てません。呼び出し間でバッファーを再利用します。リークは通常、フレームのどこかに発生します。

av_free_packetパケットにデストラクタ関数がある場合にのみ、動的に割り当てられたバッファを解放することに注意してください!

で関数がどのように定義されているかを見てくださいlibavcodec/avpacket.c

void av_free_packet(AVPacket *pkt)
{
    if (pkt) {
        if (pkt->destruct) pkt->destruct(pkt);
        pkt->data = NULL; pkt->size = 0;
        pkt->side_data       = NULL;
        pkt->side_data_elems = 0;
    }
}

関数がないpkt->destruct場合、クリーンアップは行われません!

于 2012-03-31T00:24:33.723 に答える