如何解决OpenCV CV::Mat 图像到 AVFormat 视频编写器
AVFrame *cvmatToAvframe(cv::Mat *cv_image,AVFrame *av_frame,StreamingContext *decoder) {
int width = cv_image->cols;
int height = cv_image->rows;
int typeOFImage = cv_image->type();
int cvLinesizes[1];
cvLinesizes[0] = cv_image->step1();
if (av_frame == NULL) {
av_frame = av_frame_alloc();
}
av_image_alloc(av_frame->data,av_frame->linesize,width,height,AVPixelFormat::AV_PIX_FMT_YUV420P,1);
SwsContext *conversion = sws_getContext(width,AVPixelFormat::AV_PIX_FMT_BGR24,SWS_FAST_BILINEAR,NULL,NULL);
if (!conversion) {
std::cerr << "fail to sws_getCachedContext";
return NULL;
}
sws_scale(conversion,&cv_image->data,cvLinesizes,av_frame->data,av_frame->linesize);
sws_freeContext(conversion);
return av_frame;
}
使用上面的代码转换一个使用OpenCV读取的视频。然后使用FFMPEG保存它。使用FFMPEG来写的原因是OpenCV VideoWriter非常慢。需要通过从相机读取帧并从中创建视频文件来实时进行这项工作。
int encode_video(StreamingContext *decoder,StreamingContext *encoder,AVFrame *input_frame) {
if (input_frame) input_frame->pict_type = AV_PICTURE_TYPE_NONE;
AVPacket *output_packet = av_packet_alloc();
if (!output_packet) {std::cout << "Could not allocate memory for output packet" << std::endl; return -1;}
// need to confirm is the input frame is of type video
//decoder->avfc->->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
int response = avcodec_send_frame(encoder->video_avCodecContext,input_frame);
if( (response == AVERROR(EAGAIN) || response==AVERROR_EOF))
{
std::cout << "do nothing " << std::endl;
av_packet_unref(output_packet);
return -1;
}
else if (response < 0)
{
const char* error_string = av_err2str(response);
std::cout << "Error while sending a packet to the decoder" << error_string << std::endl;
return response;
}
else
{
while (response >= 0) {
response = avcodec_receive_packet(encoder->video_avCodecContext,output_packet);
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
break;
} else if (response < 0) {
std::cout << "Error while receiving packet from encoder" << av_err2str(response) << std::endl;
return -1;
}
output_packet->stream_index = decoder->video_index;
output_packet->duration = encoder->video_avstream->time_base.den / encoder->video_avstream->time_base.num / decoder->video_avstream->avg_frame_rate.num * decoder->video_avstream->avg_frame_rate.den;
av_packet_rescale_ts(output_packet,decoder->video_avstream->time_base,encoder->video_avstream->time_base);
response = av_interleaved_write_frame(encoder->avFormatContext,output_packet);
if (response != 0) { std::cout << "Error while receiving packet from decoder" << response << av_err2str(response) << std::endl; return -1;}
}
}
av_packet_unref(output_packet);
av_packet_free(&output_packet);
return 0;
}
问题是@avcodec_receive_packet() 我得到一个错误响应(返回值-11) 无法弄清楚问题。
我正在读取本地存储在我的驱动器上的文件。 使用 Opencv VideoReader 读取文件。
我用 cap.isOpened() 循环提取帧。 接下来的步骤是从at和转换为AVFrame 编码后的最后一步编写。
while(cvcap.isOpened())
{
cv::Mat frame;
cvcap >> frame;
input_frame = cvmatToAvframe(&frame,input_frame,decoder);
encode_video(decoder,encoder,input_frame );
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。