【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;//编解码器的AVCodec
    this->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 -Y
                fwrite(this->pictureYUV->data[1],this->pCodecContext->width*this->pCodecContext->height/4,1,pyuv);//  1/4 -U
                fwrite(this->pictureYUV->data[2],this->pCodecContext->width*this->pCodecContext->height/4,1,pyuv);//  1/4 -V
                //pictureRGB 转储为QImage
                QImage 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.mfbz.cn/a/774475.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端从业者的历史难题Vue和React的抉择:难度不亚于丈母娘和媳妇

**前端从业者的历史难题&#xff1a;Vue和React的抉择——难度不亚于丈母娘和媳妇** Vue和React这两个框架无疑是当下最为流行的两个选择。它们各自拥有独特的优势和特点&#xff0c;吸引了大量的前端从业者。然而&#xff0c;对于许多从业者来说&#xff0c;如何在Vue和React…

D. Beauty of the mountains(cf955)

分析&#xff1a;有一个n*m的数组a&#xff0c;对应n*m的数组b&#xff0c;想让b0的下标的a的数组之和等于b1的下标的a的数组之和&#xff0c;你可以进行k*k的范围所有数字全部加任意数。 求出子矩阵里0和1的差值&#xff1b; #include<bits/stdc.h> using namespace st…

Android 四大组件

1. Activity 应用程序中&#xff0c;一个Activity通常是一个单独的屏幕&#xff0c;它上面可以显示一些控件&#xff0c;也可以监听并对用户的事件做出响应。 Activity之间通过Intent进行通信&#xff0c;在Intent 的描述结构中&#xff0c;有两个最重要的部分&#xff1a;动…

电子行业MES系统解决方案

工业4.0时代的工业自动化&#xff0c;将在原有自动化技术和架构下&#xff0c;实现集中式控制向分散式增强型控制的基本模式转变&#xff0c;让设备从传感器到因特网的通讯能够无缝对接&#xff0c;从而建立一个高度灵活的、个性化和数字化、融合了产品与服务的生产模式。在这种…

springboot城市菜园共享系统-计算机毕业设计源码00524

目 录 摘要 1 绪论 1.1 研究背景与意义 1.2 国内外研究现状和发展趋势 1.3论文结构与章节安排 2 城市菜园共享系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.…

Keepalived+HAProxy 集群及虚IP切换实践

1、软件介绍 ①Keepalived keepalive是一个用c语言编写的路由软件&#xff0c;这个项目的主要目标是为Linux系统和基于Linux的基础设施提供简单而健壮的负载平衡和高可用性设施。负载均衡框架依赖于众所周知且广泛使用的Linux Virtual Server (IPVS)内核模块提供第4层负载均衡…

Renderless 思想正在影响前端开发

本文由前端小伙伴方长_beezen 原创。欢迎大家踊跃投稿。 原文链接&#xff1a;https://juejin.cn/post/7385752495535472655 前言 截止到 2024 年&#xff0c;跨端应用开发所需要考虑的兼容性&#xff0c;已经涵盖了框架、平台和设备类型等多个方面&#xff0c;例如&#xff1…

ES集成到ambari中出现的常见问题归总

1.elasticesearch用户名组的问题 KeyError: uelasticsearch Error: Error: Unable to run the custom hook script [/usr/bin/python, /var/lib/ambari-agent/cache/stack-hooks/before-ANY/scripts/hook.py, ANY, /var/lib/ambari-agent/data/command-102.json, /var/lib/amb…

Runway Gen-3 实测,这就是 AI 视频生成的 No.1!视频高清化EvTexture 安装配置使用!

Runway Gen-3 实测,这就是 AI 视频生成的 No.1!视频高清化EvTexture 安装配置使用! 由于 Runway 作为一个具体的工具或平台,其详细信息在搜索结果中没有提供,我将基于假设 Runway 是一个支持人工智能和机器学习模型的创意工具,提供一个关于使用技巧和类似开源项目的文稿总…

4K Tokkit Pro for Mac:轻松管理TikTok的利器

在TikTok的海洋中畅游&#xff0c;你是否想有一个得力助手来帮你高效管理你的账号&#xff1f;4K Tokkit Pro for Mac正是你的不二之选&#xff01; 这款专为Mac用户打造的TikTok管理工具&#xff0c;拥有简洁的界面和强大的功能&#xff0c;让你轻松下载、管理和分享喜欢的Ti…

Qt(一)概念 信号与槽

文章目录 一、概念&#xff08;一&#xff09;Qt工具1. Assistant&#xff1a;帮助手册2. Designer&#xff1a;Qt设计师3. xxx.uic文件4. rcc资源文件5. moc&#xff1a;元对象编译器6. qmake7. Qtcreator&#xff1a;集成化的开发软件 &#xff08;二&#xff09;创建第一个Q…

Python爬虫教程第0篇-写在前面

为什么写这个系列 最近开发了个Python爬虫的脚本&#xff0c;去抢一个名额&#xff0c;结果是程序失败了&#xff0c;中间有各种原因&#xff0c;终究还是准备不足的问题。我想失败的经验或许也可贵&#xff0c;便总结一下当初从0开始学Python&#xff0c;一步步去写Python脚本…

多租户hive数仓

1、概念 多租户对应的是单租户&#xff0c;本篇文章重点讲解多租户&#xff0c;单租户为了解内容。 1.1 多租户 多租户技术或称多重租赁技术&#xff0c;简称SaaS&#xff0c;是一种软件架构技术&#xff0c;是实现如何在多用户环境下&#xff08;此处的多用户一般是面向企业…

14-11 2024 年的 13 个 AI 趋势

2024 年的 13 个 AI 趋势 人工智能对环境的影响和平人工智能人工智能支持的问题解决和决策针对人工智能公司的诉讼2024 年美国总统大选与人工智能威胁人工智能、网络犯罪和社会工程威胁人工智能治疗孤独与对人工智能的情感依赖人工智能影响者中国争夺人工智能霸主地位人工智能…

【浦语大模型开源探索】InternLM实战营第二期:技术笔记与全链路解析

本次课程链接在GitHub上&#xff1a; InternLM/Tutorial at camp2 (github.com) 第一次课程录播链接&#xff1a; 书生浦语大模型全链路开源体系_哔哩哔哩_bilibili InternLM2技术报告&#xff1a; arxiv.org/pdf/2403.17297.pdf 一、书生浦语大模型全链路开源体系笔记 Int…

v-html 空格/换行不生效

接口返回的内容如下&#xff1a;有空格有换行&#xff0c;但 使用v-html无效 需加css样式 white-space: pre-wrap; <div class"pretty-html" v-html"Value"></div>.pretty-html {white-space: pre-wrap; /* 保留空格和换行&#xff0c;并允许…

震撼发布!4M-21:苹果多模态AI巨擘,一键解锁21种模态

前沿科技速递&#x1f680; 来自洛桑联邦理工学院&#xff08;EPFL&#xff09;与苹果科研巨擘的强强联手&#xff0c;震撼发布全新跨时代成果——4M-21模型&#xff01;这一革命性单一模型&#xff0c;突破性地覆盖了数十种高度多样化的模态&#xff0c;通过大规模多模态数据集…

数据洞察:从零到一的数据仓库与Navicat连接全攻略【实训Day04】[完结篇]

一、数据分析 1 实现数据仓库(在hadoop101上) 1) 创建jobdata数据库 # cd $HIVE_HOME # bin/hive hive>create database jobdata; hive>use jobdata; 2) 创建原始职位数据事实表ods_jobdata_orgin(在hadoop101上) create table ods_jobdata_origin( city string CO…

【测试开发】【postman】按顺序循环执行接口

postman按顺序循环执行接口 新建接口接口排序执行请求集合 新建接口 Request 001 Request 002 Request 003 接口排序 在Request 001的Tests中添加代码 postman.setNextRequest("Request 002");在Request 002的Tests中添加代码 postman.setNextRequest("Requ…

ASP.NET Core 使用Log4net

1. Nuget安装log4net&#xff0c;图里的两个 2.项目根目录下添加log4net.config.添加下面的代码: <?xml version"1.0" encoding"utf-8"?> <configuration><!-- This section contains the log4net configuration settings --><log…