【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);
}
相关文章:
【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 restoRGB32.openVideo("../fi…...

第二证券股市资讯:深夜!突然暴涨75%!
一则重磅收买引发医药圈轰动。 北京时间7月8日晚间,美股开盘后,美国生物制药公司Morphic股价一度暴升超75%。音讯面上,生物医药巨子礼来公司官宣,将以57美元/股的价格现金收买Morphic,较上星期五的收盘价溢价79%&…...
flutter 使用wechat_assets_picker的权限检测
https://pub.dev/packages/wechat_assets_picker AssetPicker.pickAssets之前进行权限检查 pickImages() async {try {if (PermissionState.authorized ! await AssetPicker.permissionCheck()) {PermissionUtil.showAllPermissions(Permission.storage, 1);return;}final Lis…...
Mojo入门案例教程(上手篇)
以下是 Mojo 编程语言入门案例教程,内容包括 Mojo 的基本概念、变量、控制结构、函数等方面: Mojo 的基本概念 1.什么是 Mojo?:Mojo 是一种函数式编程语言,用于开发小型应用程序、脚本和工具。 2.Mojo 的特点&#x…...
如何在window执行mkfile
1、Windows cmd中出现错误:“‘make‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。”的解决方法_windows_是板栗啊-GitCode 开源社区 2、安装cmder,再通过包管理工具下载make...
Nginx 是一个非常流行的 Web 服务器和反向代理服务器
Nginx 是一个非常流行的 Web 服务器和反向代理服务器,以其高性能、稳定性、丰富的功能集和低资源消耗而闻名。下面是一个简化的 Nginx 使用教程,包括基本的安装、配置和一些常见用途。 安装 Nginx 在 Ubuntu/Debian 上安装: sudo apt upda…...
mysql怎么调整缓冲区大小
MySQL中调整缓冲区大小是数据库性能优化的重要一环。缓冲区大小直接影响了数据库的读写性能和响应速度。以下是一些常见的MySQL缓冲区及其调整方法: 一、InnoDB缓冲池(InnoDB Buffer Pool) InnoDB缓冲池是InnoDB存储引擎用来缓存表数据和索…...

计算机组成原理学习笔记(一)
计算机组成原理 [类型:: [[计算机基础课程]] ] [来源:: [[B站]] ] [主讲人:: [[咸鱼学长]] ] [评价:: ] [知识点:: [[系统软件]] & [[应用软件]] ] [简单解释:: 管理计算机系统的软件; 按照任务需要编写的程序 ] [问题:: ] [知识点:: [[机器字长]] ] [简单…...
Vue3 对跳转 同一路由传入不同参数的页面分别进行缓存
1:使用场景 从列表页跳转至不同的详情页面,对这些详情页面分别进行缓存 2:核心代码 2.1: 配置路由文件 在路由文件里对需要进行缓存的路由对象添加meta 属性 // 需要缓存的详情页面路由 { name: detail, path: /myRouter/detail…...
LinearLayout的测量流程
在日常开发中我们常常使用LinearLayout作为布局Group,本文从其源码实现出发分析测量流程。大家可以带着问题进入下面的分析流程,看看是否能找到答案。 垂直测量 View的测量入口方法是onmeasure方法。LinearLayout的onMeasure方法根据其方向而做不同的处…...
数据无忧:Ubuntu 系统迁移备份全指南
唠唠闲话 最近电脑出现了一些故障,送修期间,不得不在实验室的台式机上重装系统,配环境的过程花费了不少时间。为避免未来处理类似事情时耗费时间,特此整理一些备份策略。 先做以下准备: U盘启动盘,参考 …...

中国IDC圈探访北京•光子1号金融算力中心
今天,“AI”、“大模型”是最炙手可热的话题,全球有海量人群在工作生活中使用大模型,大模型产品涉及多模态,应用范围已涵盖电商、传媒、金融、短视频、制造等众多行业。 而回看2003年的互联网记忆, “上网”“在线”是…...

[Unity入门01] Unity基本操作
参考的傅老师的教程学了一下Unity的基础操作: [傅老師/Unity教學] Unity3D基礎入門 [華梵大學] 遊戲引擎應用基礎(Unity版本) Class#01 移动:鼠标中键旋转:鼠标右键放大:鼠标滚轮飞行模式:右键WASDQEFocus模式&…...
vivado DELAY_VALUE_XPHY、DIFF_TERM
延迟_值_XPHY PORT对象上的DELAY_VALUE_XPHY属性指定要添加的延迟量 Versal XPHY逻辑接口的输入或输出路径。在的早期阶段 opt_design在重新生成高级I/O向导IP时 DELAY_VALUE_XPHY值将从PORT复制到的XPHY实例上 输入或输出路径。Vivado设计套件中存在DRCs,以确保 DE…...

C++语言相关的常见面试题目(三)
1. List底层实现原理 省流: list底层实现了一个双向循环链表。 每个元素(或节点)包含三个部分:数据域(_M_Storage)、前驱指针(_M_prev)、后继指针(_M_next)。 数据域:存储实际数据。 前驱指针:指向链表中…...

代码随想录-Day53
739. 每日温度 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 示例 1: …...

Android 如何通过代码实时设置EditTextView光标
背景:换肤框架下,QA进行深色浅色切换说输入框光标颜色没有改变,转UI结果UI说需要修改!!!!! 本来有方法可以设置,但是 设置后未生效。重新进入该页面才生效!&a…...

202488读书笔记|《365日创意文案》——无聊的 到底是这世间, 还是自己?懂得忘却的人才能前进
202488读书笔记|《365日创意文案》——无聊的 到底是这世间, 还是自己?懂得忘却的人才能前进 1月2月3月4月5月6月7月8月9月10月11月12月 《365日创意文案》WRITES PUBLISHING,一些日常,是烟火,也是幸福的印记。 当下也…...

iperf3: error - unable to connect to server: No route to host
1.确认iperf3版本是否统一。 2.确认防火墙是否关闭。 关闭防火墙 : systemctl stop firewalld 查看防火墙状态: systemctl status firewalld 3.重新建起链接...
正则表达式中的贪心匹配
在正则表达式中,?既可以表示数量,0次或1次,等效于 {0,1},也可以跟在其它数量限定符之后,表示非贪心匹配,即匹配时匹配搜索到的尽可能短的字符串。 下面来看一个例子: T…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...

数据挖掘是什么?数据挖掘技术有哪些?
目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...