cv::Mat to AvFrame

asked 2014-07-11 22:27:58 -0600

MRDaniel gravatar image

updated 2014-07-12 00:23:21 -0600

berak gravatar image

I wrote this code to convert between OpenCV frames and AVFrames.

It works for converting from an AvFrame to a cv::Mat and the display appears correctly. However, when converting back from a cv::Mat to an AvFrame it appears that the colour channels are inverted. In that red is blue and blue is red.

The correct format is being used, and works on the first conversion. What am i missing here?


cv::Mat avframe_to_cvmat(AVFrame *frame)
{
        AVFrame dst;
        cv::Mat m;

        memset(&dst, 0, sizeof(dst));

        int w = frame->width, h = frame->height;
        m = cv::Mat(h, w, CV_8UC3);
        dst.data[0] = (uint8_t *)m.data;
        avpicture_fill( (AVPicture *)&dst, dst.data[0], PIX_FMT_BGR24, w, h);

        struct SwsContext *convert_ctx=NULL;
        enum PixelFormat src_pixfmt = (enum PixelFormat)frame->format;
        enum PixelFormat dst_pixfmt = PIX_FMT_BGR24;
        convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt,
                        SWS_FAST_BILINEAR, NULL, NULL, NULL);
        sws_scale(convert_ctx, frame->data, frame->linesize, 0, h,
                        dst.data, dst.linesize);
        sws_freeContext(convert_ctx);

        return m;
}
AVFrame cvmat_to_avframe(cv::Mat* frame)
{
        AVFrame dst;
        cv::Size frameSize = frame->size();
        AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
        AVFormatContext* outContainer = avformat_alloc_context();
        AVStream *outStream = avformat_new_stream(outContainer, encoder);
        avcodec_get_context_defaults3(outStream->codec, encoder);

        outStream->codec->pix_fmt = AV_PIX_FMT_YUV420P;
        outStream->codec->width = frame->cols;
        outStream->codec->height = frame->rows;
        avpicture_fill((AVPicture*)&dst, frame->data, PIX_FMT_BGR24, outStream->codec->width, outStream->codec->height);
        dst.width = frameSize.width;
        dst.height = frameSize.height;
        SaveFrame(&dst,dst.width,dst.height,0);
        return dst;
}
edit retag flag offensive close merge delete

Comments

if the problem is in your code, show it here, please.

berak gravatar imageberak ( 2014-07-11 23:55:13 -0600 )edit

Follow the pastebin link to the code. I can't get it formatted correctly using the code tags on this forum. It's a mess.

MRDaniel gravatar imageMRDaniel ( 2014-07-12 00:12:14 -0600 )edit
1

wasn't too hard ;9

sidenote: don't store/pass pointers to cv::Mat, use references (or copies even) instead. they behave like smartpointers, so passing pointers to that will thrash the internal refcount.

berak gravatar imageberak ( 2014-07-12 00:24:02 -0600 )edit

Has it helped? :P

MRDaniel gravatar imageMRDaniel ( 2014-07-12 09:02:42 -0600 )edit

Just a hint, aren't you mixing up the fact that openCV uses the BGR channels internally and you want them as RGB data?

StevenPuttemans gravatar imageStevenPuttemans ( 2014-07-14 06:15:00 -0600 )edit