ffmpeg解码数据转换为cv::Mat
flyfish
ffmpeg:ffmpeg-6.0
头文件文章来源:https://www.toymoban.com/news/detail-532721.html
//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模板网!