微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenCV CV::Mat 图像到 AVFormat 视频编写器

如何解决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 举报,一经查实,本站将立刻删除。