当前位置: 首页 > news >正文

【FFMPEG基础(一)】解码源码

学习分享

  • main函数
  • decodetorgb32.h 文件
  • decodetorgb32 .cpp文件

main函数

#include <QApplication>
#include "decodetorgb32.h"
int main(int argc, char *argv[])
{QApplication a(argc, argv);DecodeToRGB32 toRGB32;int res=toRGB32.openVideo("../fileIn/Warcraft3_End.avi");if(res ==0){if(toRGB32.findStream() ==0){if(toRGB32.openDecoder()==0){toRGB32.decodeRGB();}}}return a.exec();
}

decodetorgb32.h 文件

#ifndef DECODETORGB32_H
#define DECODETORGB32_H
#include <QString>
#include <QDebug>
#include <QImage>
#include <stdio.h>
extern "C"
{#include "libavcodec/avcodec.h"             //编解码库#include "libavdevice/avdevice.h"           //输入给输出设备库,读取摄像头#include "libavfilter/avfilter.h"           //音视频滤镜库;进行音视频处理和编辑#include "libavformat/avformat.h"           //文件格式和协议库#include "libavutil/avutil.h"               //音视频处理#include "libswresample/swresample.h"       //音频重采样#include "libswscale/swscale.h"             //图像进行格式转换}class DecodeToRGB32
{
public:DecodeToRGB32();/** 1、注册组件 2、打开视频* @brief openVideo* @param filename* @return  0-success  else error*/int openVideo(QString filename);/** 3、查找流媒体数据  4、查找视频流* @brief findStream* @return 0-查找到视频流数据 1-查找流媒体数据  <0无流媒体数据*/int findStream();/** 5、查找解码器  6、打开解码器* @brief openDecoder* @return*/int openDecoder();/** 读取pkt* @brief decodeRGB*/void decodeRGB();
private:AVFormatContext* pFormatContext;    //封装格式上下文结构体int video_index;                    //视频流所在的下标AVCodecContext *pCodecContext;      //编解码器上下文结构体AVCodec*deocder;                    //解码器AVPacket * pkt;                     //码流数据AVFrame * picture,* pictureRGB,*pictureYUV;//1:不纯净的携带脏数据的像素数据,2:存储转置后的纯净的RGB像素数据 ,3:存储转置后的纯净的YUV像素数据};#endif // DECODETORGB32_H

decodetorgb32 .cpp文件

#include "decodetorgb32.h"DecodeToRGB32::DecodeToRGB32()
{}
//1、注册组件 2、打开视频
int DecodeToRGB32::openVideo(QString filename)
{av_register_all();//注册所用组件//全局结构体开空间this->pFormatContext=avformat_alloc_context();//打开输入视频文件int res=avformat_open_input(&this->pFormatContext,filename.toUtf8(),nullptr,nullptr);if(res!=0){qDebug()<<"open_input fail"<<res;//不等于0,文件打开失败}return res;
}
//3、查找流媒体数据  4、查找视频流
int DecodeToRGB32::findStream()
{//1.查找流媒体数据int res= avformat_find_stream_info(this->pFormatContext,nullptr);if(res<0){qDebug()<<"find_stream_info fail"<<res;//小于0查找失败return res;}//2.查看是否有视频流for (int i=0;i<this->pFormatContext->nb_streams;i++)//输入视频的AVStream的个数{//                                streams:输入视频的AVStream数组/codec:该流对应的AVCodecContext/编解码器类型if(AVMEDIA_TYPE_VIDEO==this->pFormatContext->streams [i]->codec->codec_type){this->video_index=i;return 0;}}return res;
}
//查找解码器,打开解码器
int DecodeToRGB32::openDecoder()
{int res=-1;//编解码器上下文结构体this->pCodecContext=this->pFormatContext->streams[this->video_index]->codec;//编解码器的AVCodecthis->deocder= avcodec_find_decoder(this->pCodecContext->codec_id);//查找解码器if(nullptr==this->deocder){qDebug()<<"find_decoder fail"<<res;return 1;}//打开解码器res=avcodec_open2(this->pCodecContext,this->deocder,nullptr);if(res!=0){qDebug()<<"find_decoder fail"<<res;}return res;//0 找到了并打开   <0未打开解码器
}void DecodeToRGB32::decodeRGB()
{//7、准备数据this->pkt =(AVPacket*)malloc(sizeof(AVPacket));//存储一帧压缩编码数据int size =this->pCodecContext->width*this->pCodecContext->height;av_new_packet(this->pkt,size);//初始化像素数据this->picture  =av_frame_alloc();//创建一个存储解码的像素数结构体this->picture->width=this->pCodecContext->width;this->picture->height=this->pCodecContext->height;this->picture->format=this->pCodecContext->pix_fmt;this->pictureRGB=av_frame_alloc();this->pictureRGB->width=this->pCodecContext->width;this->pictureRGB->height=this->pCodecContext->height;this->pictureRGB->format=this->pCodecContext->pix_fmt;this->pictureYUV=av_frame_alloc();this->pictureYUV->width=this->pCodecContext->width;this->pictureYUV->height=this->pCodecContext->height;this->pictureYUV->format=this->pCodecContext->pix_fmt;//计算一帧RGB32的像素大小int imgByte=avpicture_get_size(AV_PIX_FMT_RGB32,this->pCodecContext->width,this->pCodecContext->height);//动态开空间uint8_t*buffer=(uint8_t*)malloc(imgByte*sizeof(uint8_t));//图片的数据填充avpicture_fill((AVPicture*)this->pictureRGB,buffer,AV_PIX_FMT_RGB32,this->pCodecContext->width,this->pCodecContext->height);//制定转置的规则SwsContext*swContext=sws_getContext(this->pCodecContext->width,this->pCodecContext->height,this->pCodecContext->pix_fmt,this->pCodecContext->width,this->pCodecContext->height,AV_PIX_FMT_RGB32,SWS_BICUBIC,nullptr,nullptr,nullptr);/**准备YUV数据**********************///计算一帧YUV420P的像素大小int imgByteYUV=avpicture_get_size(AV_PIX_FMT_YUV420P,this->pCodecContext->width,this->pCodecContext->height);//动态开空间uint8_t*bufferYUV=(uint8_t*)malloc(imgByte*sizeof(uint8_t));//图片的数据填充avpicture_fill((AVPicture*)this->pictureYUV,bufferYUV,AV_PIX_FMT_YUV420P,this->pCodecContext->width,this->pCodecContext->height);//制定转置的规则SwsContext*swContextYUV=sws_getContext(this->pCodecContext->width,this->pCodecContext->height,this->pCodecContext->pix_fmt,this->pCodecContext->width,this->pCodecContext->height,AV_PIX_FMT_YUV420P,SWS_BICUBIC,nullptr,nullptr,nullptr);int num=0;FILE * pyuv=fopen("../fileOut/save.yuv","wb+");//二进制方式写入char path[256]={0};//8、读取码流数据、解封装    获取一帧压缩的码流数据while(av_read_frame(this->pFormatContext,this->pkt)==0)//0成功{//判断码流数据类型是视频流if(pkt->stream_index==this->video_index){int got_num =-1;//参数一:编解码器上下文结构体  二;AVFrame* 像素数据     三:int*标志位  四:一帧压缩码流数据avcodec_decode_video2(this->pCodecContext,this->picture,&got_num,this->pkt);if(got_num !=0){qDebug()<<"解码成功:"<<num;//剔除无效数据,获取纯净的RGB32数据/*** parmam1:转置规则* srcSlice 数据* srcStride 每一行的数据* srcSliceY 从第几行开始扫描* srcSliceH 图片高度* dst       目标数据* dstStrde  一行的宽度* @brief sws_scale*///存储图片 -播放sws_scale(swContext,picture->data,picture->linesize,0,this->picture->height,this->pictureRGB->data,this->pictureRGB->linesize);//用于存储 size更小sws_scale(swContextYUV,picture->data,picture->linesize,0,this->picture->height,this->pictureYUV->data,this->pictureYUV->linesize);fwrite(this->pictureYUV->data[0],this->pCodecContext->width*this->pCodecContext->height,1,pyuv);//  1 -Yfwrite(this->pictureYUV->data[1],this->pCodecContext->width*this->pCodecContext->height/4,1,pyuv);//  1/4 -Ufwrite(this->pictureYUV->data[2],this->pCodecContext->width*this->pCodecContext->height/4,1,pyuv);//  1/4 -V//pictureRGB 转储为QImageQImage img((uchar*)buffer,this->pictureRGB->width,this->pictureRGB->height,QImage::Format_RGB32);sprintf(path,"../fileOut/image%d.png",num);img.save(path);num++;if(num>5) break;}}}qDebug()<<num;fclose(pyuv);
}
http://www.lryc.cn/news/395063.html

相关文章:

  • 第二证券股市资讯:深夜!突然暴涨75%!
  • flutter 使用wechat_assets_picker的权限检测
  • Mojo入门案例教程(上手篇)
  • 如何在window执行mkfile
  • Nginx 是一个非常流行的 Web 服务器和反向代理服务器
  • mysql怎么调整缓冲区大小
  • 计算机组成原理学习笔记(一)
  • Vue3 对跳转 同一路由传入不同参数的页面分别进行缓存
  • LinearLayout的测量流程
  • 数据无忧:Ubuntu 系统迁移备份全指南
  • 中国IDC圈探访北京•光子1号金融算力中心
  • [Unity入门01] Unity基本操作
  • vivado DELAY_VALUE_XPHY、DIFF_TERM
  • C++语言相关的常见面试题目(三)
  • 代码随想录-Day53
  • Android 如何通过代码实时设置EditTextView光标
  • 202488读书笔记|《365日创意文案》——无聊的 到底是这世间, 还是自己?懂得忘却的人才能前进
  • iperf3: error - unable to connect to server: No route to host
  • 正则表达式中的贪心匹配
  • 线程相关概念及操作
  • 2024最新版若依-RuoYi-Vue3-PostgreSQL前后端分离项目部署手册教程
  • PHP源码:新闻门户系统(附管理后台+前台)
  • 15kg级弹簧刀高速巡飞无人机技术详解
  • 中国东方资产管理25届秋招北森测评笔试如何高分通过?真题考点分析看完这篇就够了
  • 简写单词BC149
  • Chapter11让画面动起来——Shader入门精要学习笔记
  • c++之命名空间详解(namespace)
  • 【大模型】在大语言模型的璀璨星河中寻找道德的北极星
  • 嵌入式Linux之Uboot简介和移植
  • 算法整理——【贪心算法练习(1)】