diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-12-16 14:53:22 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-12-16 14:53:22 +0000 |
| commit | aa230169f8b59b7cb2da9a3bbb8ce5f7600285c0 (patch) | |
| tree | 5cde52f6c50b9a56597e0f6ebad1f8e4aa5e1c8d /src | |
| parent | 7fd2aff3af82d3e573934d046be26b72a67a93e6 (diff) | |
| parent | 3ce37f08e98b9c3a238fb1c9a6184fb7fd4e5667 (diff) | |
Merge speed-up branch.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/examine_content_job.cc | 54 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 17 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.h | 3 | ||||
| -rw-r--r-- | src/lib/film.cc | 23 | ||||
| -rw-r--r-- | src/lib/film.h | 8 | ||||
| -rw-r--r-- | src/lib/imagemagick_decoder.h | 5 | ||||
| -rw-r--r-- | src/lib/transcoder.cc | 8 | ||||
| -rw-r--r-- | src/lib/transcoder.h | 4 | ||||
| -rw-r--r-- | src/lib/video_decoder.h | 2 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 21 | ||||
| -rw-r--r-- | src/wx/film_editor.h | 2 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 4 |
12 files changed, 117 insertions, 34 deletions
diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc index dc2fc305c..70a04b825 100644 --- a/src/lib/examine_content_job.cc +++ b/src/lib/examine_content_job.cc @@ -59,30 +59,46 @@ ExamineContentJob::name () const void ExamineContentJob::run () { - /* Decode the content to get an accurate length */ + descend (1); - /* We don't want to use any existing length here, as progress - will be messed up. + /* Set the film's length to either + a) a length judged by running through the content or + b) the length from a decoder's header. */ - _film->unset_length (); - _film->set_crop (Crop ()); + if (!_film->trust_content_header()) { + /* Decode the content to get an accurate length */ + + /* We don't want to use any existing length here, as progress + will be messed up. + */ + _film->unset_length (); + _film->set_crop (Crop ()); + + shared_ptr<DecodeOptions> o (new DecodeOptions); + o->decode_audio = false; + + Decoders decoders = decoder_factory (_film, o, this); + + set_progress_unknown (); + while (!decoders.video->pass()) { + /* keep going */ + } + + _film->set_length (decoders.video->video_frame()); + + _film->log()->log (String::compose ("Video length examined as %1 frames", _film->length().get())); + + } else { + + /* Get a quick decoder to get the content's length from its header */ + + shared_ptr<DecodeOptions> o (new DecodeOptions); + Decoders d = decoder_factory (_film, o, 0); + _film->set_length (d.video->length()); - shared_ptr<DecodeOptions> o (new DecodeOptions); - o->decode_audio = false; - - descend (1); - - Decoders decoders = decoder_factory (_film, o, this); - - set_progress_unknown (); - while (!decoders.video->pass()) { - /* keep going */ + _film->log()->log (String::compose ("Video length obtained from header as %1 frames", _film->length().get())); } - _film->set_length (decoders.video->video_frame()); - - _film->log()->log (String::compose ("Video length is %1 frames", _film->length())); - ascend (); set_progress (1); set_state (FINISHED_OK); diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 24ee89b21..136843190 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -164,14 +164,7 @@ FFmpegDecoder::setup_video () throw DecodeError ("could not find video decoder"); } - /* I think this prevents problems with green hash on decodes and - "changing frame properties on the fly is not supported by all filters" - messages with some content. Although I'm not sure; needs checking. - */ - AVDictionary* opts = 0; - av_dict_set (&opts, "threads", "1", 0); - - if (avcodec_open2 (_video_codec_context, _video_codec, &opts) < 0) { + if (avcodec_open2 (_video_codec_context, _video_codec, 0) < 0) { throw DecodeError ("could not open video decoder"); } } @@ -616,7 +609,6 @@ FFmpegAudioStream::to_string () const return String::compose ("ffmpeg %1 %2 %3 %4", _id, _sample_rate, _channel_layout, _name); } - void FFmpegDecoder::out_with_sync () { @@ -680,3 +672,10 @@ FFmpegDecoder::film_changed (Film::Property p) } } +/** @return Length (in video frames) according to our content's header */ +SourceFrame +FFmpegDecoder::length () const +{ + return (double(_format_context->duration) / AV_TIME_BASE) * frames_per_second(); +} + diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 1db46a423..35688003e 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -58,7 +58,7 @@ public: , _name (n) , _id (i) {} - + std::string to_string () const; std::string name () const { @@ -91,6 +91,7 @@ public: float frames_per_second () const; Size native_size () const; + SourceFrame length () const; int time_base_numerator () const; int time_base_denominator () const; int sample_aspect_ratio_numerator () const; diff --git a/src/lib/film.cc b/src/lib/film.cc index e7f47c462..4cfe7de0a 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -85,6 +85,7 @@ int const Film::state_version = 1; Film::Film (string d, bool must_exist) : _use_dci_name (true) + , _trust_content_header (true) , _dcp_content_type (0) , _format (0) , _scaler (Scaler::from_id ("bicubic")) @@ -143,6 +144,7 @@ Film::Film (Film const & o) , _name (o._name) , _use_dci_name (o._use_dci_name) , _content (o._content) + , _trust_content_header (o._trust_content_header) , _dcp_content_type (o._dcp_content_type) , _format (o._format) , _crop (o._crop) @@ -369,6 +371,7 @@ Film::write_metadata () const f << "name " << _name << "\n"; f << "use_dci_name " << _use_dci_name << "\n"; f << "content " << _content << "\n"; + f << "trust_content_header " << (_trust_content_header ? "1" : "0") << "\n"; if (_dcp_content_type) { f << "dcp_content_type " << _dcp_content_type->pretty_name () << "\n"; } @@ -471,6 +474,8 @@ Film::read_metadata () _use_dci_name = (v == "1"); } else if (k == "content") { _content = v; + } else if (k == "trust_content_header") { + _trust_content_header = (v == "1"); } else if (k == "dcp_content_type") { _dcp_content_type = DCPContentType::from_pretty_name (v); } else if (k == "format") { @@ -871,7 +876,7 @@ Film::set_content (string c) signal_changed (CONTENT); set_content_digest (md5_digest (content_path ())); - + examine_content (); } catch (...) { @@ -882,6 +887,22 @@ Film::set_content (string c) } } + +void +Film::set_trust_content_header (bool t) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + _trust_content_header = t; + } + + signal_changed (TRUST_CONTENT_HEADER); + + if (!_trust_content_header && !content().empty()) { + /* We just said that we don't trust the content's header */ + examine_content (); + } +} void Film::set_dcp_content_type (DCPContentType const * t) diff --git a/src/lib/film.h b/src/lib/film.h index c7ebdef12..642f2d7da 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -105,6 +105,7 @@ public: NAME, USE_DCI_NAME, CONTENT, + TRUST_CONTENT_HEADER, DCP_CONTENT_TYPE, FORMAT, CROP, @@ -154,6 +155,11 @@ public: return _content; } + bool trust_content_header () const { + boost::mutex::scoped_lock lm (_state_mutex); + return _trust_content_header; + } + DCPContentType const * dcp_content_type () const { boost::mutex::scoped_lock lm (_state_mutex); return _dcp_content_type; @@ -318,6 +324,7 @@ public: void set_name (std::string); void set_use_dci_name (bool); void set_content (std::string); + void set_trust_content_header (bool); void set_dcp_content_type (DCPContentType const *); void set_format (Format const *); void set_crop (Crop); @@ -390,6 +397,7 @@ private: * or an absolute path. */ std::string _content; + bool _trust_content_header; /** The type of content that this Film represents (feature, trailer etc.) */ DCPContentType const * _dcp_content_type; /** The format to present this Film in (flat, scope, etc.) */ diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index 75107ef4f..cfcf4b4f6 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -35,6 +35,11 @@ public: Size native_size () const; + SourceFrame length () const { + /* We don't know */ + return 0; + } + int audio_channels () const { return 0; } diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc index f44a3ed7b..87a1fb3f2 100644 --- a/src/lib/transcoder.cc +++ b/src/lib/transcoder.cc @@ -64,7 +64,9 @@ Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const DecodeOptions> o, J /* Set up the decoder to use the film's set streams */ _decoders.video->set_subtitle_stream (f->subtitle_stream ()); - _decoders.audio->set_audio_stream (f->audio_stream ()); + if (_decoders.audio) { + _decoders.audio->set_audio_stream (f->audio_stream ()); + } if (_matcher) { _decoders.video->connect_video (_matcher); @@ -73,7 +75,7 @@ Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const DecodeOptions> o, J _decoders.video->connect_video (_encoder); } - if (_matcher && _delay_line) { + if (_matcher && _delay_line && _decoders.audio) { _decoders.audio->connect_audio (_delay_line); _delay_line->connect_audio (_matcher); _matcher->connect_audio (_gain); @@ -97,7 +99,7 @@ Transcoder::go () _decoders.video->set_progress (); } - if (!done[1] && dynamic_pointer_cast<Decoder> (_decoders.audio) != dynamic_pointer_cast<Decoder> (_decoders.video)) { + if (!done[1] && _decoders.audio && dynamic_pointer_cast<Decoder> (_decoders.audio) != dynamic_pointer_cast<Decoder> (_decoders.video)) { done[1] = _decoders.audio->pass (); } else { done[1] = true; diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h index f27984aaa..b50113742 100644 --- a/src/lib/transcoder.h +++ b/src/lib/transcoder.h @@ -57,6 +57,10 @@ public: void go (); + boost::shared_ptr<VideoDecoder> video_decoder () const { + return _decoders.video; + } + protected: /** A Job that is running this Transcoder, or 0 */ Job* _job; diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index 41e876e0a..f682941d1 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -33,6 +33,8 @@ public: virtual float frames_per_second () const = 0; /** @return native size in pixels */ virtual Size native_size () const = 0; + /** @return length (in source video frames), according to our content's header */ + virtual SourceFrame length () const = 0; virtual int time_base_numerator () const = 0; virtual int time_base_denominator () const = 0; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 7083290c5..d33f89ce6 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -114,6 +114,11 @@ FilmEditor::make_film_panel () _content = new wxFilePickerCtrl (_film_panel, wxID_ANY, wxT (""), wxT ("Select Content File"), wxT("*.*")); _film_sizer->Add (_content, 1, wxEXPAND); + _trust_content_header = new wxCheckBox (_film_panel, wxID_ANY, wxT ("Trust content's header")); + video_control (_trust_content_header); + _film_sizer->Add (_trust_content_header, 1); + _film_sizer->AddSpacer (0); + add_label_to_sizer (_film_sizer, _film_panel, "Content Type"); _dcp_content_type = new wxComboBox (_film_panel, wxID_ANY, wxT (""), wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_READONLY); _film_sizer->Add (_dcp_content_type); @@ -174,6 +179,7 @@ FilmEditor::connect_to_widgets () _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this); _format->Connect (wxID_ANY, wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this); _content->Connect (wxID_ANY, wxEVT_COMMAND_FILEPICKER_CHANGED, wxCommandEventHandler (FilmEditor::content_changed), 0, this); + _trust_content_header->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_header_changed), 0, this); _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this); _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this); _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this); @@ -427,6 +433,16 @@ FilmEditor::content_changed (wxCommandEvent &) } } +void +FilmEditor::trust_content_header_changed (wxCommandEvent &) +{ + if (!_film) { + return; + } + + _film->set_trust_content_header (_trust_content_header->GetValue ()); +} + /** Called when the DCP A/B switch has been toggled */ void FilmEditor::dcp_ab_toggled (wxCommandEvent &) @@ -495,6 +511,9 @@ FilmEditor::film_changed (Film::Property p) setup_subtitle_control_sensitivity (); setup_streams (); break; + case Film::TRUST_CONTENT_HEADER: + checked_set (_trust_content_header, _film->trust_content_header ()); + break; case Film::SUBTITLE_STREAMS: setup_subtitle_control_sensitivity (); setup_streams (); @@ -692,6 +711,7 @@ FilmEditor::set_film (shared_ptr<Film> f) film_changed (Film::NAME); film_changed (Film::USE_DCI_NAME); film_changed (Film::CONTENT); + film_changed (Film::TRUST_CONTENT_HEADER); film_changed (Film::DCP_CONTENT_TYPE); film_changed (Film::FORMAT); film_changed (Film::CROP); @@ -729,6 +749,7 @@ FilmEditor::set_things_sensitive (bool s) _edit_dci_button->Enable (s); _format->Enable (s); _content->Enable (s); + _trust_content_header->Enable (s); _left_crop->Enable (s); _right_crop->Enable (s); _top_crop->Enable (s); diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index 428b994b8..7e75b4bf0 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -61,6 +61,7 @@ private: void top_crop_changed (wxCommandEvent &); void bottom_crop_changed (wxCommandEvent &); void content_changed (wxCommandEvent &); + void trust_content_header_changed (wxCommandEvent &); void format_changed (wxCommandEvent &); void dcp_trim_start_changed (wxCommandEvent &); void dcp_trim_end_changed (wxCommandEvent &); @@ -118,6 +119,7 @@ private: wxComboBox* _format; /** The Film's content file */ wxFilePickerCtrl* _content; + wxCheckBox* _trust_content_header; /** The Film's left crop */ wxSpinCtrl* _left_crop; /** The Film's right crop */ diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 1cf45fd4e..8312fa5e5 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -168,7 +168,9 @@ FilmViewer::slider_moved (wxCommandEvent& ev) void FilmViewer::seek_and_update (SourceFrame f) { - _decoders.video->seek (f); + if (_decoders.video->seek (f)) { + return; + } shared_ptr<Image> last = _display; while (last == _display) { |
