transcode_init()函数是在转换前做准备工作的.此处看一下它的真面目,不废话,看注释吧:
- //为转换过程做准备
- staticinttranscode_init(OutputFile*output_files,
- intnb_output_files,
- InputFile*input_files,
- intnb_input_files)
- {
- intret=0,i,j,k;
- AVFormatContext*oc;
- AVCodecContext*codec,*icodec;
- OutputStream*ost;
- InputStream*ist;
- charerror[1024];
- intwant_sdp=1;
- /*initframerateemulation*/
- //初始化帧率仿真(转换时是不按帧率来的,但如果要求帧率仿真,就可以做到)
- for(i=0;i<nb_input_files;i++)
- {
- InputFile*ifile=&input_files[i];
- //如果一个输入文件被要求帧率仿真(指的是即使是转换也像播放那样按照帧率来进行),
- //则为这个文件中所有流记录下开始时间
- if(ifile->rate_emu)
- for(j=0;j<ifile->nb_streams;j++)
- input_streams[j+ifile->ist_index].start=av_gettime();
- }
- /*outputstreaminit*/
- for(i=0;i<nb_output_files;i++)
- {
- //什么也没做,只是做了个判断而已
- oc=output_files[i].ctx;
- if(!oc->nb_streams&&!(oc->oformat->flags&AVFMT_NOSTREAMS))
- {
- av_dump_format(oc,i,oc->filename,1);
- av_log(NULL,AV_LOG_ERROR,
- "Outputfile#%ddoesnotcontainanystream\n",i);
- returnAVERROR(EINVAL);
- }
- }
- //轮循所有的输出流,跟据对应的输入流,设置其编解码器的参数
- for(i=0;i<nb_output_streams;i++)
- {
- //轮循所有的输出流
- ost=&output_streams[i];
- //输出流对应的FormatContext
- oc=output_files[ost->file_index].ctx;
- //取得输出流对应的输入流
- ist=&input_streams[ost->source_index];
- //attachment_filename是不是这样的东西:一个文件,它单独容纳一个输出流?此处不懂
- if(ost->attachment_filename)
- continue;
- codec=ost->st->codec;//输出流的编解码器结构
- icodec=ist->st->codec;//输入流的编解码器结构
- //先把能复制的复制一下
- ost->st->disposition=ist->st->disposition;
- codec->bits_per_raw_sample=icodec->bits_per_raw_sample;
- codec->chroma_sample_location=icodec->chroma_sample_location;
- //如果只是复制一个流(不用解码后再编码),则把输入流的编码参数直接复制给输出流
- //此时是不需要解码也不需要编码的,所以不需打开解码器和编码器
- if(ost->stream_copy)
- {
- //计算输出流的编解码器的extradata的大小,然后分配容纳extradata的缓冲
- //然后把输入流的编解码器的extradata复制到输出流的编解码器中
- uint64_textra_size=(uint64_t)icodec->extradata_size
- +FF_INPUT_BUFFER_PADDING_SIZE;
- if(extra_size>INT_MAX){
- returnAVERROR(EINVAL);
- }
- /*ifstream_copyisselected,noneedtodecodeorencode*/
- codec->codec_id=icodec->codec_id;
- codec->codec_type=icodec->codec_type;
- if(!codec->codec_tag){
- if(!oc->oformat->codec_tag
- ||av_codec_get_id(oc->oformat->codec_tag,icodec->codec_tag)==codec->codec_id
- ||av_codec_get_tag(oc->oformat->codec_tag,icodec->codec_id)<=0)
- codec->codec_tag=icodec->codec_tag;
- }
- codec->bit_rate=icodec->bit_rate;
- codec->rc_max_rate=icodec->rc_max_rate;
- codec->rc_buffer_size=icodec->rc_buffer_size;
- codec->extradata=av_mallocz(extra_size);
- if(!codec->extradata){
- returnAVERROR(ENOMEM);
- }
- memcpy(codec->extradata,icodec->extradata,icodec->extradata_size);
- codec->extradata_size=icodec->extradata_size;
- //重新鼓捣一下timebase(这家伙就是帧率)
- codec->time_base=ist->st->time_base;
- //如果输出文件是avi,做一点特殊处理
- if(!strcmp(oc->oformat->name,"avi")){
- if(copy_tb<0
- &&av_q2d(icodec->time_base)*icodec->ticks_per_frame>
- 2*av_q2d(ist->st->time_base)
- &&av_q2d(ist->st->time_base)<1.0/500
- ||copy_tb==0)
- {
- codec->time_base=icodec->time_base;
- codec->time_base.num*=icodec->ticks_per_frame;
- codec->time_base.den*=2;
- }
- }
- elseif(!(oc->oformat->flags&AVFMT_VARIABLE_FPS))
- {
- if(copy_tb<0
- &&av_q2d(icodec->time_base)*icodec->ticks_per_frame
- >av_q2d(ist->st->time_base)
- &&av_q2d(ist->st->time_base)<1.0/500
- ||copy_tb==0)
- {
- codec->time_base=icodec->time_base;
- codec->time_base.num*=icodec->ticks_per_frame;
- }
- }
- //再修正一下帧率
- av_reduce(&codec->time_base.num,&codec->time_base.den,
- codec->time_base.num,codec->time_base.den,INT_MAX);
- //单独复制各不同媒体自己的编码参数
- switch(codec->codec_type)
- {
- caseAVMEDIA_TYPE_AUDIO:
- //音频的
- if(audio_volume!=256){
- av_log(NULL,AV_LOG_FATAL,
- "-acodeccopyand-volareincompatible(framesarenotdecoded)\n");
- exit_program(1);
- }
- codec->channel_layout=icodec->channel_layout;
- codec->sample_rate=icodec->sample_rate;
- codec->channels=icodec->channels;
- codec->frame_size=icodec->frame_size;
- codec->audio_service_type=icodec->audio_service_type;
- codec->block_align=icodec->block_align;
- break;
- caseAVMEDIA_TYPE_VIDEO:
- //视频的
- codec->pix_fmt=icodec->pix_fmt;
- codec->width=icodec->width;
- codec->height=icodec->height;
- codec->has_b_frames=icodec->has_b_frames;
- if(!codec->sample_aspect_ratio.num){
- codec->sample_aspect_ratio=ost->st->sample_aspect_ratio=
- ist->st->sample_aspect_ratio.num?ist->st->sample_aspect_ratio:
- ist->st->codec->sample_aspect_ratio.num?ist->st->codec->sample_aspect_ratio:(AVRational){0,1};
- }
- ost->st->avg_frame_rate=ist->st->avg_frame_rate;
- break;
- caseAVMEDIA_TYPE_SUBTITLE:
- //字幕的
- codec->width=icodec->width;
- codec->height=icodec->height;
- break;
- caseAVMEDIA_TYPE_DATA:
- caseAVMEDIA_TYPE_ATTACHMENT:
- //??的
- break;
- default:
- abort();
- }
- }
- else
- {
- //如果不是复制,就麻烦多了
- //获取编码器
- if(!ost->enc)
- ost->enc=avcodec_find_encoder(ost->st->codec->codec_id);
- //因为需要转换,所以既需解码又需编码
- ist->decoding_needed=1;
- ost->encoding_needed=1;
- switch(codec->codec_type)
- {
- caseAVMEDIA_TYPE_AUDIO:
- //鼓捣音频编码器的参数,基本上是把一些不合适的参数替换掉
- ost->fifo=av_fifo_alloc(1024);//音频数据所在的缓冲
- if(!ost->fifo){
- returnAVERROR(ENOMEM);
- }
- //采样率
- if(!codec->sample_rate)
- codec->sample_rate=icodec->sample_rate;
- choose_sample_rate(ost->st,ost->enc);
- codec->time_base=(AVRational){1,codec->sample_rate};
- //样点格式
- if(codec->sample_fmt==AV_SAMPLE_FMT_NONE)
- codec->sample_fmt=icodec->sample_fmt;
- choose_sample_fmt(ost->st,ost->enc);
- //声道
- if(ost->audio_channels_mapped){
- /*therequestedoutputchannelissettothenumberof
- *-map_channelonlyifno-acarespecified*/
- if(!codec->channels){
- codec->channels=ost->audio_channels_mapped;
- codec->channel_layout=av_get_default_channel_layout(codec->channels);
- if(!codec->channel_layout){
- av_log(NULL,AV_LOG_FATAL,"Unabletofindanappropriatechannellayoutforrequestednumberofchannel\n);
- exit_program(1);
- }
- }
- /*fillunusedchannelmappingwith-1(whichmeansamuted
- *channelincasethenumberofoutputchannelsisbigger
- *thanthenumberofmappedchannel)*/
- for(j=ost->audio_channels_mapped;j<FF_ARRAY_ELEMS(ost->audio_channels_map);j++)
- <span></span>ost->audio_channels_map[j]=-1;
- }elseif(!codec->channels){
- codec->channels=icodec->channels;
- codec->channel_layout=icodec->channel_layout;
- }
- if(av_get_channel_layout_nb_channels(codec->channel_layout)!=codec->channels)
- codec->channel_layout=0;
- //是否需要重采样
- ost->audio_resample=codec->sample_rate!=icodec->sample_rate||audio_sync_method>1;
- ost->audio_resample|=codec->sample_fmt!=icodec->sample_fmt||
- codec->channel_layout!=icodec->channel_layout;
- icodec->request_channels=codec->channels;
- ost->resample_sample_fmt=icodec->sample_fmt;
- ost->resample_sample_rate=icodec->sample_rate;
- ost->resample_channels=icodec->channels;
- break;
- caseAVMEDIA_TYPE_VIDEO:
- //鼓捣视频编码器的参数,基本上是把一些不合适的参数替换掉
- if(codec->pix_fmt==PIX_FMT_NONE)
- codec->pix_fmt=icodec->pix_fmt;
- choose_pixel_fmt(ost->st,ost->enc);
- if(ost->st->codec->pix_fmt==PIX_FMT_NONE){
- av_log(NULL,AV_LOG_FATAL,"Videopixelformatisunknown,streamcannotbeencoded\n");
- exit_program(1);
- }
- //宽高
- if(!codec->width||!codec->height){
- codec->width=icodec->width;
- codec->height=icodec->height;
- }
- //视频是否需要重采样
- ost->video_resample=codec->width!=icodec->width||
- codec->height!=icodec->height||
- codec->pix_fmt!=icodec->pix_fmt;
- if(ost->video_resample){
- codec->bits_per_raw_sample=frame_bits_per_raw_sample;
- }
- ost->resample_height=icodec->height;
- ost->resample_width=icodec->width;
- ost->resample_pix_fmt=icodec->pix_fmt;
- //计算帧率
- if(!ost->frame_rate.num)
- ost->frame_rate=ist->st->r_frame_rate.num?
- ist->st->r_frame_rate:(AVRational){25,1};
- if(ost->enc&&ost->enc->supported_framerates&&!ost->force_fps){
- intidx=av_find_nearest_q_idx(ost->frame_rate,ost->enc->supported_framerates);
- ost->frame_rate=ost->enc->supported_framerates[idx];
- }
- codec->time_base=(AVRational){ost->frame_rate.den,ost->frame_rate.num};
- if(av_q2d(codec->time_base)<0.001&&
- video_sync_method&&
- (video_sync_method==1||
- (video_sync_method<0&&!
- (oc->oformat->flags&AVFMT_VARIABLE_FPS))))
- {
- av_log(oc,AV_LOG_WARNING,"Framerateveryhighforamuxernoteffcicientlysupportingit.\n"
- "Pleaseconsiderspecifiyingalowerframerate,adifferentmuxeror-vsync2\n");
- }
- <span></span>for(j=0;j<ost->forced_kf_count;j++)
- ost->forced_kf_pts[j]=av_rescale_q(ost->forced_kf_pts[j],
- AV_TIME_BASE_Q,codec->time_base);
- break;
- caseAVMEDIA_TYPE_SUBTITLE:
- break;
- default:
- abort();
- break;
- }
- /*twopassmode*/
- if(codec->codec_id!=CODEC_ID_H264&&
- (codec->flags&(CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)))
- {
- charlogfilename[1024];
- FILE*f;
- snprintf(logfilename,sizeof(logfilename),"%s-%d.log",
- pass_logfilename_prefix?pass_logfilename_prefix:DEFAULT_PASS_LOGFILENAME_PREFIX,
- i);
- if(codec->flags&CODEC_FLAG_PASS2){
- char*logbuffer;
- size_tlogbuffer_size;
- if(cmdutils_read_file(logfilename,&logbuffer,&logbuffer_size)<0){
- av_log(NULL,AV_LOG_FATAL,
- "Errorreadinglogfile'%s'forpass-2encoding\n",
- logfilename);
- exit_program(1);
- }
- codec->stats_in=logbuffer;
- }
- if(codec->flags&CODEC_FLAG_PASS1){
- f=fopen(logfilename,"wb");
- if(!f){
- av_log(NULL,AV_LOG_FATAL,"Cannotwritelogfile'%s'forpass-1encoding:%s\n",
- logfilename,strerror(errno));
- exit_program(1);
- }
- ost->logfile=f;
- }
- }
- }
- if(codec->codec_type==AVMEDIA_TYPE_VIDEO){
- /*maximumvideobuffersizeis6-bytesperpixel,plusDPXheadersize(1664)*/
- //计算编码输出缓冲的大小,计算一个最大值
- intsize=codec->width*codec->height;
- bit_buffer_size=FFMAX(bit_buffer_size,7*size+10000);
- }
- }
- //分配编码后数据所在的缓冲
- if(!bit_buffer)
- bit_buffer=av_malloc(bit_buffer_size);
- if(!bit_buffer){
- av_log(NULL,AV_LOG_ERROR,
- "Cannotallocate%dbytesoutputbuffer\n",
- bit_buffer_size);
- returnAVERROR(ENOMEM);
- }
- //轮循所有输出流,打开每个输出流的编码器
- for(i=0;i<nb_output_streams;i++)
- {
- ost=&output_streams[i];
- if(ost->encoding_needed){
- //当然,只有在需要编码时才打开编码器
- AVCodec*codec=ost->enc;
- AVCodecContext*dec=input_streams[ost->source_index].st->codec;
- if(!codec){
- snprintf(error,sizeof(error),
- "Encoder(codec%s)notfoundforoutputstream#%d:%d",
- avcodec_get_name(ost->st->codec->codec_id),
- ost->file_index,ost->index);
- ret=AVERROR(EINVAL);
- gotodump_format;
- }
- if(dec->subtitle_header){
- ost->st->codec->subtitle_header=av_malloc(dec->subtitle_header_size);
- if(!ost->st->codec->subtitle_header){
- ret=AVERROR(ENOMEM);
- gotodump_format;
- }
- memcpy(ost->st->codec->subtitle_header,
- dec->subtitle_header,dec->subtitle_header_size);
- ost->st->codec->subtitle_header_size=dec->subtitle_header_size;
- }
- //打开啦
- if(avcodec_open2(ost->st->codec,codec,&ost->opts)<0){
- snprintf(error,sizeof(error),
- "Errorwhileopeningencoderforoutputstream#%d:%d-maybeincorrectparameterssuchasbit_rate,rate,widthorheight",
- ost->file_index,ost->index);
- ret=AVERROR(EINVAL);
- gotodump_format;
- }
- assert_codec_experimental(ost->st->codec,1);
- assert_avoptions(ost->opts);
- if(ost->st->codec->bit_rate&&ost->st->codec->bit_rate<1000)
- av_log(NULL,AV_LOG_WARNING,
- "Thebitrateparameterissettoolow."
- "Ittakesbits/sasargument,notkbits/s\n");
- extra_size+=ost->st->codec->extradata_size;
- if(ost->st->codec->me_threshold)
- input_streams[ost->source_index].st->codec->debug|=FF_DEBUG_MV;
- }
- }
- //初始化所有的输入流(主要做的就是在需要时打开解码器)
- for(i=0;i<nb_input_streams;i++)
- if((ret=init_input_stream(i,output_streams,nb_output_streams,
- error,sizeof(error)))<0)
- gotodump_format;
- /*discardunusedprograms*/
- for(i=0;i<nb_input_files;i++){
- InputFile*ifile=&input_files[i];
- for(j=0;j<ifile->ctx->nb_programs;j++){
- AVProgram*p=ifile->ctx->programs[j];
- intdiscard=AVDISCARD_ALL;
- for(k=0;k<p->nb_stream_indexes;k++){
- if(!input_streams[ifile->ist_index+p->stream_index[k]].discard){
- discard=AVDISCARD_DEFAULT;
- break;
- }
- }
- p->discard=discard;
- }
- }
- //打开所有输出文件,写入媒体文件头
- for(i=0;i<nb_output_files;i++){
- oc=output_files[i].ctx;
- oc->interrupt_callback=int_cb;
- if(avformat_write_header(oc,&output_files[i].opts)<0){
- snprintf(error,sizeof(error),
- "Couldnotwriteheaderforoutputfile#%d(incorrectcodecparameters?)",
- i);
- ret=AVERROR(EINVAL);
- gotodump_format;
- }
- //assert_avoptions(output_files[i].opts);
- if(strcmp(oc->oformat->name,"rtp")){
- want_sdp=0;
- }
- }
- return0;
- }
transcode_init()函数是在转换前做准备工作的.此处看一下它的真面目,不废话,看注释吧:
- //为转换过程做准备
- staticinttranscode_init(OutputFile*output_files,
- intnb_output_files,
- InputFile*input_files,
- intnb_input_files)
- {
- intret=0,i,j,k;
- AVFormatContext*oc;
- AVCodecContext*codec,*icodec;
- OutputStream*ost;
- InputStream*ist;
- charerror[1024];
- intwant_sdp=1;
- /*initframerateemulation*/
- //初始化帧率仿真(转换时是不按帧率来的,但如果要求帧率仿真,就可以做到)
- for(i=0;i<nb_input_files;i++)
- {
- InputFile*ifile=&input_files[i];
- //如果一个输入文件被要求帧率仿真(指的是即使是转换也像播放那样按照帧率来进行),
- //则为这个文件中所有流记录下开始时间
- if(ifile->rate_emu)
- for(j=0;j<ifile->nb_streams;j++)
- input_streams[j+ifile->ist_index].start=av_gettime();
- }
- /*outputstreaminit*/
- for(i=0;i<nb_output_files;i++)
- {
- //什么也没做,只是做了个判断而已
- oc=output_files[i].ctx;
- if(!oc->nb_streams&&!(oc->oformat->flags&AVFMT_NOSTREAMS))
- {
- av_dump_format(oc,i,oc->filename,1);
- av_log(NULL,AV_LOG_ERROR,
- "Outputfile#%ddoesnotcontainanystream\n",i);
- returnAVERROR(EINVAL);
- }
- }
- //轮循所有的输出流,跟据对应的输入流,设置其编解码器的参数
- for(i=0;i<nb_output_streams;i++)
- {
- //轮循所有的输出流
- ost=&output_streams[i];
- //输出流对应的FormatContext
- oc=output_files[ost->file_index].ctx;
- //取得输出流对应的输入流
- ist=&input_streams[ost->source_index];
- //attachment_filename是不是这样的东西:一个文件,它单独容纳一个输出流?此处不懂
- if(ost->attachment_filename)
- continue;
- codec=ost->st->codec;//输出流的编解码器结构
- icodec=ist->st->codec;//输入流的编解码器结构
- //先把能复制的复制一下
- ost->st->disposition=ist->st->disposition;
- codec->bits_per_raw_sample=icodec->bits_per_raw_sample;
- codec->chroma_sample_location=icodec->chroma_sample_location;
- //如果只是复制一个流(不用解码后再编码),则把输入流的编码参数直接复制给输出流
- //此时是不需要解码也不需要编码的,所以不需打开解码器和编码器
- if(ost->stream_copy)
- {
- //计算输出流的编解码器的extradata的大小,然后分配容纳extradata的缓冲
- //然后把输入流的编解码器的extradata复制到输出流的编解码器中
- uint64_textra_size=(uint64_t)icodec->extradata_size
- +FF_INPUT_BUFFER_PADDING_SIZE;
- if(extra_size>INT_MAX){
- returnAVERROR(EINVAL);
- }
- /*ifstream_copyisselected,noneedtodecodeorencode*/
- codec->codec_id=icodec->codec_id;
- codec->codec_type=icodec->codec_type;
- if(!codec->codec_tag){
- if(!oc->oformat->codec_tag
- ||av_codec_get_id(oc->oformat->codec_tag,icodec->codec_tag)==codec->codec_id
- ||av_codec_get_tag(oc->oformat->codec_tag,icodec->codec_id)<=0)
- codec->codec_tag=icodec->codec_tag;
- }
- codec->bit_rate=icodec->bit_rate;
- codec->rc_max_rate=icodec->rc_max_rate;
- codec->rc_buffer_size=icodec->rc_buffer_size;
- codec->extradata=av_mallocz(extra_size);
- if(!codec->extradata){
- returnAVERROR(ENOMEM);
- }
- memcpy(codec->extradata,icodec->extradata,icodec->extradata_size);
- codec->extradata_size=icodec->extradata_size;
- //重新鼓捣一下timebase(这家伙就是帧率)
- codec->time_base=ist->st->time_base;
- //如果输出文件是avi,做一点特殊处理
- if(!strcmp(oc->oformat->name,"avi")){
- if(copy_tb<0
- &&av_q2d(icodec->time_base)*icodec->ticks_per_frame>
- 2*av_q2d(ist->st->time_base)
- &&av_q2d(ist->st->time_base)<1.0/500
- ||copy_tb==0)
- {
- codec->time_base=icodec->time_base;
- codec->time_base.num*=icodec->ticks_per_frame;
- codec->time_base.den*=2;
- }
- }
- elseif(!(oc->oformat->flags&AVFMT_VARIABLE_FPS))
- {
- if(copy_tb<0
- &&av_q2d(icodec->time_base)*icodec->ticks_per_frame
- >av_q2d(ist->st->time_base)
- &&av_q2d(ist->st->time_base)<1.0/500
- ||copy_tb==0)
- {
- codec->time_base=icodec->time_base;
- codec->time_base.num*=icodec->ticks_per_frame;
- }
- }
- //再修正一下帧率
- av_reduce(&codec->time_base.num,&codec->time_base.den,
- codec->time_base.num,codec->time_base.den,INT_MAX);
- //单独复制各不同媒体自己的编码参数
- switch(codec->codec_type)
- {
- caseAVMEDIA_TYPE_AUDIO:
- //音频的
- if(audio_volume!=256){
- av_log(NULL,AV_LOG_FATAL,
- "-acodeccopyand-volareincompatible(framesarenotdecoded)\n");
- exit_program(1);
- }
- codec->channel_layout=icodec->channel_layout;
- codec->sample_rate=icodec->sample_rate;
- codec->channels=icodec->channels;
- codec->frame_size=icodec->frame_size;
- codec->audio_service_type=icodec->audio_service_type;
- codec->block_align=icodec->block_align;
- break;
- caseAVMEDIA_TYPE_VIDEO:
- //视频的
- codec->pix_fmt=icodec->pix_fmt;
- codec->width=icodec->width;
- codec->height=icodec->height;
- codec->has_b_frames=icodec->has_b_frames;
- if(!codec->sample_aspect_ratio.num){
- codec->sample_aspect_ratio=ost->st->sample_aspect_ratio=
- ist->st->sample_aspect_ratio.num?ist->st->sample_aspect_ratio:
- ist->st->codec->sample_aspect_ratio.num?ist->st->codec->sample_aspect_ratio:(AVRational){0,1};
- }
- ost->st->avg_frame_rate=ist->st->avg_frame_rate;
- break;
- caseAVMEDIA_TYPE_SUBTITLE:
- //字幕的
- codec->width=icodec->width;
- codec->height=icodec->height;
- break;
- caseAVMEDIA_TYPE_DATA:
- caseAVMEDIA_TYPE_ATTACHMENT:
- //??的
- break;
- default:
- abort();
- }
- }
- else
- {
- //如果不是复制,就麻烦多了
- //获取编码器
- if(!ost->enc)
- ost->enc=avcodec_find_encoder(ost->st->codec->codec_id);
- //因为需要转换,所以既需解码又需编码
- ist->decoding_needed=1;
- ost->encoding_needed=1;
- switch(codec->codec_type)
- {
- caseAVMEDIA_TYPE_AUDIO:
- //鼓捣音频编码器的参数,基本上是把一些不合适的参数替换掉
- ost->fifo=av_fifo_alloc(1024);//音频数据所在的缓冲
- if(!ost->fifo){
- returnAVERROR(ENOMEM);
- }
- //采样率
- if(!codec->sample_rate)
- codec->sample_rate=icodec->sample_rate;
- choose_sample_rate(ost->st,ost->enc);
- codec->time_base=(AVRational){1,codec->sample_rate};
- //样点格式
- if(codec->sample_fmt==AV_SAMPLE_FMT_NONE)
- codec->sample_fmt=icodec->sample_fmt;
- choose_sample_fmt(ost->st,ost->enc);
- //声道
- if(ost->audio_channels_mapped){
- /*therequestedoutputchannelissettothenumberof
- *-map_channelonlyifno-acarespecified*/
- if(!codec->channels){
- codec->channels=ost->audio_channels_mapped;
- codec->channel_layout=av_get_default_channel_layout(codec->channels);
- if(!codec->channel_layout){
- av_log(NULL,AV_LOG_FATAL,"Unabletofindanappropriatechannellayoutforrequestednumberofchannel\n);
- exit_program(1);
- }
- }
- /*fillunusedchannelmappingwith-1(whichmeansamuted
- *channelincasethenumberofoutputchannelsisbigger
- *thanthenumberofmappedchannel)*/
- for(j=ost->audio_channels_mapped;j<FF_ARRAY_ELEMS(ost->audio_channels_map);j++)
- <span></span>ost->audio_channels_map[j]=-1;
- }elseif(!codec->channels){
- codec->channels=icodec->channels;
- codec->channel_layout=icodec->channel_layout;
- }
- if(av_get_channel_layout_nb_channels(codec->channel_layout)!=codec->channels)
- codec->channel_layout=0;
- //是否需要重采样
- ost->audio_resample=codec->sample_rate!=icodec->sample_rate||audio_sync_method>1;
- ost->audio_resample|=codec->sample_fmt!=icodec->sample_fmt||
- codec->channel_layout!=icodec->channel_layout;
- icodec->request_channels=codec->channels;
- ost->resample_sample_fmt=icodec->sample_fmt;
- ost->resample_sample_rate=icodec->sample_rate;
- ost->resample_channels=icodec->channels;
- break;
- caseAVMEDIA_TYPE_VIDEO:
- //鼓捣视频编码器的参数,基本上是把一些不合适的参数替换掉
- if(codec->pix_fmt==PIX_FMT_NONE)
- codec->pix_fmt=icodec->pix_fmt;
- choose_pixel_fmt(ost->st,ost->enc);
- if(ost->st->codec->pix_fmt==PIX_FMT_NONE){
- av_log(NULL,AV_LOG_FATAL,"Videopixelformatisunknown,streamcannotbeencoded\n");
- exit_program(1);
- }
- //宽高
- if(!codec->width||!codec->height){
- codec->width=icodec->width;
- codec->height=icodec->height;
- }
- //视频是否需要重采样
- ost->video_resample=codec->width!=icodec->width||
- codec->height!=icodec->height||
- codec->pix_fmt!=icodec->pix_fmt;
- if(ost->video_resample){
- codec->bits_per_raw_sample=frame_bits_per_raw_sample;
- }
- ost->resample_height=icodec->height;
- ost->resample_width=icodec->width;
- ost->resample_pix_fmt=icodec->pix_fmt;
- //计算帧率
- if(!ost->frame_rate.num)
- ost->frame_rate=ist->st->r_frame_rate.num?
- ist->st->r_frame_rate:(AVRational){25,1};
- if(ost->enc&&ost->enc->supported_framerates&&!ost->force_fps){
- intidx=av_find_nearest_q_idx(ost->frame_rate,ost->enc->supported_framerates);
- ost->frame_rate=ost->enc->supported_framerates[idx];
- }
- codec->time_base=(AVRational){ost->frame_rate.den,ost->frame_rate.num};
- if(av_q2d(codec->time_base)<0.001&&
- video_sync_method&&
- (video_sync_method==1||
- (video_sync_method<0&&!
- (oc->oformat->flags&AVFMT_VARIABLE_FPS))))
- {
- av_log(oc,AV_LOG_WARNING,"Framerateveryhighforamuxernoteffcicientlysupportingit.\n"
- "Pleaseconsiderspecifiyingalowerframerate,adifferentmuxeror-vsync2\n");
- }
- <span></span>for(j=0;j<ost->forced_kf_count;j++)
- ost->forced_kf_pts[j]=av_rescale_q(ost->forced_kf_pts[j],
- AV_TIME_BASE_Q,codec->time_base);
- break;
- caseAVMEDIA_TYPE_SUBTITLE:
- break;
- default:
- abort();
- break;
- }
- /*twopassmode*/
- if(codec->codec_id!=CODEC_ID_H264&&
- (codec->flags&(CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)))
- {
- charlogfilename[1024];
- FILE*f;
- snprintf(logfilename,sizeof(logfilename),"%s-%d.log",
- pass_logfilename_prefix?pass_logfilename_prefix:DEFAULT_PASS_LOGFILENAME_PREFIX,
- i);
- if(codec->flags&CODEC_FLAG_PASS2){
- char*logbuffer;
- size_tlogbuffer_size;
- if(cmdutils_read_file(logfilename,&logbuffer,&logbuffer_size)<0){
- av_log(NULL,AV_LOG_FATAL,
- "Errorreadinglogfile'%s'forpass-2encoding\n",
- logfilename);
- exit_program(1);
- }
- codec->stats_in=logbuffer;
- }
- if(codec->flags&CODEC_FLAG_PASS1){
- f=fopen(logfilename,"wb");
- if(!f){
- av_log(NULL,AV_LOG_FATAL,"Cannotwritelogfile'%s'forpass-1encoding:%s\n",
- logfilename,strerror(errno));
- exit_program(1);
- }
- ost->logfile=f;
- }
- }
- }
- if(codec->codec_type==AVMEDIA_TYPE_VIDEO){
- /*maximumvideobuffersizeis6-bytesperpixel,plusDPXheadersize(1664)*/
- //计算编码输出缓冲的大小,计算一个最大值
- intsize=codec->width*codec->height;
- bit_buffer_size=FFMAX(bit_buffer_size,7*size+10000);
- }
- }
- //分配编码后数据所在的缓冲
- if(!bit_buffer)
- bit_buffer=av_malloc(bit_buffer_size);
- if(!bit_buffer){
- av_log(NULL,AV_LOG_ERROR,
- "Cannotallocate%dbytesoutputbuffer\n",
- bit_buffer_size);
- returnAVERROR(ENOMEM);
- }
- //轮循所有输出流,打开每个输出流的编码器
- for(i=0;i<nb_output_streams;i++)
- {
- ost=&output_streams[i];
- if(ost->encoding_needed){
- //当然,只有在需要编码时才打开编码器
- AVCodec*codec=ost->enc;
- AVCodecContext*dec=input_streams[ost->source_index].st->codec;
- if(!codec){
- snprintf(error,sizeof(error),
- "Encoder(codec%s)notfoundforoutputstream#%d:%d",
- avcodec_get_name(ost->st->codec->codec_id),
- ost->file_index,ost->index);
- ret=AVERROR(EINVAL);
- gotodump_format;
- }
- if(dec->subtitle_header){
- ost->st->codec->subtitle_header=av_malloc(dec->subtitle_header_size);
- if(!ost->st->codec->subtitle_header){
- ret=AVERROR(ENOMEM);
- gotodump_format;
- }
- memcpy(ost->st->codec->subtitle_header,
- dec->subtitle_header,dec->subtitle_header_size);
- ost->st->codec->subtitle_header_size=dec->subtitle_header_size;
- }
- //打开啦
- if(avcodec_open2(ost->st->codec,codec,&ost->opts)<0){
- snprintf(error,sizeof(error),
- "Errorwhileopeningencoderforoutputstream#%d:%d-maybeincorrectparameterssuchasbit_rate,rate,widthorheight",
- ost->file_index,ost->index);
- ret=AVERROR(EINVAL);
- gotodump_format;
- }
- assert_codec_experimental(ost->st->codec,1);
- assert_avoptions(ost->opts);
- if(ost->st->codec->bit_rate&&ost->st->codec->bit_rate<1000)
- av_log(NULL,AV_LOG_WARNING,
- "Thebitrateparameterissettoolow."
- "Ittakesbits/sasargument,notkbits/s\n");
- extra_size+=ost->st->codec->extradata_size;
- if(ost->st->codec->me_threshold)
- input_streams[ost->source_index].st->codec->debug|=FF_DEBUG_MV;
- }
- }
- //初始化所有的输入流(主要做的就是在需要时打开解码器)
- for(i=0;i<nb_input_streams;i++)
- if((ret=init_input_stream(i,output_streams,nb_output_streams,
- error,sizeof(error)))<0)
- gotodump_format;
- /*discardunusedprograms*/
- for(i=0;i<nb_input_files;i++){
- InputFile*ifile=&input_files[i];
- for(j=0;j<ifile->ctx->nb_programs;j++){
- AVProgram*p=ifile->ctx->programs[j];
- intdiscard=AVDISCARD_ALL;
- for(k=0;k<p->nb_stream_indexes;k++){
- if(!input_streams[ifile->ist_index+p->stream_index[k]].discard){
- discard=AVDISCARD_DEFAULT;
- break;
- }
- }
- p->discard=discard;
- }
- }
- //打开所有输出文件,写入媒体文件头
- for(i=0;i<nb_output_files;i++){
- oc=output_files[i].ctx;
- oc->interrupt_callback=int_cb;
- if(avformat_write_header(oc,&output_files[i].opts)<0){
- snprintf(error,sizeof(error),
- "Couldnotwriteheaderforoutputfile#%d(incorrectcodecparameters?)",
- i);
- ret=AVERROR(EINVAL);
- gotodump_format;
- }
- //assert_avoptions(output_files[i].opts);
- if(strcmp(oc->oformat->name,"rtp")){
- want_sdp=0;
- }
- }
- return0;
- }