Понадобилось тут мне сконвертировать 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 она не очищается самостоятельно!
В вашем случае замените форматы на те, с которыми работаете.
Вот как-то так…