summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-12-16 14:53:22 +0000
committerCarl Hetherington <cth@carlh.net>2012-12-16 14:53:22 +0000
commitaa230169f8b59b7cb2da9a3bbb8ce5f7600285c0 (patch)
tree5cde52f6c50b9a56597e0f6ebad1f8e4aa5e1c8d /src/lib
parent7fd2aff3af82d3e573934d046be26b72a67a93e6 (diff)
parent3ce37f08e98b9c3a238fb1c9a6184fb7fd4e5667 (diff)
Merge speed-up branch.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/examine_content_job.cc54
-rw-r--r--src/lib/ffmpeg_decoder.cc17
-rw-r--r--src/lib/ffmpeg_decoder.h3
-rw-r--r--src/lib/film.cc23
-rw-r--r--src/lib/film.h8
-rw-r--r--src/lib/imagemagick_decoder.h5
-rw-r--r--src/lib/transcoder.cc8
-rw-r--r--src/lib/transcoder.h4
-rw-r--r--src/lib/video_decoder.h2
9 files changed, 91 insertions, 33 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;