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

简介:

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

#include <avcodec.h>
#include <avformat.h>
#include <stdio.h>
#include <avutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main(int argc,char **argv)
{   
  const char *input_file_name="/root/movies/ddh1.mpg";
  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\n",input_file_name);
     exit(1);
  }//打开输入文件
  if(av_find_stream_info(ic)<0)
  {
     printf("can't find suitable codec parameters\n");
     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\n");
         }
         else if(ic->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
         {
          //printf("audio\n");
            audioindex=i;
         }
  }
   if(videoindex==-1)
   {
          printf("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)
  {
     printf("can't find suitable video decoder\n");
     exit(1);
  }//找到合适的视频解码器
  if(avcodec_open(vCodecCtx,vCodec)<0)
  {
     printf("can't open the video decoder\n");
     exit(1);
  }//打开该视频解码器
   if(audioindex==-1)
     {
        printf("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)
  {
     printf("can't find suitable audio decoder\n");
     exit(1);
  }//找到合适的音频解码器
  if(avcodec_open(aCodecCtx,aCodec)<0)
  {
     printf("can't open the audio decoder\n");
     exit(1);
  }//打开该音频解码器
//下面为输出文件处理部分
    const char *output_file_name="/root/123.avi";
    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\n");
           exit(0);
    }//判断是否可以判断输出文件的编码格式
    oc=av_alloc_format_context();
    if(!oc)
    {
           printf("Memory error\n");
           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\n");
          exit(0);
    }
    oVcc=avcodec_alloc_context();
    oVcc=video_st->codec;
    oVcc->codec_id=CODEC_ID_MPEG4;
    oVcc->codec_type=CODEC_TYPE_VIDEO;
    oVcc->bit_rate=2500000;
    oVcc->width=704;
    oVcc->height=480;
    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;
    audio_st=av_new_stream(oc,oc->nb_streams);
    if(!audio_st)
    {
           printf("could not alloc audio stream\n");
           exit(0);
    }  
    avcodec_get_context_defaults2(audio_st->codec,CODEC_TYPE_AUDIO);
    oAcc=avcodec_alloc_context();
    oAcc=audio_st->codec;
    oAcc->codec_id=CODEC_ID_MP3;
    oAcc->codec_type=CODEC_TYPE_AUDIO;
    oAcc->bit_rate=aCodecCtx->bit_rate;
    oAcc->sample_rate=aCodecCtx->sample_rate;
    oAcc->channels=2;
    if (av_set_parameters(oc, NULL) < 0) 
    {
           printf( "Invalid output format parameters\n");                         
              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_MPEG4);
    if(!oVc)
    {
       printf("can't find suitable video encoder\n");
           exit(0);
    }//找到合适的视频编码器
    if(avcodec_open(oVcc,oVc)<0)
    {
           printf("can't open the output video codec\n");
           exit(0);
    }//打开视频编码器
    oAc=avcodec_find_encoder(CODEC_ID_MP3);
    if(!oAc)
    {
           printf("can't find suitable audio encoder\n");
           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\n",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\n",output_file_name);
              exit(0);
       }//打开输出文件
    }
    if(!oc->nb_streams)
    {
           fprintf(stderr,"output file dose not contain any stream\n");
           exit(0);
    }//查看输出文件是否含有流信息
  if(av_write_header(oc)<0)
  {
      fprintf(stderr, "Could not write header for output file\n");
      exit(1);
  }[/i][/i]
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);
  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\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=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
             ret=av_write_frame(oc, &packet); 
                    //img_convert((AVPicture *)vFrame, PIX_FMT_RGB24, (AVPicture*)oVFrame, oVcc->pix_fmt,oVcc->width,oVcc-
>height);
            //SaveFrame(vFrame,oVcc->width,oVcc->height,frame_index); 
                    if(ret!=0)
                    {
                      printf("while write video frame error\n");
                      exit(0);
                    }
          }
          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=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\n");
                       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, 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 (av_write_frame(oc, &pkt) != 0) 
            {
               fprintf(stderr, "Error while writing audio frame\n");
               exit(1);
                }
         }
          } 
          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);
}


本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2009/09/04/1560165.html,如需转载请自行联系原作者
相关文章
|
19天前
|
编解码 NoSQL Java
使用Spring Boot + Redis 队列实现视频文件上传及FFmpeg转码的技术分享
【8月更文挑战第30天】在当前的互联网应用中,视频内容的处理与分发已成为不可或缺的一部分。对于视频平台而言,高效、稳定地处理用户上传的视频文件,并对其进行转码以适应不同设备的播放需求,是提升用户体验的关键。本文将围绕使用Spring Boot结合Redis队列技术来实现视频文件上传及FFmpeg转码的过程,分享一系列技术干货。
57 3
|
1月前
|
编解码 Linux
CentOS安装ffmpeg并转码视频为mp4
CentOS安装ffmpeg并转码视频为mp4
101 0
|
3月前
|
Python
Python使用ffmpeg下载m3u8拼接为视频
Python使用ffmpeg下载m3u8拼接为视频
142 1
|
3月前
|
Web App开发 安全 Linux
FFmpeg开发笔记(二十六)Linux环境安装ZLMediaKit实现视频推流
《FFmpeg开发实战》书中介绍轻量级流媒体服务器MediaMTX,但其功能有限,不适合生产环境。推荐使用国产开源的ZLMediaKit,它支持多种流媒体协议和音视频编码标准。以下是华为欧拉系统下编译安装ZLMediaKit和FFmpeg的步骤,包括更新依赖、下载源码、配置、编译、安装以及启动MediaServer服务。此外,还提供了通过FFmpeg进行RTSP和RTMP推流,并使用VLC播放器拉流的示例。
170 3
FFmpeg开发笔记(二十六)Linux环境安装ZLMediaKit实现视频推流
|
3月前
|
Java Linux
ffmpeg音频格式转换、合成、速率调整
ffmpeg音频格式转换、合成、速率调整
|
3月前
|
编解码 Linux 计算机视觉
python 调用ffmpeg使用usb摄像头录制视频,输出h264格式,自动获取摄像头的最佳帧率和最大画面尺寸
使用 Python 调用 FFmpeg 进行 USB 摄像头视频录制,需先确保安装 FFmpeg 和 Python 的 `subprocess` 模块。代码示例展示了如何自动获取摄像头的最佳帧率和最大分辨率,然后录制视频。首先通过 FFmpeg 列出摄像头格式获取信息,解析出帧率和分辨率,选择最优值。之后调用 FFmpeg 命令录制视频,设置帧率、分辨率等参数。注意 `/dev/video0` 是 Linux 的摄像头设备路径,Windows 系统需相应调整。代码中未直接实现自动获取最佳参数,通常需要借助其他库如 OpenCV。
|
3月前
|
Linux 开发工具
Linux下视频截取命令 使用【ffmpeg】使用
Linux下视频截取命令 使用【ffmpeg】使用
35 1
|
3月前
|
编解码
FFmpeg之转码
FFmpeg之转码
|
11天前
|
编解码 移动开发 安全
FFmpeg开发笔记(五十)聊聊几种流媒体传输技术的前世今生
自互联网普及以来,流媒体技术特别是视频直播技术不断进步,出现了多种传输协议。早期的MMS由微软主导,但随WMV格式衰落而减少使用。RTSP由网景和RealNetworks联合提出,支持多种格式,但在某些现代应用中不再受支持。RTMP由Adobe开发,曾广泛用于网络直播,但因HTML5不支持Flash而受影响。HLS由苹果开发,基于HTTP,适用于点播。SRT和RIST均为较新协议,强调安全与可靠性,尤其SRT在电视直播中应用增多。尽管RTMP仍占一定市场,但SRT等新协议正逐渐兴起。
41 8
FFmpeg开发笔记(五十)聊聊几种流媒体传输技术的前世今生
|
17天前
|
Web App开发 Java 视频直播
FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP
对于软件、计算机等专业的毕业生,毕业设计需实现实用软件或APP。新颖的设计应结合最新技术,如5G时代的音视频技术。示例包括: 1. **短视频分享APP**: 集成FFmpeg实现视频剪辑功能,如添加字幕、转场特效等。 2. **电商购物APP**: 具备直播带货功能,使用RTMP/SRT协议支持流畅直播体验。 3. **同城生活APP**: 引入WebRTC技术实现可信的视频通话功能。这些应用不仅实用,还能展示开发者紧跟技术潮流的能力。
46 4
FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP