ffmpeg源码分析:transcode_init()函数

transcode_init()函数是在转换前做准备工作的.此处看一下它的真面目,不废话,看注释吧:

  1. //为转换过程做准备
  2. staticinttranscode_init(OutputFile*output_files,
  3. intnb_output_files,
  4. InputFile*input_files,
  5. intnb_input_files)
  6. {
  7. intret=0,i,j,k;
  8. AVFormatContext*oc;
  9. AVCodecContext*codec,*icodec;
  10. OutputStream*ost;
  11. InputStream*ist;
  12. charerror[1024];
  13. intwant_sdp=1;
  14. /*initframerateemulation*/
  15. //初始化帧率仿真(转换时是不按帧率来的,但如果要求帧率仿真,就可以做到)
  16. for(i=0;i<nb_input_files;i++)
  17. {
  18. InputFile*ifile=&input_files[i];
  19. //如果一个输入文件被要求帧率仿真(指的是即使是转换也像播放那样按照帧率来进行),
  20. //则为这个文件中所有流记录下开始时间
  21. if(ifile->rate_emu)
  22. for(j=0;j<ifile->nb_streams;j++)
  23. input_streams[j+ifile->ist_index].start=av_gettime();
  24. }
  25. /*outputstreaminit*/
  26. for(i=0;i<nb_output_files;i++)
  27. {
  28. //什么也没做,只是做了个判断而已
  29. oc=output_files[i].ctx;
  30. if(!oc->nb_streams&&!(oc->oformat->flags&AVFMT_NOSTREAMS))
  31. {
  32. av_dump_format(oc,i,oc->filename,1);
  33. av_log(NULL,AV_LOG_ERROR,
  34. "Outputfile#%ddoesnotcontainanystream\n",i);
  35. returnAVERROR(EINVAL);
  36. }
  37. }
  38. //轮循所有的输出流,跟据对应的输入流,设置其编解码器的参数
  39. for(i=0;i<nb_output_streams;i++)
  40. {
  41. //轮循所有的输出流
  42. ost=&output_streams[i];
  43. //输出流对应的FormatContext
  44. oc=output_files[ost->file_index].ctx;
  45. //取得输出流对应的输入流
  46. ist=&input_streams[ost->source_index];
  47. //attachment_filename是不是这样的东西:一个文件,它单独容纳一个输出流?此处不懂
  48. if(ost->attachment_filename)
  49. continue;
  50. codec=ost->st->codec;//输出流的编解码器结构
  51. icodec=ist->st->codec;//输入流的编解码器结构
  52. //先把能复制的复制一下
  53. ost->st->disposition=ist->st->disposition;
  54. codec->bits_per_raw_sample=icodec->bits_per_raw_sample;
  55. codec->chroma_sample_location=icodec->chroma_sample_location;
  56. //如果只是复制一个流(不用解码后再编码),则把输入流的编码参数直接复制给输出流
  57. //此时是不需要解码也不需要编码的,所以不需打开解码器和编码器
  58. if(ost->stream_copy)
  59. {
  60. //计算输出流的编解码器的extradata的大小,然后分配容纳extradata的缓冲
  61. //然后把输入流的编解码器的extradata复制到输出流的编解码器中
  62. uint64_textra_size=(uint64_t)icodec->extradata_size
  63. +FF_INPUT_BUFFER_PADDING_SIZE;
  64. if(extra_size>INT_MAX){
  65. returnAVERROR(EINVAL);
  66. }
  67. /*ifstream_copyisselected,noneedtodecodeorencode*/
  68. codec->codec_id=icodec->codec_id;
  69. codec->codec_type=icodec->codec_type;
  70. if(!codec->codec_tag){
  71. if(!oc->oformat->codec_tag
  72. ||av_codec_get_id(oc->oformat->codec_tag,icodec->codec_tag)==codec->codec_id
  73. ||av_codec_get_tag(oc->oformat->codec_tag,icodec->codec_id)<=0)
  74. codec->codec_tag=icodec->codec_tag;
  75. }
  76. codec->bit_rate=icodec->bit_rate;
  77. codec->rc_max_rate=icodec->rc_max_rate;
  78. codec->rc_buffer_size=icodec->rc_buffer_size;
  79. codec->extradata=av_mallocz(extra_size);
  80. if(!codec->extradata){
  81. returnAVERROR(ENOMEM);
  82. }
  83. memcpy(codec->extradata,icodec->extradata,icodec->extradata_size);
  84. codec->extradata_size=icodec->extradata_size;
  85. //重新鼓捣一下timebase(这家伙就是帧率)
  86. codec->time_base=ist->st->time_base;
  87. //如果输出文件是avi,做一点特殊处理
  88. if(!strcmp(oc->oformat->name,"avi")){
  89. if(copy_tb<0
  90. &&av_q2d(icodec->time_base)*icodec->ticks_per_frame>
  91. 2*av_q2d(ist->st->time_base)
  92. &&av_q2d(ist->st->time_base)<1.0/500
  93. ||copy_tb==0)
  94. {
  95. codec->time_base=icodec->time_base;
  96. codec->time_base.num*=icodec->ticks_per_frame;
  97. codec->time_base.den*=2;
  98. }
  99. }
  100. elseif(!(oc->oformat->flags&AVFMT_VARIABLE_FPS))
  101. {
  102. if(copy_tb<0
  103. &&av_q2d(icodec->time_base)*icodec->ticks_per_frame
  104. >av_q2d(ist->st->time_base)
  105. &&av_q2d(ist->st->time_base)<1.0/500
  106. ||copy_tb==0)
  107. {
  108. codec->time_base=icodec->time_base;
  109. codec->time_base.num*=icodec->ticks_per_frame;
  110. }
  111. }
  112. //再修正一下帧率
  113. av_reduce(&codec->time_base.num,&codec->time_base.den,
  114. codec->time_base.num,codec->time_base.den,INT_MAX);
  115. //单独复制各不同媒体自己的编码参数
  116. switch(codec->codec_type)
  117. {
  118. caseAVMEDIA_TYPE_AUDIO:
  119. //音频的
  120. if(audio_volume!=256){
  121. av_log(NULL,AV_LOG_FATAL,
  122. "-acodeccopyand-volareincompatible(framesarenotdecoded)\n");
  123. exit_program(1);
  124. }
  125. codec->channel_layout=icodec->channel_layout;
  126. codec->sample_rate=icodec->sample_rate;
  127. codec->channels=icodec->channels;
  128. codec->frame_size=icodec->frame_size;
  129. codec->audio_service_type=icodec->audio_service_type;
  130. codec->block_align=icodec->block_align;
  131. break;
  132. caseAVMEDIA_TYPE_VIDEO:
  133. //视频的
  134. codec->pix_fmt=icodec->pix_fmt;
  135. codec->width=icodec->width;
  136. codec->height=icodec->height;
  137. codec->has_b_frames=icodec->has_b_frames;
  138. if(!codec->sample_aspect_ratio.num){
  139. codec->sample_aspect_ratio=ost->st->sample_aspect_ratio=
  140. ist->st->sample_aspect_ratio.num?ist->st->sample_aspect_ratio:
  141. ist->st->codec->sample_aspect_ratio.num?ist->st->codec->sample_aspect_ratio:(AVRational){0,1};
  142. }
  143. ost->st->avg_frame_rate=ist->st->avg_frame_rate;
  144. break;
  145. caseAVMEDIA_TYPE_SUBTITLE:
  146. //字幕的
  147. codec->width=icodec->width;
  148. codec->height=icodec->height;
  149. break;
  150. caseAVMEDIA_TYPE_DATA:
  151. caseAVMEDIA_TYPE_ATTACHMENT:
  152. //??的
  153. break;
  154. default:
  155. abort();
  156. }
  157. }
  158. else
  159. {
  160. //如果不是复制,就麻烦多了
  161. //获取编码器
  162. if(!ost->enc)
  163. ost->enc=avcodec_find_encoder(ost->st->codec->codec_id);
  164. //因为需要转换,所以既需解码又需编码
  165. ist->decoding_needed=1;
  166. ost->encoding_needed=1;
  167. switch(codec->codec_type)
  168. {
  169. caseAVMEDIA_TYPE_AUDIO:
  170. //鼓捣音频编码器的参数,基本上是把一些不合适的参数替换掉
  171. ost->fifo=av_fifo_alloc(1024);//音频数据所在的缓冲
  172. if(!ost->fifo){
  173. returnAVERROR(ENOMEM);
  174. }
  175. //采样率
  176. if(!codec->sample_rate)
  177. codec->sample_rate=icodec->sample_rate;
  178. choose_sample_rate(ost->st,ost->enc);
  179. codec->time_base=(AVRational){1,codec->sample_rate};
  180. //样点格式
  181. if(codec->sample_fmt==AV_SAMPLE_FMT_NONE)
  182. codec->sample_fmt=icodec->sample_fmt;
  183. choose_sample_fmt(ost->st,ost->enc);
  184. //声道
  185. if(ost->audio_channels_mapped){
  186. /*therequestedoutputchannelissettothenumberof
  187. *-map_channelonlyifno-acarespecified*/
  188. if(!codec->channels){
  189. codec->channels=ost->audio_channels_mapped;
  190. codec->channel_layout=av_get_default_channel_layout(codec->channels);
  191. if(!codec->channel_layout){
  192. av_log(NULL,AV_LOG_FATAL,"Unabletofindanappropriatechannellayoutforrequestednumberofchannel\n);
  193. exit_program(1);
  194. }
  195. }
  196. /*fillunusedchannelmappingwith-1(whichmeansamuted
  197. *channelincasethenumberofoutputchannelsisbigger
  198. *thanthenumberofmappedchannel)*/
  199. for(j=ost->audio_channels_mapped;j<FF_ARRAY_ELEMS(ost->audio_channels_map);j++)
  200. <span></span>ost->audio_channels_map[j]=-1;
  201. }elseif(!codec->channels){
  202. codec->channels=icodec->channels;
  203. codec->channel_layout=icodec->channel_layout;
  204. }
  205. if(av_get_channel_layout_nb_channels(codec->channel_layout)!=codec->channels)
  206. codec->channel_layout=0;
  207. //是否需要重采样
  208. ost->audio_resample=codec->sample_rate!=icodec->sample_rate||audio_sync_method>1;
  209. ost->audio_resample|=codec->sample_fmt!=icodec->sample_fmt||
  210. codec->channel_layout!=icodec->channel_layout;
  211. icodec->request_channels=codec->channels;
  212. ost->resample_sample_fmt=icodec->sample_fmt;
  213. ost->resample_sample_rate=icodec->sample_rate;
  214. ost->resample_channels=icodec->channels;
  215. break;
  216. caseAVMEDIA_TYPE_VIDEO:
  217. //鼓捣视频编码器的参数,基本上是把一些不合适的参数替换掉
  218. if(codec->pix_fmt==PIX_FMT_NONE)
  219. codec->pix_fmt=icodec->pix_fmt;
  220. choose_pixel_fmt(ost->st,ost->enc);
  221. if(ost->st->codec->pix_fmt==PIX_FMT_NONE){
  222. av_log(NULL,AV_LOG_FATAL,"Videopixelformatisunknown,streamcannotbeencoded\n");
  223. exit_program(1);
  224. }
  225. //宽高
  226. if(!codec->width||!codec->height){
  227. codec->width=icodec->width;
  228. codec->height=icodec->height;
  229. }
  230. //视频是否需要重采样
  231. ost->video_resample=codec->width!=icodec->width||
  232. codec->height!=icodec->height||
  233. codec->pix_fmt!=icodec->pix_fmt;
  234. if(ost->video_resample){
  235. codec->bits_per_raw_sample=frame_bits_per_raw_sample;
  236. }
  237. ost->resample_height=icodec->height;
  238. ost->resample_width=icodec->width;
  239. ost->resample_pix_fmt=icodec->pix_fmt;
  240. //计算帧率
  241. if(!ost->frame_rate.num)
  242. ost->frame_rate=ist->st->r_frame_rate.num?
  243. ist->st->r_frame_rate:(AVRational){25,1};
  244. if(ost->enc&&ost->enc->supported_framerates&&!ost->force_fps){
  245. intidx=av_find_nearest_q_idx(ost->frame_rate,ost->enc->supported_framerates);
  246. ost->frame_rate=ost->enc->supported_framerates[idx];
  247. }
  248. codec->time_base=(AVRational){ost->frame_rate.den,ost->frame_rate.num};
  249. if(av_q2d(codec->time_base)<0.001&&
  250. video_sync_method&&
  251. (video_sync_method==1||
  252. (video_sync_method<0&&!
  253. (oc->oformat->flags&AVFMT_VARIABLE_FPS))))
  254. {
  255. av_log(oc,AV_LOG_WARNING,"Framerateveryhighforamuxernoteffcicientlysupportingit.\n"
  256. "Pleaseconsiderspecifiyingalowerframerate,adifferentmuxeror-vsync2\n");
  257. }
  258. <span></span>for(j=0;j<ost->forced_kf_count;j++)
  259. ost->forced_kf_pts[j]=av_rescale_q(ost->forced_kf_pts[j],
  260. AV_TIME_BASE_Q,codec->time_base);
  261. break;
  262. caseAVMEDIA_TYPE_SUBTITLE:
  263. break;
  264. default:
  265. abort();
  266. break;
  267. }
  268. /*twopassmode*/
  269. if(codec->codec_id!=CODEC_ID_H264&&
  270. (codec->flags&(CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)))
  271. {
  272. charlogfilename[1024];
  273. FILE*f;
  274. snprintf(logfilename,sizeof(logfilename),"%s-%d.log",
  275. pass_logfilename_prefix?pass_logfilename_prefix:DEFAULT_PASS_LOGFILENAME_PREFIX,
  276. i);
  277. if(codec->flags&CODEC_FLAG_PASS2){
  278. char*logbuffer;
  279. size_tlogbuffer_size;
  280. if(cmdutils_read_file(logfilename,&logbuffer,&logbuffer_size)<0){
  281. av_log(NULL,AV_LOG_FATAL,
  282. "Errorreadinglogfile'%s'forpass-2encoding\n",
  283. logfilename);
  284. exit_program(1);
  285. }
  286. codec->stats_in=logbuffer;
  287. }
  288. if(codec->flags&CODEC_FLAG_PASS1){
  289. f=fopen(logfilename,"wb");
  290. if(!f){
  291. av_log(NULL,AV_LOG_FATAL,"Cannotwritelogfile'%s'forpass-1encoding:%s\n",
  292. logfilename,strerror(errno));
  293. exit_program(1);
  294. }
  295. ost->logfile=f;
  296. }
  297. }
  298. }
  299. if(codec->codec_type==AVMEDIA_TYPE_VIDEO){
  300. /*maximumvideobuffersizeis6-bytesperpixel,plusDPXheadersize(1664)*/
  301. //计算编码输出缓冲的大小,计算一个最大值
  302. intsize=codec->width*codec->height;
  303. bit_buffer_size=FFMAX(bit_buffer_size,7*size+10000);
  304. }
  305. }
  306. //分配编码后数据所在的缓冲
  307. if(!bit_buffer)
  308. bit_buffer=av_malloc(bit_buffer_size);
  309. if(!bit_buffer){
  310. av_log(NULL,AV_LOG_ERROR,
  311. "Cannotallocate%dbytesoutputbuffer\n",
  312. bit_buffer_size);
  313. returnAVERROR(ENOMEM);
  314. }
  315. //轮循所有输出流,打开每个输出流的编码器
  316. for(i=0;i<nb_output_streams;i++)
  317. {
  318. ost=&output_streams[i];
  319. if(ost->encoding_needed){
  320. //当然,只有在需要编码时才打开编码器
  321. AVCodec*codec=ost->enc;
  322. AVCodecContext*dec=input_streams[ost->source_index].st->codec;
  323. if(!codec){
  324. snprintf(error,sizeof(error),
  325. "Encoder(codec%s)notfoundforoutputstream#%d:%d",
  326. avcodec_get_name(ost->st->codec->codec_id),
  327. ost->file_index,ost->index);
  328. ret=AVERROR(EINVAL);
  329. gotodump_format;
  330. }
  331. if(dec->subtitle_header){
  332. ost->st->codec->subtitle_header=av_malloc(dec->subtitle_header_size);
  333. if(!ost->st->codec->subtitle_header){
  334. ret=AVERROR(ENOMEM);
  335. gotodump_format;
  336. }
  337. memcpy(ost->st->codec->subtitle_header,
  338. dec->subtitle_header,dec->subtitle_header_size);
  339. ost->st->codec->subtitle_header_size=dec->subtitle_header_size;
  340. }
  341. //打开啦
  342. if(avcodec_open2(ost->st->codec,codec,&ost->opts)<0){
  343. snprintf(error,sizeof(error),
  344. "Errorwhileopeningencoderforoutputstream#%d:%d-maybeincorrectparameterssuchasbit_rate,rate,widthorheight",
  345. ost->file_index,ost->index);
  346. ret=AVERROR(EINVAL);
  347. gotodump_format;
  348. }
  349. assert_codec_experimental(ost->st->codec,1);
  350. assert_avoptions(ost->opts);
  351. if(ost->st->codec->bit_rate&&ost->st->codec->bit_rate<1000)
  352. av_log(NULL,AV_LOG_WARNING,
  353. "Thebitrateparameterissettoolow."
  354. "Ittakesbits/sasargument,notkbits/s\n");
  355. extra_size+=ost->st->codec->extradata_size;
  356. if(ost->st->codec->me_threshold)
  357. input_streams[ost->source_index].st->codec->debug|=FF_DEBUG_MV;
  358. }
  359. }
  360. //初始化所有的输入流(主要做的就是在需要时打开解码器)
  361. for(i=0;i<nb_input_streams;i++)
  362. if((ret=init_input_stream(i,output_streams,nb_output_streams,
  363. error,sizeof(error)))<0)
  364. gotodump_format;
  365. /*discardunusedprograms*/
  366. for(i=0;i<nb_input_files;i++){
  367. InputFile*ifile=&input_files[i];
  368. for(j=0;j<ifile->ctx->nb_programs;j++){
  369. AVProgram*p=ifile->ctx->programs[j];
  370. intdiscard=AVDISCARD_ALL;
  371. for(k=0;k<p->nb_stream_indexes;k++){
  372. if(!input_streams[ifile->ist_index+p->stream_index[k]].discard){
  373. discard=AVDISCARD_DEFAULT;
  374. break;
  375. }
  376. }
  377. p->discard=discard;
  378. }
  379. }
  380. //打开所有输出文件,写入媒体文件头
  381. for(i=0;i<nb_output_files;i++){
  382. oc=output_files[i].ctx;
  383. oc->interrupt_callback=int_cb;
  384. if(avformat_write_header(oc,&output_files[i].opts)<0){
  385. snprintf(error,sizeof(error),
  386. "Couldnotwriteheaderforoutputfile#%d(incorrectcodecparameters?)",
  387. i);
  388. ret=AVERROR(EINVAL);
  389. gotodump_format;
  390. }
  391. //assert_avoptions(output_files[i].opts);
  392. if(strcmp(oc->oformat->name,"rtp")){
  393. want_sdp=0;
  394. }
  395. }
  396. return0;
  397. }

原文地址:http://blog.csdn.net/niu_gao/article/details/7175421

transcode_init()函数是在转换前做准备工作的.此处看一下它的真面目,不废话,看注释吧:

  1. //为转换过程做准备
  2. staticinttranscode_init(OutputFile*output_files,
  3. intnb_output_files,
  4. InputFile*input_files,
  5. intnb_input_files)
  6. {
  7. intret=0,i,j,k;
  8. AVFormatContext*oc;
  9. AVCodecContext*codec,*icodec;
  10. OutputStream*ost;
  11. InputStream*ist;
  12. charerror[1024];
  13. intwant_sdp=1;
  14. /*initframerateemulation*/
  15. //初始化帧率仿真(转换时是不按帧率来的,但如果要求帧率仿真,就可以做到)
  16. for(i=0;i<nb_input_files;i++)
  17. {
  18. InputFile*ifile=&input_files[i];
  19. //如果一个输入文件被要求帧率仿真(指的是即使是转换也像播放那样按照帧率来进行),
  20. //则为这个文件中所有流记录下开始时间
  21. if(ifile->rate_emu)
  22. for(j=0;j<ifile->nb_streams;j++)
  23. input_streams[j+ifile->ist_index].start=av_gettime();
  24. }
  25. /*outputstreaminit*/
  26. for(i=0;i<nb_output_files;i++)
  27. {
  28. //什么也没做,只是做了个判断而已
  29. oc=output_files[i].ctx;
  30. if(!oc->nb_streams&&!(oc->oformat->flags&AVFMT_NOSTREAMS))
  31. {
  32. av_dump_format(oc,i,oc->filename,1);
  33. av_log(NULL,AV_LOG_ERROR,
  34. "Outputfile#%ddoesnotcontainanystream\n",i);
  35. returnAVERROR(EINVAL);
  36. }
  37. }
  38. //轮循所有的输出流,跟据对应的输入流,设置其编解码器的参数
  39. for(i=0;i<nb_output_streams;i++)
  40. {
  41. //轮循所有的输出流
  42. ost=&output_streams[i];
  43. //输出流对应的FormatContext
  44. oc=output_files[ost->file_index].ctx;
  45. //取得输出流对应的输入流
  46. ist=&input_streams[ost->source_index];
  47. //attachment_filename是不是这样的东西:一个文件,它单独容纳一个输出流?此处不懂
  48. if(ost->attachment_filename)
  49. continue;
  50. codec=ost->st->codec;//输出流的编解码器结构
  51. icodec=ist->st->codec;//输入流的编解码器结构
  52. //先把能复制的复制一下
  53. ost->st->disposition=ist->st->disposition;
  54. codec->bits_per_raw_sample=icodec->bits_per_raw_sample;
  55. codec->chroma_sample_location=icodec->chroma_sample_location;
  56. //如果只是复制一个流(不用解码后再编码),则把输入流的编码参数直接复制给输出流
  57. //此时是不需要解码也不需要编码的,所以不需打开解码器和编码器
  58. if(ost->stream_copy)
  59. {
  60. //计算输出流的编解码器的extradata的大小,然后分配容纳extradata的缓冲
  61. //然后把输入流的编解码器的extradata复制到输出流的编解码器中
  62. uint64_textra_size=(uint64_t)icodec->extradata_size
  63. +FF_INPUT_BUFFER_PADDING_SIZE;
  64. if(extra_size>INT_MAX){
  65. returnAVERROR(EINVAL);
  66. }
  67. /*ifstream_copyisselected,noneedtodecodeorencode*/
  68. codec->codec_id=icodec->codec_id;
  69. codec->codec_type=icodec->codec_type;
  70. if(!codec->codec_tag){
  71. if(!oc->oformat->codec_tag
  72. ||av_codec_get_id(oc->oformat->codec_tag,icodec->codec_tag)==codec->codec_id
  73. ||av_codec_get_tag(oc->oformat->codec_tag,icodec->codec_id)<=0)
  74. codec->codec_tag=icodec->codec_tag;
  75. }
  76. codec->bit_rate=icodec->bit_rate;
  77. codec->rc_max_rate=icodec->rc_max_rate;
  78. codec->rc_buffer_size=icodec->rc_buffer_size;
  79. codec->extradata=av_mallocz(extra_size);
  80. if(!codec->extradata){
  81. returnAVERROR(ENOMEM);
  82. }
  83. memcpy(codec->extradata,icodec->extradata,icodec->extradata_size);
  84. codec->extradata_size=icodec->extradata_size;
  85. //重新鼓捣一下timebase(这家伙就是帧率)
  86. codec->time_base=ist->st->time_base;
  87. //如果输出文件是avi,做一点特殊处理
  88. if(!strcmp(oc->oformat->name,"avi")){
  89. if(copy_tb<0
  90. &&av_q2d(icodec->time_base)*icodec->ticks_per_frame>
  91. 2*av_q2d(ist->st->time_base)
  92. &&av_q2d(ist->st->time_base)<1.0/500
  93. ||copy_tb==0)
  94. {
  95. codec->time_base=icodec->time_base;
  96. codec->time_base.num*=icodec->ticks_per_frame;
  97. codec->time_base.den*=2;
  98. }
  99. }
  100. elseif(!(oc->oformat->flags&AVFMT_VARIABLE_FPS))
  101. {
  102. if(copy_tb<0
  103. &&av_q2d(icodec->time_base)*icodec->ticks_per_frame
  104. >av_q2d(ist->st->time_base)
  105. &&av_q2d(ist->st->time_base)<1.0/500
  106. ||copy_tb==0)
  107. {
  108. codec->time_base=icodec->time_base;
  109. codec->time_base.num*=icodec->ticks_per_frame;
  110. }
  111. }
  112. //再修正一下帧率
  113. av_reduce(&codec->time_base.num,&codec->time_base.den,
  114. codec->time_base.num,codec->time_base.den,INT_MAX);
  115. //单独复制各不同媒体自己的编码参数
  116. switch(codec->codec_type)
  117. {
  118. caseAVMEDIA_TYPE_AUDIO:
  119. //音频的
  120. if(audio_volume!=256){
  121. av_log(NULL,AV_LOG_FATAL,
  122. "-acodeccopyand-volareincompatible(framesarenotdecoded)\n");
  123. exit_program(1);
  124. }
  125. codec->channel_layout=icodec->channel_layout;
  126. codec->sample_rate=icodec->sample_rate;
  127. codec->channels=icodec->channels;
  128. codec->frame_size=icodec->frame_size;
  129. codec->audio_service_type=icodec->audio_service_type;
  130. codec->block_align=icodec->block_align;
  131. break;
  132. caseAVMEDIA_TYPE_VIDEO:
  133. //视频的
  134. codec->pix_fmt=icodec->pix_fmt;
  135. codec->width=icodec->width;
  136. codec->height=icodec->height;
  137. codec->has_b_frames=icodec->has_b_frames;
  138. if(!codec->sample_aspect_ratio.num){
  139. codec->sample_aspect_ratio=ost->st->sample_aspect_ratio=
  140. ist->st->sample_aspect_ratio.num?ist->st->sample_aspect_ratio:
  141. ist->st->codec->sample_aspect_ratio.num?ist->st->codec->sample_aspect_ratio:(AVRational){0,1};
  142. }
  143. ost->st->avg_frame_rate=ist->st->avg_frame_rate;
  144. break;
  145. caseAVMEDIA_TYPE_SUBTITLE:
  146. //字幕的
  147. codec->width=icodec->width;
  148. codec->height=icodec->height;
  149. break;
  150. caseAVMEDIA_TYPE_DATA:
  151. caseAVMEDIA_TYPE_ATTACHMENT:
  152. //??的
  153. break;
  154. default:
  155. abort();
  156. }
  157. }
  158. else
  159. {
  160. //如果不是复制,就麻烦多了
  161. //获取编码器
  162. if(!ost->enc)
  163. ost->enc=avcodec_find_encoder(ost->st->codec->codec_id);
  164. //因为需要转换,所以既需解码又需编码
  165. ist->decoding_needed=1;
  166. ost->encoding_needed=1;
  167. switch(codec->codec_type)
  168. {
  169. caseAVMEDIA_TYPE_AUDIO:
  170. //鼓捣音频编码器的参数,基本上是把一些不合适的参数替换掉
  171. ost->fifo=av_fifo_alloc(1024);//音频数据所在的缓冲
  172. if(!ost->fifo){
  173. returnAVERROR(ENOMEM);
  174. }
  175. //采样率
  176. if(!codec->sample_rate)
  177. codec->sample_rate=icodec->sample_rate;
  178. choose_sample_rate(ost->st,ost->enc);
  179. codec->time_base=(AVRational){1,codec->sample_rate};
  180. //样点格式
  181. if(codec->sample_fmt==AV_SAMPLE_FMT_NONE)
  182. codec->sample_fmt=icodec->sample_fmt;
  183. choose_sample_fmt(ost->st,ost->enc);
  184. //声道
  185. if(ost->audio_channels_mapped){
  186. /*therequestedoutputchannelissettothenumberof
  187. *-map_channelonlyifno-acarespecified*/
  188. if(!codec->channels){
  189. codec->channels=ost->audio_channels_mapped;
  190. codec->channel_layout=av_get_default_channel_layout(codec->channels);
  191. if(!codec->channel_layout){
  192. av_log(NULL,AV_LOG_FATAL,"Unabletofindanappropriatechannellayoutforrequestednumberofchannel\n);
  193. exit_program(1);
  194. }
  195. }
  196. /*fillunusedchannelmappingwith-1(whichmeansamuted
  197. *channelincasethenumberofoutputchannelsisbigger
  198. *thanthenumberofmappedchannel)*/
  199. for(j=ost->audio_channels_mapped;j<FF_ARRAY_ELEMS(ost->audio_channels_map);j++)
  200. <span></span>ost->audio_channels_map[j]=-1;
  201. }elseif(!codec->channels){
  202. codec->channels=icodec->channels;
  203. codec->channel_layout=icodec->channel_layout;
  204. }
  205. if(av_get_channel_layout_nb_channels(codec->channel_layout)!=codec->channels)
  206. codec->channel_layout=0;
  207. //是否需要重采样
  208. ost->audio_resample=codec->sample_rate!=icodec->sample_rate||audio_sync_method>1;
  209. ost->audio_resample|=codec->sample_fmt!=icodec->sample_fmt||
  210. codec->channel_layout!=icodec->channel_layout;
  211. icodec->request_channels=codec->channels;
  212. ost->resample_sample_fmt=icodec->sample_fmt;
  213. ost->resample_sample_rate=icodec->sample_rate;
  214. ost->resample_channels=icodec->channels;
  215. break;
  216. caseAVMEDIA_TYPE_VIDEO:
  217. //鼓捣视频编码器的参数,基本上是把一些不合适的参数替换掉
  218. if(codec->pix_fmt==PIX_FMT_NONE)
  219. codec->pix_fmt=icodec->pix_fmt;
  220. choose_pixel_fmt(ost->st,ost->enc);
  221. if(ost->st->codec->pix_fmt==PIX_FMT_NONE){
  222. av_log(NULL,AV_LOG_FATAL,"Videopixelformatisunknown,streamcannotbeencoded\n");
  223. exit_program(1);
  224. }
  225. //宽高
  226. if(!codec->width||!codec->height){
  227. codec->width=icodec->width;
  228. codec->height=icodec->height;
  229. }
  230. //视频是否需要重采样
  231. ost->video_resample=codec->width!=icodec->width||
  232. codec->height!=icodec->height||
  233. codec->pix_fmt!=icodec->pix_fmt;
  234. if(ost->video_resample){
  235. codec->bits_per_raw_sample=frame_bits_per_raw_sample;
  236. }
  237. ost->resample_height=icodec->height;
  238. ost->resample_width=icodec->width;
  239. ost->resample_pix_fmt=icodec->pix_fmt;
  240. //计算帧率
  241. if(!ost->frame_rate.num)
  242. ost->frame_rate=ist->st->r_frame_rate.num?
  243. ist->st->r_frame_rate:(AVRational){25,1};
  244. if(ost->enc&&ost->enc->supported_framerates&&!ost->force_fps){
  245. intidx=av_find_nearest_q_idx(ost->frame_rate,ost->enc->supported_framerates);
  246. ost->frame_rate=ost->enc->supported_framerates[idx];
  247. }
  248. codec->time_base=(AVRational){ost->frame_rate.den,ost->frame_rate.num};
  249. if(av_q2d(codec->time_base)<0.001&&
  250. video_sync_method&&
  251. (video_sync_method==1||
  252. (video_sync_method<0&&!
  253. (oc->oformat->flags&AVFMT_VARIABLE_FPS))))
  254. {
  255. av_log(oc,AV_LOG_WARNING,"Framerateveryhighforamuxernoteffcicientlysupportingit.\n"
  256. "Pleaseconsiderspecifiyingalowerframerate,adifferentmuxeror-vsync2\n");
  257. }
  258. <span></span>for(j=0;j<ost->forced_kf_count;j++)
  259. ost->forced_kf_pts[j]=av_rescale_q(ost->forced_kf_pts[j],
  260. AV_TIME_BASE_Q,codec->time_base);
  261. break;
  262. caseAVMEDIA_TYPE_SUBTITLE:
  263. break;
  264. default:
  265. abort();
  266. break;
  267. }
  268. /*twopassmode*/
  269. if(codec->codec_id!=CODEC_ID_H264&&
  270. (codec->flags&(CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)))
  271. {
  272. charlogfilename[1024];
  273. FILE*f;
  274. snprintf(logfilename,sizeof(logfilename),"%s-%d.log",
  275. pass_logfilename_prefix?pass_logfilename_prefix:DEFAULT_PASS_LOGFILENAME_PREFIX,
  276. i);
  277. if(codec->flags&CODEC_FLAG_PASS2){
  278. char*logbuffer;
  279. size_tlogbuffer_size;
  280. if(cmdutils_read_file(logfilename,&logbuffer,&logbuffer_size)<0){
  281. av_log(NULL,AV_LOG_FATAL,
  282. "Errorreadinglogfile'%s'forpass-2encoding\n",
  283. logfilename);
  284. exit_program(1);
  285. }
  286. codec->stats_in=logbuffer;
  287. }
  288. if(codec->flags&CODEC_FLAG_PASS1){
  289. f=fopen(logfilename,"wb");
  290. if(!f){
  291. av_log(NULL,AV_LOG_FATAL,"Cannotwritelogfile'%s'forpass-1encoding:%s\n",
  292. logfilename,strerror(errno));
  293. exit_program(1);
  294. }
  295. ost->logfile=f;
  296. }
  297. }
  298. }
  299. if(codec->codec_type==AVMEDIA_TYPE_VIDEO){
  300. /*maximumvideobuffersizeis6-bytesperpixel,plusDPXheadersize(1664)*/
  301. //计算编码输出缓冲的大小,计算一个最大值
  302. intsize=codec->width*codec->height;
  303. bit_buffer_size=FFMAX(bit_buffer_size,7*size+10000);
  304. }
  305. }
  306. //分配编码后数据所在的缓冲
  307. if(!bit_buffer)
  308. bit_buffer=av_malloc(bit_buffer_size);
  309. if(!bit_buffer){
  310. av_log(NULL,AV_LOG_ERROR,
  311. "Cannotallocate%dbytesoutputbuffer\n",
  312. bit_buffer_size);
  313. returnAVERROR(ENOMEM);
  314. }
  315. //轮循所有输出流,打开每个输出流的编码器
  316. for(i=0;i<nb_output_streams;i++)
  317. {
  318. ost=&output_streams[i];
  319. if(ost->encoding_needed){
  320. //当然,只有在需要编码时才打开编码器
  321. AVCodec*codec=ost->enc;
  322. AVCodecContext*dec=input_streams[ost->source_index].st->codec;
  323. if(!codec){
  324. snprintf(error,sizeof(error),
  325. "Encoder(codec%s)notfoundforoutputstream#%d:%d",
  326. avcodec_get_name(ost->st->codec->codec_id),
  327. ost->file_index,ost->index);
  328. ret=AVERROR(EINVAL);
  329. gotodump_format;
  330. }
  331. if(dec->subtitle_header){
  332. ost->st->codec->subtitle_header=av_malloc(dec->subtitle_header_size);
  333. if(!ost->st->codec->subtitle_header){
  334. ret=AVERROR(ENOMEM);
  335. gotodump_format;
  336. }
  337. memcpy(ost->st->codec->subtitle_header,
  338. dec->subtitle_header,dec->subtitle_header_size);
  339. ost->st->codec->subtitle_header_size=dec->subtitle_header_size;
  340. }
  341. //打开啦
  342. if(avcodec_open2(ost->st->codec,codec,&ost->opts)<0){
  343. snprintf(error,sizeof(error),
  344. "Errorwhileopeningencoderforoutputstream#%d:%d-maybeincorrectparameterssuchasbit_rate,rate,widthorheight",
  345. ost->file_index,ost->index);
  346. ret=AVERROR(EINVAL);
  347. gotodump_format;
  348. }
  349. assert_codec_experimental(ost->st->codec,1);
  350. assert_avoptions(ost->opts);
  351. if(ost->st->codec->bit_rate&&ost->st->codec->bit_rate<1000)
  352. av_log(NULL,AV_LOG_WARNING,
  353. "Thebitrateparameterissettoolow."
  354. "Ittakesbits/sasargument,notkbits/s\n");
  355. extra_size+=ost->st->codec->extradata_size;
  356. if(ost->st->codec->me_threshold)
  357. input_streams[ost->source_index].st->codec->debug|=FF_DEBUG_MV;
  358. }
  359. }
  360. //初始化所有的输入流(主要做的就是在需要时打开解码器)
  361. for(i=0;i<nb_input_streams;i++)
  362. if((ret=init_input_stream(i,output_streams,nb_output_streams,
  363. error,sizeof(error)))<0)
  364. gotodump_format;
  365. /*discardunusedprograms*/
  366. for(i=0;i<nb_input_files;i++){
  367. InputFile*ifile=&input_files[i];
  368. for(j=0;j<ifile->ctx->nb_programs;j++){
  369. AVProgram*p=ifile->ctx->programs[j];
  370. intdiscard=AVDISCARD_ALL;
  371. for(k=0;k<p->nb_stream_indexes;k++){
  372. if(!input_streams[ifile->ist_index+p->stream_index[k]].discard){
  373. discard=AVDISCARD_DEFAULT;
  374. break;
  375. }
  376. }
  377. p->discard=discard;
  378. }
  379. }
  380. //打开所有输出文件,写入媒体文件头
  381. for(i=0;i<nb_output_files;i++){
  382. oc=output_files[i].ctx;
  383. oc->interrupt_callback=int_cb;
  384. if(avformat_write_header(oc,&output_files[i].opts)<0){
  385. snprintf(error,sizeof(error),
  386. "Couldnotwriteheaderforoutputfile#%d(incorrectcodecparameters?)",
  387. i);
  388. ret=AVERROR(EINVAL);
  389. gotodump_format;
  390. }
  391. //assert_avoptions(output_files[i].opts);
  392. if(strcmp(oc->oformat->name,"rtp")){
  393. want_sdp=0;
  394. }
  395. }
  396. return0;
  397. }

原文地址:http://blog.csdn.net/niu_gao/article/details/7175421

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值