PS:由于目前开发RTSP服务器传输模块时用到了h264文件,所以攻了一段时间去实现h264的视频编解码,借用FFmpeg SDK实现了任意文件格式之间的转换,并实现了流媒体实时播放,目前音视频同步需要稍加完善,视频编码代码已成功移植到Visual Stdio平台。
以下文档来自FFmpeg工程组(http://www.ffmpeg.com.cn/index.php开发事例)
实现转码一个普通视频文件为视频mpeg4,音频mp3的功能的程序
本程序源引自FFmpeg工程组,实现转码一个普通视频文件为视频mpeg4,音频mp3的功能(如需更多示例源码可参阅bbs.anychat.cn)
- #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);
- }
source download: http://files.cnblogs.com/msopengl/ffmpegh264codec.rar
作者:jemmyLiu
出处:http://www.cnblogs.com/msopengl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。