X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Fffmpeg_decoder.cc;h=83bce18308ae3b42de919ad6ffc26fe356ee3d61;hp=ae44ff5220d04a2730087b89ea4b7f49a24e1be3;hb=aeb835a18c8df347e0ed68fb24631b320abeb611;hpb=f26af8112b03b5233eb5239defd11a7428b705ad diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index ae44ff522..83bce1830 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -47,10 +47,10 @@ extern "C" { #include "i18n.h" -#define LOG_GENERAL(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); -#define LOG_ERROR(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_ERROR); -#define LOG_WARNING_NC(...) _video_content->film()->log()->log (__VA_ARGS__, Log::TYPE_WARNING); -#define LOG_WARNING(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_WARNING); +#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::vector; @@ -67,51 +67,9 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr c, shared_ptr , SubtitleDecoder (c) , FFmpeg (c) , _log (log) + , _pts_offset (pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->video_frame_rate())) { - /* Audio and video frame PTS values may not start with 0. We want - to fiddle them so that: - 1. One of them starts at time 0. - 2. The first video PTS value ends up on a frame boundary. - - Then we remove big initial gaps in PTS and we allow our - insertion of black frames to work. - - We will do: - audio_pts_to_use = audio_pts_from_ffmpeg + pts_offset; - video_pts_to_use = video_pts_from_ffmpeg + pts_offset; - */ - - /* First, make one of them start at 0 */ - - vector > streams = c->ffmpeg_audio_streams (); - - _pts_offset = ContentTime::min (); - - if (c->first_video ()) { - _pts_offset = - c->first_video().get (); - } - - BOOST_FOREACH (shared_ptr i, streams) { - if (i->first_audio) { - _pts_offset = max (_pts_offset, - i->first_audio.get ()); - } - } - - /* If _pts_offset is positive we would be pushing things from a -ve PTS to be played. - I don't think we ever want to do that, as it seems things at -ve PTS are not meant - to be seen (use for alignment bars etc.); see mantis #418. - */ - if (_pts_offset > ContentTime ()) { - _pts_offset = ContentTime (); - } - - /* Now adjust so that the video pts starts on a frame */ - if (c->first_video ()) { - ContentTime first_video = c->first_video().get() + _pts_offset; - ContentTime const old_first_video = first_video; - _pts_offset += first_video.round_up (c->video_frame_rate ()) - old_first_video; - } } void @@ -366,7 +324,7 @@ FFmpegDecoder::decode_audio_packet () } if (frame_finished) { - ContentTime const ct = ContentTime::from_seconds ( + ContentTime ct = ContentTime::from_seconds ( av_frame_get_best_effort_timestamp (_frame) * av_q2d ((*stream)->stream (_format_context)->time_base)) + _pts_offset; @@ -375,7 +333,19 @@ FFmpegDecoder::decode_audio_packet () 0, (*stream)->stream(_format_context)->codec->channels, _frame->nb_samples, audio_sample_format (*stream), 1 ); - audio (*stream, deinterleave_audio (*stream, _frame->data, data_size), ct); + shared_ptr data = deinterleave_audio (*stream, _frame->data, data_size); + + if (ct < ContentTime ()) { + /* Discard audio data that comes before time 0 */ + Frame const remove = min (int64_t (data->frames()), (-ct).frames_ceil(double((*stream)->frame_rate ()))); + data->move (remove, 0, data->frames() - remove); + data->set_frames (data->frames() - remove); + ct += ContentTime::from_frames (remove, (*stream)->frame_rate ()); + } + + if (data->frames() > 0) { + audio (*stream, data, ct); + } } copy_packet.data += decode_result; @@ -442,8 +412,6 @@ FFmpegDecoder::decode_subtitle_packet () indicate that the previous subtitle should stop. We can ignore it here. */ return; - } else if (sub.num_rects > 1) { - throw DecodeError (_("multi-part subtitles not yet supported")); } /* Subtitle PTS (within the source, not taking into account any of the @@ -457,23 +425,25 @@ FFmpegDecoder::decode_subtitle_packet () period.to = sub_period.to.get() + _pts_offset; } else { /* We have to look up the `to' time in the stream's records */ - period.to = ffmpeg_content()->subtitle_stream()->find_subtitle_to (sub_period.from); + period.to = ffmpeg_content()->subtitle_stream()->find_subtitle_to (period.from); } - AVSubtitleRect const * rect = sub.rects[0]; - - switch (rect->type) { - case SUBTITLE_NONE: - break; - case SUBTITLE_BITMAP: - decode_bitmap_subtitle (rect, period); - break; - case SUBTITLE_TEXT: - cout << "XXX: SUBTITLE_TEXT " << rect->text << "\n"; - break; - case SUBTITLE_ASS: - cout << "XXX: SUBTITLE_ASS " << rect->ass << "\n"; - break; + for (unsigned int i = 0; i < sub.num_rects; ++i) { + AVSubtitleRect const * rect = sub.rects[i]; + + switch (rect->type) { + case SUBTITLE_NONE: + break; + case SUBTITLE_BITMAP: + decode_bitmap_subtitle (rect, period); + break; + case SUBTITLE_TEXT: + cout << "XXX: SUBTITLE_TEXT " << rect->text << "\n"; + break; + case SUBTITLE_ASS: + cout << "XXX: SUBTITLE_ASS " << rect->ass << "\n"; + break; + } } avsubtitle_free (&sub);