Ask Your Question
0

How to convert OpenCV's Mat format to FFMPEG's avframe format?

asked 2017-08-28 02:08:44 -0600

md612 gravatar image

I made the conversion between FFmpeg's avframe and OpenCV's mat. But the following code doesn't convert the avframe to mat and mat to avframe correctly. The first part converts avframe to mat format and the second part converts mat to avframe format.

Here is my source code:

 AVFrame* ProcessFrame(AVFrame *frame, int stream_index)
{
 //first part
    AVStream *in_stream = ifmt_ctx->streams[stream_index];
    AVCodecContext *pCodecCtx = in_stream->codec;

    AVFrame  *pFrameRGB = NULL;

    struct SwsContext * img_convert_ctx = NULL;
    if(img_convert_ctx == NULL){
        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
                                         pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
                                         AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
    }
    pFrameRGB = av_frame_alloc();
    int size = avpicture_get_size(AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);

    uint8_t  *out_bufferRGB = (uint8_t *)av_malloc(size);

    avpicture_fill((AVPicture *)pFrameRGB, out_bufferRGB, AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);

    sws_scale(img_convert_ctx, frame->data, frame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

    Mat imageFrame = Mat(pCodecCtx->height, pCodecCtx->width, CV_8UC3);

    memcpy(imageFrame.data, out_bufferRGB, size);
    delete[] out_bufferRGB;

   ///////////////////////////////////////////////////////////
   //second part starts

    avpicture_fill((AVPicture *)pFrameRGB, imageFrame.data,AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);

    struct SwsContext * convert_ctx = NULL;
    if(convert_ctx == NULL){
        convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
                                         AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height,
                                         pCodecCtx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
    }

    AVFrame *srcFrame = av_frame_alloc();
    size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

    uint8_t  *out_buffer = (uint8_t *)av_malloc(size);

    avpicture_fill((AVPicture *)srcFrame, out_buffer, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

    sws_scale(convert_ctx, pFrameRGB->data, pFrameRGB->linesize, 0, pCodecCtx->height, srcFrame->data, srcFrame->linesize);

    delete[] out_buffer;
    av_free(pFrameRGB);

    srcFrame->width = frame->width;
    srcFrame->height = frame->height;
    srcFrame->format = frame->format;

    av_frame_copy_props(srcFrame, frame);

    return srcFrame;
}
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-08-28 02:55:28 -0600

Ziri gravatar image

updated 2017-08-28 03:01:37 -0600

Instead of :

Mat imageFrame = Mat(pCodecCtx->height, pCodecCtx->width, CV_8UC3);

memcpy(imageFrame.data, out_bufferRGB, size);

You can initialize Mat like this : (note : you're getting BGR buffer not RGB)

Mat mat(pCodecCtx->height, pCodecCtx->width, CV_8UC3, out_bufferRGB, (add image step here));
edit flag offensive delete link more

Comments

Thanks. I have corrected it according to your suggestion. But the produced video still has a grey strip across the middle of the video and some frames are broken. I think it is created by the process from Mat to avframe (i.e. the second part) since the imshow function shows a complete video to me.

md612 gravatar imagemd612 ( 2017-08-28 04:54:10 -0600 )edit

did you add the correct step ? you can try AUTO_STEP too. Make sure step and image depth are right.

Ziri gravatar imageZiri ( 2017-08-28 10:15:23 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-08-28 02:08:44 -0600

Seen: 2,818 times

Last updated: Aug 28 '17