FFmpeg音视频编解码实践总结

PS:由于目前开发RTSP服务器传输模块时用到了h264文件,所以攻了一段时间去实现h264的视频编解码,借用FFmpeg SDK实现了任意文件格式之间的转换,并实现了流媒体实时播放,目前音视频同步需要稍加完善,视频编码代码已成功移植到Visual Stdio平台。

以下文档来自FFmpeg工程组(http://www.ffmpeg.com.cn/index.php开发事例)

实现转码一个普通视频文件为视频mpeg4,音频mp3的功能的程序

本程序源引自FFmpeg工程组,实现转码一个普通视频文件为视频mpeg4,音频mp3的功能(如需更多示例源码可参阅bbs.anychat.cn)

 

  
  
  
  
  1. #include <avcodec.h> 
  2. #include <avformat.h> 
  3. #include <stdio.h> 
  4. #include <avutil.h> 
  5. #include <stdio.h> 
  6. #include <stdlib.h> 
  7. #include <string.h> 
  8. main(int argc,char **argv)  
  9. {     
  10.   const char *input_file_name="/root/movies/ddh1.mpg";  
  11.   av_register_all();//注册库中所有可用的文件格式和编码器  
  12.   AVFormatContext *ic;  
  13.   //输入文件处理部分  
  14.   ic=av_alloc_format_context();  
  15.   if(av_open_input_file(&ic,input_file_name,NULL,0,NULL)!=0)  
  16.   {  
  17.      printf("can't open the file %s\n",input_file_name);  
  18.      exit(1);  
  19.   }//打开输入文件  
  20.   if(av_find_stream_info(ic)<0)  
  21.   {  
  22.      printf("can't find suitable codec parameters\n");  
  23.      exit(1);  
  24.   }//取出流信息  
  25.   dump_format(ic,0,input_file_name,0);//列出输入文件的相关流信息  
  26.   int i;  
  27.   int videoindex=-1;int audioindex=-1;  
  28.   for(i=0;i<ic->nb_streams;i++)  
  29.   {      
  30.      if(ic->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)  
  31.          {  
  32.             videoindex=i;  
  33.           //printf("video\n");  
  34.          }  
  35.          else if(ic->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)  
  36.          {  
  37.           //printf("audio\n");  
  38.             audioindex=i;  
  39.          }  
  40.   }  
  41.    if(videoindex==-1)  
  42.    {  
  43.           printf("can't find video stream\n");  
  44.           exit(1);  
  45.    }//没有找到视频流  
  46.   AVCodecContext *vCodecCtx;  
  47.   vCodecCtx=ic->streams[videoindex]->codec;//取得视频流编码上下文指针  
  48.   AVCodec *vCodec;  
  49.   vCodec=avcodec_find_decoder(vCodecCtx->codec_id);  
  50.   if(vCodec==NULL)  
  51.   {  
  52.      printf("can't find suitable video decoder\n");  
  53.      exit(1);  
  54.   }//找到合适的视频解码器  
  55.   if(avcodec_open(vCodecCtx,vCodec)<0)  
  56.   {  
  57.      printf("can't open the video decoder\n");  
  58.      exit(1);  
  59.   }//打开该视频解码器  
  60.    if(audioindex==-1)  
  61.      {  
  62.         printf("can't find audio stream\n");  
  63.         exit(1);  
  64.      }//没有找到音频流  
  65.   AVCodecContext *aCodecCtx;  
  66.   aCodecCtx=ic->streams[audioindex]->codec;  
  67.   AVCodec *aCodec;  
  68.   aCodec=avcodec_find_decoder(aCodecCtx->codec_id);  
  69.   if(aCodec==NULL)  
  70.   {  
  71.      printf("can't find suitable audio decoder\n");  
  72.      exit(1);  
  73.   }//找到合适的音频解码器  
  74.   if(avcodec_open(aCodecCtx,aCodec)<0)  
  75.   {  
  76.      printf("can't open the audio decoder\n");  
  77.      exit(1);  
  78.   }//打开该音频解码器  
  79. //下面为输出文件处理部分  
  80.     const char *output_file_name="/root/123.avi";  
  81.     AVOutputFormat *fmt;  
  82.     AVFormatContext *oc;  
  83.     AVCodecContext *oVcc,*oAcc;  
  84.     AVCodec *oVc,*oAc;  
  85.     AVStream *video_st,*audio_st;  
  86.     AVFrame *oVFrame,*oAFrame;  
  87.     double video_pts;  
  88.     oVFrame=avcodec_alloc_frame();  
  89.     fmt=guess_format(NULL,output_file_name,NULL);  
  90.     if(!fmt)  
  91.     {  
  92.            printf("could not deduce output format from outfile extension\n");  
  93.            exit(0);  
  94.     }//判断是否可以判断输出文件的编码格式  
  95.     oc=av_alloc_format_context();  
  96.     if(!oc)  
  97.     {  
  98.            printf("Memory error\n");  
  99.            exit(0);  
  100.     }  
  101.     oc->oformat=fmt;  
  102.     pstrcpy(oc->filename,sizeof(oc->filename),output_file_name);  
  103.     video_st=av_new_stream(oc,0);  
  104.     if(!video_st)  
  105.     {  
  106.           printf("could not alloc video stream\n");  
  107.           exit(0);  
  108.     }  
  109.     oVcc=avcodec_alloc_context();  
  110.     oVcc=video_st->codec;  
  111.     oVcc->codec_id=CODEC_ID_MPEG4;  
  112.     oVcc->codec_type=CODEC_TYPE_VIDEO;  
  113.     oVcc->bit_rate=2500000;  
  114.     oVcc->width=704;  
  115.     oVcc->height=480;  
  116.     oVcc->time_base=vCodecCtx->time_base;  
  117.     oVcc->gop_size=vCodecCtx->gop_size;  
  118.     //oVcc->pix_fmt=vCodecCtx->pix_fmt;  
  119.     oVcc->pix_fmt=vCodecCtx->pix_fmt;  
  120.     oVcc->max_b_frames=vCodecCtx->max_b_frames;  
  121.     video_st->r_frame_rate=ic->streams[videoindex]->r_frame_rate;  
  122.     audio_st=av_new_stream(oc,oc->nb_streams);  
  123.     if(!audio_st)  
  124.     {  
  125.            printf("could not alloc audio stream\n");  
  126.            exit(0);  
  127.     }    
  128.     avcodec_get_context_defaults2(audio_st->codec,CODEC_TYPE_AUDIO);  
  129.     oAcc=avcodec_alloc_context();  
  130.     oAcc=audio_st->codec;  
  131.     oAcc->codec_id=CODEC_ID_MP3;  
  132.     oAcc->codec_type=CODEC_TYPE_AUDIO;  
  133.     oAcc->bit_rate=aCodecCtx->bit_rate;  
  134.     oAcc->sample_rate=aCodecCtx->sample_rate;  
  135.     oAcc->channels=2;  
  136.     if (av_set_parameters(oc, NULL) < 0)   
  137.     {  
  138.            printf( "Invalid output format parameters\n");                           
  139.               exit(0);                                 
  140.     }//设置必要的输出参数  
  141.     strcpy(oc->title,ic->title);  
  142.     strcpy(oc->author,ic->author);  
  143.     strcpy(oc->copyright,ic->copyright);  
  144.     strcpy(oc->comment,ic->comment);  
  145.     strcpy(oc->album,ic->album);  
  146.     oc->year=ic->year;  
  147.     oc->track=ic->track;  
  148.     strcpy(oc->genre,ic->genre);  
  149.     dump_format(oc,0,output_file_name,1);//列出输出文件的相关流信息  
  150.     oVc=avcodec_find_encoder(CODEC_ID_MPEG4);  
  151.     if(!oVc)  
  152.     {  
  153.        printf("can't find suitable video encoder\n");  
  154.            exit(0);  
  155.     }//找到合适的视频编码器  
  156.     if(avcodec_open(oVcc,oVc)<0)  
  157.     {  
  158.            printf("can't open the output video codec\n");  
  159.            exit(0);  
  160.     }//打开视频编码器  
  161.     oAc=avcodec_find_encoder(CODEC_ID_MP3);  
  162.     if(!oAc)  
  163.     {  
  164.            printf("can't find suitable audio encoder\n");  
  165.            exit(0);  
  166.     }//找到合适的音频编码器  
  167.     if(avcodec_open(oAcc,oAc)<0)  
  168.     {  
  169.            printf("can't open the output audio codec");  
  170.            exit(0);  
  171.     }//打开音频编码器  
  172.     /*if(url_exist(output_file_name))  
  173.     {  
  174.        printf("the output file name %s has exist,please select other\n",output_file_name);  
  175.        exit(0);  
  176.     }//判断该输出文件是否已经存在*/  
  177.     if (!(oc->flags & AVFMT_NOFILE))  
  178.     {  
  179.        if(url_fopen(&oc->pb,output_file_name,URL_WRONLY)<0)  
  180.        {  
  181.               printf("can't open the output file %s\n",output_file_name);  
  182.               exit(0);  
  183.        }//打开输出文件  
  184.     }  
  185.     if(!oc->nb_streams)  
  186.     {  
  187.            fprintf(stderr,"output file dose not contain any stream\n");  
  188.            exit(0);  
  189.     }//查看输出文件是否含有流信息  
  190.   if(av_write_header(oc)<0)  
  191.   {  
  192.       fprintf(stderr, "Could not write header for output file\n");  
  193.       exit(1);  
  194.   }[/i][/i]  
  195. AVPacket packet;  
  196.   uint8_t *ptr,*out_buf;  
  197.   int out_size;  
  198.   static short *samples=NULL;  
  199.   static unsigned int samples_size=0;  
  200.   uint8_t *video_outbuf,*audio_outbuf;int video_outbuf_size,audio_outbuf_size;  
  201.   video_outbuf_size=400000;  
  202.   video_outbuf= (unsigned char *) malloc(video_outbuf_size);  
  203.   audio_outbuf_size = 10000;  
  204.   audio_outbuf = av_malloc(audio_outbuf_size);  
  205.   int flag;int frameFinished;int len;int frame_index=0,ret;  
  206.           while(av_read_frame(ic,&packet)>=0)//从输入文件中读取一个包  
  207.        {  
  208.           if(packet.stream_index==videoindex)//判断是否为当前视频流中的包  
  209.           {  
  210.          len=avcodec_decode_video(vCodecCtx,oVFrame,&frameFinished,packet.data,packet.size);//若为视频包,解码该视频包  
  211.                  if(len<0)  
  212.                  {  
  213.                     printf("Error while decoding\n");  
  214.                     exit(0);  
  215.                  }  
  216.          if(frameFinished)//判断视频祯是否读完  
  217.          {  
  218.              fflush(stdout);  
  219.              oVFrame->pts=av_rescale(frame_index,AV_TIME_BASE*(int64_t)oVcc->time_base.num,oVcc->time_base.den);  
  220.              oVFrame->pict_type=0;  
  221.              out_size = avcodec_encode_video(oVcc, video_outbuf, video_outbuf_size, oVFrame);     
  222.              if (out_size > 0)              
  223.              {                     
  224.                  AVPacket pkt;                 
  225.                  av_init_packet(&pkt);                                 
  226.                  if(oVcc->coded_frame && oVcc->coded_frame->key_frame)                                         
  227.                      pkt.flags |= PKT_FLAG_KEY;                                          
  228.                      pkt.flags = packet.flags;                        
  229.                      pkt.stream_indexvideo_st->index;                                                 
  230.                      pkt.datavideo_outbuf;                                                           
  231.                      pkt.sizeout_size;                                               
  232.                      ret=av_write_frame(oc, &pkt);                                         
  233.              }  
  234.              frame_index++;  
  235.          }  
  236.          else  
  237.              ret=av_write_frame(oc, &packet);   
  238.                     //img_convert((AVPicture *)vFrame, PIX_FMT_RGB24, (AVPicture*)oVFrame, oVcc->pix_fmt,oVcc->width,oVcc-  
  239. >height);  
  240.             //SaveFrame(vFrame,oVcc->width,oVcc->height,frame_index);   
  241.                     if(ret!=0)  
  242.                     {  
  243.                       printf("while write video frame error\n");  
  244.                       exit(0);  
  245.                     }  
  246.           }  
  247.           else if(packet.stream_index==audioindex)  
  248.       {  
  249.          len=packet.size;  
  250.          ptr=packet.data;  
  251.              int ret=0;  
  252.              while(len>0)  
  253.              {  
  254.                     out_buf=NULL;  
  255.                     out_size=0;  
  256.                     if(&packet)  
  257.                samples=av_fast_realloc(samples,&samples_size,FFMAX(packet.size*sizeof  
  258. (*samples),AVCODEC_MAX_AUDIO_FRAME_SIZE));  
  259.                     out_size=samples_size;  
  260.                     ret=avcodec_decode_audio(aCodecCtx,samples,&out_size,ptr,len);//若为音频包,解码该音频包  
  261.                     if(ret<0)  
  262.                     {  
  263.                        printf("while decode audio failure\n");  
  264.                        exit(0);  
  265.                     }  
  266.             fflush(stdout);  
  267.             ptr+=ret;  
  268.             len-=ret;  
  269.             if(out_size<=0)  
  270.                continue;  
  271.             out_buf=(uint8_t *)samples;  
  272.             AVPacket pkt;  
  273.             av_init_packet(&pkt);  
  274.             pkt.sizeavcodec_encode_audio(oAcc, audio_outbuf, audio_outbuf_size, out_buf);  
  275.             pkt.ptsav_rescale_q(oAcc->coded_frame->pts, oAcc->time_base, audio_st->time_base);  
  276.             pkt.flags |= PKT_FLAG_KEY;  
  277.             pkt.stream_indexaudioindex;  
  278.             pkt.dataaudio_outbuf;  
  279.             if (av_write_frame(oc, &pkt) != 0)   
  280.             {  
  281.                fprintf(stderr, "Error while writing audio frame\n");  
  282.                exit(1);  
  283.                 }  
  284.          }  
  285.           }   
  286.           av_free_packet(&packet);  
  287.        }   
  288. av_write_trailer(oc);  
  289. for(i = 0; i < oc->nb_streams; i++)   
  290. {              
  291.   av_freep(&oc->streams[i]->codec);                         
  292.   av_freep(&oc->streams[i]);                             
  293. }  
  294. url_fclose(oc);  
  295. av_free(oc);  
  296. av_free(oVFrame);  
  297. av_free(out_buf);  
  298. avcodec_close(vCodecCtx);  
  299. avcodec_close(aCodecCtx);  
  300. av_close_input_file(ic);  
source download:  http://files.cnblogs.com/msopengl/ffmpegh264codec.rar
 
作者:jemmyLiu
出处:http://www.cnblogs.com/msopengl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

你可能感兴趣的:(ffmpeg,音视频技术,h264,流媒体技术,音视频编解码)