X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fvideo_decoder.cc;h=f3d3a31041583b6a7b0fba7a115b7e29f8d45d7b;hb=ee77b3cf5f59f775e75e628aa28e8f2f9f941530;hp=b5cc7d15887717e9a506141d74ab0066f265c3be;hpb=d0d584a7dde6de383302615634fdee17e9724fe8;p=dcpomatic.git diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index b5cc7d158..f3d3a3104 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2014 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,45 +18,102 @@ */ #include "video_decoder.h" -#include "subtitle.h" -#include "film.h" #include "image.h" -#include "ratio.h" +#include "content_video.h" #include "i18n.h" using std::cout; +using std::list; using boost::shared_ptr; +using boost::optional; -VideoDecoder::VideoDecoder (shared_ptr f) - : Decoder (f) - , _next_video_frame (0) +VideoDecoder::VideoDecoder (shared_ptr c) + : _video_content (c) { } -void -VideoDecoder::video (shared_ptr image, bool same, VideoContent::Frame frame) +shared_ptr +VideoDecoder::decoded_video (VideoFrame frame) { - Video (image, same, frame); - _next_video_frame = frame + 1; + for (list >::const_iterator i = _decoded_video.begin(); i != _decoded_video.end(); ++i) { + if ((*i)->frame == frame) { + return *i; + } + } + + return shared_ptr (); } -#if 0 +shared_ptr +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 */ + seek (ContentTime::from_frames (frame, _video_content->video_frame_rate()), accurate); + } + + shared_ptr dec; + + /* Now enough pass() calls will either: + * (a) give us what we want, or + * (b) hit the end of the decoder. + */ + if (accurate) { + /* We are being accurate, so we want the right frame */ + while (!decoded_video (frame) && !pass ()) {} + dec = decoded_video (frame); + } else { + /* Any frame will do: use the first one that comes out of pass() */ + while (_decoded_video.empty() && !pass ()) {} + if (!_decoded_video.empty ()) { + dec = _decoded_video.front (); + } + } + + /* Clean up decoded_video */ + while (!_decoded_video.empty() && _decoded_video.front()->frame < (frame - 1)) { + _decoded_video.pop_front (); + } -/** Called by subclasses when a subtitle is ready. - * s may be 0 to say that there is no current subtitle. - * @param s New current subtitle, or 0. - */ + return dec; +} + + +/** Called by subclasses when they have a video frame ready */ void -VideoDecoder::subtitle (shared_ptr s) +VideoDecoder::video (shared_ptr image, VideoFrame frame) { - _timed_subtitle = s; - - if (_timed_subtitle) { - Position const p = _timed_subtitle->subtitle()->position (); - _timed_subtitle->subtitle()->set_position (Position (p.x - _video_content->crop().left, p.y - _video_content->crop().top)); + switch (_video_content->video_frame_type ()) { + case VIDEO_FRAME_TYPE_2D: + _decoded_video.push_back (shared_ptr (new ContentVideo (image, EYES_BOTH, frame))); + break; + case VIDEO_FRAME_TYPE_3D_ALTERNATE: + _decoded_video.push_back (shared_ptr (new ContentVideo (image, (frame % 2) ? EYES_RIGHT : EYES_LEFT, frame))); + break; + case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT: + { + int const half = image->size().width / 2; + _decoded_video.push_back (shared_ptr (new ContentVideo (image->crop (Crop (0, half, 0, 0), true), EYES_LEFT, frame))); + _decoded_video.push_back (shared_ptr (new ContentVideo (image->crop (Crop (half, 0, 0, 0), true), EYES_RIGHT, frame))); + break; + } + case VIDEO_FRAME_TYPE_3D_TOP_BOTTOM: + { + int const half = image->size().height / 2; + _decoded_video.push_back (shared_ptr (new ContentVideo (image->crop (Crop (0, 0, 0, half), true), EYES_LEFT, frame))); + _decoded_video.push_back (shared_ptr (new ContentVideo (image->crop (Crop (0, 0, half, 0), true), EYES_RIGHT, frame))); + break; + } + default: + assert (false); } } -#endif + +void +VideoDecoder::seek (ContentTime, bool) +{ + _decoded_video.clear (); +}