+int FFMPEG::can_render(const char *fformat, const char *type)
+{
+ FileSystem fs;
+ char option_path[BCTEXTLEN];
+ FFMPEG::set_option_path(option_path, type);
+ fs.update(option_path);
+ int total_files = fs.total_files();
+ for( int i=0; i<total_files; ++i ) {
+ const char *name = fs.get_entry(i)->get_name();
+ const char *ext = strrchr(name,'.');
+ if( !ext ) continue;
+ if( !strcmp(fformat, ++ext) ) return 1;
+ }
+ return 0;
+}
+
+int FFMPEG::get_ff_option(const char *nm, const char *options, char *value)
+{
+ for( const char *cp=options; *cp!=0; ) {
+ char line[BCTEXTLEN], *bp = line, *ep = bp+sizeof(line)-1;
+ while( bp < ep && *cp && *cp!='\n' ) *bp++ = *cp++;
+ if( *cp ) ++cp;
+ *bp = 0;
+ if( !line[0] || line[0] == '#' || line[0] == ';' ) continue;
+ char key[BCSTRLEN], val[BCTEXTLEN];
+ if( FFMPEG::scan_option_line(line, key, val) ) continue;
+ if( !strcmp(key, nm) ) {
+ strncpy(value, val, BCSTRLEN);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void FFMPEG::scan_audio_options(Asset *asset, EDL *edl)
+{
+ char cin_sample_fmt[BCSTRLEN];
+ int cin_fmt = AV_SAMPLE_FMT_NONE;
+ const char *options = asset->ff_audio_options;
+ if( !get_ff_option("cin_sample_fmt", options, cin_sample_fmt) )
+ cin_fmt = (int)av_get_sample_fmt(cin_sample_fmt);
+ if( cin_fmt < 0 ) {
+ char audio_codec[BCSTRLEN]; audio_codec[0] = 0;
+ AVCodec *av_codec = !FFMPEG::get_codec(audio_codec, "audio", asset->acodec) ?
+ avcodec_find_encoder_by_name(audio_codec) : 0;
+ if( av_codec && av_codec->sample_fmts )
+ cin_fmt = find_best_sample_fmt_of_list(av_codec->sample_fmts, AV_SAMPLE_FMT_FLT);
+ }
+ if( cin_fmt < 0 ) cin_fmt = AV_SAMPLE_FMT_S16;
+ const char *name = av_get_sample_fmt_name((AVSampleFormat)cin_fmt);
+ if( !name ) name = _("None");
+ strcpy(asset->ff_sample_format, name);
+
+ char value[BCSTRLEN];
+ if( !get_ff_option("cin_bitrate", options, value) )
+ asset->ff_audio_bitrate = atoi(value);
+ if( !get_ff_option("cin_quality", options, value) )
+ asset->ff_audio_quality = atoi(value);
+}
+
+void FFMPEG::load_audio_options(Asset *asset, EDL *edl)
+{
+ char options_path[BCTEXTLEN];
+ set_option_path(options_path, "audio/%s", asset->acodec);
+ if( !load_options(options_path,
+ asset->ff_audio_options,
+ sizeof(asset->ff_audio_options)) )
+ scan_audio_options(asset, edl);
+}
+
+void FFMPEG::scan_video_options(Asset *asset, EDL *edl)
+{
+ char cin_pix_fmt[BCSTRLEN];
+ int cin_fmt = AV_PIX_FMT_NONE;
+ const char *options = asset->ff_video_options;
+ if( !get_ff_option("cin_pix_fmt", options, cin_pix_fmt) )
+ cin_fmt = (int)av_get_pix_fmt(cin_pix_fmt);
+ if( cin_fmt < 0 ) {
+ char video_codec[BCSTRLEN]; video_codec[0] = 0;
+ AVCodec *av_codec = !get_codec(video_codec, "video", asset->vcodec) ?
+ avcodec_find_encoder_by_name(video_codec) : 0;
+ if( av_codec && av_codec->pix_fmts ) {
+ if( edl ) {
+ int color_model = edl->session->color_model;
+ int max_bits = BC_CModels::calculate_pixelsize(color_model) * 8;
+ max_bits /= BC_CModels::components(color_model);
+ cin_fmt = avcodec_find_best_pix_fmt_of_list(av_codec->pix_fmts,
+ (BC_CModels::is_yuv(color_model) ?
+ (max_bits > 8 ? AV_PIX_FMT_AYUV64LE : AV_PIX_FMT_YUV444P) :
+ (max_bits > 8 ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB24)), 0, 0);
+ }
+ else
+ cin_fmt = av_codec->pix_fmts[0];
+ }
+ }
+ if( cin_fmt < 0 ) cin_fmt = AV_PIX_FMT_YUV420P;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((AVPixelFormat)cin_fmt);
+ const char *name = desc ? desc->name : _("None");
+ strcpy(asset->ff_pixel_format, name);
+
+ char value[BCSTRLEN];
+ if( !get_ff_option("cin_bitrate", options, value) )
+ asset->ff_video_bitrate = atoi(value);
+ if( !get_ff_option("cin_quality", options, value) )
+ asset->ff_video_quality = atoi(value);
+}
+
+void FFMPEG::load_video_options(Asset *asset, EDL *edl)
+{
+ char options_path[BCTEXTLEN];
+ set_option_path(options_path, "video/%s", asset->vcodec);
+ if( !load_options(options_path,
+ asset->ff_video_options,
+ sizeof(asset->ff_video_options)) )
+ scan_video_options(asset, edl);
+}
+
+int FFMPEG::load_defaults(const char *path, const char *type,
+ char *codec, char *codec_options, int len)
+{
+ char default_file[BCTEXTLEN];
+ set_option_path(default_file, "%s/%s.dfl", path, type);
+ FILE *fp = fopen(default_file,"r");
+ if( !fp ) return 1;
+ fgets(codec, BCSTRLEN, fp);
+ char *cp = codec;
+ while( *cp && *cp!='\n' ) ++cp;
+ *cp = 0;
+ while( len > 0 && fgets(codec_options, len, fp) ) {
+ int n = strlen(codec_options);
+ codec_options += n; len -= n;
+ }
+ fclose(fp);
+ set_option_path(default_file, "%s/%s", path, codec);
+ return load_options(default_file, codec_options, len);
+}
+
+void FFMPEG::set_asset_format(Asset *asset, EDL *edl, const char *text)
+{
+ if( asset->format != FILE_FFMPEG ) return;
+ if( text != asset->fformat )
+ strcpy(asset->fformat, text);
+ if( asset->audio_data && !asset->ff_audio_options[0] ) {
+ if( !load_defaults("audio", text, asset->acodec,
+ asset->ff_audio_options, sizeof(asset->ff_audio_options)) )
+ scan_audio_options(asset, edl);
+ else
+ asset->audio_data = 0;
+ }
+ if( asset->video_data && !asset->ff_video_options[0] ) {
+ if( !load_defaults("video", text, asset->vcodec,
+ asset->ff_video_options, sizeof(asset->ff_video_options)) )
+ scan_video_options(asset, edl);
+ else
+ asset->video_data = 0;
+ }
+}
+