From f2caad0df1a451e2aff68dfd37277faa72116e12 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 20 May 2013 14:27:00 +0100 Subject: Various time-related fixes; fix daft hang on decodes. --- src/lib/ffmpeg_content.cc | 1 - src/lib/ffmpeg_decoder.cc | 68 +++++++++++++++++++++++++---------------------- src/lib/ffmpeg_decoder.h | 2 +- src/lib/player.cc | 6 ++--- src/lib/playlist.cc | 4 ++- src/lib/subtitle.cc | 10 ++++--- src/lib/subtitle.h | 12 +++++---- src/lib/video_decoder.cc | 6 +++-- src/lib/video_decoder.h | 2 +- 9 files changed, 60 insertions(+), 51 deletions(-) (limited to 'src/lib') diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 55281ff9b..f0df15193 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -245,7 +245,6 @@ FFmpegContent::output_audio_frame_rate (shared_ptr film) const if (frc.change_speed) { t *= video_frame_rate() * frc.factor() / film->dcp_video_frame_rate(); - cout << "-> " << t << "\n"; } return rint (t); diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index d21a93e29..e99a960ce 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -1,3 +1,5 @@ +/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ + /* Copyright (C) 2012 Carl Hetherington @@ -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 graph; - - list >::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 graph; + + list >::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 > images = graph->process (_frame); + + for (list >::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 > images = graph->process (_frame); - - for (list >::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; } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index e6fa9cc82..760fc084d 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -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 (); diff --git a/src/lib/player.cc b/src/lib/player.cc index 9cc166204..e38b12ec3 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -1,3 +1,5 @@ +/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ + /* Copyright (C) 2013 Carl Hetherington @@ -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; } diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index 8f4a35ac2..912d90f0e 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -1,3 +1,5 @@ +/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ + /* Copyright (C) 2013 Carl Hetherington @@ -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 (time)); + node->add_child ("Time")->add_child_text (lexical_cast (time)); } class FrameRateCandidate diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc index 5c1ad9706..eafccd9b5 100644 --- a/src/lib/subtitle.cc +++ b/src/lib/subtitle.cc @@ -1,3 +1,5 @@ +/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ + /* Copyright (C) 2012 Carl Hetherington @@ -45,8 +47,8 @@ TimedSubtitle::TimedSubtitle (AVSubtitle const & sub) double const packet_time = static_cast (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; } diff --git a/src/lib/subtitle.h b/src/lib/subtitle.h index 2b77eb4cb..52bd35923 100644 --- a/src/lib/subtitle.h +++ b/src/lib/subtitle.h @@ -1,3 +1,5 @@ +/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ + /* Copyright (C) 2012 Carl Hetherington @@ -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 () const { return _subtitle; @@ -74,8 +76,8 @@ public: private: /** the subtitle */ boost::shared_ptr _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; }; diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index a24059da2..533fdcf1a 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -1,3 +1,5 @@ +/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ + /* Copyright (C) 2012 Carl Hetherington @@ -41,10 +43,10 @@ VideoDecoder::VideoDecoder (shared_ptr 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, bool same, double t) +VideoDecoder::emit_video (shared_ptr image, bool same, Time t) { shared_ptr sub; if (_timed_subtitle && _timed_subtitle->displayed_at (t)) { diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index 88730f518..a73c7d11e 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -56,7 +56,7 @@ protected: virtual PixelFormat pixel_format () const = 0; - void emit_video (boost::shared_ptr, bool, double); + void emit_video (boost::shared_ptr, bool, Time); void emit_subtitle (boost::shared_ptr); private: -- cgit v1.2.3