X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_content.cc;h=00499cf135a737be9672cfec85b503485bc9bf49;hb=38fda7888663429d452b9c71902e8bb5239dd720;hp=b030fe397bc1cc3b188a4e9567e770893ee14ef7;hpb=8db8de91e2a5489da345fae7544753f4cb2f5ab4;p=dcpomatic.git diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index b030fe397..00499cf13 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -19,11 +19,12 @@ #include #include "ffmpeg_content.h" -#include "ffmpeg_decoder.h" +#include "ffmpeg_examiner.h" #include "compose.hpp" #include "job.h" #include "util.h" #include "filter.h" +#include "film.h" #include "log.h" #include "i18n.h" @@ -33,6 +34,7 @@ using std::stringstream; using std::vector; using std::list; using std::cout; +using std::pair; using boost::shared_ptr; using boost::lexical_cast; @@ -46,6 +48,7 @@ FFmpegContent::FFmpegContent (shared_ptr f, boost::filesystem::path : Content (f, p) , VideoContent (f, p) , AudioContent (f, p) + , SubtitleContent (f, p) { } @@ -54,6 +57,7 @@ FFmpegContent::FFmpegContent (shared_ptr f, shared_ptr > c = node->node_children ("SubtitleStream"); for (list >::const_iterator i = c.begin(); i != c.end(); ++i) { @@ -75,18 +79,8 @@ FFmpegContent::FFmpegContent (shared_ptr f, shared_ptr >::iterator i = c.begin(); i != c.end(); ++i) { _filters.push_back (Filter::from_id ((*i)->content ())); } -} - -FFmpegContent::FFmpegContent (FFmpegContent const & o) - : Content (o) - , VideoContent (o) - , AudioContent (o) - , _subtitle_streams (o._subtitle_streams) - , _subtitle_stream (o._subtitle_stream) - , _audio_streams (o._audio_streams) - , _audio_stream (o._audio_stream) -{ + _first_video = node->optional_number_child ("FirstVideo"); } void @@ -96,6 +90,7 @@ FFmpegContent::as_xml (xmlpp::Node* node) const Content::as_xml (node); VideoContent::as_xml (node); AudioContent::as_xml (node); + SubtitleContent::as_xml (node); boost::mutex::scoped_lock lm (_mutex); @@ -118,6 +113,10 @@ FFmpegContent::as_xml (xmlpp::Node* node) const for (vector::const_iterator i = _filters.begin(); i != _filters.end(); ++i) { node->add_child("Filter")->add_child_text ((*i)->id ()); } + + if (_first_video) { + node->add_child("FirstVideo")->add_child_text (lexical_cast (_first_video.get ())); + } } void @@ -130,42 +129,66 @@ FFmpegContent::examine (shared_ptr job) shared_ptr film = _film.lock (); assert (film); - shared_ptr decoder (new FFmpegDecoder (film, shared_from_this (), true, false)); + shared_ptr examiner (new FFmpegExaminer (shared_from_this ())); + + VideoContent::Frame video_length = 0; + video_length = examiner->video_length (); + film->log()->log (String::compose ("Video length obtained from header as %1 frames", video_length)); - ContentVideoFrame video_length = 0; - video_length = decoder->video_length (); - film->log()->log (String::compose ("Video length obtained from header as %1 frames", decoder->video_length ())); + { + boost::mutex::scoped_lock lm (_mutex); - { - boost::mutex::scoped_lock lm (_mutex); + _video_length = video_length; - _video_length = video_length; + _subtitle_streams = examiner->subtitle_streams (); + if (!_subtitle_streams.empty ()) { + _subtitle_stream = _subtitle_streams.front (); + } + + _audio_streams = examiner->audio_streams (); + if (!_audio_streams.empty ()) { + _audio_stream = _audio_streams.front (); + } - _subtitle_streams = decoder->subtitle_streams (); - if (!_subtitle_streams.empty ()) { - _subtitle_stream = _subtitle_streams.front (); - } - - _audio_streams = decoder->audio_streams (); - if (!_audio_streams.empty ()) { - _audio_stream = _audio_streams.front (); - } - } + _first_video = examiner->first_video (); + } - take_from_video_decoder (decoder); + take_from_video_examiner (examiner); - signal_changed (ContentProperty::LENGTH); - signal_changed (FFmpegContentProperty::SUBTITLE_STREAMS); - signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); - signal_changed (FFmpegContentProperty::AUDIO_STREAMS); - signal_changed (FFmpegContentProperty::AUDIO_STREAM); - signal_changed (AudioContentProperty::AUDIO_CHANNELS); + signal_changed (ContentProperty::LENGTH); + signal_changed (FFmpegContentProperty::SUBTITLE_STREAMS); + signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); + signal_changed (FFmpegContentProperty::AUDIO_STREAMS); + signal_changed (FFmpegContentProperty::AUDIO_STREAM); + signal_changed (AudioContentProperty::AUDIO_CHANNELS); } string FFmpegContent::summary () const { - return String::compose (_("Movie: %1"), file().filename().string()); + return String::compose (_("%1 [movie]"), file().filename().string()); +} + +string +FFmpegContent::technical_summary () const +{ + string as = "none"; + if (_audio_stream) { + as = String::compose ("id %1", _audio_stream->id); + } + + string ss = "none"; + if (_subtitle_stream) { + ss = String::compose ("id %1", _subtitle_stream->id); + } + + pair filt = Filter::ffmpeg_strings (_filters); + + return Content::technical_summary() + " - " + + VideoContent::technical_summary() + " - " + + String::compose ( + "ffmpeg: audio %1, subtitle %2, filters %3 %4", as, ss, filt.first, filt.second + ); } string @@ -186,38 +209,38 @@ FFmpegContent::information () const void FFmpegContent::set_subtitle_stream (shared_ptr s) { - { - boost::mutex::scoped_lock lm (_mutex); - _subtitle_stream = s; - } + { + boost::mutex::scoped_lock lm (_mutex); + _subtitle_stream = s; + } - signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); + signal_changed (FFmpegContentProperty::SUBTITLE_STREAM); } void FFmpegContent::set_audio_stream (shared_ptr s) { - { - boost::mutex::scoped_lock lm (_mutex); - _audio_stream = s; - } + { + boost::mutex::scoped_lock lm (_mutex); + _audio_stream = s; + } - signal_changed (FFmpegContentProperty::AUDIO_STREAM); + signal_changed (FFmpegContentProperty::AUDIO_STREAM); } -ContentAudioFrame +AudioContent::Frame FFmpegContent::audio_length () const { int const cafr = content_audio_frame_rate (); int const vfr = video_frame_rate (); - ContentVideoFrame const vl = video_length (); + VideoContent::Frame const vl = video_length (); boost::mutex::scoped_lock lm (_mutex); - if (!_audio_stream) { - return 0; - } - - return video_frames_to_audio_frames (vl, cafr, vfr); + if (!_audio_stream) { + return 0; + } + + return video_frames_to_audio_frames (vl, cafr, vfr); } int @@ -225,11 +248,11 @@ FFmpegContent::audio_channels () const { boost::mutex::scoped_lock lm (_mutex); - if (!_audio_stream) { - return 0; - } + if (!_audio_stream) { + return 0; + } - return _audio_stream->channels; + return _audio_stream->channels; } int @@ -237,11 +260,11 @@ FFmpegContent::content_audio_frame_rate () const { boost::mutex::scoped_lock lm (_mutex); - if (!_audio_stream) { - return 0; - } + if (!_audio_stream) { + return 0; + } - return _audio_stream->frame_rate; + return _audio_stream->frame_rate; } int @@ -253,7 +276,7 @@ FFmpegContent::output_audio_frame_rate () const /* Resample to a DCI-approved sample rate */ double t = dcp_audio_frame_rate (content_audio_frame_rate ()); - FrameRateConversion frc (video_frame_rate(), film->dcp_video_frame_rate()); + FrameRateConversion frc (video_frame_rate(), film->video_frame_rate()); /* Compensate if the DCP is being run at a different frame rate to the source; that is, if the video is run such that it will @@ -262,7 +285,7 @@ FFmpegContent::output_audio_frame_rate () const */ if (frc.change_speed) { - t *= video_frame_rate() * frc.factor() / film->dcp_video_frame_rate(); + t *= video_frame_rate() * frc.factor() / film->video_frame_rate(); } return rint (t); @@ -271,22 +294,23 @@ FFmpegContent::output_audio_frame_rate () const bool operator== (FFmpegSubtitleStream const & a, FFmpegSubtitleStream const & b) { - return a.id == b.id; + return a.id == b.id; } bool operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b) { - return a.id == b.id; + return a.id == b.id; } FFmpegAudioStream::FFmpegAudioStream (shared_ptr node) + : mapping (node->node_child ("Mapping")) { name = node->string_child ("Name"); id = node->number_child ("Id"); frame_rate = node->number_child ("FrameRate"); channels = node->number_child ("Channels"); - mapping = AudioMapping (node->node_child ("Mapping")); + first_audio = node->optional_number_child ("FirstAudio"); } void @@ -296,6 +320,9 @@ FFmpegAudioStream::as_xml (xmlpp::Node* root) const root->add_child("Id")->add_child_text (lexical_cast (id)); root->add_child("FrameRate")->add_child_text (lexical_cast (frame_rate)); root->add_child("Channels")->add_child_text (lexical_cast (channels)); + if (first_audio) { + root->add_child("FirstAudio")->add_child_text (lexical_cast (first_audio.get ())); + } mapping.as_xml (root->add_child("Mapping")); } @@ -316,20 +343,14 @@ FFmpegSubtitleStream::as_xml (xmlpp::Node* root) const root->add_child("Id")->add_child_text (lexical_cast (id)); } -shared_ptr -FFmpegContent::clone () const -{ - return shared_ptr (new FFmpegContent (*this)); -} - Time FFmpegContent::length () const { shared_ptr film = _film.lock (); assert (film); - FrameRateConversion frc (video_frame_rate (), film->dcp_video_frame_rate ()); - return video_length() * frc.factor() * TIME_HZ / film->dcp_video_frame_rate (); + FrameRateConversion frc (video_frame_rate (), film->video_frame_rate ()); + return video_length() * frc.factor() * TIME_HZ / film->video_frame_rate (); } AudioMapping @@ -361,3 +382,24 @@ FFmpegContent::set_audio_mapping (AudioMapping m) audio_stream()->mapping = m; signal_changed (AudioContentProperty::AUDIO_MAPPING); } + +string +FFmpegContent::identifier () const +{ + stringstream s; + + s << VideoContent::identifier(); + + boost::mutex::scoped_lock lm (_mutex); + + if (_subtitle_stream) { + s << "_" << _subtitle_stream->id; + } + + for (vector::const_iterator i = _filters.begin(); i != _filters.end(); ++i) { + s << "_" << (*i)->id (); + } + + return s.str (); +} +