求助利用ffmpeg抽取mp4中音频并保存为wav格式
MP4文件大小19M,抽取后的音频文件大小为130M,还有噪音,时间也被拉长了,请问这是怎么回事?
代码如下:
#include <windows.h>
#include <iostream>
using namespace std;
extern "C"
{
#include "libavcodec\avcodec.h"
#include "libavformat\avformat.h"
}
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avcodec.lib")
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
struct RIFF_HEADER
{
char szRiffID[4];
DWORD dwRiffSize;
char szRiffFormat[4];
};
struct FMT_BLOCK
{
char szFmtID[4];
DWORD dwFmtSize;
WORD wFormatTag;
WORD wChannels;
DWORD dwSamplesPerSec;
DWORD dwAvgBytesPerSec;
WORD wBlockAlign;
WORD wBitsPerSample;
};
struct DATA_BLOCK
{
char szDataID[4];
DWORD dwDataSize;
};
int main()
{
AVFormatContext* pFormatCtx = NULL;
AVCodecContext* pCodecCtx;
AVCodec* pCodec = NULL;
AVPacket packet;
int AudioStream = -1;
char* SrcFile = "test.mp3";
av_register_all();
if(avformat_open_input(&pFormatCtx, SrcFile, NULL, NULL) != 0)
{
cout << "Cannot open source file!" << endl;
return -1;
}
if(av_find_stream_info(pFormatCtx) < 0)
{
cout << "Cannot find stream info!" << endl;
return -1;
}
av_dump_format(pFormatCtx, 0, SrcFile, false);
for(int i = 0; i < pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
AudioStream = i;
break;
}
}
if(AudioStream == -1)
{
cout << "Cannot find a audio stream!" << endl;
return -1;
}
pCodecCtx = pFormatCtx->streams[AudioStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec == NULL)
{
cout << "Cannot find codec!" << endl;
return -1;
}
if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
cout << "Cannot open codec!" << endl;
return -1;
}
uint8_t* pktData;
int pktSize, outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
uint8_t* inBuf = (uint8_t*)malloc(outSize);
FILE* pWavFile;
pWavFile = fopen("r.wav", "wb");
while(av_read_frame(pFormatCtx, &packet) >= 0)
{
if(packet.stream_index == AudioStream)
{
pktData = packet.data;
pktSize = packet.size;
while(pktSize > 0)
{
outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
int len = avcodec_decode_audio3(pCodecCtx, (int16_t*)inBuf, &outSize, &packet);
if(len < 0)
{
cout << "Error while decoding!" << endl;
break;
}
if(outSize > 0)
{
fwrite(inBuf, 1, outSize, pWavFile);
fflush(pWavFile);
}
pktSize -= len;
//pktData += len;
}
}
av_free_packet(&packet);
}
free(inBuf);
fseek(pWavFile, 0, SEEK_SET);
int bits;
switch(pCodecCtx->sample_fmt)
{
case AV_SAMPLE_FMT_S16:
bits = 16; break;
case AV_SAMPLE_FMT_S32:
bits = 32; break;
case AV_SAMPLE_FMT_U8:
bits = 8; break;
default:
bits = 16; break;
}
printf("bits:%d sample_rate:%d channels:%d sample_fmt:%d\n", bits, pCodecCtx->sample_rate, pCodecCtx->channels, pCodecCtx->sample_fmt);
RIFF_HEADER riffHeader;
memcpy(riffHeader.szRiffID, "RIFF", 4);
riffHeader.dwRiffSize = pFormatCtx->duration * (bits / 8) * pCodecCtx->sample_rate * pCodecCtx->channels + 36;
memcpy(riffHeader.szRiffFormat, "WAVE", 4);
fwrite(&riffHeader, 1, sizeof(riffHeader), pWavFile);
FMT_BLOCK fmtBlock;
memcpy(fmtBlock.szFmtID, "fmt ", 4);
fmtBlock.dwFmtSize = 0x10;
fmtBlock.wFormatTag = 0x01;
fmtBlock.wChannels = pCodecCtx->channels;
fmtBlock.dwSamplesPerSec = pCodecCtx->sample_rate;
fmtBlock.dwAvgBytesPerSec = (bits / 8) * pCodecCtx->sample_rate * pCodecCtx->channels;
fmtBlock.wBlockAlign = (bits / 8) * pCodecCtx->channels;
fmtBlock.wBitsPerSample = bits;
fwrite(&fmtBlock, 1, sizeof(fmtBlock), pWavFile);
DATA_BLOCK dataBlock;
memcpy(dataBlock.szDataID, "data", 4);
dataBlock.dwDataSize = (bits / 8) * pFormatCtx->duration * pCodecCtx->sample_rate * pCodecCtx->channels;
fwrite(&dataBlock, 1, sizeof(dataBlock), pWavFile);
fflush(pWavFile);
fseek(pWavFile, 44, SEEK_SET);
fclose(pWavFile);
avcodec_close(pCodecCtx);
av_close_input_file(pFormatCtx);
cout << "Success!" << endl;
cin.get();
return 0;
}