很难很难! 前后搞了一个月有于。。。。
目的:从一个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;i<ic->nb_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; }