2013-03-11 2 views
0

Итак, я написал базовый декодер для ffmpeg, который просто считывает данные пикселов входных кадров (хранится в формате RGB 8) и помещает их непосредственно в выходной буфер. (Также RGB 8) Проблема заключается в том, что, когда я использую этот декодер в ffmpeg, он говорит, что есть 1 неизданный буфер. (Протестировано с использованием ffmpeg -i Test.utah Test.png). К сожалению, я не уверен, о каком буфере это говорит, поскольку я не создаю свой собственный буфер. Я попытался освободить буфер кодированного_кода AVContext в методе закрытия декодеров, но это вызывает ошибки сегментации.буфер ffmpeg не выпущен

Любая помощь была бы принята с благодарностью.

static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) 
{ 
    int ret;   /*Hold return from get_buffer */ 
    int skipSize;  /*Number of dummy bytes to skip per line*/ 
    int fseek=8;  /*Location of the first pixel*/ 
    int i=0; int j=0; /*Output buffer seek index/Input Buffer seek index*/ 
    const uint8_t *buf = avpkt->data; /*Hold a pointer to the input buffer*/ 
    AVFrame *pict=data; /*Hold a pointer to the output buffer*/ 

    /*Set the output pixel format to RGB8*/ 
    avctx->pix_fmt = AV_PIX_FMT_RGB8; 

    /*Get the width and height*/ 
    bytestream_get_le32(&buf); 
    avctx->width=bytestream_get_le16(&buf); 
    avctx->height=bytestream_get_le16(&buf); 

    /*Release the old buffer*/ 
    if (pict->data[0]) avctx->release_buffer(avctx, pict); 

    /*Aquire a large enough data buffer to hold the decompressed picture*/ 
    if (ret=ff_get_buffer(avctx, pict) < 0) return ret; 
    skipSize=pict->linesize[0] - avctx->width; 

    /*Transfer input buffer to output buffer*/ 
    for(int y=0;y<avctx->height;y++){ 
     for(int x=0;x<avctx->width;x++){ 
      pict->data[0][i]=avpkt->data[fseek+j]; 
      j++; 
      i++; 
     } 
     i+=skipSize; 
    } 

    /*Inform ffmpeg the output is a key frame and that it is ready for external usage*/ 
    pict->pict_type  = AV_PICTURE_TYPE_I; 
    pict->key_frame  = 1; 
    *got_frame=1; 
    return 0; 
} 
+0

Это нагрузка кода - как вы думаете, вы можете обрезать ее только для соответствующих частей? Пользователям будет сложно помочь вам, если у вас есть такой код. Возможно, отделите ключевые части и сохраните весь фрагмент кода в нижней части вопроса. – Jesse

+0

Мне бы хотелось сократить этот код еще, но это довольно голые кости, как есть. Тем не менее, я отредактировал его в попытке сделать его максимально читаемым. – ByteByter

ответ

1

Вы не разместили метод .close для этого объекта декодера. У тебя есть один? В большинстве FFmpeg-декодеров это принимает вид codecname_decode_end(). Этот метод/функция вызывается после завершения декодирования и дает декодеру возможность очистить после себя.

Где я клоню:

decode_frame call #0: no frame held; frame allocated 
decode_frame call #1: free frame allocated during call #0; frame allocated 
decode_frame call #2: free frame allocated during call #1; frame allocated 
[...] 
decode_frame call #n: free frame allocated during call #(n-1); frame allocated 

Но когда это все сделано, декодер все еще держит кадр, выделенный во время #n decode_frame вызова. codecname_decode_end() позволяет декодеру освобождать последний кадр.

+0

Где хранится последний кадр? В коде AVContext coded_frame? Я попытался освободить это в методе закрытия, например, если (avctx-> coded_frame-> data [0]) avctx-> release_buffer (avctx, avctx-> coded_frame); , но это просто приводит к возникновению ошибки сегментации. – ByteByter

+0

Я рекомендую запустить gdb или Valgrind для быстрой диагностики segfault (и убедитесь, что вы используете отладочную версию ffmpeg, которая является «ffmpeg_g», поэтому вы получаете символы). Вы знакомы с этими инструментами? –

+0

Я немного знаком с gdb (достаточно, чтобы сделать трассировку стека) Вам нужно сделать специальную сборку для ffmpeg_g? – ByteByter

Смежные вопросы