去官网下载源码自己编译所需要的库,或者直接从官网下载已经编写好的库,由于本例是Window平台下的开发,而官网已经有了编译好的库,所以直接下载编译所需要的库文件即可。下载地址:需要下载两个压缩包,Dev版本和Shared版本,其中Dev版本是头文件和lib库文件,Shared是包含运行所需要的dll文件。
下载完成后,需要把这些头文件、静态库、动态链接库引入到我们的工程里面,不过在Windows下面,头文件除了要用到FFMPEG提供的,还要使用另外三个文件:inttypes.h,stdint.h,_mingw.h,这三个文件放到FFMPEG头文件的根目录下即可。
自编译源码方法
// C++代码需要加这个!!否则找不到函数的
extern "C"
{
#include "libavcodec\avcodec.h"
#include "libavformat\avformat.h"
#include "libswscale\swscale.h"
// 链接的ffmpeg库,我把所有可能需要用到的都写这里了
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "avcodec.lib")
#pragma comment (lib, "avdevice.lib")
#pragma comment (lib, "avfilter.lib")
#pragma comment (lib, "avformat.lib")
#pragma comment (lib, "avutil.lib")
#pragma comment (lib, "swresample.lib")
#pragma comment (lib, "swscale.lib")
};
int main(int argc, char* argv[])
{
AVFormatContext* pFormatCtx;
AVOutputFormat* fmt;
AVStream* audio_st;
AVCodecContext* pCodecCtx;
AVCodec* pCodec;
uint8_t* frame_buf;
AVFrame* frame;
int size;
FILE *fileIn = fopen("Beyond.pcm", "rb");
char* fileOut = "Beyond.aac";
// 初始化注册FFMPEG以供使用
av_register_all();
// 解码文件格式
avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, fileOut);
fmt = pFormatCtx->oformat;
//注意输出路径
if (avio_open(&pFormatCtx->pb, fileOut, AVIO_FLAG_READ_WRITE) < 0)
{
printf("输出文件打开失败!\n");
return -1;
}
audio_st = avformat_new_stream(pFormatCtx, 0);
if (audio_st == NULL)
{
printf("新建流失败!!!\n");
return -1;
}
// 设定转码信息
pCodecCtx = audio_st->codec;
pCodecCtx->codec_id = fmt->audio_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
pCodecCtx->sample_rate= 44100; // 音频的采样率
pCodecCtx->channel_layout=AV_CH_LAYOUT_STEREO;
pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
pCodecCtx->bit_rate = 64000; // 音频的比特率
//调试输出格式信息
av_dump_format(pFormatCtx, 0, fileOut, 1);
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec)
{
printf("找不到输入文件所需的编码器!\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0)
{
printf("打开编码器失败!\n");
return -1;
}
frame = avcodec_alloc_frame();
frame->nb_samples= pCodecCtx->frame_size;
frame->format= pCodecCtx->sample_fmt;
size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1);
frame_buf = (uint8_t *)av_malloc(size);
avcodec_fill_audio_frame(frame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1);
// 填充输出的头文件信息
avformat_write_header(pFormatCtx,NULL);
AVPacket pkt;
av_new_packet(&pkt,size);
for (int i=0; ; i++)
{
//读入PCM
if (fread(frame_buf, 1, size, fileIn) < 0)
{
printf("文件读取错误!\n");
return -1;
}
else if(feof(fileIn))
{
break;
}
frame->data[0] = frame_buf; //采样信号
frame->pts=i*100;
int got_frame=0;
//编码
int ret = avcodec_encode_audio2(pCodecCtx, &pkt,frame, &got_frame);
if(ret < 0)
{
printf("编码错误!\n");
return -1;
}
if (got_frame==1)
{
pkt.stream_index = audio_st->index;
ret = av_write_frame(pFormatCtx, &pkt);
av_free_packet(&pkt);
}
}
//写文件尾
av_write_trailer(pFormatCtx);
//清理
if (audio_st)
{
avcodec_close(audio_st->codec);
av_free(frame);
av_free(frame_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
fclose(fileIn);
printf("转码完毕!!!\n");
return 0;
}
由于FFMPEG会没事就修改接口,所以不同版本的FFMPEG可能会编译不过,反正2015年1月23日17:29:31是可以编译通过的。