这个程序实现了从音视频文件中抽取出音频流数据并保存成wav音频格式文件的功能。
#include "avcodec.h"
#include "avformat.h"
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
struct RIFF_HEADER{
char szRiffID[4]; //= {'R','I','F','F'};
DWORD dwRiffSize;
char szRiffFormat[4]; //"WAVE"
};
struct WAVE_FORMAT{
char szWaveID[4];
DWORD wFSize;
WORD wFormatTag;
WORD wChannels;
DWORD dwSamplesPerSec;
DWORD dwAvgBytesPerSec;
WORD wBlockAlign;
WORD wBitsPerSample;
};
struct FMT_BLOCK{
char szFmtID[4];// 'f','m','t',' '
DWORD dwFmtSize;
WAVE_FORMAT wavFormat;
};
struct DATA_BLOCK{
char szDataID[4]; // 'd','a','t','a'
DWORD dwDataSize;
};
int main()
{
AVFormatContext *pFormatCtx;
int i, audioStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVPacket packet;
char* infile="b.mp4";
av_register_all();
if (av_open_input_file(&pFormatCtx, infile, NULL, 0, NULL) != 0)
return -1; // Couldn't open file
if (av_find_stream_info(pFormatCtx) < 0)
return -1; // Couldn't find stream information
dump_format(pFormatCtx, 0, infile, false);
audioStream = -1;
for (i=0; i<pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO){
audioStream=i;
break;
}
}
if (audioStream == -1)
return -1; // Didn't find a video stream
pCodecCtx = pFormatCtx->streams[audioStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
return -1; // Codec not found
if (avcodec_open(pCodecCtx, pCodec) < 0)
return -1; // Could not open codec
uint8_t *pktdata;
int pktsize;
int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
uint8_t * inbuf = (uint8_t *)malloc(out_size);
FILE* pFileWav;
int fileSize;
pFileWav= fopen("b.wav","wb");
fseek(pFileWav,44,SEEK_SET);
fileSize = 44;
while(av_read_frame(pFormatCtx, &packet)>=0) {
if(packet.stream_index==audioStream) {
pktdata = packet.data;
pktsize = packet.size;
while(pktsize>0)
{
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
//解码
int len = avcodec_decode_audio(pCodecCtx,(short*)inbuf,&out_size,pktdata,pktsize);
if (len<0)
{
printf("Error while decoding.\n");
break;
}
if(out_size>0)
{
fwrite(inbuf,1,out_size,pFileWav);//pcm记录
fflush(pFileWav);
fileSize += out_size;
}
pktsize -= len;
pktdata += len;
}
}
av_free_packet(&packet);
}
//写头部信息
fseek(pFileWav,0,SEEK_SET);
RIFF_HEADER riffHeader;
memcpy(riffHeader.szRiffID,"RIFF",4);
riffHeader.dwRiffSize = fileSize - 8;
memcpy(riffHeader.szRiffFormat,"WAVE",4);
fwrite(&riffHeader,1,sizeof(riffHeader),pFileWav);
WAVE_FORMAT waveFormat;
memcpy(waveFormat.szWaveID,"fmt ",4);
waveFormat.wFSize = 0x10;
waveFormat.wFormatTag = 1 ; //pcm
waveFormat.wChannels = pCodecCtx->channels;
waveFormat.dwSamplesPerSec = pCodecCtx->sample_rate;
waveFormat.wBlockAlign = pCodecCtx->bits_per_sample/8 * waveFormat.wChannels;//(多个声道)每个采样的字节数,
waveFormat.dwAvgBytesPerSec = waveFormat.dwSamplesPerSec*waveFormat.wBlockAlign; // 每秒钟的字节数
waveFormat.wBitsPerSample = pCodecCtx->bits_per_sample; //一个声道每个采样的bit数
fwrite(&waveFormat,1,sizeof(waveFormat),pFileWav);
DATA_BLOCK dataBlock;
memcpy(dataBlock.szDataID,"data",4);
dataBlock.dwDataSize = fileSize - 44;
fwrite(&dataBlock,1,sizeof(dataBlock),pFileWav);
avcodec_close(pCodecCtx);
av_close_input_file(pFormatCtx);
return 0;
}