Обработка AVFrame с использованием мата opencv, вызывающего ошибку кодирования

Я пытаюсь декодировать видеофайл с помощью ffmpeg, захватить объект AVFrame, преобразовать его в объект mat opencv, выполнить некоторую обработку, затем преобразовать его обратно в объект AVFrame и закодировать обратно в видеофайл.

Что ж, программа запускается, но результат плохой.

Я продолжаю получать ошибки, такие как «верхний блок недоступен для запрошенного внутреннего режима в 7 19», «ошибка при декодировании MB 7 19, байтовый поток 358», «скрытие ошибок 294 DC, 294AC, 294 MV в P-кадре» и т. Д.

И видео получилось повсюду блестящим. вот так, введите описание изображения здесь

Я предполагаю, это потому, что мои методы AVFrame to Mat и Mat to AVFrame, и вот они

//unspecified function
temp_rgb_frame = avcodec_alloc_frame(); 
int numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height); 
uint8_t * frame2_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); 
avpicture_fill((AVPicture*)temp_rgb_frame, frame2_buffer, PIX_FMT_RGB24, width, height);

void CoreProcessor::Mat2AVFrame(cv::Mat **input, AVFrame *output)
{
    //create a AVPicture frame from the opencv Mat input image
    avpicture_fill((AVPicture *)temp_rgb_frame,
        (uint8_t *)(*input)->data,
        AV_PIX_FMT_RGB24,
        (*input)->cols,
        (*input)->rows);

    //convert the frame to the color space and pixel format specified in the sws context

    sws_scale(
        rgb_to_yuv_context, 
        temp_rgb_frame->data,
        temp_rgb_frame->linesize,
        0, height, 
        ((AVPicture *)output)->data, 
        ((AVPicture *)output)->linesize);

    (*input)->release();

}

void CoreProcessor::AVFrame2Mat(AVFrame *pFrame, cv::Mat **mat)
{
    sws_scale(
        yuv_to_rgb_context, 
        ((AVPicture*)pFrame)->data, 
        ((AVPicture*)pFrame)->linesize, 
        0, height, 
        ((AVPicture *)temp_rgb_frame)->data,
        ((AVPicture *)temp_rgb_frame)->linesize);

    *mat = new cv::Mat(pFrame->height, pFrame->width, CV_8UC3, temp_rgb_frame->data[0]);
}

void CoreProcessor::process_frame(AVFrame *pFrame)
{
    cv::Mat *mat = NULL;
    AVFrame2Mat(pFrame, &mat);
    Mat2AVFrame(&mat, pFrame);
}

Я что-то не так делаю с памятью? Потому что, если я удалю часть обработки, просто декодирую, а затем закодирую кадр, результат будет правильным.


person user2789801    schedule 13.11.2014    source источник
comment
мотивация для (*input)->release();? а где объявлен temp_rgb_frame?   -  person UmNyobe    schedule 13.11.2014
comment
temp_rgb_frame инициализируется перед запуском основной части декодирования, как это temp_rgb_frame = avcodec_alloc_frame(); int numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height); uint8_t * frame2_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture*)temp_rgb_frame, frame2_buffer, PIX_FMT_RGB24, width, height); И я хочу освободить мат, поэтому я вызвал метод выпуска после его преобразования обратно в AVFrame   -  person user2789801    schedule 13.11.2014
comment
Моя ошибка, в моем коде я допустил ошибку в части temp_rgb_frame initialization, я неправильно установил формат пикселей, он должен быть PIX_FMT_RGB24, но я установил его на PIX_FMT_YUV420P, теперь он работает! Спасибо UmNyobe !!!   -  person user2789801    schedule 13.11.2014
comment
обратите внимание, что avpicture_fill не выполняет глубокую копию данных. Он только устанавливает указатели и размер линии на основе параметра. Это означает, что при удалении исходных данных вы работаете с освобожденной памятью.   -  person UmNyobe    schedule 13.11.2014
comment
правильно !, я удалил код выпуска. Спасибо! :)   -  person user2789801    schedule 17.11.2014


Ответы (1)


Ну оказывается я ошибся при инициализации temp_rgb_frame, если должно быть так,

temp_rgb_frame = avcodec_alloc_frame();
int numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
uint8_t * frame2_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture*)temp_rgb_frame, frame2_buffer, PIX_FMT_RGB24, width, height);
person user2789801    schedule 13.11.2014