//初始化、註冊編解碼器
avcodec_init();
av_register_all();
avformat_network_init();
//選取測試檔案
char* FileName="test.mp4";
string strFileName(FileName);
WavMaker test(AudioName.c_str());//初始化wav物件
//嘗試開啟測試檔案
AVFormatContext *pFormatCtx;
if(av_open_input_file(&pFormatCtx, FileName, NULL, 0, NULL) !=0 )
{
printf("開啟檔案失敗\n");
return -1;
}
dump_format(pFormatCtx, 0, NULL, NULL);//列印相關引數
//尋找流資訊,獲取格式上下文資訊
int err = av_find_stream_info(pFormatCtx);
if(err < 0)
{
printf("檢視流資訊失敗");
return 0;
}
//找到所有的音訊流和視訊流
vector<int> v_video_index;
vector<int> v_audio_index;
for(int i = 0;i<pFormatCtx->nb_streams;i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
{
v_audio_index.push_back(i);
}
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
{
v_video_index.push_back(i);
}
}
//取第一條音訊流,作為測試
AVCodecContext *pAVCodecCtx = pFormatCtx->streams[v_audio_index[0]]->codec;
AVCodec *pAVCodec = avcodec_find_decoder(pAVCodecCtx->codec_id);//找到相應的解碼器
if(!pAVCodec)
{
printf("Unsupported codec!\n");
return -1;
}
avcodec_open(pAVCodecCtx,pAVCodec); //獲取編碼器上下文資訊
//初始化包
AVPacket packet;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
int16_t * outbuf = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE * 2]; //解碼完一幀pcm緩衝區
//輸出wav檔名
int index1 = strFileName.rfind('.');
string AudioName = strFileName.substr( 0, index1) + ".wav";
WavMaker test(AudioName.c_str());
int count = 0;
while(av_read_frame(pFormatCtx,&packet)>=0)//讀取包
{
if(packet.stream_index==v_audio_index[0])//只解碼第一條音訊流
{
uint8_t *pktdata = packet.data;
int pktsize = packet.size;
while (pktsize > 0)
{
int times=0;
int out_size =AVCODEC_MAX_AUDIO_FRAME_SIZE*2;
int len = avcodec_decode_audio3(pAVCodecCtx, (short *)outbuf, &out_size, &packet);
if (len < 0)
{
fprintf(stderr, "Error while decoding\n");
break;
}
if (out_size > 0)
{
test.writebody((uint8_t*)outbuf,out_size); //解碼後的資料寫入檔案
break;
}
pktsize -= len;
pktdata += len;
}
}
av_free_packet(&packet);//釋放packet
}
test.writeheader(pAVCodecCtx->channels,pAVCodecCtx->sample_rate);//寫wav頭
test.closeFile();//關閉檔案