Понадобилось тут мне сконвертировать AVFrame в Mat для дальнейших издевательст с помощью OpenCV, загуглил я это дело, и нашёл кучу способов.
Вот один из них:
void AVFrameToMat(const AVFrame * frame, Mat& image)
{
int width = frame->width;
int height = frame->height;
image = Mat(height, width, CV_8UC3);
int cvLinesizes[1];
cvLinesizes[0] = image.step1();
SwsContext* conversion = sws_getContext(width, height, (AVPixelFormat) frame->format, width, height, PIX_FMT_BGR24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
sws_scale(conversion, frame->data, frame->linesize, 0, height, &image.data, cvLinesizes);
sws_freeContext(conversion);
}
Мне одному кажется, что столько преобразований излишни? Ведь OpenCV напрямую позволяет работать со всеми форматами и можно сделать преобразование напрямую!
В моём случае я работаю с форматом видео YUV420P.
if ( m_picture->format == AV_PIX_FMT_YUV420P ) {
int numBytes=avpicture_get_size(AV_PIX_FMT_YUV420P, m_picture->width, m_picture->height);
uint8_t * buffer = reinterpret_cast<uint8_t *>(av_malloc(numBytes));
avpicture_layout( ( AVPicture*)m_picture, AV_PIX_FMT_YUV420P, m_picture->width, m_picture->height, buffer, numBytes); //av_image_copy_to_buffer() в новом API
Mat yuv = Mat(m_picture->height+m_picture->height/2, m_picture->width, CV_8UC1, buffer );
Mat gray = Mat(m_picture->height, m_picture->width, CV_8UC1, buffer ); //-- Если нужно получить сразу в градациях серого (формат YUV содержит в первом канале как раз в градациях серого кадр)
Mat rgb = Mat(m_picture->height, m_picture->width, CV_8UC3);
cvtColor(yuv, rgb, CV_YUV420p2RGB);
imshow("RGB", rgb);
imshow("GRAY", gray);
}
ВАЖНО: Не забудьте очистить память из под buffer, так как после удаления Mat она не очищается самостоятельно!
В вашем случае замените форматы на те, с которыми работаете.
Вот как-то так…