Я пытаюсь декодировать видеофайл с помощью 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);
}
Я что-то не так делаю с памятью? Потому что, если я удалю часть обработки, просто декодирую, а затем закодирую кадр, результат будет правильным.
(*input)->release();
? а где объявлен temp_rgb_frame? - person UmNyobe   schedule 13.11.2014temp_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.2014temp_rgb_frame
initialization, я неправильно установил формат пикселей, он должен бытьPIX_FMT_RGB24
, но я установил его наPIX_FMT_YUV420P
, теперь он работает! Спасибо UmNyobe !!! - person user2789801   schedule 13.11.2014avpicture_fill
не выполняет глубокую копию данных. Он только устанавливает указатели и размер линии на основе параметра. Это означает, что при удалении исходных данных вы работаете с освобожденной памятью. - person UmNyobe   schedule 13.11.2014