Various time-related fixes; fix daft hang on decodes.
authorCarl Hetherington <cth@carlh.net>
Mon, 20 May 2013 13:27:00 +0000 (14:27 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 20 May 2013 13:27:00 +0000 (14:27 +0100)
12 files changed:
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/player.cc
src/lib/playlist.cc
src/lib/subtitle.cc
src/lib/subtitle.h
src/lib/video_decoder.cc
src/lib/video_decoder.h
src/wx/film_editor.cc
src/wx/film_viewer.cc
src/wx/film_viewer.h

index 55281ff9ba40352c59988e236fcc852f318e727a..f0df1519393e96c423fa1f935b1357e6fe5cf7d9 100644 (file)
@@ -245,7 +245,6 @@ FFmpegContent::output_audio_frame_rate (shared_ptr<const Film> film) const
 
        if (frc.change_speed) {
                t *= video_frame_rate() * frc.factor() / film->dcp_video_frame_rate();
-               cout << "-> " << t << "\n";
        }
 
        return rint (t);
index d21a93e2926c2dc59c211dc28ea406f8a5e0078b..e99a960cef4723095ab6017b278f0c5a78a51e95 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 
@@ -220,8 +222,6 @@ FFmpegDecoder::setup_subtitle ()
 bool
 FFmpegDecoder::pass ()
 {
-       cout << "FFmpeg::pass\n";
-       
        int r = av_read_frame (_format_context, &_packet);
 
        if (r < 0) {
@@ -240,7 +240,7 @@ FFmpegDecoder::pass ()
                /* XXX: should we reset _packet.data and size after each *_decode_* call? */
                
                if (_decode_video) {
-                       decode_video_packet ();
+                       while (decode_video_packet ());
                }
 
                if (_ffmpeg_content->audio_stream() && _decode_audio) {
@@ -592,40 +592,44 @@ FFmpegDecoder::decode_audio_packet ()
        }
 }
 
-void
+bool
 FFmpegDecoder::decode_video_packet ()
 {
        int frame_finished;
-       while (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
-               boost::mutex::scoped_lock lm (_filter_graphs_mutex);
-               
-               shared_ptr<FilterGraph> graph;
-               
-               list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
-               while (i != _filter_graphs.end() && !(*i)->can_process (libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) {
-                       ++i;
-               }
+       if (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) < 0 || !frame_finished) {
+               return false;
+       }
                
-               if (i == _filter_graphs.end ()) {
-                       graph.reset (new FilterGraph (_film, this, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format));
-                       _filter_graphs.push_back (graph);
-                       _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format));
+       boost::mutex::scoped_lock lm (_filter_graphs_mutex);
+       
+       shared_ptr<FilterGraph> graph;
+       
+       list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
+       while (i != _filter_graphs.end() && !(*i)->can_process (libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) {
+               ++i;
+       }
+       
+       if (i == _filter_graphs.end ()) {
+               graph.reset (new FilterGraph (_film, this, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format));
+               _filter_graphs.push_back (graph);
+               _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format));
+       } else {
+               graph = *i;
+       }
+       
+       list<shared_ptr<Image> > images = graph->process (_frame);
+       
+       for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
+               int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
+               if (bet != AV_NOPTS_VALUE) {
+                       /* XXX: may need to insert extra frames / remove frames here ...
+                          (as per old Matcher)
+                       */
+                       emit_video (*i, false, bet * av_q2d (_format_context->streams[_video_stream]->time_base) * TIME_HZ);
                } else {
-                       graph = *i;
-               }
-               
-               list<shared_ptr<Image> > images = graph->process (_frame);
-               
-               for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
-                       int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
-                       if (bet != AV_NOPTS_VALUE) {
-                               /* XXX: may need to insert extra frames / remove frames here ...
-                                  (as per old Matcher)
-                               */
-                               emit_video (*i, false, bet * av_q2d (_format_context->streams[_video_stream]->time_base));
-                       } else {
-                               _film->log()->log ("Dropping frame without PTS");
-                       }
+                       _film->log()->log ("Dropping frame without PTS");
                }
        }
+
+       return true;
 }
index e6fa9cc8216770ac430882234a3ebb5bdaec2b37..760fc084dd36c61ccf856b428794592597c9fbb9 100644 (file)
@@ -97,7 +97,7 @@ private:
        void setup_audio ();
        void setup_subtitle ();
 
-       void decode_video_packet ();
+       bool decode_video_packet ();
        void decode_audio_packet ();
 
        void maybe_add_subtitle ();
index 9cc1662048dbd8dd17aaa1492177cf2ea6018409..e38b12ec35286d64e299d499ba2f43a375a3b487 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
 
@@ -80,8 +82,6 @@ Player::pass ()
                _have_valid_decoders = true;
        }
 
-       cout << "-> Player::pass\n";
-       
         /* Here we are just finding the active decoder with the earliest last emission time, then
            calling pass on it.  If there is no decoder, we skip our position on until there is.
            Hence this method will cause video and audio to be emitted, and it is up to the
@@ -114,11 +114,9 @@ Player::pass ()
         } else if (next_wait < TIME_MAX) {
                 _position += next_wait;
         } else {
-               cout << "<- Player::pass\n";
                 return true;
         }
 
-       cout << "<- Player::pass\n";
         return false;
 }
 
index 8f4a35ac2790d51c7d918ca1bbbdc80ee35bb492..912d90f0e5f482d19404101e282e713a1268b48e 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
 
@@ -203,7 +205,7 @@ Playlist::Region::as_xml (xmlpp::Node* node) const
 {
        xmlpp::Node* sub = node->add_child ("Content");
        content->as_xml (sub);
-       sub->add_child ("Time")->add_child_text (lexical_cast<string> (time));
+       node->add_child ("Time")->add_child_text (lexical_cast<string> (time));
 }
 
 class FrameRateCandidate
index 5c1ad97064fd1042450b99638d21de8a62f049b5..eafccd9b503651e2744bb53117c8c699e8c6bc0c 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 
@@ -45,8 +47,8 @@ TimedSubtitle::TimedSubtitle (AVSubtitle const & sub)
        double const packet_time = static_cast<double> (sub.pts) / AV_TIME_BASE;
        
        /* hence start time for this sub */
-       _from = packet_time + (double (sub.start_display_time) / 1e3);
-       _to = packet_time + (double (sub.end_display_time) / 1e3);
+       _from = (packet_time + (double (sub.start_display_time) / 1e3)) * TIME_HZ;
+       _to = (packet_time + (double (sub.end_display_time) / 1e3)) * TIME_HZ;
 
        if (sub.num_rects > 1) {
                throw DecodeError (_("multi-part subtitles not yet supported"));
@@ -80,9 +82,9 @@ TimedSubtitle::TimedSubtitle (AVSubtitle const & sub)
        _subtitle.reset (new Subtitle (Position (rect->x, rect->y), image));
 }      
 
-/** @param t Time in seconds from the start of the source */
+/** @param t Time from the start of the source */
 bool
-TimedSubtitle::displayed_at (double t) const
+TimedSubtitle::displayed_at (Time t) const
 {
        return t >= _from && t <= _to;
 }
index 2b77eb4cb881eda16dbcac8a627a306ea1bff913..52bd35923b8c0e1b9101dcd676c7ea8d507e083e 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 
@@ -65,7 +67,7 @@ class TimedSubtitle
 public:
        TimedSubtitle (AVSubtitle const &);
 
-       bool displayed_at (double t) const;
+       bool displayed_at (Time) const;
        
        boost::shared_ptr<Subtitle> subtitle () const {
                return _subtitle;
@@ -74,8 +76,8 @@ public:
 private:
        /** the subtitle */
        boost::shared_ptr<Subtitle> _subtitle;
-       /** display from time in seconds from the start of the film */
-       double _from;
-       /** display to time in seconds from the start of the film */
-       double _to;
+       /** display from time from the start of the content */
+       Time _from;
+       /** display to time from the start of the content */
+       Time _to;
 };
index a24059da2d9138d9c1b155ed13bb009f4867769c..533fdcf1a435d6aeb88eb298285ef6843c40bec4 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 
@@ -41,10 +43,10 @@ VideoDecoder::VideoDecoder (shared_ptr<const Film> f)
 /** Called by subclasses to tell the world that some video data is ready.
  *  We find a subtitle then emit it for listeners.
  *  @param image frame to emit.
- *  @param t Time of the frame within the source, in seconds.
+ *  @param t Time of the frame within the source.
  */
 void
-VideoDecoder::emit_video (shared_ptr<Image> image, bool same, double t)
+VideoDecoder::emit_video (shared_ptr<Image> image, bool same, Time t)
 {
        shared_ptr<Subtitle> sub;
        if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
index 88730f5183c92407f9c3d8b68ff166a50e2f6ab6..a73c7d11e0e67ff8a9a01b2440f47410cc26ee6f 100644 (file)
@@ -56,7 +56,7 @@ protected:
        
        virtual PixelFormat pixel_format () const = 0;
 
-       void emit_video (boost::shared_ptr<Image>, bool, double);
+       void emit_video (boost::shared_ptr<Image>, bool, Time);
        void emit_subtitle (boost::shared_ptr<TimedSubtitle>);
 
 private:
index 32def46412aedcf227dae50f6c012b3564905167..8916751439c236344f60048df56e4a609adf6895 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 
@@ -337,13 +339,13 @@ FilmEditor::make_content_panel ()
 
                 wxBoxSizer* b = new wxBoxSizer (wxVERTICAL);
                 _content_add = new wxButton (_content_panel, wxID_ANY, _("Add..."));
-                b->Add (_content_add);
+                b->Add (_content_add, 1, wxEXPAND | wxLEFT | wxRIGHT);
                 _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove"));
-                b->Add (_content_remove);
+                b->Add (_content_remove, 1, wxEXPAND | wxLEFT | wxRIGHT);
                 _content_properties = new wxButton (_content_panel, wxID_ANY, _("Properties..."));
                 b->Add (_content_properties);
                _content_timeline = new wxButton (_content_panel, wxID_ANY, _("Timeline..."));
-               b->Add (_content_timeline);
+               b->Add (_content_timeline, 1, wxEXPAND | wxLEFT | wxRIGHT);
 
                 s->Add (b, 0, wxALL, 4);
 
index 11c826a26eee51bec9625f5203a1fdbec8683088..2f69235c150d953f6d924060ba71de2f484b9804 100644 (file)
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
 /*
     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 
@@ -388,7 +390,7 @@ FilmViewer::check_play_state ()
 }
 
 void
-FilmViewer::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, double t)
+FilmViewer::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, Time t)
 {
        _raw_frame = image;
        _raw_sub = sub;
@@ -398,9 +400,9 @@ FilmViewer::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subti
        _got_frame = true;
 
        double const fps = _film->dcp_video_frame_rate ();
-       _frame->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps))));
+       _frame->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps / TIME_HZ))));
 
-       double w = t;
+       double w = static_cast<double>(t) / TIME_HZ;
        int const h = (w / 3600);
        w -= h * 3600;
        int const m = (w / 60);
@@ -425,8 +427,6 @@ FilmViewer::get_frame ()
                return;
        }
 
-       cout << "-> FilmViewer::get_frame()\n";
-
        try {
                _got_frame = false;
                while (!_got_frame) {
@@ -443,8 +443,6 @@ FilmViewer::get_frame ()
                check_play_state ();
                error_dialog (this, wxString::Format (_("Could not decode video for view (%s)"), std_to_wx(e.what()).data()));
        }
-
-       cout << "<- FilmViewer::get_frame()\n";
 }
 
 void
index 02d862ca0c42472dd8cefb6de594b116725e6a68..68d51bfbded2accec2137ad088f2d173267f59e1 100644 (file)
@@ -67,7 +67,7 @@ private:
        void slider_moved (wxScrollEvent &);
        void play_clicked (wxCommandEvent &);
        void timer (wxTimerEvent &);
-       void process_video (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, double);
+       void process_video (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, Time);
        void calculate_sizes ();
        void check_play_state ();
        void update_from_raw ();