Make the viewer respond to filter changes.
[dcpomatic.git] / src / lib / encoder.cc
index 62ba922daffc5c66f881afe11ee9cc8e63a7765b..1fc7d5997630f32477f17e355bfb2e89a7b551a7 100644 (file)
 
 #include "encoder.h"
 #include "util.h"
+#include "options.h"
 
+using std::pair;
 using namespace boost;
 
 int const Encoder::_history_size = 25;
 
-/** @param s FilmState of the film that we are encoding.
+/** @param f Film that we are encoding.
  *  @param o Options.
- *  @param l Log.
  */
-Encoder::Encoder (shared_ptr<const FilmState> s, shared_ptr<const Options> o, Log* l)
-       : _fs (s)
+Encoder::Encoder (shared_ptr<const Film> f, shared_ptr<const EncodeOptions> o)
+       : _film (f)
        , _opt (o)
-       , _log (l)
        , _just_skipped (false)
-       , _last_frame (0)
+       , _video_frame (0)
+       , _audio_frame (0)
 {
 
 }
@@ -68,23 +69,22 @@ Encoder::skipping () const
        return _just_skipped;
 }
 
-/** @return Index of last frame to be successfully encoded */
-int
-Encoder::last_frame () const
+/** @return Number of video frames that have been received */
+SourceFrame
+Encoder::video_frame () const
 {
        boost::mutex::scoped_lock (_history_mutex);
-       return _last_frame;
+       return _video_frame;
 }
 
 /** Should be called when a frame has been encoded successfully.
- *  @param n Frame index.
+ *  @param n Source frame index.
  */
 void
-Encoder::frame_done (int n)
+Encoder::frame_done ()
 {
        boost::mutex::scoped_lock lock (_history_mutex);
        _just_skipped = false;
-       _last_frame = n;
        
        struct timeval tv;
        gettimeofday (&tv, 0);
@@ -103,3 +103,56 @@ Encoder::frame_skipped ()
        boost::mutex::scoped_lock lock (_history_mutex);
        _just_skipped = true;
 }
+
+void
+Encoder::process_video (shared_ptr<Image> i, boost::shared_ptr<Subtitle> s)
+{
+       if (_opt->video_skip != 0 && (_video_frame % _opt->video_skip) != 0) {
+               ++_video_frame;
+               return;
+       }
+
+       if (_opt->video_range) {
+               pair<SourceFrame, SourceFrame> const r = _opt->video_range.get();
+               if (_video_frame < r.first || _video_frame >= r.second) {
+                       ++_video_frame;
+                       return;
+               }
+       }
+
+       do_process_video (i, s);
+       ++_video_frame;
+}
+
+void
+Encoder::process_audio (shared_ptr<AudioBuffers> data)
+{
+       if (_opt->audio_range) {
+
+               shared_ptr<AudioBuffers> trimmed (new AudioBuffers (*data.get ()));
+               
+               /* Range that we are encoding */
+               pair<int64_t, int64_t> required_range = _opt->audio_range.get();
+               /* Range of this block of data */
+               pair<int64_t, int64_t> this_range (_audio_frame, _audio_frame + trimmed->frames());
+
+               if (this_range.second < required_range.first || required_range.second < this_range.first) {
+                       /* No part of this audio is within the required range */
+                       return;
+               } else if (required_range.first >= this_range.first && required_range.first < this_range.second) {
+                       /* Trim start */
+                       int64_t const shift = required_range.first - this_range.first;
+                       trimmed->move (shift, 0, trimmed->frames() - shift);
+                       trimmed->set_frames (trimmed->frames() - shift);
+               } else if (required_range.second >= this_range.first && required_range.second < this_range.second) {
+                       /* Trim end */
+                       trimmed->set_frames (required_range.second - this_range.first);
+               }
+
+               data = trimmed;
+       }
+
+       do_process_audio (data);
+
+       _audio_frame += data->frames ();
+}