【FFMPEG应用篇】使用FFMPEG解析H264编码为YUV格式

头文件

#pragma once#ifndef _VIDEO_DECODING_HEADER_
#define _VIDEO_DECODING_HEADER_#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096extern "C"
{
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
}/*************************************************
Struct:			CodecCtx
Description:	FFMpeg编解码器上下文
*************************************************/
typedef struct
{AVCodec			*pCodec;				//编解码器实例指针AVCodecContext	*pCodecContext;			//编解码器上下文,指定了编解码的参数AVCodecParserContext *pCodecParserCtx;	//编解码解析器,从码流中截取完整的一个NAL Unit数据AVFrame			*frame;					//封装图像对象指针AVPacket		pkt;					//封装码流对象实例
} CodecCtx;#endif

cpp文件

/*************
解码主要步骤:
1.解析输入参数,获取待解码的码流数据
2.初始化相应的FFMpeg结构
3.循环读取并解析输入码流数据--由2进制码流解析为FFMpeg可以处理的包数据
4.解码解析出的包为像素数据
5.写出像素数据
6.收尾工作
*************/#include<stdio.h>
#include<stdint.h>
#include"VideoDecodingHeader.h"#define INBUF_SIZE 4096   //接受区域大小FILE* pFin = NULL;
FILE* pFout = NULL;AVCodec* pCodec = NULL;
AVCodecContext* pCodecContext = NULL;
AVCodecParserContext* pCodecParserCtx = NULL;   //码流解码供解码器使用的包AVFrame* frame = NULL;
AVPacket pkt;static int open_input_output_file(char **argv)
{const char* inputFileName = argv[1];const char* outputFileName = argv[2];//fopen_s 以二进制只读的方式打开inputFileName,返回FILE指针fopen_s(&pFin, inputFileName, "rb+");if (!pFin){printf("Error: open input file failed.\n");return -1;}fopen_s(&pFout, outputFileName, "wb+");if (!pFout){printf("Error: open input file failed.\n");return -1;}return 0;
}
//打开解码器且初始化
static int open_decoder()
{//注册组件avcodec_register_all();//初始化最后输出的pktav_init_packet(&pkt);//查找解码器pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);if (!pCodec){return -1;}pCodecContext = avcodec_alloc_context3(pCodec);if (!pCodecContext){return -1;}if (pCodec->capabilities & AV_CODEC_CAP_TRUNCATED){pCodecContext->flags |= AV_CODEC_CAP_TRUNCATED;}//初始化解析器pCodecParserCtx = av_parser_init(AV_CODEC_ID_H264);if (!pCodecParserCtx){printf("Error:alloc parser failed.\n");return -1;}//打开解码器if (avcodec_open2(pCodecContext, pCodec, NULL) < 0){printf("Error:open condec failed.\n");return -1;}//开辟frame空间frame = av_frame_alloc();if (!frame){printf("Error:alloc frame failed.\n");return -1;}return 0;}
//写出YUV数据
static void write_out_yuv_frame(AVFrame *frame)
{uint8_t **pBuf = frame->data;//保存地址int*	pStride = frame->linesize;//保存位宽for (int color_idx = 0; color_idx < 3; color_idx++){int		nWidth = color_idx == 0 ? frame->width : frame->width / 2;int		nHeight = color_idx == 0 ? frame->height : frame->height / 2;for (int idx = 0; idx < nHeight; idx++){fwrite(pBuf[color_idx], 1, nWidth, pFout);pBuf[color_idx] += pStride[color_idx];}fflush(pFout);}
}
//收尾工作
static void Close()
{fclose(pFin);fclose(pFout);avcodec_close(pCodecContext);av_free(pCodecContext);av_frame_free(&frame);}int main(int argc, char **argv)
{//从输入文件读取码流数据保存到的缓存位置uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];if (open_input_output_file(argv) < 0){return -1;}else{printf("Open input/ouput file succeed\n");}if (open_decoder() < 0){return -1;}else{printf("Open decoder file succeed\n");}//解码循环int uDataSize = 0, len = 0;int got_frame = 0;uint8_t* pDataPtr = NULL;while (true){uDataSize = fread_s(inbuf, INBUF_SIZE, 1, INBUF_SIZE, pFin);if (uDataSize == 0){break;}pDataPtr = inbuf;while (uDataSize>0){len = av_parser_parse2(pCodecParserCtx, pCodecContext,&pkt.data, &pkt.size,pDataPtr, uDataSize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);pDataPtr += len;uDataSize -= len;//pkt.size==0没有解析完if (pkt.size == 0){continue;}//!=0成功解析出一个packet的码流printf("Parse 1 packet.\n");int ret = avcodec_decode_video2(pCodecContext, frame, &got_frame, &pkt);if (ret < 0){printf("Error: decode failed.\n");return -1;}if (got_frame){printf("Decoded 1 frame OK! Width x Height: (%d x %d)\n", frame->width, frame->height);write_out_yuv_frame(frame);}else{break;}}}pkt.data = NULL;pkt.size = 0;while (true){int ret = avcodec_decode_video2(pCodecContext, frame, &got_frame, &pkt);if (ret < 0){printf("Error: decode failed.\n");return -1;}if (got_frame){printf("Flush Decoded 1 frame OK! Width x Height: (%d x %d)\n", frame->width, frame->height);write_out_yuv_frame(frame);}}Close();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 反射api_Java学习笔记--反射API

反射API1.反射API的介绍通过反射API可以获取Java程序在运行时刻的内部结构。比如Java类中包含的构造方法、域和方法等元素&#xff0c;并可以与这些元素进行交换。按照 一般地面向对象的设计思路&#xff0c;一个对象的内部状态都应该通过相应的方法来改变&#xff0c;而不是直…

c++各类型有效范围

int -2147483648 ~ 2147483647 float 有6-7位有效数字 double 有15-16位有效数字

couchbase_具有Couchbase,Java EE和WildFly的CRUD Java应用程序

couchbaseCouchbase是一个开源的NoSQL文档数据库。 它允许访问&#xff0c;索引和查询JSON文档&#xff0c;同时利用集成的分布式缓存来实现高性能数据访问。 开发人员可以使用不同的语言&#xff08;Java&#xff0c;Go&#xff0c;.NET&#xff0c;Node&#xff0c;PHP&…

java 对象的态_Java面向对象-------多态总结

1.多态&#xff1a;是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口&#xff0c;使用不同的实例而执行不同操作&#xff0c;如图所示&#xff1a;多态性是对象多种表现形式的体现。2.多态作用&#xff1a;1. 消除类型之间的耦合关系2. 可替换性3. 可扩充性4…

C++ 【随想录】(六)C++后端向JS前端转换

需要包含的头文件 #include"comutil.h" #include"<string> BSTR转string BSTR bstrText ::SysAllocString(L"Test"); string str _com_util::ConvertBSTRToString(bstrText); SysFreeString(bstrText); string转BSTR…

netbeans连接数据库_NetBeans Java EE技巧#1 –数据库中的实体类

netbeans连接数据库NetBeans IDE是开发各种应用程序的绝佳选择。 具体来说&#xff0c;我每天都使用它来开发和维护Java EE应用程序。 在过去的几个发行版中&#xff0c;不仅Java EE的生产力提高了&#xff0c;而且NetBeans IDE还减少了开发应用程序的时间……使Java EE和NetBe…

java spring eventbus_spring集成guava的event bus

Guava的event busguava&#xff0c; https://github.com/google/guava 是一个非常有名的Java类库&#xff0c;提供了很多在日常开发中常用的集合、函数接口等。此外&#xff0c;guava还提供了一个模块叫做event bus&#xff0c;生产者往event bus上投递消息&#xff0c;event b…

LeetCode 66 加一

原题链接 关键词 &#xff1a;数组 模拟法 解题思路: 此题为处理数组&#xff0c;数组特点 --数组下标 可以前后覆盖 数组元素可交换等。 此题分为三种情况 1.传入数为234形式 &#xff0c;加一后无进位。直接在最后一个数组1即可 2.传入数为239形式&#xff0c;即…

jboss fuse 教程_使用JBoss Fuse和OpenShift进行Cloud Native Camel骑行

jboss fuse 教程红帽公司最近发布了一个微服务集成工具包&#xff0c;用于在OpenShift v3的Docker和Kubernetes环境中运行我们的微服务。 为了帮助人们更好地理解这一点&#xff0c;我将Rider Auto应用程序迁移到一组微服务中&#xff0c;该应用程序已经存在了一段时间&#xf…

java streamhandler_java中的Lamdba表达式和Stream

基于JDK 1.81、循环&#xff1a;// 以前的循环方式for (String player : players) {System.out.print(player "; ");}// 使用 lambda 表达式以及函数操作(functional operation)players.forEach((player) -> System.out.print(player "; "));// 在 Ja…

LeetCode 217 存在重复元素

原题链接 关键词 数组 排序 重复 解题思路 1.先把数组进行排序&#xff0c;然后比较是否有相邻的两个数字相等 ,有返回TRUE 无则返回FALSE 2.需要注意的是nums.size()-1 因为是从下标0开始&#xff0c;所以要-1&#xff0c;否则会造成数组越界 class Solution { pu…

java 代码运行速度慢_C代码的运行速度总是比Java快,对吧? 错误!

java 代码运行速度慢因此&#xff0c;我们都知道&#xff0c;Java解释缓慢且C的编译和优化运行速度非常快。 您可能知道&#xff0c;情况截然不同。 TL; DR Java适用于星座图&#xff0c;它的速度更快&#xff0c;在JIT上可以执行内联&#xff0c;因为所有方法/功能都是可见的…

LeetCode 26.删除排序数组中的重复项

原题 标签 &#xff1a; 数组 重复元素 有序 双指针 快慢指针 解题思路: 1.判断数组是否为空&#xff0c;为空返回0 2.我们可以放置两个指针 &#xff0c;其中 k 是慢指针&#xff0c;用来存下所有不同的数&#xff0c;而 j 是快指针用来扫描整个数组。只要 nums[i] n…

javaone_JavaOne 2015 –又一年,又向前迈进了一步

javaoneJavaOne 2015 San Francisco于10月25日至29日举行。 我很自豪地说这是我第九个人参加JavaOne&#xff0c;第七个人是演讲者&#xff0c;第四个人是Oracle员工&#xff0c;第三个人是内容委员会成员&#xff0c;第二个人是项目负责人。 我认为对于JavaOne来说&#xff0c…

lnp和mysql分开安装_毕业设计之LNP+DISCUZ +分离的数据库操作

环境介绍&#xff1a;CentOS6.9最小化安装https://nginx.org/download/nginx-1.16.1.tar.gzhttps://www.php.net/distributions/php-7.3.14.tar.gzhttps://cdn.mysql.com//Downloads/MySQL-5.7/mysql-boost-5.7.29.tar.gznginxphp主机&#xff1a;192.168.111.141mysql主机&…

LeetCode 268 缺失数字

原题链接 标签&#xff1a; 数组 排序 解题思路: 1. 先进行排序 2. 0--N之间只有一个数没有出现&#xff0c;并且这是数组缺失的数字等于所在数组下标 3. 利用双指针&#xff0c;找到相差1的两个数组返回慢指针所指向值1&#xff0c;既可找到缺失的数字 …

java ee jms_在Java EE 7中自动配置JMS资源

java ee jmsJMS 2.0&#xff08;Java EE 7平台的一部分&#xff09;引入了许多不错的功能 。 其中之一是能够声明JMS资源以进行自动部署。 Java EE 7之前的版本 使用Resource注入连接工厂 使用Resource查找目标位置&#xff08;队列/主题&#xff09; 拉出Session对象&#…

python窗口居中_Python: tkinter窗口屏幕居中,设置窗口最大,最小尺寸实例

我就废话不多说了。大家直接看代码吧&#xff01;#!/usr/bin/env python#codingutf-8窗口屏幕居中,设置窗口最大,最小尺寸...版权所有 2014 yao_yu (http://blog.csdn.net/yao_yu_126)本代码以MIT许可协议发布2014-04-15 创建import tkinter as tkfrom tkinter import ttkdef g…

取得二进制最右面为1的数

取得二进制最右面为1的数 int rightOne eO & (~eO 1);

java中hotspot_Java 8中HotSpot选项的改进文档

java中hotspotOracle的HotSpot Java 8实现中引入的一些小但受欢迎的功能之一是在启动器的文档中添加了许多常见的HotSpot Java启动器 &#xff08; java &#xff09;选项/标志。 过去&#xff0c;甚至对某些相当常见的HotSpot JVM选项都感兴趣的开发人员不得不潜在地寻找多个不…