cv::Mat to AvFrame
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;
}
if the problem is in your code, show it here, please.
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.
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.
Has it helped? :P
Just a hint, aren't you mixing up the fact that openCV uses the BGR channels internally and you want them as RGB data?