很难很难! 前后搞了一个月有于。。。。
目的:从一个avi转码到mp4,avi(视频编码器:mpeg4,音频编码:mpeg2 Audio,),mp4(视频编码器:h264/avc,音频编码器:mpeg2 Audio)
结果,基本可以了,视频还有一点问题,音频可以了!这里先贴代码在这里,接下来再慢慢完善吧,音频肯定要重采样的,视频也是要重新缩放的。。。还有音视频的同步也木有做,等都做完了再来加注释吧。。。
int mp4Tomp4(char* srcname, char* destname )
{
LOGI("LOGI----------------0");
input_file_name= srcname;
av_register_all();
AVFormatContext *ic = NULL;
LOGI("LOGI----------------02");
LOGI("LOGI----------------1 input_file %s",input_file_name);
// ic=av_alloc_format_context();
// avformat_alloc_output_context2(&ic, NULL, NULL, input_file_name);
if(avformat_open_input(&ic, input_file_name, NULL, NULL) < 0)
{
LOGI("can't open the file %s\n",input_file_name);
exit(1);
}
if(avformat_find_stream_info(ic,NULL)<0)
{
LOGI("can't find suitable codec parameters\n");
exit(1);
}
LOGI("LOGI----------------2");
// av_dump_format(ic,0,input_file_name,1);
int i;
int videoindex=-1;int audioindex=-1;
for(i=0;inb_streams;i++)
{
if(ic->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
{
videoindex=i;
LOGI("video %d\n",videoindex);
}
else if(ic->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
{
audioindex=i;
LOGI("audio %d\n",audioindex);
}
}
LOGI("LOGI----------------3");
if(videoindex==-1)
{
LOGI("can't find video stream\n");
exit(1);
}
AVCodecContext *vCodecCtx;
vCodecCtx=ic->streams[videoindex]->codec;
AVCodec *vCodec;
vCodec=avcodec_find_decoder(vCodecCtx->codec_id);
if(vCodec==NULL)
{
LOGI("can't find suitable video decoder\n");
exit(1);
}//�ҵ����ʵ���Ƶ������
if(avcodec_open2(vCodecCtx,vCodec,NULL)<0)
{
LOGI("can't open the video decoder\n");
exit(1);
}//�
LOGI("LOGI----------------4,%d",vCodecCtx->codec_id);
if(audioindex==-1)
{
LOGI("can't find audio stream\n");
// exit(1);
}
AVCodecContext *aCodecCtx;
aCodecCtx=ic->streams[audioindex]->codec;
AVCodec *aCodec;
aCodec=avcodec_find_decoder(aCodecCtx->codec_id);
if(aCodec==NULL)
{
LOGI("can't find suitable audio decoder\n");
exit(1);
}
if(avcodec_open2(aCodecCtx,aCodec,NULL)<0)
{
LOGI("can't open the audio decoder\n");
exit(1);
}
LOGI("LOGI----------------5 output file");
const char *output_file_name= destname;
AVOutputFormat *fmt;
AVFormatContext *oc;
AVCodecContext *oVcc,*oAcc;
AVCodec *oVc,*oAc;
AVStream *video_st,*audio_st;
AVFrame *oVFrame = NULL,*oAFrame = NULL;
oVFrame=avcodec_alloc_frame();
oAFrame=avcodec_alloc_frame();
// fmt=av_guess_format(NULL,output_file_name,NULL);
// if(!fmt)
// {
// printf("could not deduce output format from outfile extension\n");
// exit(0);
// }
// oc=av_alloc_format_context();
LOGI("LOGI----------------6");
avformat_alloc_output_context2(&oc, NULL, NULL, output_file_name);
if(!oc)
{
LOGI("Memory error\n");
exit(0);
}
oc->oformat->video_codec = AV_CODEC_ID_H264;
oc->oformat->audio_codec = aCodecCtx->codec_id;
fmt=oc->oformat;
video_st = NULL;
audio_st = NULL;
pstrcpy(oc->filename,sizeof(oc->filename),output_file_name);
LOGI("LOGI----------------7");
video_st=avformat_new_stream(oc,NULL);
if(!video_st)
{
LOGI("could not alloc video stream\n");
exit(0);
}
// oVcc=avcodec_alloc_context3(video_st->codec);
LOGI("===============%d",vCodecCtx->pix_fmt);
oVcc=video_st->codec;
oVc = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!oVc) {
LOGI("1111codec not found\n");
exit(1);
}
avcodec_get_context_defaults3(oVcc,oVc);// do what
oVcc->codec_id=AV_CODEC_ID_H264;
oVcc->codec_type=AVMEDIA_TYPE_VIDEO;
//固定码率控制
oVcc->bit_rate=12000;
// oVcc->bit_rate_tolerance=200000;
oVcc->rc_min_rate =12000;//设置最小视频码率容忍度
oVcc->rc_max_rate = 12000;//设置最大视频码率容忍度
oVcc->bit_rate_tolerance = 12000;
oVcc->rc_buffer_size=12000;//设置码率控制缓冲区大小
oVcc->rc_initial_buffer_occupancy = oVcc->rc_buffer_size*3/4;
oVcc->rc_buffer_aggressivity= ( float )1.0;
oVcc->rc_initial_cplx= 0.5;
oVcc->qcompress =0;//视频量化标度压缩(VBR)
oVcc->qmin = 10;//最小视频量化标度(VBR) 就是采样的比例吧??
oVcc->qmax = 50;//最大视频量化标度(VBR)
// oVcc->global_quality = 10;
//-qscale q 使用固定的视频量化标度(VBR)
//可变码率控制
// oVcc->flags |= CODEC_FLAG_QSCALE;
// oVcc->rc_min_rate =100000;
// oVcc->rc_max_rate = 200000;
// oVcc->bit_rate = 150000;
oVcc->width=320;
oVcc->height=240;
oVcc->time_base.den = 25;
oVcc->time_base.num = 1;
// oVcc->time_base=vCodecCtx->time_base;
oVcc->gop_size=10;//该值表示每10帧会插入一个I帧(intra frame)
//oVcc->pix_fmt=vCodecCtx->pix_fmt;
oVcc->pix_fmt=vCodecCtx->pix_fmt;
oVcc->max_b_frames=vCodecCtx->max_b_frames;
video_st->r_frame_rate=ic->streams[videoindex]->r_frame_rate;// frame rate
// audio_st=av_new_stream(oc,oc->nb_streams); //
LOGI("LOGI----------------8 %d",oVcc->codec_id);
if(! strcmp( oc-> oformat-> name, "mp4" ) || !strcmp (oc ->oformat ->name , "mov" ) || !strcmp (oc ->oformat ->name , "3gp" ))
oVcc->flags |= CODEC_FLAG_GLOBAL_HEADER ;
audio_st=avformat_new_stream(oc,NULL);
if(!audio_st)
{
LOGI("could not alloc audio stream\n");
exit(0);
}
// audio_st->id=1;
oAcc=avcodec_alloc_context3(aCodecCtx->codec);
LOGI("LOGI----------------9.6");
oAcc=audio_st->codec;
oAc = avcodec_find_encoder(aCodecCtx->codec_id);
if (!oAc) {
LOGI("1111codec not found\n");
exit(1);
}
avcodec_get_context_defaults3(oAcc,oAc);
ReSampleContext *rsc = NULL;
oAcc->codec_id=aCodecCtx->codec_id;
oAcc->codec_type=AVMEDIA_TYPE_AUDIO;
oAcc->bit_rate=aCodecCtx->bit_rate;// bit rate
oAcc->sample_rate=aCodecCtx->sample_rate;
oAcc->sample_fmt = AV_SAMPLE_FMT_S16;
oAcc->channels = 1;
oAcc->frame_size = aCodecCtx->frame_size;
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
oAcc->flags |= CODEC_FLAG_GLOBAL_HEADER;
LOGI("LOGI----------------81 %d",oAcc->sample_rate);
if(! strcmp( oc-> oformat-> name, "mp4" ) || !strcmp (oc ->oformat ->name , "mov" ) || !strcmp (oc ->oformat ->name , "3gp" ))
oAcc->flags |= CODEC_FLAG_GLOBAL_HEADER ;
av_dump_format(oc,0,output_file_name,1);
oVc=avcodec_find_encoder(oVcc->codec_id);
if(!oVc)
{
LOGI("can't find suitable video encoder\n");
exit(0);
}
int rett = 0;
if((rett =avcodec_open2(oVcc,oVc,NULL))<0)
{
LOGI("can't open the output video codec %d", rett);
exit(0);
}
oAc=avcodec_find_encoder(aCodecCtx->codec_id);
if(!oAc)
{
LOGI("can't find suitable audio encoder\n");
exit(0);
}
if(avcodec_open2(oAcc,oAc,NULL)<0)
{
LOGI("can't open the output audio codec11");
exit(0);
}
/*if(url_exist(output_file_name))
{
printf("the output file name %s has exist,please select other\n",output_file_name);
exit(0);
}*/
if (!(oc->flags & AVFMT_NOFILE))
{
if (avio_open(&oc->pb, output_file_name, AVIO_FLAG_WRITE) < 0) {
LOGI("Could not open '%s'\n", output_file_name);
return 1;
}
}
if(!oc->nb_streams)
{
LOGI("output file dose not contain any stream\n");
exit(0);
}
LOGI("LOGI----------------11");
if(avformat_write_header(oc,NULL)<0)
{
LOGI("Could not write header for output file\n");
exit(1);
}
LOGI("LOGI----------------12 hebing");
AVPacket packet;
uint8_t *ptr,*out_buf;
int out_size;
int16_t *samples=NULL,resample_buffer = NULL;
static unsigned int samples_size=0;
uint8_t *video_outbuf,*audio_outbuf;
int video_outbuf_size,audio_outbuf_size;
video_outbuf_size=100000;
video_outbuf= (unsigned char *) malloc(video_outbuf_size);
audio_outbuf_size = 10000;
//audio_outbuf = av_malloc(audio_outbuf_size);
audio_outbuf = (unsigned char *) malloc(audio_outbuf_size);
int flag;int frameFinished,frameFinished2;int len;int frame_index=0,ret,ret1; int got_output=0;
LOGI("LOGI----------------13 ");
FILE* f;
f = fopen("video/11111111.aac", "wb");
AVFifoBuffer *fifo;
fifo= av_fifo_alloc(1024);
if(!fifo)
return -1;
// oAFrame->nb_samples = oAcc->frame_size;
// oAFrame->format = oAcc->sample_fmt;
// oAFrame->channel_layout = oAcc->channel_layout;
while(av_read_frame(ic,&packet)>=0)
{
if(packet.stream_index==videoindex)
{
LOGI("LOGI----------------14.4 ");
len=avcodec_decode_video2(vCodecCtx,oVFrame,&frameFinished,&packet);
LOGI("%d",len);
if(len<0)
{
LOGI("Error while decoding\n");
exit(0);
}
if(frameFinished)
{
fflush(stdout);
//
oVFrame->pts=av_rescale(frame_index,AV_TIME_BASE*(int64_t)oVcc->time_base.num,oVcc->time_base.den);
oVFrame->pict_type=AV_PICTURE_TYPE_NONE;
out_size = avcodec_encode_video(oVcc, video_outbuf, video_outbuf_size, oVFrame);
if (out_size > 0)
{
AVPacket pkt;
av_init_packet(&pkt);//执行此语句后pkt的pts和dts都设为no了
if(oVcc->coded_frame && oVcc->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.flags = packet.flags;
pkt.stream_index= video_st->index;
pkt.data= video_outbuf;
pkt.size= out_size;
ret=av_write_frame(oc, &pkt);
// ret=av_interleaved_write_frame(oc,&packet);
LOGI("%d----111111----%d----",packet.size,pkt.size);
}
frame_index++;
}
else
{
LOGI("LOGI----------------16 ");
LOGI(".....\n");
}
#if 0
if(ret!=0)
{
LOGI("while write video frame error\n");
// exit(0);
}
#endif
} else if (packet.stream_index == audioindex) {
LOGI("LOGI----------------17, %d ", audioindex);
int ret = 0;
while (packet.size > 0) {
LOGI("LOGI----------------18 ");
out_buf = NULL;
if (packet.size > 0)
samples = (short *) av_fast_realloc(samples, &samples_size,
FFMAX(packet.size*sizeof
(*samples),2000)); //AVCODEC_MAX_AUDIO_FRAME_SIZE=
LOGI("LOGI----------------19 ");
ret = avcodec_decode_audio4(aCodecCtx, oAFrame, &frameFinished2,
&packet);
// ret = avcodec_decode_audio3(aCodecCtx,samples,&out_size,&packet);//若为音频包,解码该音频包
LOGI("retretret:%d", ret);
if (ret < 0) {
LOGI("while decode audio failure\n");
exit(0);
}
packet.data += ret;
packet.size -= ret;
av_fifo_generic_write(fifo,oAFrame->data[0],oAFrame->linesize[0],NULL);
if (frameFinished2) {
// LOGI("----------lddfd,%d",fwrite(oAFrame->data[0], oAFrame->linesize[0], 1, pcm));
// fflush(pcm);
// int data_size = av_samples_get_buffer_size(NULL, aCodecCtx->channels,
// oAFrame->nb_samples,
// aCodecCtx->sample_fmt, 1);
// fwrite(oAFrame->data[0], 1, data_size/2, pcm);
// fflush(pcm);
LOGI("LOGI----------------20 ");
out_buf = (uint8_t *) samples;
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
ret1 = avcodec_encode_audio2(oAcc, &pkt, oAFrame,
&got_output);
if (ret1 < 0) {
fprintf(stderr, "Error encoding audio frame\n");
exit(1);
}
// pkt.size = avcodec_encode_audio(oAcc, audio_outbuf, audio_outbuf_size, (short int*)samples);
if (got_output) {
LOGI("dfd,");
// fwrite(pkt.data, 1, pkt.size, f);//fwrite(pkt.data, 1, pkt.size, f);不用av_interleaved_write_frame,直接写入aac文件就可以播放,说明解码没有问题!
// pkt.dts = AV_NOPTS_VALUE;
if (oAcc->coded_frame&& oAcc->coded_frame->pts != AV_NOPTS_VALUE) {
pkt.pts= av_rescale_q(oAcc->coded_frame->pts, oAcc->time_base, audio_st->time_base);
}
LOGI("===========================");
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = audio_st->index;
LOGI("=====-=-=-=----=-=-=-=-=-=-=-");
av_write_frame(oc, &pkt);
av_free_packet(&pkt);
}
}
/** 采样,但是不对
ReSampleContext *rsc = NULL;
rsc = av_audio_resample_init(
oAcc->channels, aCodecCtx->channels,
oAcc->sample_rate, aCodecCtx->sample_rate,
oAcc->sample_fmt, aCodecCtx->sample_fmt,
16, 10, 0, 0.8);
AVFifoBuffer *iofifo;
iofifo = av_fifo_alloc(192000*2);
int bs;
bs = audio_resample(rsc, (short *)resample_buffer, samples,
out_size/(aCodecCtx->channels*2));
ret = av_fifo_generic_write(iofifo, (uint8_t *)resample_buffer,
bs*oAcc->channels*2, NULL);
audio_outbuf_size = oAcc->frame_size * 2 * oAcc->channels;
while( av_fifo_size(iofifo) >= audio_outbuf_size )
{
ret = av_fifo_generic_read(iofifo, out_buf, audio_outbuf_size, NULL);
ret = avcodec_encode_audio(oAcc, audio_outbuf,audio_outbuf_size, (short *)out_buf);
pkt.size = ret;
pkt.stream_index= audioindex;
pkt.data= audio_outbuf;
ret = av_write_frame(oc, &pkt);
}
}**/
}
}
LOGI("----------while");
av_free_packet(&packet);
}
LOGI("LOGI----------------18 ");
av_write_trailer(oc);
LOGI("LOGI----------------end ");
for(i = 0; i < oc->nb_streams; i++)
{
av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]);
}
LOGI("LOGI----------------end 1");
//url_fclose(oc);
av_free(oc);
av_free(oVFrame);
//av_free(out_buf);
LOGI("LOGI----------------end 2");
avcodec_close(vCodecCtx);
avcodec_close(aCodecCtx);
avformat_close_input(&ic);
LOGI("LOGI----------------end 3");
return 1;
}