初学ffmpeg解码

VC下FFmpeg开发环境的搭建
• 新建控制台工程
▫ 打开VC++
▫ 文件->新建->项目->Win32控制台应用程序
• 拷贝FFmpeg开发文件
▫ 头文件(.h)拷贝至项目文件夹的include子文件夹下
▫ 导入库文件(
.lib)拷贝至项目文件夹的lib子文件夹下
▫ 动态库文件(.dll)拷贝至项目文件夹下
• 配置开发文件
▫ 打开属性面板
 解决方案资源管理器->右键单击项目->属性
▫ 头文件配置
 配置属性->C/C+±>常规->附加包含目录,输入“include”(刚才拷贝
头文件的目录)
▫ 导入库配置
 配置属性->链接器->常规->附加库目录,输入“lib” (刚才拷贝库文
件的目录)
 配置属性->链接器->输入->附加依赖项,输入“avcodec.lib;
avformat.lib; avutil.lib; avdevice.lib; avfilter.lib;
postproc.lib; swresample.lib; swscale.lib”(导入库的文件名)
▫ 动态库不用配置
• 测试
▫ 创建源代码文件
 在工程中创建一个包含main()函数的C/C++文件(如果已经有了可以跳
过这一步)。
▫ 包含头文件
 如果是C语言中使用FFmpeg,则直接使用下面代码
#include “libavcodec/avcodec.h”
 如果是C++语言中使用FFmpeg,则使用下面代码
#define __STDC_CONSTANT_MACROS
extern “C”
{
#include "libavcodec/avcodec.h "
}
main()中调用一个FFmpeg的接口函数
 例如下面代码打印出了FFmpeg的配置信息
int main(int argc, char
argv[]){
printf(“%s”, avcodec_configuration());
return 0;
}
如果运行无误,则代表FFmpeg已经配置完成。

下面是纯手写手写源码

#include <stdio.h>
#define __STDC_CONSTANT_MACROS
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
}
int main(int argc,char*argv[])
{
	//printf("%s", avformat_configuration());//验证ffmpeg是否配置成功
	AVFormatContext *pFormatCxt;//封装格式上下文
	AVCodecContext *pCodecCxt;//解码器上下文
	AVCodec *pCodec;//解码器
	AVFrame *pFrame, *pFrameyvu;//pFrame接收解码后的数据,pFrameyvu接收pFrame缩放后的数据
	AVPacket* packet;

	struct SwsContext* imgSrc;//接收缩放前的图片信息指针
	uint8_t *out_bufsize;//申请空间大小
	int got_picture;//如果没有帧可以解压缩,则为零,否则为非零。
	int ret=0;//判断返回值
	int frmae_count=0;//解码一帧的记数
	int videoindex=-1;//保存视频流序号

	char filepath[] = "Titanic.ts";//输入的音视频文件
	//注册并初始化组件
	av_register_all();
	avformat_network_init();

	pFormatCxt = avformat_alloc_context();//初始化封装格式上下文
	
	if (avformat_open_input(&pFormatCxt, filepath, NULL, NULL)!=0)//打开输入文件
	{
		printf("avformat_open_input fail");
		return -1;
	}
	if(avformat_find_stream_info(pFormatCxt,NULL) < 0)//寻找流信息
	{
		printf("avformat_find_stream_info fail");
		return -1;
	}
	for (unsigned int i = 0; i < pFormatCxt->nb_streams; i++)//找到视频流索引
	{
		if (pFormatCxt->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			videoindex = i;
			break;
		}
	}
	if (videoindex == -1)
	{
		printf("find_videoindex fail");
		return -1;
	}
	
	pCodecCxt = pFormatCxt->streams[videoindex]->codec;//初始化解码器上下文
	pCodec = avcodec_find_decoder(pCodecCxt->codec_id);//寻找解码器
	if (pCodec == NULL)
	{
		printf("avcodec_find_decoder fail");
		return -1;
	}

	if(avcodec_open2(pCodecCxt, pCodec, NULL) < 0)//打开解码器
	{
		printf("avcodec_open2 fail");
		return -1;
	}

	//打印视频信息。
	//-----------video info------------
	printf("-----------video info------------\n");
	av_dump_format(pFormatCxt, 0, filepath, 0);
	printf("---------------------------------\n");

	FILE *logfile;
	logfile = fopen("logfile.txt", "wb+");
	fprintf(logfile, "视频名字:%s\n", pFormatCxt->filename);
	fprintf(logfile,"视频时长:%d\n",(int)pFormatCxt->duration);
	fprintf(logfile, "视频宽x高:%dx%d\n", pCodecCxt->width, pCodecCxt->height);
	fprintf(logfile, "视频码率:%d\n", pFormatCxt->bit_rate);



	//初始化pFrame、pFrameyvu
	pFrame = av_frame_alloc();
	pFrameyvu = av_frame_alloc();


	//为图片缩放做准备
	out_bufsize = (uint8_t*)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCxt->width, pCodecCxt->height));
	avpicture_fill((AVPicture*)pFrameyvu,out_bufsize, PIX_FMT_YUV420P, pCodecCxt->width, pCodecCxt->height);
	
	imgSrc=sws_getContext(pCodecCxt->width, pCodecCxt->height, pCodecCxt->pix_fmt,
		pCodecCxt->width, pCodecCxt->height, PIX_FMT_YUV420P,
		SWS_BICUBIC,NULL,NULL,NULL
		);
	
	//为packet初始化、申请内存空间
	packet= (AVPacket*)av_malloc(sizeof(AVPacket));


	FILE* h264file;
	h264file = fopen("h264file.h264", "wb+");

	FILE* yuvfile;
	yuvfile = fopen("yuvfile.yuv", "wb+");

	//解码流程
	while (av_read_frame(pFormatCxt, packet) >=0 )
	{
		if (packet->stream_index == videoindex)
		{
			fwrite(packet->data, 1, packet->size, h264file);//写h264文件
			ret=avcodec_decode_video2(pCodecCxt, pFrame, &got_picture, packet);//解码一帧视频
			if (ret < 0)
			{
				printf("avcodec_decode_video2 fail");
				return -1;
			}
			if (got_picture)//将解码后的视频缩放(不缩放得到的视频宽度比原始视频宽)
			{			
				sws_scale(imgSrc, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCxt->height, pFrameyvu->data, pFrameyvu->linesize);//图像缩放
				printf("解码第%d帧视频成功\n", frmae_count);

				//写yuv文件
				fwrite(pFrameyvu->data[0], 1, pCodecCxt->width* pCodecCxt->height, yuvfile);//写h264文件
				fwrite(pFrameyvu->data[1], 1, pCodecCxt->width * pCodecCxt->height/4, yuvfile);//写h264文件
				fwrite(pFrameyvu->data[2], 1, pCodecCxt->width * pCodecCxt->height/4, yuvfile);//写h264文件
				frmae_count++;
			}
			
		}
		av_free_packet(packet);
	}
	fclose(logfile);
	fclose(h264file);
	fclose(yuvfile);

	sws_freeContext(imgSrc);


	av_frame_free(&pFrame);
	av_frame_free(&pFrameyvu);
	avcodec_close(pCodecCxt);
	avformat_close_input(&pFormatCxt);

	return 0;
}

源代码下载:ffmpeg解码视频源代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雷久虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值