1

I am following the FFmpeg video enconding example here, but it makes some dummy YUV420P frames and I have a BGR image already captured from a camera.

I am not sure how to use frame->data[] and frame->linesize[] for filling them with my BGR image instead, so I can encode an H264 video.


EDIT:

I have the following code (it's called for every new picture the camera sends) after Ronald's answer:

    .............
    AVFrame *bgrFrame = av_frame_alloc();

    bgrFrame->width = originalBGRImage.cols;
    bgrFrame->height = originalBGRImage.rows;

    ret = av_image_alloc(bgrFrame->data, bgrFrame->linesize, bgrFrame->width, bgrFrame->height, AV_PIX_FMT_BGR24, 32);

    /////////////////////////////////////
    // This works and prevents memory leak....if I remove it, it consumes all the RAM....but I can't free this memory here, since I will use it later...
    av_freep(&bgrFrame->data[0]);
    av_frame_free(&bgrFrame);
    return;
    /////////////////////////////////////

    ret = av_image_fill_pointers(bgrFrame->data, AV_PIX_FMT_BGR24, bgrFrame->height, originalBGRImage.data, bgrFrame->linesize);

    /////////////////////////////////////
    // Here is where I am done using the memory so I will want to free it...but this same code crashes the program.
    av_freep(&bgrFrame->data[0]);
    av_frame_free(&bgrFrame);
    return;
    /////////////////////////////////////

So if I remove the av_freep(&bgrFrame->data[0]); at the end of the code I will have a memory leak...but leaving it there crashes....so what's the correct way to free the used memory?

Michel Feinstein
  • 13,416
  • 16
  • 91
  • 173

1 Answers1

1

Use av_image_fill_linesizes() to fill the linesizes (unless they're padded, in which case you should specify them manually), and after that use av_image_fill_pointers() to fill the data pointers. As pix_fmt, use AV_PIX_FMT_BGR24.

Now, that gives you a BGR24 picture. You can encode that as a RGB H264 image using the libx264rgb encoder. If you want to encoder YUV H264, you will first need to convert the RGB image to YUV, which you can do using libswscale. Google "libswscale example" to find example code on how to do that.

Ronald S. Bultje
  • 10,828
  • 26
  • 47
  • Is it just my impression or will `av_image_alloc()` do the `av_image_fill_linesizes()` job too, so I just need to call `av_image_fill_linesizes()` to fill the data with my picture? – Michel Feinstein Feb 03 '16 at 22:04
  • av_image_alloc will do it for you, yes. – Ronald S. Bultje Feb 03 '16 at 22:17
  • And will `av_frame_free()` free `frame->data[]` too? The code documentation appears to me that yes, it will, but the source code didn't. So I have `av_freep(&frame->data[0])` just in case – Michel Feinstein Feb 03 '16 at 22:26
  • If you used `av_frame_alloc()` to allocate frame contents, `av_frame_free()` will free them, yes. If you manually assigned the pointers, they don't use `AVBufferRef` and thus will not be touched by `av_frame_free()`. – Ronald S. Bultje Feb 04 '16 at 01:18
  • `av_image_fill_pointers()` is causing a memory leak.....if I make a `av_freep(&frame->data[0]);` after it, the program crashes, and if I don't it consumes all my memory......what's the correct way to clean it's memory? – Michel Feinstein Feb 12 '16 at 20:57
  • We can take this over to chat perhaps, but what crashes? Does it crash in the call to av_freep? Or does it crash inside av_frame_free when you call av_freep before it? And does valgrind tell you why? – Ronald S. Bultje Feb 12 '16 at 21:24
  • I just got home for the weekend and I don't have the code here, otherwise chat would be the best choice! ... The call to av_freep() crashes immediately, I guess something was set to null by av_image_fill_pointers() – Michel Feinstein Feb 12 '16 at 21:34
  • That suggests the data is double-free'ed (e.g. you're reusing originalBGRImage.data), or that frame itself is already NULL (or previously free'ed). valgrind would tell you which of the two it is. – Ronald S. Bultje Feb 13 '16 at 00:37
  • Ronald, after digging more on the library, I found `av_image_fill_arrays()`, I think this is the right choice for me, since I already have the image, and I just want to fill `linesizes[]` and `data[]`.....So this will be called instead of `av_image_alloc()`, `av_image_fill_linesizes()` and `av_image_fill_pointers()`...right? – Michel Feinstein Feb 23 '16 at 22:08