zoukankan      html  css  js  c++  java
  • FFMPEG_avi转码到mp4(aac+h264)源码

    #include <ffmpeg/avcodec.h>
    #include <ffmpeg/avformat.h>
    #include <stdio.h>
    #include <ffmpeg/avutil.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    void pstrcpy(char *buf, int buf_size, const char *str)
    {
        int c;//why int here
        char *q = buf;
     
        if (buf_size <= 0)
            return;
     
        for(;;) {
            c = *str++;
            if (c == 0 || q >= buf + buf_size - 1)
                break;
            *q++ = c;
        }
        *q = '';
    }
    main(int argc,char **argv)
    {   
      const char *input_file_name="/home/movie.avi";
      av_register_all();//注册库中所有可用的文件格式和编码器
      AVFormatContext *ic;
      //输入文件处理部分
      ic=av_alloc_format_context();
      if(av_open_input_file(&ic,input_file_name,NULL,0,NULL)!=0)
      {
         printf("can't open the file %s ",input_file_name);
         exit(1);
      }//打开输入文件  
      if(av_find_stream_info(ic)<0)
      {
         printf("can't find suitable codec parameters ");
         exit(1);
      }//取出流信息
       
      dump_format(ic,0,input_file_name,0);//列出输入文件的相关流信息
      int i;
      int videoindex=-1;int audioindex=-1;
      for(i=0;i<ic->nb_streams;i++)
      {   
         if(ic->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
             {
                videoindex=i;
              //printf("video ");
             }
             else if(ic->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
             {
              //printf("audio ");
                audioindex=i;
             }
      }
       if(videoindex==-1)
       {
              printf("can't find video stream ");
              exit(1);
       }//没有找到视频流
        
        
      AVCodecContext *vCodecCtx;
      vCodecCtx=ic->streams[videoindex]->codec;//取得视频流编码上下文指针
      AVCodec *vCodec;
      vCodec=avcodec_find_decoder(vCodecCtx->codec_id);
      if(vCodec==NULL)
      {
         printf("can't find suitable video decoder ");
         exit(1);
      }//找到合适的视频解码器
      if(avcodec_open(vCodecCtx,vCodec)<0)
      {
         printf("can't open the video decoder ");
         exit(1);
      }//打开该视频解码器
       
       
       if(audioindex==-1)
         {
            printf("can't find audio stream ");
            exit(1);
         }//没有找到音频流
      AVCodecContext *aCodecCtx;
      aCodecCtx=ic->streams[audioindex]->codec;
      AVCodec *aCodec;
      aCodec=avcodec_find_decoder(aCodecCtx->codec_id);
      if(aCodec==NULL)
      {
         printf("can't find suitable audio decoder ");
         exit(1);
      }//找到合适的音频解码器
      if(avcodec_open(aCodecCtx,aCodec)<0)
      {
         printf("can't open the audio decoder ");
         exit(1);
      }//打开该音频解码器
       
       
    //下面为输出文件处理部分
        const char *output_file_name="/home/result.aac";
        AVOutputFormat *fmt;
        AVFormatContext *oc;
        AVCodecContext *oVcc,*oAcc;
        AVCodec *oVc,*oAc;
        AVStream *video_st,*audio_st;
        AVFrame *oVFrame,*oAFrame;
        double video_pts;
        oVFrame=avcodec_alloc_frame();
        fmt=guess_format(NULL,output_file_name,NULL);
        if(!fmt)
        {
               printf("could not deduce output format from outfile extension ");
               exit(0);
        }//判断是否可以判断输出文件的编码格式
        oc=av_alloc_format_context();
        if(!oc)
        {
               printf("Memory error ");
               exit(0);
        }
        oc->oformat=fmt;
       pstrcpy(oc->filename,sizeof(oc->filename),output_file_name);
       
        video_st=av_new_stream(oc,0);
        if(!video_st)
        {
              printf("could not alloc video stream ");
              exit(0);
        }
        oVcc=avcodec_alloc_context();
        oVcc=video_st->codec;
        oVcc->codec_id=CODEC_ID_H264;
        oVcc->codec_type=CODEC_TYPE_VIDEO;
        oVcc->bit_rate=1000000;
        oVcc->width=320;
        oVcc->height=240;
        oVcc->time_base=vCodecCtx->time_base;
        oVcc->gop_size=vCodecCtx->gop_size;
        //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);   //
        audio_st=av_new_stream(oc,1);
        if(!audio_st)
        {
               printf("could not alloc audio stream ");
               exit(0);
        }  
       // avcodec_get_context_defaults2(audio_st->codec,CODEC_TYPE_AUDIO);
       avcodec_get_context_defaults(audio_st->codec);//  do what
        oAcc=avcodec_alloc_context();
        oAcc=audio_st->codec;
        oAcc->codec_id=CODEC_ID_AAC;
        oAcc->codec_type=CODEC_TYPE_AUDIO;
        oAcc->bit_rate=aCodecCtx->bit_rate;// bit rate
        oAcc->sample_rate=aCodecCtx->sample_rate;
        oAcc->channels=2;
        if (av_set_parameters(oc, NULL) < 0)
        {
               printf( "Invalid output format parameters ");                        
                  exit(0);                              
        }//设置必要的输出参数
        strcpy(oc->title,ic->title);
        strcpy(oc->author,ic->author);
        strcpy(oc->copyright,ic->copyright);
        strcpy(oc->comment,ic->comment);
        strcpy(oc->album,ic->album);
        oc->year=ic->year;
        oc->track=ic->track;
        strcpy(oc->genre,ic->genre);
        dump_format(oc,0,output_file_name,1);//列出输出文件的相关流信息
        oVc=avcodec_find_encoder(CODEC_ID_H264);
        if(!oVc)
        {
           printf("can't find suitable video encoder ");
               exit(0);
        }//找到合适的视频编码器
        if(avcodec_open(oVcc,oVc)<0)
        {
               printf("can't open the output video codec ");
               exit(0);
        }//打开视频编码器
        oAc=avcodec_find_encoder(CODEC_ID_AAC);
        if(!oAc)
        {
               printf("can't find suitable audio encoder ");
               exit(0);
        }//找到合适的音频编码器
        if(avcodec_open(oAcc,oAc)<0)
        {
               printf("can't open the output audio codec");
               exit(0);
        }//打开音频编码器
        /*if(url_exist(output_file_name))
        {
           printf("the output file name %s has exist,please select other ",output_file_name);
           exit(0);
        }//判断该输出文件是否已经存在*/
        if (!(oc->flags & AVFMT_NOFILE))
        {
           if(url_fopen(&oc->pb,output_file_name,URL_WRONLY)<0)
           {
                  printf("can't open the output file %s ",output_file_name);
                  exit(0);
           }//打开输出文件
        }
        if(!oc->nb_streams)
        {
               fprintf(stderr,"output file dose not contain any stream ");
               exit(0);
        }//查看输出文件是否含有流信息
      if(av_write_header(oc)<0)
      {
          fprintf(stderr, "Could not write header for output file ");
          exit(1);
      }
       
    AVPacket packet;
      uint8_t *ptr,*out_buf;
      int out_size;
      static short *samples=NULL;
      static unsigned int samples_size=0;
      uint8_t *video_outbuf,*audio_outbuf;
      int video_outbuf_size,audio_outbuf_size;
      video_outbuf_size=400000;
      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;int len;int frame_index=0,ret;
              while(av_read_frame(ic,&packet)>=0)//从输入文件中读取一个包
           {
              if(packet.stream_index==videoindex)//判断是否为当前视频流中的包
              {
             len=avcodec_decode_video(vCodecCtx,oVFrame,&frameFinished,packet.data,packet.size);//若为视频包,解码该视频包
                     if(len<0)
                     {
                        printf("Error while decoding ");
                        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=0;
                 out_size = avcodec_encode_video(oVcc, video_outbuf, video_outbuf_size, oVFrame);   
                 if (out_size > 0)            
                 {                  
                     AVPacket pkt;               
                     av_init_packet(&pkt);                              
                     if(oVcc->coded_frame && oVcc->coded_frame->key_frame)                                       
                         pkt.flags |= 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);                                       
                 }
                 frame_index++;
             }
             else
                {
                  printf("..... ");                                       
                 }
                       #if 0
                       if(ret!=0)
                        {
                          printf("while write video frame error ");
                         // exit(0);
                        }
                        #endif
                       
              }else if(packet.stream_index==audioindex)
          {
             len=packet.size;
             ptr=packet.data;
                 int ret=0;
                 while(len>0)
                 {
                        out_buf=NULL;
                        out_size=0;
                        if(&packet)
                   samples=(short *)av_fast_realloc(samples,&samples_size,FFMAX(packet.size*sizeof
    (*samples),AVCODEC_MAX_AUDIO_FRAME_SIZE));
                        out_size=samples_size;
                        ret=avcodec_decode_audio(aCodecCtx,samples,&out_size,ptr,len);//若为音频包,解码该音频包
                        if(ret<0)
                        {
                           printf("while decode audio failure ");
                           exit(0);
                        }
                fflush(stdout);
                ptr+=ret;
                len-=ret;
                if(out_size<=0)
                   continue;
                out_buf=(uint8_t *)samples;
                AVPacket pkt;
                av_init_packet(&pkt);
                pkt.size= avcodec_encode_audio(oAcc, audio_outbuf, audio_outbuf_size, (short int*)out_buf);
                pkt.pts= av_rescale_q(oAcc->coded_frame->pts, oAcc->time_base, audio_st->time_base);
                pkt.flags |= PKT_FLAG_KEY;
                pkt.stream_index= audioindex;
                pkt.data= audio_outbuf;
                
              #if 1
                if (av_write_frame(oc, &pkt) != 0)
                        {
                   fprintf(stderr, "Error while writing audio frame ");
                   exit(1);
                    }
                  #endif  
                 }
              }
              av_free_packet(&packet);
           }
           
    av_write_trailer(oc);
     
    for(i = 0; i < oc->nb_streams; i++)
    {            
      av_freep(&oc->streams[i]->codec);                       
      av_freep(&oc->streams[i]);                           
    }
    //url_fclose(oc);
    av_free(oc);
    av_free(oVFrame);
    av_free(out_buf);
    avcodec_close(vCodecCtx);
    avcodec_close(aCodecCtx);
    av_close_input_file(ic);
     
    }

    来源:http://my.oschina.net/u/555701/blog/56744

  • 相关阅读:
    mysql双主配置
    nginx js、css多个请求合并为一个请求(concat模块)
    PHP中利用Redis管道加快执行
    总结最近游戏中活动出现被刷问题。
    问题记录--负载均衡的均衡器配置了高可用导致问题
    php的session获取不到问题之ie浏览器(yaf框架)
    Django URLs error: view must be a callable or a list/tuple in the case of include()
    在Sublime Text运行Python.How to run Python code from Sumblime Text
    JavaWeb项目自动化部署测试学习
    hadoop2.5.1+hbase1.1.2安装与配置
  • 原文地址:https://www.cnblogs.com/sunminmin/p/4512575.html
Copyright © 2011-2022 走看看