ffmpeg解码数据转换为cv::Mat

这篇具有很好参考价值的文章主要介绍了ffmpeg解码数据转换为cv::Mat。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ffmpeg解码数据转换为cv::Mat

flyfish

ffmpeg:ffmpeg-6.0

头文件

//flyfish
#include <stdio.h>
#include <unistd.h>
// Opencv
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect.hpp>

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
};


class FFmpegDecoder {

public :

    FFmpegDecoder();
    ~FFmpegDecoder();
    void init();
    void decode(unsigned char *inputbuf, size_t size);


private:
    AVCodecParserContext *parser;
    AVPacket *pkt_;
    const AVCodec *codec_;
    AVCodecContext *c_ = nullptr;
    AVFrame *frame_;
    AVFrame * frame_bgr_;

    uint8_t *data_;
    void decoding(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt);
    void save();
    void end();

//test
    std::string get_time_for_image_file_name();
};

实现文件文章来源地址https://www.toymoban.com/news/detail-532721.html

#include "FFmpegDecoder.h"
#include <locale>
#include <iostream>
#include <ctime>
#include <iomanip>
#include <codecvt>

FFmpegDecoder::~FFmpegDecoder()
{
    end();
}
void FFmpegDecoder::end()
{
    av_parser_close(parser);
    avcodec_free_context(&c_);
    av_frame_free(&frame_);
    av_frame_free(&frame_bgr_);
    av_packet_free(&pkt_);
}
void FFmpegDecoder::save()
{


    int bgr_size = av_image_get_buffer_size(AV_PIX_FMT_BGR24, c_->width,c_->height,1);

    uint8_t *out_buffer  = (uint8_t *) av_malloc(bgr_size);

    av_image_fill_arrays(frame_bgr_->data, frame_bgr_->linesize, out_buffer, AV_PIX_FMT_BGR24, c_->width, c_->height,1);

    SwsContext* img_convert_ctx =sws_getContext(c_->width, c_->height, c_->pix_fmt,c_->width, c_->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL,NULL);
    cv::Mat mat=cv::Mat(cv::Size(c_->width, c_->height), CV_8UC3);


    sws_scale(img_convert_ctx, (const uint8_t *const *)frame_->data,
              frame_->linesize, 0, c_->height, frame_bgr_->data, frame_bgr_->linesize);

    memcpy(mat.data, out_buffer, bgr_size);
    sws_freeContext(img_convert_ctx);
    av_free(out_buffer);


    //test
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
    std::cout <<"ms:"<<ms.count() << std::endl;

    //cv::imwrite(get_time_for_image_file_name(),mat);
    mat.release();


}


void FFmpegDecoder::decoding(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)
{


    int ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) {
        fprintf(stderr, "Error sending a packet for decoding\n");
        
        return;
    }

    while (ret >= 0) {
        ret = avcodec_receive_frame(dec_ctx, frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during decoding\n");
            
            return;
        }

        printf("saving frame %3" PRId64"\n", dec_ctx->frame_num);
        fflush(stdout);

        save();
    }
}

void FFmpegDecoder::decode(unsigned char *inbuf, size_t data_size){


    int ret=0;
    data_ = inbuf;
    while (data_size > 0) {
        ret = av_parser_parse2(parser, c_, &pkt_->data, &pkt_->size,
                               data_, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
        if (ret < 0) {
            fprintf(stderr, "Error while parsing\n");
            
            return;
        }
        data_      += ret;
        data_size -= ret;

        if (pkt_->size)
            decoding(c_, frame_, pkt_);

    }
}

void FFmpegDecoder::init() {


    pkt_ = av_packet_alloc();
    codec_ = avcodec_find_decoder(AV_CODEC_ID_H264);

    // codec =avcodec_find_decoder_by_name("h264_mediacodec");
    if (!codec_) {
        fprintf(stderr, "Codec not found\n");
        
    }

    parser = av_parser_init(codec_->id);
    if (!parser) {
        fprintf(stderr, "parser not found\n");
        
    }

    c_ = avcodec_alloc_context3(codec_);
    if (!c_) {
        fprintf(stderr, "Could not allocate video codec context\n");
        // exit(1);
    }

    if (avcodec_open2(c_, codec_, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        // exit(1);
    }

    frame_ = av_frame_alloc();
    if (!frame_) {
        fprintf(stderr, "Could not allocate video frame\n");
        
    }

    //bgr
    frame_bgr_=av_frame_alloc();


}



FFmpegDecoder::FFmpegDecoder() {
    init();
}



std::string FFmpegDecoder::get_time_for_image_file_name()
{
    //时分妙
    std::string rootPath ="/data/tmp/";

    auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    std::stringstream ss;
    ss << std::put_time(std::localtime(&t), "%Y_%m_%d_%H_%M_%S_");
    std::string str_time = ss.str();
    //纳秒
    std::string tail = std::to_string(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count());

    return rootPath + str_time + tail + ".jpg";
}

到了这里,关于ffmpeg解码数据转换为cv::Mat的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV buffer转cv::Mat

    void convertBuf2Mat(void* input_ptr, vx_uint32 width, vx_uint32 height, cv::Mat frame) {     // 计算亮度通道和色度通道的大小     size_t y_size = width * height;     size_t uv_size = y_size / 2;     // 创建一个只包含亮度通道的 cv::Mat 对象     cv::Mat y_channel(height, width, CV_8UC1, (unsigned char*)input_ptr);     // 设

    2024年02月07日
    浏览(25)
  • opencv学习(9):cv::Scalar、cv::Mat::zeros

            cv::Scalar是opencv的一个结构体,其定义如下:(c++中的结构体如下,可以存放1~4个数值。)         表示图像颜色时,单通道图像用下标[0]即可,三通道图像用下标[0]、[1]、[2]分别表示B、G、R通道         其中:                 白色:rgb(255,255,255)  

    2024年02月08日
    浏览(38)
  • 【debug】OpenCV出现问题:undefined reference to ‘cv::Mat::Mat()‘

    参考:动手学ROS2 分析原因: undefined reference to \\\'cv::Mat::Mat()\\\' 原因在于g++找不到库文件,解决方法就是我们帮助它定位到库文件的位置,并通过-L参数指定库目录,-l(小写L)指定库的名字。 解决方法: 在执行命令时添加后缀参数

    2024年02月08日
    浏览(35)
  • OpenCV中cv::Mat矩阵的四种遍历

    at方法遍历 单通道 运行结果 at方法遍历 多通道 (下面这种方式,既能遍历,又能修改) 运行结果: 对比程序:(下面这种方式,只能遍历,不能修改) 运行结果 第一种写法 运行结果 更一般的写法:把里面的3改成矩阵的通道数 a.channels() ,如下: 运行结果 上面这种写法

    2024年02月13日
    浏览(37)
  • OpenCV:矩阵表达式:代数和cv::Mat

    OpenCV是一个强大的计算机视觉库,它提供了丰富的功能和工具,用于处理图像数据。在OpenCV中,矩阵是一种核心数据结构,而矩阵表达式则是一种强大的工具,用于在图像处理和计算机视觉任务中对矩阵进行代数运算。本文将深入探讨OpenCV中的矩阵表达式,以及它们与cv::Ma

    2024年01月19日
    浏览(27)
  • [OpenCV][C++编程] cv::mat的定义与赋值

    可以通过在/目录下直接搜索opencv,确定opencv所在的目录: lopencv_core 是opencv的核心, -lopencv_highgui包含读取图像和显示图像的函数 -lopencv_imgproc包含图像处理函数(非机器学习方法),例如线性滤波,边缘检测、膨胀腐蚀、检测直线、仿射变换等等。 -lopencv_ml包含机器学习算法

    2024年02月09日
    浏览(35)
  • jni-Android Bitmap与OpenCV cv::Mat互转

    在封装so库的时候,底层c++代码的实现使用了OpenCV对图片进行操作,而Android中从摄像头中获取到的图片数据类型是Bitmap数据类型的,所以这里就避免不了做数据类型的转换。转换的方案主要有两种, 一种是封装的JNI接口方法直接接收cv::Mat数据类型的参数, 第二种是JNI方法的

    2024年02月01日
    浏览(29)
  • [OpenCV] CV_32F与CV_8U之间的数据类型转换

    最近在c++使用OpenCV时,总会因为类型转换为发生图片颜色错误,在网上查了些方法都不适用,总结下自己探索的经验。 经常使用的是8UC(n)与32FC(n),其中8U在0-255之间使用整数对应颜色,32F在0-1之间使用小数对应颜色; 在使用 converTo() 进行数据类型转换时,数据值并不会发生内

    2024年02月12日
    浏览(43)
  • 利用ffmpeg和opencv进行视频的解码播放

    引子 OpenCV中有自己的用于处理图片和视频的类VideoCapture,可以很方便的读入文件和显示。 现在视频数据流是ffmpeg解码h264文件得到的,由于要依赖该数据源进行相应的后续处理,所以需要将ffmpeg中得到的数据缓存转换成可以被OpenCV处理的Mat类对象。 ffmpeg介绍 FFmpeg是一个开源

    2024年02月13日
    浏览(34)
  • 在IOS上YUV NV21格式的CVPixelBufferRef转opencv的RGB格式cv::Mat的方法

    因为业务需要,要做这样一个转换。目前写了两种转换方法。 在iphonex真机上运行,一种方法需要24ms一帧,CPU占用率85%,另一种需要17ms一帧,CPU占用率140%。下面就来详细说说。 转换思路是CVPixelBufferRef-UIImage-cv::Mat的路线。 直接上方法: 先是CVPixelBufferRef-UIImage的方法 然后是

    2024年02月12日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包