0

So, I have written a basic decoder for ffmpeg that simply reads the input frames pixel data (Stored using RGB 8 format), and places it directly into the output buffer. (Also RGB 8) The problem is that when I use this decoder in ffmpeg, it says that there is 1 unreleased buffer.(Tested using ffmpeg -i Test.utah Test.png). Unfortunately, I am unsure of what buffer it is talking about, as I am not creating my own buffer. I have tried releasing the AVContext's coded_frame buffer in my decoders closing method, but this causes segmentation faults.

Any help would be greatly appreciated.

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;
}
Tuxdude
  • 47,485
  • 15
  • 109
  • 110
ByteByter
  • 86
  • 8
  • That's a load of code - do you think you can trim it down to the relevant parts only? It'd be hard for users to help you easily if you've got that much code up there. Possibly separate the key parts, and keep the whole chunk of code towards the bottom of the question. – Jesse Mar 11 '13 at 00:33
  • I would love to cut down this code more, but It's pretty bare bones as it is. However, I have edited it in an attempt to make it as readable as possible. – ByteByter Mar 11 '13 at 02:04

1 Answers1

1

You didn't post the .close method for this decoder object. Do you have one? In most FFmpeg decoders, this takes the form of codecname_decode_end(). This method/function is called after decoding is finished and gives the decoder the opportunity to clean up after itself.

Where I'm going with this:

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

But when it's all done, the decoder is still holding the frame allocated during decode_frame call #n. codecname_decode_end() allows the decoder to free that last frame.

Multimedia Mike
  • 12,660
  • 5
  • 46
  • 62
  • Where is the last frame stored? In the AVContext coded_frame? I have tried freeing this in the closing method like so, if (avctx->coded_frame->data[0]) avctx->release_buffer(avctx,avctx->coded_frame); but it just causes a segmentation fault to occur. – ByteByter Mar 11 '13 at 21:34
  • I recommend running either gdb or Valgrind to diagnose the segfault quickly (and be sure you're running the debug version of ffmpeg, which is 'ffmpeg_g', so you get symbols). Are you familiar with those tools? – Multimedia Mike Mar 11 '13 at 21:38
  • I'm slightly familiar with gdb.(Enough so to do a stack trace) Do you need to do a special build for ffmpeg_g? – ByteByter Mar 11 '13 at 21:43
  • That's good enough. Running the errant command line through gdb should point to the exact line where things are crashing. If it's completely non-obvious why it's crashing, run 'valgrind ffmpeg_g -i Test.utah Test.png' and see if it finds memory corruption that might lead to a segfault. – Multimedia Mike Mar 11 '13 at 21:45
  • Ok, so after some debugging and testing I have found out that the reason why release_buffer() is causing a crash when I call it on the coded_frame, is because the AVCodecContext coded_frame is null. (Which kind of makes sense because I never initialize it as I am writing directly to the output buffer.[using the void *data pointer]) However this leads me back to my original question as to which buffer is not getting released? Any ideas? – ByteByter Mar 12 '13 at 00:05
  • For some reason this seems to be the culprit. decode_frame call #0: no frame held; frame allocated The number of buffers upon the last call to decode_frame is 0. – ByteByter Mar 12 '13 at 00:25