X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Fffmpeg_decoder.cc;h=ce20997c84bcebefdc20dd2f90329155545cc505;hp=665ee3e13d630217e07041744caffa55142d06c7;hb=a5be11a965c2c38442e4e069874e7e21b5b43a5c;hpb=df17bbd25da69fc38eb2dcd8b4a2531cf0bab0bc diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 665ee3e13..ce20997c8 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -27,6 +27,7 @@ #include "image.h" #include "util.h" #include "log.h" +#include "dcpomatic_log.h" #include "ffmpeg_decoder.h" #include "text_decoder.h" #include "ffmpeg_audio_stream.h" @@ -58,10 +59,6 @@ extern "C" { #include "i18n.h" -#define LOG_GENERAL(...) _log->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL); -#define LOG_ERROR(...) _log->log (String::compose (__VA_ARGS__), LogEntry::TYPE_ERROR); -#define LOG_WARNING_NC(...) _log->log (__VA_ARGS__, LogEntry::TYPE_WARNING); -#define LOG_WARNING(...) _log->log (String::compose (__VA_ARGS__), LogEntry::TYPE_WARNING); using std::cout; using std::string; @@ -78,14 +75,14 @@ using boost::optional; using boost::dynamic_pointer_cast; using dcp::Size; -FFmpegDecoder::FFmpegDecoder (shared_ptr c, shared_ptr log, bool fast) +FFmpegDecoder::FFmpegDecoder (shared_ptr film, shared_ptr c, bool fast) : FFmpeg (c) - , _log (log) + , Decoder (film) , _have_current_subtitle (false) { if (c->video) { - video.reset (new VideoDecoder (this, c, log)); - _pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate()); + video.reset (new VideoDecoder (this, c)); + _pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate(film)); /* It doesn't matter what size or pixel format this is, it just needs to be black */ _black_image.reset (new Image (AV_PIX_FMT_RGB24, dcp::Size (128, 128), true)); _black_image->make_black (); @@ -94,12 +91,12 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr c, shared_ptr } if (c->audio) { - audio.reset (new AudioDecoder (this, c->audio, log, fast)); + audio.reset (new AudioDecoder (this, c->audio, fast)); } - if (c->only_caption()) { + if (c->only_text()) { /* XXX: this time here should be the time of the first subtitle, not 0 */ - caption.push_back (shared_ptr (new TextDecoder (this, c->only_caption(), log, ContentTime()))); + text.push_back (shared_ptr (new TextDecoder (this, c->only_text(), ContentTime()))); } _next_time.resize (_format_context->nb_streams); @@ -115,7 +112,7 @@ FFmpegDecoder::flush () /* XXX: should we reset _packet.data and size after each *_decode_* call? */ - while (video && decode_video_packet ()) {} + while (video && decode_video_packet()) {} if (audio) { decode_audio_packet (); @@ -123,21 +120,21 @@ FFmpegDecoder::flush () /* Make sure all streams are the same length and round up to the next video frame */ - FrameRateChange const frc = _ffmpeg_content->film()->active_frame_rate_change(_ffmpeg_content->position()); - ContentTime full_length (_ffmpeg_content->full_length(), frc); + FrameRateChange const frc = film()->active_frame_rate_change(_ffmpeg_content->position()); + ContentTime full_length (_ffmpeg_content->full_length(film()), frc); full_length = full_length.ceil (frc.source); if (video) { double const vfr = _ffmpeg_content->video_frame_rate().get(); Frame const f = full_length.frames_round (vfr); - Frame v = video->position().frames_round (vfr) + 1; + Frame v = video->position(film()).frames_round(vfr) + 1; while (v < f) { - video->emit (shared_ptr (new RawImageProxy (_black_image)), v); + video->emit (film(), shared_ptr (new RawImageProxy (_black_image)), v); ++v; } } BOOST_FOREACH (shared_ptr i, _ffmpeg_content->ffmpeg_audio_streams ()) { - ContentTime a = audio->stream_position(i); + ContentTime a = audio->stream_position(film(), i); /* Unfortunately if a is 0 that really means that we don't know the stream position since there has been no data on it since the last seek. In this case we'll just do nothing here. I'm not sure if that's the right idea. @@ -147,7 +144,7 @@ FFmpegDecoder::flush () ContentTime to_do = min (full_length - a, ContentTime::from_seconds (0.1)); shared_ptr silence (new AudioBuffers (i->channels(), to_do.frames_ceil (i->frame_rate()))); silence->make_silent (); - audio->emit (i, silence, a); + audio->emit (film(), i, silence, a); a += to_do; } } @@ -184,7 +181,7 @@ FFmpegDecoder::pass () if (_video_stream && si == _video_stream.get() && !video->ignore()) { decode_video_packet (); - } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index(_format_context, si) && !only_caption()->ignore()) { + } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index(_format_context, si) && !only_text()->ignore()) { decode_subtitle_packet (); } else { decode_audio_packet (); @@ -479,7 +476,7 @@ FFmpegDecoder::decode_audio_packet () /* Give this data provided there is some, and its time is sane */ if (ct >= ContentTime() && data->frames() > 0) { - audio->emit (*stream, data, ct); + audio->emit (film(), *stream, data, ct); } } @@ -525,9 +522,11 @@ FFmpegDecoder::decode_video_packet () if (i->second != AV_NOPTS_VALUE) { double const pts = i->second * av_q2d (_format_context->streams[_video_stream.get()]->time_base) + _pts_offset.seconds (); + video->emit ( + film(), shared_ptr (new RawImageProxy (image)), - llrint (pts * _ffmpeg_content->active_video_frame_rate ()) + llrint(pts * _ffmpeg_content->active_video_frame_rate(film())) ); } else { LOG_WARNING_NC ("Dropping frame without PTS"); @@ -549,9 +548,9 @@ FFmpegDecoder::decode_subtitle_packet () /* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */ if (_have_current_subtitle) { if (_current_subtitle_to) { - only_caption()->emit_stop (min(*_current_subtitle_to, subtitle_period(sub).from + _pts_offset)); + only_text()->emit_stop (min(*_current_subtitle_to, subtitle_period(sub).from + _pts_offset)); } else { - only_caption()->emit_stop (subtitle_period(sub).from + _pts_offset); + only_text()->emit_stop (subtitle_period(sub).from + _pts_offset); } _have_current_subtitle = false; } @@ -593,7 +592,7 @@ FFmpegDecoder::decode_subtitle_packet () } if (_current_subtitle_to) { - only_caption()->emit_stop (*_current_subtitle_to); + only_text()->emit_stop (*_current_subtitle_to); } avsubtitle_free (&sub); @@ -660,8 +659,19 @@ FFmpegDecoder::decode_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime out_p += image->stride()[0] / sizeof (uint32_t); } - int const target_width = subtitle_codec_context()->width; - int const target_height = subtitle_codec_context()->height; + int target_width = subtitle_codec_context()->width; + if (target_width == 0 && video_codec_context()) { + /* subtitle_codec_context()->width == 0 has been seen in the wild but I don't + know if it's supposed to mean something from FFmpeg's point of view. + */ + target_width = video_codec_context()->width; + } + int target_height = subtitle_codec_context()->height; + if (target_height == 0 && video_codec_context()) { + target_height = video_codec_context()->height; + } + DCPOMATIC_ASSERT (target_width); + DCPOMATIC_ASSERT (target_height); dcpomatic::Rect const scaled_rect ( static_cast (rect->x) / target_width, static_cast (rect->y) / target_height, @@ -669,7 +679,7 @@ FFmpegDecoder::decode_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime static_cast (rect->h) / target_height ); - only_caption()->emit_bitmap_start (from, image, scaled_rect); + only_text()->emit_bitmap_start (from, image, scaled_rect); } void @@ -702,6 +712,6 @@ FFmpegDecoder::decode_ass_subtitle (string ass, ContentTime from) ); BOOST_FOREACH (sub::Subtitle const & i, sub::collect > (raw)) { - only_caption()->emit_plain_start (from, i); + only_text()->emit_plain_start (from, i); } }