使用SDKv3实现音频文件格式转换
From Ffmpeg工程组
经过测试,MP3-〉MP2/MP3等没有问题,但是转换成WAV转换成功了,播放起来音乐不正常,有拖沓感。 源码如下:(VS2003编译通过,新建一个空的控制台工程,把这个CPP添加进去就可以)
// AVConvert.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#ifdef __cplusplus
extern "C"
{
#include "avcodec.h"
#include "avformat.h"
#include "avutil.h"
}
#endif //__cplusplus
#include <windows.h>
#include <excpt.h>
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
void SafeFreeCodecContext(AVCodecContext *pCodecCtx)
{
__try
{
if (pCodecCtx!=NULL)
avcodec_close(pCodecCtx);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// if file is rmvb, avcodec_close will raise error from internal~
return;
}
}
int Safe_av_find_stream_info(AVFormatContext * pFormatCtx)
{
__try
{
return av_find_stream_info(pFormatCtx);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// if file is corrupted, av_find_stream_info will raise devide zero error from internal~
return -1;
}
}
void SaveCloseFormatContext(AVFormatContext * pFormatCtx)
{
__try
{
if (pFormatCtx!=NULL)
av_close_input_file(pFormatCtx);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// if file is mov, av_close_input_file will raise error from internal~
return;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
if (argc<2)
{
printf("AVConvert.exe inputfile outputfile");
return -1;
}
av_register_all();
const char * infile = argv[1];
const char * outfile = argv[2];
AVFormatContext *pInFmtCtx=NULL;
if (av_open_input_file(&pInFmtCtx, infile, NULL, 0, NULL)!=0)
{
printf("av_open_input_file failed.\n");
return 1; // Couldn't open file
}
if (pInFmtCtx==NULL)
{
printf("av_open_input_file OK, but FormatContext==NULL");
return 1; // Couldn't open file
}
if(Safe_av_find_stream_info(pInFmtCtx)<0)
{
printf("av_find_stream_info failed.");
return 2; // Couldn't find stream
}
unsigned int i, audioStream;
// Find the first audio stream
audioStream = -1;
for(i=0; i<pInFmtCtx->nb_streams; i++)
if(pInFmtCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
{
audioStream=i;
break;
}
if(audioStream==-1)
{
printf("input file has no audio stream");
return 3; // Didn't find a audio stream
}
AVCodecContext *pInCodecCtx=NULL;
// Get a pointer to the codec context for the audio stream
pInCodecCtx = pInFmtCtx->streams[audioStream]->codec;
AVCodec *pInCodec=NULL;
// Find the decoder for the audio stream
pInCodec = avcodec_find_decoder(pInCodecCtx->codec_id);
if(pInCodec==NULL)
{
printf("no Decoder found");
return 4; // Codec not found
}
// Inform the codec that we can handle truncated bitstreams -- i.e.,
// bitstreams where frame boundaries can fall in the middle of packets
//if(pInCodec->capabilities & CODEC_CAP_TRUNCATED)
// pInCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
// Open codec
if(avcodec_open(pInCodecCtx, pInCodec)<0)
{
printf("avcodec_open failed.");
return 5; // Could not open codec
}
AVOutputFormat * oFormat = guess_format(NULL,outfile,NULL);
if (oFormat==NULL)
{
printf("not found output file format");
return 6;
}
AVFormatContext * oFmtCtx = av_alloc_format_context();
if (oFmtCtx==NULL)
{
printf("av_alloc_format_context failed");
return 7;
}
oFmtCtx->oformat = oFormat;
AVStream * oStream = av_new_stream(oFmtCtx,0);
AVCodecContext * oCodecCtx = oStream->codec;
oCodecCtx->codec_id = oFmtCtx->oformat->audio_codec;
oCodecCtx->codec_type = CODEC_TYPE_AUDIO;
oCodecCtx->sample_rate = pInFmtCtx->streams[audioStream]->codec->sample_rate;
oCodecCtx->bit_rate = pInFmtCtx->streams[audioStream]->codec->bit_rate;
oCodecCtx->channels = pInFmtCtx->streams[audioStream]->codec->channels;
AVCodec * pOutCodec = avcodec_find_encoder(oStream->codec->codec_id);
// Open codec
if(avcodec_open(oCodecCtx, pOutCodec)<0)
{
printf("avcodec_open failed.");
return 5; // Could not open codec
}
if (av_set_parameters(oFmtCtx, NULL) < 0)
{
printf("Invalid output format parameters\n");
return 8;
}
dump_format(oFmtCtx, 0, outfile, 1);
dump_format(pInFmtCtx, 0, infile, 0);
if (!(oFormat->flags & AVFMT_NOFILE))
{
if (url_fopen(&oFmtCtx->pb, outfile, URL_WRONLY) < 0)
{
fprintf(stderr, "Could not open '%s'\n", outfile);
return 9;
}
}
av_write_header(oFmtCtx);
static AVPacket packet;
int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
uint8_t * inbuf = (uint8_t *)malloc(out_size);
uint8_t * pinbuf = NULL;
int ob_size = FF_MIN_BUFFER_SIZE;
uint8_t * outbuf = (uint8_t *)malloc(ob_size);
int inputSampleSize = pInCodecCtx->frame_size * 2 * pInCodecCtx->channels;//获取Sample大小
int outputSampleSize = oCodecCtx->frame_size * 2 * oCodecCtx->channels;//获取输出Sample大小
uint8_t * pktdata = NULL;
int pktsize = 0;
int len = 0;
av_init_packet(&packet);
while(av_read_frame(pInFmtCtx, &packet)>=0)
{
// Is this a packet from the audio stream?
if(packet.stream_index==audioStream)
{
pktdata = packet.data;
pktsize = packet.size;
while (pktsize>0)
{
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio2(pInCodecCtx,(short *)inbuf,&out_size,pktdata,pktsize);
if (len<0)
{
printf("Error while decoding.\n");
break;
}
if (out_size>0)
{
pinbuf = inbuf;
for (i=0;i<out_size;i+=inputSampleSize)
{
AVPacket pkt;
av_init_packet(&pkt);
ob_size = FF_MIN_BUFFER_SIZE;
pkt.size= avcodec_encode_audio(oCodecCtx, outbuf, ob_size, (short *)pinbuf);
pkt.pts= av_rescale_q(oCodecCtx->coded_frame->pts, oCodecCtx->time_base, oStream->time_base);
pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= oStream->index;
pkt.data= outbuf;
/* write the compressed frame in the media file */
if (av_write_frame(oFmtCtx, &pkt) != 0) {
printf("Error while writing audio frame\n");
break;
}
pinbuf += inputSampleSize;
}
}
pktsize -= len;
pktdata += len;
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
free(inbuf);
free(outbuf);
av_write_trailer(oFmtCtx);
//avcodec_close(oStream->codec);//why error here?!
// free the streams
for(i = 0; i < oFmtCtx->nb_streams; i++) {
av_freep(&oFmtCtx->streams[i]->codec);
av_freep(&oFmtCtx->streams[i]);
}
if (!(oFormat->flags & AVFMT_NOFILE)) {
// close the output file
url_fclose(&oFmtCtx->pb);
}
// free the stream
av_free(oFmtCtx);
SafeFreeCodecContext(pInCodecCtx);
SaveCloseFormatContext(pInFmtCtx);
printf("Convert Action is OK!\n");
getchar();
return 0;
}
有关该问题的讨论帖可参考ffmpeg工程组论坛中的相关讨论:
有关使用SDKv3实现音频文件格式转换的讨论
