summaryrefslogtreecommitdiff
path: root/src/lib/ffmpeg_decoder.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2017-09-03 01:41:50 +0100
committerCarl Hetherington <cth@carlh.net>2017-09-03 01:41:50 +0100
commit48cd8b6a44ab689ad2eb8e6d86e086def995d9ba (patch)
treed96937d79dc201c89ac4957007b23b7df9f934fb /src/lib/ffmpeg_decoder.cc
parent4b05c69e14f43826a59128b4b27316c9f9d9a84e (diff)
Cope with e.g. truehd audio streams having not every audio frame arriving with a pts.
Diffstat (limited to 'src/lib/ffmpeg_decoder.cc')
-rw-r--r--src/lib/ffmpeg_decoder.cc37
1 files changed, 30 insertions, 7 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index af309cdbe..3cbd0304e 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -100,6 +100,8 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log>
if (c->subtitle) {
subtitle.reset (new SubtitleDecoder (this, c->subtitle, log));
}
+
+ _next_time.resize (_format_context->nb_streams);
}
void
@@ -392,11 +394,12 @@ FFmpegDecoder::decode_audio_packet ()
*/
AVPacket copy_packet = _packet;
+ int const stream_index = copy_packet.stream_index;
/* XXX: inefficient */
vector<shared_ptr<FFmpegAudioStream> > streams = ffmpeg_content()->ffmpeg_audio_streams ();
vector<shared_ptr<FFmpegAudioStream> >::const_iterator stream = streams.begin ();
- while (stream != streams.end () && !(*stream)->uses_index (_format_context, copy_packet.stream_index)) {
+ while (stream != streams.end () && !(*stream)->uses_index (_format_context, stream_index)) {
++stream;
}
@@ -426,13 +429,24 @@ FFmpegDecoder::decode_audio_packet ()
}
if (frame_finished) {
- ContentTime ct = ContentTime::from_seconds (
- av_frame_get_best_effort_timestamp (_frame) *
- av_q2d ((*stream)->stream (_format_context)->time_base))
- + _pts_offset;
-
shared_ptr<AudioBuffers> data = deinterleave_audio (*stream);
+ ContentTime ct;
+ if (_frame->pts == AV_NOPTS_VALUE && _next_time[stream_index]) {
+ /* In some streams we see not every frame coming through with a timestamp; for those
+ that have AV_NOPTS_VALUE we need to work out the timestamp ourselves. This is
+ particularly noticeable with TrueHD streams (see #1111).
+ */
+ ct = *_next_time[stream_index];
+ } else {
+ ct = ContentTime::from_seconds (
+ av_frame_get_best_effort_timestamp (_frame) *
+ av_q2d ((*stream)->stream (_format_context)->time_base))
+ + _pts_offset;
+ }
+
+ _next_time[stream_index] = ct + ContentTime::from_frames(data->frames(), (*stream)->frame_rate());
+
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 ())));
@@ -442,7 +456,16 @@ FFmpegDecoder::decode_audio_packet ()
}
if (ct < ContentTime()) {
- LOG_WARNING ("Crazy timestamp %1", to_string (ct));
+ LOG_WARNING (
+ "Crazy timestamp %1 for %2 samples in stream %3 packet pts %4 (ts=%5 tb=%6, off=%7)",
+ to_string(ct),
+ data->frames(),
+ copy_packet.stream_index,
+ copy_packet.pts,
+ av_frame_get_best_effort_timestamp(_frame),
+ av_q2d((*stream)->stream(_format_context)->time_base),
+ to_string(_pts_offset)
+ );
}
/* Give this data provided there is some, and its time is sane */