X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Ffileffmpeg.C;h=6cc3f58886c5a7887fe77d0229e218cc11dc19c1;hp=4d7c713b9304e202d45bd3d4ba79a51932f78c57;hb=066bf914215f31bbfe598f2cbce10d130f7fc519;hpb=f110e7626d433b4724befe0871a3a35f9f81f264 diff --git a/cinelerra-5.1/cinelerra/fileffmpeg.C b/cinelerra-5.1/cinelerra/fileffmpeg.C index 4d7c713b..6cc3f588 100644 --- a/cinelerra-5.1/cinelerra/fileffmpeg.C +++ b/cinelerra-5.1/cinelerra/fileffmpeg.C @@ -11,6 +11,7 @@ #include "bcwindowbase.h" #include "bitspopup.h" #include "ctype.h" +#include "edl.h" #include "ffmpeg.h" #include "filebase.h" #include "file.h" @@ -25,7 +26,7 @@ #include "videodevice.inc" FileFFMPEG::FileFFMPEG(Asset *asset, File *file) - : FileBase(asset, file) + : FileBase(asset, file) { ff = 0; if(asset->format == FILE_UNKNOWN) @@ -40,8 +41,7 @@ FileFFMPEG::~FileFFMPEG() FFMpegConfigNum::FFMpegConfigNum(BC_Window *window, int x, int y, char *title_text, int *output) - : BC_TumbleTextBox(window, (int64_t)*output, - (int64_t)-1, (int64_t)25000000, 100, y, 100) + : BC_TumbleTextBox(window, *output, -1, INT_MAX, 100, y, 100) { this->window = window; this->x = x; this->y = y; @@ -59,15 +59,23 @@ void FFMpegConfigNum::create_objects() BC_TumbleTextBox::create_objects(); } -int FFMpegConfigNum::update_text(const char *text) +int FFMpegConfigNum::update_param(const char *param, const char *opts) { - BC_TumbleTextBox::update(text); - return handle_event(); + char value[BCSTRLEN]; + if( !FFMPEG::get_ff_option(param, opts, value) ) { + if( (*output = atoi(value)) < 0 ) { + disable(1); + return 0; + } + } + BC_TumbleTextBox::update((int64_t)*output); + enable(); + return 1; } int FFMpegConfigNum::handle_event() { - *output = atol(get_text()); + *output = atoi(get_text()); return 1; } @@ -80,6 +88,22 @@ FFMpegAudioNum::FFMpegAudioNum(BC_Window *window, int FFMpegAudioBitrate::handle_event() { int ret = FFMpegAudioNum::handle_event(); + Asset *asset = window()->asset; + if( asset->ff_audio_bitrate > 0 ) + window()->quality->disable(); + else if( !window()->quality->get_textbox()->is_hidden() ) + window()->quality->enable(); + return ret; +} + +int FFMpegAudioQuality::handle_event() +{ + int ret = FFMpegAudioNum::handle_event(); + Asset *asset = window()->asset; + if( asset->ff_audio_quality >= 0 ) + window()->bitrate->disable(); + else if( !window()->bitrate->get_textbox()->is_hidden() ) + window()->bitrate->enable(); return ret; } @@ -93,9 +117,9 @@ int FFMpegVideoBitrate::handle_event() { int ret = FFMpegVideoNum::handle_event(); Asset *asset = window()->asset; - if( asset->ff_video_bitrate ) + if( asset->ff_video_bitrate > 0 ) window()->quality->disable(); - else + else if( !window()->quality->get_textbox()->is_hidden() ) window()->quality->enable(); return ret; } @@ -104,14 +128,76 @@ int FFMpegVideoQuality::handle_event() { int ret = FFMpegVideoNum::handle_event(); Asset *asset = window()->asset; - if( asset->ff_video_quality ) + if( asset->ff_video_quality >= 0 ) window()->bitrate->disable(); - else + else if( !window()->bitrate->get_textbox()->is_hidden() ) window()->bitrate->enable(); return ret; } -void FileFFMPEG::set_parameters(char *cp, int len, const char *bp) +FFMpegPixelFormat::FFMpegPixelFormat(FFMPEGConfigVideo *vid_config, + int x, int y, int w, int list_h) + : BC_PopupTextBox(vid_config, 0, 0, x, y, w, list_h) +{ + this->vid_config = vid_config; +} + +int FFMpegPixelFormat::handle_event() +{ + strncpy(vid_config->asset->ff_pixel_format, get_text(), + sizeof(vid_config->asset->ff_pixel_format)); + return 1; +} + +void FFMpegPixelFormat::update_formats() +{ + pixfmts.remove_all_objects(); + char video_codec[BCSTRLEN]; video_codec[0] = 0; + const char *vcodec = vid_config->asset->vcodec; + AVCodec *av_codec = !FFMPEG::get_codec(video_codec, "video", vcodec) ? + avcodec_find_encoder_by_name(video_codec) : 0; + const AVPixelFormat *pix_fmts = av_codec ? av_codec->pix_fmts : 0; + if( pix_fmts ) { + for( int i=0; pix_fmts[i]>=0; ++i ) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmts[i]); + if( desc ) pixfmts.append(new BC_ListBoxItem(desc->name)); + } + } + update_list(&pixfmts); +} + +FFMpegSampleFormat::FFMpegSampleFormat(FFMPEGConfigAudio *aud_config, + int x, int y, int w, int list_h) + : BC_PopupTextBox(aud_config, 0, 0, x, y, w, list_h) +{ + this->aud_config = aud_config; +} + +int FFMpegSampleFormat::handle_event() +{ + strncpy(aud_config->asset->ff_sample_format, get_text(), + sizeof(aud_config->asset->ff_sample_format)); + return 1; +} + +void FFMpegSampleFormat::update_formats() +{ + samplefmts.remove_all_objects(); + char audio_codec[BCSTRLEN]; audio_codec[0] = 0; + const char *acodec = aud_config->asset->acodec; + AVCodec *av_codec = !FFMPEG::get_codec(audio_codec, "audio", acodec) ? + avcodec_find_encoder_by_name(audio_codec) : 0; + const AVSampleFormat *sample_fmts = av_codec ? av_codec->sample_fmts : 0; + if( sample_fmts ) { + for( int i=0; sample_fmts[i]>=0; ++i ) { + const char *name = av_get_sample_fmt_name(sample_fmts[i]); + if( name ) samplefmts.append(new BC_ListBoxItem(name)); + } + } + update_list(&samplefmts); +} + +void FileFFMPEG::set_options(char *cp, int len, const char *bp) { char *ep = cp + len-2, ch = 0; while( cp < ep && *bp != 0 ) { ch = *bp++; *cp++ = ch; } @@ -121,26 +207,35 @@ void FileFFMPEG::set_parameters(char *cp, int len, const char *bp) void FileFFMPEG::get_parameters(BC_WindowBase *parent_window, Asset *asset, BC_WindowBase *&format_window, - int audio_options, int video_options) + int audio_options, int video_options, EDL *edl) { - if(audio_options) { - FFMPEGConfigAudio *window = new FFMPEGConfigAudio(parent_window, asset); + Asset *ff_asset = new Asset(); + ff_asset->copy_from(asset, 0); + if( audio_options ) { + FFMPEGConfigAudio *window = new FFMPEGConfigAudio(parent_window, ff_asset, edl); format_window = window; window->create_objects(); - if( !window->run_window() ) - set_parameters(asset->ff_audio_options, sizeof(asset->ff_audio_options), - window->audio_options->get_text()); + if( !window->run_window() ) { + asset->copy_from(ff_asset,0); + set_options(asset->ff_audio_options, + sizeof(asset->ff_audio_options), + window->audio_options->get_text()); + } delete window; } - else if(video_options) { - FFMPEGConfigVideo *window = new FFMPEGConfigVideo(parent_window, asset); + else if( video_options ) { + FFMPEGConfigVideo *window = new FFMPEGConfigVideo(parent_window, ff_asset, edl); format_window = window; window->create_objects(); - if( !window->run_window() ) - set_parameters(asset->ff_video_options, sizeof(asset->ff_video_options), - window->video_options->get_text()); + if( !window->run_window() ) { + asset->copy_from(ff_asset,0); + set_options(asset->ff_video_options, + sizeof(asset->ff_video_options), + window->video_options->get_text()); + } delete window; } + ff_asset->remove_user(); } int FileFFMPEG::check_sig(Asset *asset) @@ -203,7 +298,6 @@ int FileFFMPEG::select_video_stream(Asset *asset, int vstream) if( !ff || !asset->video_data ) return 1; asset->width = ff->ff_video_width(vstream); asset->height = ff->ff_video_height(vstream); - asset->video_length = ff->ff_video_frames(vstream); if( (asset->video_length = ff->ff_video_frames(vstream)) < 2 ) asset->video_length = asset->video_length < 0 ? 0 : -1; asset->frame_rate = ff->ff_frame_rate(vstream); @@ -234,6 +328,7 @@ int FileFFMPEG::open_file(int rd, int wr) asset->channels = audio_channels; asset->sample_rate = ff->ff_sample_rate(0); asset->audio_length = ff->ff_audio_samples(0); + strcpy(asset->acodec, ff->ff_audio_format(0)); } int video_layers = ff->ff_total_video_layers(); if( video_layers > 0 ) { @@ -247,6 +342,7 @@ int FileFFMPEG::open_file(int rd, int wr) (asset->video_length = ff->ff_video_frames(0)) < 2 ) asset->video_length = asset->video_length < 0 ? 0 : -1; if( !asset->frame_rate ) asset->frame_rate = ff->ff_frame_rate(0); + strcpy(asset->vcodec, ff->ff_video_format(0)); } IndexState *index_state = asset->index_state; index_state->read_markers(file->preferences->index_directory, asset->path); @@ -327,60 +423,37 @@ int FileFFMPEG::colormodel_supported(int colormodel) return colormodel; } -int FileFFMPEG::get_best_colormodel(Asset *asset, int driver) + +int FileFFMPEG::get_best_colormodel(int driver, int vstream) { + if( vstream < 0 ) vstream = 0; + int is_mpeg = !ff ? 0 : ff->ff_video_mpeg_color_range(vstream); + switch(driver) { case PLAYBACK_X11: - return BC_RGB888; - case PLAYBACK_X11_XV: - case PLAYBACK_ASYNCHRONOUS: - return BC_YUV888; - case PLAYBACK_X11_GL: - return BC_YUV888; - case PLAYBACK_DV1394: - case PLAYBACK_FIREWIRE: - return BC_YUV422P; - case VIDEO4LINUX2: - return BC_RGB888; - case VIDEO4LINUX2JPEG: - return BC_COMPRESSED; - case CAPTURE_DVB: - case VIDEO4LINUX2MPEG: - return BC_YUV422P; - case CAPTURE_JPEG_WEBCAM: - return BC_COMPRESSED; - case CAPTURE_YUYV_WEBCAM: - return BC_YUV422; - case CAPTURE_FIREWIRE: - case CAPTURE_IEC61883: - return BC_YUV422P; + case PLAYBACK_X11_GL: return is_mpeg ? BC_YUV888 : BC_RGB888; + case PLAYBACK_X11_XV: return BC_YUV420P; } return BC_RGB888; } - -int FileFFMPEG::get_ff_option(const char *nm, const char *options, char *value) +int FileFFMPEG::get_best_colormodel(Asset *asset, int driver) { - 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) ) { - strcpy(value, val); - return 0; - } + switch(driver) { +// the direct X11 color model requires scaling in the codec + case SCREENCAPTURE: + case PLAYBACK_X11: + case PLAYBACK_X11_GL: return BC_RGB888; + case PLAYBACK_X11_XV: return BC_YUV420P; } - return 1; + + return BC_YUV420P; } //====== -FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset) +FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset, EDL *edl) : BC_Window(_(PROGRAM_NAME ": Audio Preset"), parent_window->get_abs_cursor_x(1), parent_window->get_abs_cursor_y(1), @@ -388,6 +461,7 @@ FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset) { this->parent_window = parent_window; this->asset = asset; + this->edl = edl; preset_popup = 0; bitrate = 0; @@ -404,6 +478,11 @@ FFMPEGConfigAudio::~FFMPEGConfigAudio() unlock_window(); } +void FFMPEGConfigAudio::load_options() +{ + FFMPEG::load_audio_options(asset, edl); +} + void FFMPEGConfigAudio::create_objects() { int x = 10, y = 10; @@ -442,8 +521,26 @@ void FFMPEGConfigAudio::create_objects() bitrate = new FFMpegAudioBitrate(this, x, y, _("Bitrate:"), &asset->ff_audio_bitrate); bitrate->create_objects(); bitrate->set_increment(1000); + bitrate->set_boundaries((int64_t)0, (int64_t)INT_MAX); + y += bitrate->get_h() + 5; + quality = new FFMpegAudioQuality(this, x, y, _("Quality:"), &asset->ff_audio_quality); + quality->create_objects(); + quality->set_increment(1); + quality->set_boundaries((int64_t)-1, (int64_t)51); + y += quality->get_h() + 10; + + add_subwindow(new BC_Title(x, y, _("Samples:"))); + sample_format = new FFMpegSampleFormat(this, x+90, y, 100, 120); + sample_format->create_objects(); + if( asset->acodec[0] ) { + sample_format->update_formats(); + if( !asset->ff_audio_options[0] ) + load_options(); + } + if( !asset->ff_sample_format[0] ) strcpy(asset->ff_sample_format, _("None")); + sample_format->update(asset->ff_sample_format); + y += sample_format->get_h() + 10; - y += bitrate->get_h() + 10; BC_Title *title = new BC_Title(x, y, _("Audio Options:")); add_subwindow(title); @@ -452,24 +549,19 @@ void FFMPEGConfigAudio::create_objects() add_subwindow(new FFOptionsViewAudio(this, x1, y, _("view"))); y += 25; - if( !asset->ff_audio_options[0] && asset->acodec[0] ) { - FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec); - FFMPEG::load_options(option_path, asset->ff_audio_options, - sizeof(asset->ff_audio_options)); - } - - audio_options = new FFAudioOptions(this, x, y, get_w()-x-20, 10, + audio_options = new FFAudioOptions(this, x, y, get_w()-x-20, 8, sizeof(asset->ff_audio_options)-1, asset->ff_audio_options); audio_options->create_objects(); add_subwindow(new BC_OKButton(this)); add_subwindow(new BC_CancelButton(this)); + show_window(1); - char value[BCTEXTLEN]; - if( !FileFFMPEG::get_ff_option("cin_bitrate", asset->ff_audio_options, value) ) - bitrate->update_text(value); + bitrate->update_param("cin_bitrate", asset->ff_audio_options); + quality->update_param("cin_quality", asset->ff_audio_options); + + if( asset->ff_audio_bitrate > 0 ) quality->disable(); + else if( asset->ff_audio_quality >= 0 ) bitrate->disable(); - show_window(1); - bitrate->handle_event(); unlock_window(); } @@ -496,16 +588,16 @@ FFMPEGConfigAudioPopup::FFMPEGConfigAudioPopup(FFMPEGConfigAudio *popup, int x, int FFMPEGConfigAudioPopup::handle_event() { strcpy(popup->asset->acodec, get_text()); + popup->sample_format->update_formats(); Asset *asset = popup->asset; - char option_path[BCTEXTLEN]; - FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec); - FFMPEG::load_options(option_path, asset->ff_audio_options, - sizeof(asset->ff_audio_options)); + asset->ff_audio_bitrate = 0; asset->ff_audio_quality = -1; + popup->load_options(); popup->audio_options->update(asset->ff_audio_options); + popup->audio_options->set_text_row(0); - char value[BCTEXTLEN]; - if( !FileFFMPEG::get_ff_option("cin_bitrate", asset->ff_audio_options, value) ) - popup->bitrate->update_text(value); + popup->bitrate->update_param("cin_bitrate", asset->ff_audio_options); + popup->quality->update_param("cin_quality", asset->ff_audio_options); + popup->sample_format->update(asset->ff_sample_format); return 1; } @@ -525,7 +617,7 @@ int FFMPEGConfigAudioToggle::handle_event() //====== -FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset) +FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset, EDL *edl) : BC_Window(_(PROGRAM_NAME ": Video Preset"), parent_window->get_abs_cursor_x(1), parent_window->get_abs_cursor_y(1), @@ -533,7 +625,10 @@ FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset) { this->parent_window = parent_window; this->asset = asset; + this->edl = edl; preset_popup = 0; + ff_options_dialog = 0; + pixel_format = 0; bitrate = 0; quality = 0; @@ -542,13 +637,19 @@ FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset) FFMPEGConfigVideo::~FFMPEGConfigVideo() { - delete ff_options_dialog; lock_window("FFMPEGConfigVideo::~FFMPEGConfigVideo"); - if(preset_popup) delete preset_popup; + delete ff_options_dialog; + delete pixel_format; + delete preset_popup; presets.remove_all_objects(); unlock_window(); } +void FFMPEGConfigVideo::load_options() +{ + FFMPEG::load_video_options(asset, edl); +} + void FFMPEGConfigVideo::create_objects() { int x = 10, y = 10; @@ -584,22 +685,34 @@ void FFMPEGConfigVideo::create_objects() preset_popup = new FFMPEGConfigVideoPopup(this, x, y); preset_popup->create_objects(); - if( asset->ff_video_bitrate && asset->ff_video_quality ) { - asset->ff_video_bitrate = 0; - asset->ff_video_quality = 0; + if( asset->ff_video_bitrate > 0 && asset->ff_video_quality >= 0 ) { + asset->ff_video_bitrate = 0; asset->ff_video_quality = -1; } y += 50; bitrate = new FFMpegVideoBitrate(this, x, y, _("Bitrate:"), &asset->ff_video_bitrate); bitrate->create_objects(); bitrate->set_increment(100000); + bitrate->set_boundaries((int64_t)0, (int64_t)INT_MAX); y += bitrate->get_h() + 5; quality = new FFMpegVideoQuality(this, x, y, _("Quality:"), &asset->ff_video_quality); quality->create_objects(); quality->set_increment(1); - quality->set_boundaries((int64_t)0, (int64_t)31); - + quality->set_boundaries((int64_t)-1, (int64_t)51); y += quality->get_h() + 10; + + add_subwindow(new BC_Title(x, y, _("Pixels:"))); + pixel_format = new FFMpegPixelFormat(this, x+90, y, 100, 120); + pixel_format->create_objects(); + if( asset->vcodec[0] ) { + pixel_format->update_formats(); + if( !asset->ff_video_options[0] ) + load_options(); + } + if( !asset->ff_pixel_format[0] ) strcpy(asset->ff_pixel_format, _("None")); + pixel_format->update(asset->ff_pixel_format); + y += pixel_format->get_h() + 10; + BC_Title *title = new BC_Title(x, y, _("Video Options:")); add_subwindow(title); @@ -608,29 +721,18 @@ void FFMPEGConfigVideo::create_objects() add_subwindow(new FFOptionsViewVideo(this, x1, y, _("view"))); y += 25; - if( !asset->ff_video_options[0] && asset->vcodec[0] ) { - FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec); - FFMPEG::load_options(option_path, asset->ff_video_options, - sizeof(asset->ff_video_options)); - } - - video_options = new FFVideoOptions(this, x, y, get_w()-x-20, 10, + video_options = new FFVideoOptions(this, x, y, get_w()-x-20, 8, sizeof(asset->ff_video_options)-1, asset->ff_video_options); video_options->create_objects(); add_subwindow(new BC_OKButton(this)); add_subwindow(new BC_CancelButton(this)); + show_window(1); - char value[BCTEXTLEN]; - if( !FileFFMPEG::get_ff_option("cin_quality", asset->ff_video_options, value) ) - quality->update_text(value); - if( !FileFFMPEG::get_ff_option("cin_bitrate", asset->ff_video_options, value) ) - bitrate->update_text(value); + bitrate->update_param("cin_bitrate", asset->ff_video_options); + quality->update_param("cin_quality", asset->ff_video_options); - show_window(1); - if( asset->ff_video_bitrate ) - quality->disable(); - if( asset->ff_video_quality ) - bitrate->disable(); + if( asset->ff_video_bitrate > 0 ) quality->disable(); + else if( asset->ff_video_quality >= 0 ) bitrate->disable(); unlock_window(); } @@ -657,19 +759,16 @@ FFMPEGConfigVideoPopup::FFMPEGConfigVideoPopup(FFMPEGConfigVideo *popup, int x, int FFMPEGConfigVideoPopup::handle_event() { strcpy(popup->asset->vcodec, get_text()); + popup->pixel_format->update_formats(); Asset *asset = popup->asset; - char option_path[BCTEXTLEN]; - FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec); - FFMPEG::load_options(option_path, asset->ff_video_options, - sizeof(asset->ff_video_options)); + asset->ff_video_bitrate = 0; asset->ff_video_quality = -1; + popup->load_options(); popup->video_options->update(asset->ff_video_options); + popup->video_options->set_text_row(0); - char value[BCTEXTLEN]; - if( !FileFFMPEG::get_ff_option("cin_quality", asset->ff_video_options, value) ) { - popup->quality->update_text(value); - } - if( !FileFFMPEG::get_ff_option("cin_bitrate", asset->ff_video_options, value) ) - popup->bitrate->update_text(value); + popup->bitrate->update_param("cin_bitrate", asset->ff_video_options); + popup->quality->update_param("cin_quality", asset->ff_video_options); + popup->pixel_format->update(asset->ff_pixel_format); return 1; } @@ -864,16 +963,16 @@ char *FFOptions_Opt::get(char *vp, int sz) void *obj = (void *)options->obj; uint8_t *bp = 0; if( av_opt_get(obj, opt->name, 0, &bp) >= 0 && bp != 0 ) { - const char *val = (const char *)bp; + const char *val = (const char *)bp; if( opt->unit && *val ) { int id = atoi(val); const char *uid = unit_name(id); if( uid ) val = uid; } - cp = sz >= 0 ? strncpy(vp,val,sz) : strcpy(vp, val); - if( sz > 0 ) vp[sz-1] = 0; - av_freep(&bp); - } + cp = sz >= 0 ? strncpy(vp,val,sz) : strcpy(vp, val); + if( sz > 0 ) vp[sz-1] = 0; + av_freep(&bp); + } return cp; } @@ -1066,6 +1165,9 @@ void FFOptions::initialize(FFOptionsWindow *win, int kind) if( dupl ) continue; FFOptions_Opt *fopt = new FFOptions_Opt(this, opt, opt->name); append(fopt); + AVDictionaryEntry *elem = av_dict_get(win->dialog->ff_opts, + opt->name, 0, AV_DICT_IGNORE_SUFFIX); + if( elem && elem->value ) fopt->set(elem->value); char val[BCTEXTLEN], *vp = fopt->get(val, sizeof(val)); fopt->item_value->update(vp); }