summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-07-01 15:05:13 +0100
committerCarl Hetherington <cth@carlh.net>2014-07-01 15:05:13 +0100
commit6f071ce94bb7cff1106e2ef6d8eb4363694435f2 (patch)
tree65fa1844ae470bc9011733ecff4f016ba5a4671e /src/lib
parent15f23b356b757a9697bf1a9ec30c243ab8070404 (diff)
Remove FFmpegDecoder minimal_run and care on seeking, as the VideoDecoder/AudioDecoder has to cope with stuff per-stream anyway.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ffmpeg_decoder.cc79
-rw-r--r--src/lib/ffmpeg_decoder.h3
-rw-r--r--src/lib/player.cc19
-rw-r--r--src/lib/player.h3
-rw-r--r--src/lib/player_video.cc4
-rw-r--r--src/lib/player_video.h7
-rw-r--r--src/lib/video_decoder.cc15
7 files changed, 38 insertions, 92 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 42be8227e..dfd8786b3 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -282,71 +282,6 @@ FFmpegDecoder::bytes_per_audio_sample () const
return av_get_bytes_per_sample (audio_sample_format ());
}
-int
-FFmpegDecoder::minimal_run (boost::function<bool (optional<ContentTime>, optional<ContentTime>, int)> finished)
-{
- int frames_read = 0;
- optional<ContentTime> last_video;
- optional<ContentTime> last_audio;
-
- while (!finished (last_video, last_audio, frames_read)) {
- int r = av_read_frame (_format_context, &_packet);
- if (r < 0) {
- /* We should flush our decoders here, possibly yielding a few more frames,
- but the consequence of having to do that is too hideous to contemplate.
- Instead we give up and say that you can't seek too close to the end
- of a file.
- */
- return frames_read;
- }
-
- ++frames_read;
-
- double const time_base = av_q2d (_format_context->streams[_packet.stream_index]->time_base);
-
- if (_packet.stream_index == _video_stream) {
-
- av_frame_unref (_frame);
-
- int got_picture = 0;
- r = avcodec_decode_video2 (video_codec_context(), _frame, &got_picture, &_packet);
- if (r >= 0 && got_picture) {
- last_video = ContentTime::from_seconds (av_frame_get_best_effort_timestamp (_frame) * time_base) + _pts_offset;
- }
-
- } else if (_ffmpeg_content->audio_stream() && _ffmpeg_content->audio_stream()->uses_index (_format_context, _packet.stream_index)) {
- AVPacket copy_packet = _packet;
- while (copy_packet.size > 0) {
-
- int got_frame;
- r = avcodec_decode_audio4 (audio_codec_context(), _frame, &got_frame, &_packet);
- if (r >= 0 && got_frame) {
- last_audio = ContentTime::from_seconds (av_frame_get_best_effort_timestamp (_frame) * time_base) + _pts_offset;
- }
-
- copy_packet.data += r;
- copy_packet.size -= r;
- }
- }
-
- av_free_packet (&_packet);
- }
-
- return frames_read;
-}
-
-bool
-FFmpegDecoder::seek_overrun_finished (ContentTime seek, optional<ContentTime> last_video, optional<ContentTime> last_audio) const
-{
- return (last_video && last_video.get() >= seek) || (last_audio && last_audio.get() >= seek);
-}
-
-bool
-FFmpegDecoder::seek_final_finished (int n, int done) const
-{
- return n == done;
-}
-
void
FFmpegDecoder::seek_and_flush (ContentTime t)
{
@@ -393,21 +328,7 @@ FFmpegDecoder::seek (ContentTime time, bool accurate)
initial_seek = ContentTime (0);
}
- /* Initial seek time in the video stream's timebase */
-
- seek_and_flush (initial_seek);
-
- if (!accurate) {
- /* That'll do */
- return;
- }
-
- int const N = minimal_run (boost::bind (&FFmpegDecoder::seek_overrun_finished, this, time, _1, _2));
-
seek_and_flush (initial_seek);
- if (N > 0) {
- minimal_run (boost::bind (&FFmpegDecoder::seek_final_finished, this, N - 1, _3));
- }
}
void
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index 2859e2345..e44ac152f 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -66,9 +66,6 @@ private:
void maybe_add_subtitle ();
boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t** data, int size);
- bool seek_overrun_finished (ContentTime, boost::optional<ContentTime>, boost::optional<ContentTime>) const;
- bool seek_final_finished (int, int) const;
- int minimal_run (boost::function<bool (boost::optional<ContentTime>, boost::optional<ContentTime>, int)>);
void seek_and_flush (ContentTime);
bool has_subtitle_during (ContentTimePeriod) const;
diff --git a/src/lib/player.cc b/src/lib/player.cc
index b634028ba..925719169 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -293,11 +293,12 @@ Player::set_approximate_size ()
}
shared_ptr<PlayerVideo>
-Player::black_player_video_frame () const
+Player::black_player_video_frame (DCPTime time) const
{
return shared_ptr<PlayerVideo> (
new PlayerVideo (
shared_ptr<const ImageProxy> (new RawImageProxy (_black_image, _film->log ())),
+ time,
Crop (),
_video_container_size,
_video_container_size,
@@ -326,7 +327,7 @@ Player::get_video (DCPTime time, bool accurate)
if (ov.empty ()) {
/* No video content at this time */
- pvf.push_back (black_player_video_frame ());
+ pvf.push_back (black_player_video_frame (time));
} else {
/* Create a PlayerVideo from the content's video at this time */
@@ -338,7 +339,7 @@ Player::get_video (DCPTime time, bool accurate)
list<ContentVideo> content_video = decoder->get_video (dcp_to_content_video (piece, time), accurate);
if (content_video.empty ()) {
- pvf.push_back (black_player_video_frame ());
+ pvf.push_back (black_player_video_frame (time));
return pvf;
}
@@ -353,6 +354,7 @@ Player::get_video (DCPTime time, bool accurate)
shared_ptr<PlayerVideo> (
new PlayerVideo (
i->image,
+ content_video_to_dcp (piece, i->frame),
content->crop (),
image_size,
_video_container_size,
@@ -508,6 +510,17 @@ Player::dcp_to_content_video (shared_ptr<const Piece> piece, DCPTime t) const
return DCPTime (s + piece->content->trim_start()).frames (_film->video_frame_rate()) * piece->frc.factor ();
}
+DCPTime
+Player::content_video_to_dcp (shared_ptr<const Piece> piece, VideoFrame f) const
+{
+ DCPTime t = DCPTime::from_frames (f / piece->frc.factor (), _film->video_frame_rate()) - piece->content->trim_start () + piece->content->position ();
+ if (t < DCPTime ()) {
+ t = DCPTime ();
+ }
+
+ return t;
+}
+
AudioFrame
Player::dcp_to_content_audio (shared_ptr<const Piece> piece, DCPTime t) const
{
diff --git a/src/lib/player.h b/src/lib/player.h
index 04503c27a..3ee909f97 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -117,9 +117,10 @@ private:
std::list<PositionImage> process_content_text_subtitles (std::list<boost::shared_ptr<ContentTextSubtitle> >) const;
void update_subtitle_from_text ();
VideoFrame dcp_to_content_video (boost::shared_ptr<const Piece> piece, DCPTime t) const;
+ DCPTime content_video_to_dcp (boost::shared_ptr<const Piece> piece, VideoFrame f) const;
AudioFrame dcp_to_content_audio (boost::shared_ptr<const Piece> piece, DCPTime t) const;
ContentTime dcp_to_content_subtitle (boost::shared_ptr<const Piece> piece, DCPTime t) const;
- boost::shared_ptr<PlayerVideo> black_player_video_frame () const;
+ boost::shared_ptr<PlayerVideo> black_player_video_frame (DCPTime) const;
/** @return Pieces of content type C that overlap a specified time range in the DCP */
template<class C>
diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc
index f8e4a3e66..3c513848a 100644
--- a/src/lib/player_video.cc
+++ b/src/lib/player_video.cc
@@ -30,6 +30,7 @@ using dcp::raw_convert;
PlayerVideo::PlayerVideo (
shared_ptr<const ImageProxy> in,
+ DCPTime time,
Crop crop,
dcp::Size inter_size,
dcp::Size out_size,
@@ -39,6 +40,7 @@ PlayerVideo::PlayerVideo (
ColourConversion colour_conversion
)
: _in (in)
+ , _time (time)
, _crop (crop)
, _inter_size (inter_size)
, _out_size (out_size)
@@ -52,6 +54,7 @@ PlayerVideo::PlayerVideo (
PlayerVideo::PlayerVideo (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket, shared_ptr<Log> log)
{
+ _time = DCPTime (node->number_child<DCPTime::Type> ("Time"));
_crop = Crop (node);
_inter_size = dcp::Size (node->number_child<int> ("InterWidth"), node->number_child<int> ("InterHeight"));
@@ -118,6 +121,7 @@ PlayerVideo::image () const
void
PlayerVideo::add_metadata (xmlpp::Node* node) const
{
+ node->add_child("Time")->add_child_text (raw_convert<string> (_time.get ()));
_crop.as_xml (node);
_in->add_metadata (node->add_child ("In"));
node->add_child("InterWidth")->add_child_text (raw_convert<string> (_inter_size.width));
diff --git a/src/lib/player_video.h b/src/lib/player_video.h
index 73557bbfd..7d2787783 100644
--- a/src/lib/player_video.h
+++ b/src/lib/player_video.h
@@ -36,7 +36,7 @@ class Log;
class PlayerVideo
{
public:
- PlayerVideo (boost::shared_ptr<const ImageProxy>, Crop, dcp::Size, dcp::Size, Scaler const *, Eyes, Part, ColourConversion);
+ PlayerVideo (boost::shared_ptr<const ImageProxy>, DCPTime, Crop, dcp::Size, dcp::Size, Scaler const *, Eyes, Part, ColourConversion);
PlayerVideo (boost::shared_ptr<cxml::Node>, boost::shared_ptr<Socket>, boost::shared_ptr<Log>);
void set_subtitle (PositionImage);
@@ -46,6 +46,10 @@ public:
void add_metadata (xmlpp::Node* node) const;
void send_binary (boost::shared_ptr<Socket> socket) const;
+ DCPTime time () const {
+ return _time;
+ }
+
Eyes eyes () const {
return _eyes;
}
@@ -56,6 +60,7 @@ public:
private:
boost::shared_ptr<const ImageProxy> _in;
+ DCPTime _time;
Crop _crop;
dcp::Size _inter_size;
dcp::Size _out_size;
diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc
index 43b1049cc..bfd7a7e3e 100644
--- a/src/lib/video_decoder.cc
+++ b/src/lib/video_decoder.cc
@@ -61,8 +61,12 @@ VideoDecoder::decoded_video (VideoFrame frame)
list<ContentVideo>
VideoDecoder::get_video (VideoFrame frame, bool accurate)
{
- if (_decoded_video.empty() || (frame < _decoded_video.front().frame || frame > (_decoded_video.back().frame + 1))) {
- /* Either we have no decoded data, or what we do have is a long way from what we want: seek */
+ /* At this stage, if we have get_video()ed before, _decoded_video will contain the last frame that this
+ method returned (and possibly a few more). If the requested frame is not in _decoded_video and it is not the next
+ one after the end of _decoded_video we need to seek.
+ */
+
+ if (_decoded_video.empty() || frame < _decoded_video.front().frame || frame > (_decoded_video.back().frame + 1)) {
seek (ContentTime::from_frames (frame, _video_content->video_frame_rate()), accurate);
}
@@ -70,7 +74,8 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate)
/* Now enough pass() calls should either:
* (a) give us what we want, or
- * (b) hit the end of the decoder.
+ * (b) give us something after what we want, indicating that we will never get what we want, or
+ * (c) hit the end of the decoder.
*/
if (accurate) {
/* We are being accurate, so we want the right frame.
@@ -105,8 +110,8 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate)
}
}
- /* Clean up decoded_video */
- while (!_decoded_video.empty() && _decoded_video.front().frame < (frame - 1)) {
+ /* Clean up _decoded_video; keep the frame we are returning, but nothing before that */
+ while (!_decoded_video.empty() && _decoded_video.front().frame < dec.front().frame) {
_decoded_video.pop_front ();
}