ffmpeg转码(avi转mp4)

很难很难! 前后搞了一个月有于。。。。

目的:从一个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;
}



   

你可能感兴趣的:(ffmpeg)