From b1283679663c4775504b238378c588f972affcd8 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 18 Jun 2013 19:35:24 +0100 Subject: Don't get stuck in an infinite loop when avcodec_decode_audio4 returns an error. --- src/lib/ffmpeg_decoder.cc | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'src/lib/ffmpeg_decoder.cc') diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index bcfbea431..cad247e5a 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -691,23 +691,26 @@ FFmpegDecoder::decode_audio_packet () int frame_finished; int const decode_result = avcodec_decode_audio4 (_audio_codec_context, _frame, &frame_finished, ©_packet); - if (decode_result >= 0) { - if (frame_finished) { + if (decode_result < 0) { + /* error */ + break; + } + + if (frame_finished) { - /* Where we are in the source, in seconds */ - double const source_pts_seconds = av_q2d (_format_context->streams[copy_packet.stream_index]->time_base) - * av_frame_get_best_effort_timestamp(_frame); - - int const data_size = av_samples_get_buffer_size ( - 0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1 - ); - - assert (_audio_codec_context->channels == _film->audio_channels()); - Audio (deinterleave_audio (_frame->data, data_size), source_pts_seconds); - } + /* Where we are in the source, in seconds */ + double const source_pts_seconds = av_q2d (_format_context->streams[copy_packet.stream_index]->time_base) + * av_frame_get_best_effort_timestamp(_frame); - copy_packet.data += decode_result; - copy_packet.size -= decode_result; + int const data_size = av_samples_get_buffer_size ( + 0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1 + ); + + assert (_audio_codec_context->channels == _film->audio_channels()); + Audio (deinterleave_audio (_frame->data, data_size), source_pts_seconds); } + + copy_packet.data += decode_result; + copy_packet.size -= decode_result; } } -- cgit v1.2.3 From 814f799b280cbf8e73f61ad283a199e211ed0c5e Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 27 Jun 2013 01:16:37 +0100 Subject: Various bits of backported 1.0 --- src/lib/ffmpeg_decoder.cc | 10 ++++++++++ src/lib/ffmpeg_decoder.h | 5 +++++ src/lib/job.cc | 6 +++++- src/lib/ui_signaller.h | 5 ++++- src/wx/job_manager_view.cc | 1 - test/test.cc | 4 +++- 6 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src/lib/ffmpeg_decoder.cc') diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index cad247e5a..c2143b949 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -61,6 +61,8 @@ using boost::optional; using boost::dynamic_pointer_cast; using libdcp::Size; +boost::mutex FFmpegDecoder::_mutex; + FFmpegDecoder::FFmpegDecoder (shared_ptr f, DecodeOptions o) : Decoder (f, o) , VideoDecoder (f, o) @@ -83,6 +85,8 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr f, DecodeOptions o) FFmpegDecoder::~FFmpegDecoder () { + boost::mutex::scoped_lock lm (_mutex); + if (_audio_codec_context) { avcodec_close (_audio_codec_context); } @@ -157,6 +161,8 @@ FFmpegDecoder::setup_general () void FFmpegDecoder::setup_video () { + boost::mutex::scoped_lock lm (_mutex); + _video_codec_context = _format_context->streams[_video_stream]->codec; _video_codec = avcodec_find_decoder (_video_codec_context->codec_id); @@ -172,6 +178,8 @@ FFmpegDecoder::setup_video () void FFmpegDecoder::setup_audio () { + boost::mutex::scoped_lock lm (_mutex); + if (!_audio_stream) { return; } @@ -194,6 +202,8 @@ FFmpegDecoder::setup_audio () void FFmpegDecoder::setup_subtitle () { + boost::mutex::scoped_lock lm (_mutex); + if (!_subtitle_stream || _subtitle_stream->id() >= int (_format_context->nb_streams)) { return; } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 0c89b973d..198f4294e 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -107,6 +107,9 @@ public: private: + /* No copy construction */ + FFmpegDecoder (FFmpegDecoder const &); + bool pass (); bool do_seek (double p, bool, bool); PixelFormat pixel_format () const; @@ -145,4 +148,6 @@ private: std::list > _filter_graphs; boost::mutex _filter_graphs_mutex; + + static boost::mutex _mutex; }; diff --git a/src/lib/job.cc b/src/lib/job.cc index 9a5812fa7..8bb43a91f 100644 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@ -27,6 +27,7 @@ #include "job.h" #include "util.h" #include "cross.h" +#include "ui_signaller.h" #include "i18n.h" @@ -172,8 +173,11 @@ Job::set_state (State s) boost::mutex::scoped_lock lm (_state_mutex); _state = s; - if (_state == FINISHED_OK || _state == FINISHED_ERROR) { + if (_state == FINISHED_OK || _state == FINISHED_ERROR || _state == FINISHED_CANCELLED) { _ran_for = elapsed_time (); + if (ui_signaller) { + ui_signaller->emit (boost::bind (boost::ref (Finished))); + } } } diff --git a/src/lib/ui_signaller.h b/src/lib/ui_signaller.h index 221bcbe95..0d19660bf 100644 --- a/src/lib/ui_signaller.h +++ b/src/lib/ui_signaller.h @@ -60,7 +60,10 @@ public: } /** This should wake the UI and make it call ui_idle() */ - virtual void wake_ui () = 0; + virtual void wake_ui () { + /* This is only a sensible implementation when there is no GUI... */ + ui_idle (); + } private: /** A io_service which is used as the conduit for messages */ diff --git a/src/wx/job_manager_view.cc b/src/wx/job_manager_view.cc index 5cd9f2e15..cfe09aec8 100644 --- a/src/wx/job_manager_view.cc +++ b/src/wx/job_manager_view.cc @@ -133,7 +133,6 @@ JobManagerView::update () if (!(*i)->finished_cancelled()) { _job_records[*i].gauge->SetValue (100); } - (*i)->Finished (); _job_records[*i].finalised = true; _job_records[*i].cancel->Enable (false); if (!(*i)->error_details().empty ()) { diff --git a/test/test.cc b/test/test.cc index 65b1f9056..74d967a46 100644 --- a/test/test.cc +++ b/test/test.cc @@ -40,6 +40,7 @@ #include "ffmpeg_decoder.h" #include "sndfile_decoder.h" #include "trimmer.h" +#include "ui_signaller.h" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE dvdomatic_test #include @@ -64,6 +65,8 @@ struct TestConfig Config::instance()->set_default_dci_metadata (DCIMetadata ()); Config::instance()->set_default_format (static_cast (0)); Config::instance()->set_default_dcp_content_type (static_cast (0)); + + ui_signaller = new UISignaller (); } }; @@ -103,4 +106,3 @@ new_test_film (string name) #include "job_test.cc" #include "client_server_test.cc" #include "image_test.cc" - -- cgit v1.2.3