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解码视频源代码