Revert "[M120 Migration]Fix for crash during chrome exit"
[platform/framework/web/chromium-efl.git] / media / filters / audio_timestamp_validator.cc
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/audio_timestamp_validator.h"
6
7 #include <memory>
8
9 namespace media {
10
11 // Defines how many milliseconds of DecoderBuffer timestamp gap will be allowed
12 // before warning the user. See CheckForTimestampGap(). Value of 50 chosen, as
13 // this is low enough to catch issues early, but high enough to avoid noise for
14 // containers like WebM that default to low granularity timestamp precision.
15 const int kGapWarningThresholdMsec = 50;
16
17 // Limits the number of adjustments to |audio_ts_offset_| in order to reach a
18 // stable state where gaps between encoded timestamps match decoded output
19 // intervals. See CheckForTimestampGap().
20 const int kLimitTriesForStableTiming = 5;
21
22 // Limits the milliseconds of difference between expected and actual timestamps
23 // gaps to consider timestamp expectations "stable". 1 chosen because some
24 // containers (WebM) default to millisecond timestamp precision. See
25 // CheckForTimestampGap().
26 const int kStableTimeGapThrsholdMsec = 1;
27
28 // Maximum number of timestamp gap warnings sent to MediaLog.
29 const int kMaxTimestampGapWarnings = 10;
30
31 AudioTimestampValidator::AudioTimestampValidator(
32     const AudioDecoderConfig& decoder_config,
33     MediaLog* media_log)
34     : has_codec_delay_(decoder_config.codec_delay() > 0),
35       media_log_(media_log),
36       audio_base_ts_(kNoTimestamp),
37       reached_stable_state_(false),
38       num_unstable_audio_tries_(0),
39       limit_unstable_audio_tries_(kLimitTriesForStableTiming),
40       drift_warning_threshold_msec_(kGapWarningThresholdMsec) {
41   DCHECK(decoder_config.IsValidConfig());
42 }
43
44 AudioTimestampValidator::~AudioTimestampValidator() = default;
45
46 void AudioTimestampValidator::CheckForTimestampGap(
47     const DecoderBuffer& buffer) {
48   if (buffer.end_of_stream())
49     return;
50   DCHECK_NE(kNoTimestamp, buffer.timestamp());
51
52   // If audio_base_ts_ == kNoTimestamp, we are processing our first buffer.
53   // If stream has neither codec delay nor discard padding, we should expect
54   // timestamps and output durations to line up from the start (i.e. be stable).
55   if (audio_base_ts_ == kNoTimestamp && !has_codec_delay_ &&
56       buffer.discard_padding().first == base::TimeDelta() &&
57       buffer.discard_padding().second == base::TimeDelta()) {
58     DVLOG(3) << __func__ << " Expecting stable timestamps - stream has neither "
59              << "codec delay nor discard padding.";
60     limit_unstable_audio_tries_ = 0;
61   }
62
63   // Don't continue checking timestamps if we've exhausted tries to reach stable
64   // state. This suggests the media's encoded timestamps are way off.
65   if (num_unstable_audio_tries_ > limit_unstable_audio_tries_)
66     return;
67
68   // Keep resetting encode base ts until we start getting decode output. Some
69   // codecs/containers (e.g. chained Ogg) will take several encoded buffers
70   // before producing the first decoded output.
71   if (!audio_output_ts_helper_) {
72     audio_base_ts_ = buffer.timestamp();
73     DVLOG(3) << __func__
74              << " setting audio_base:" << audio_base_ts_.InMicroseconds();
75     return;
76   }
77
78   base::TimeDelta expected_ts = audio_output_ts_helper_->GetTimestamp();
79   base::TimeDelta ts_delta = buffer.timestamp() - expected_ts;
80
81   // Reconciling encoded buffer timestamps with decoded output often requires
82   // adjusting expectations by some offset. This accounts for varied (and at
83   // this point unknown) handling of front trimming and codec delay. Codec delay
84   // and skip trimming may or may not be accounted for in the encoded timestamps
85   // depending on the codec (e.g. MP3 vs Opus) and  demuxers used (e.g. FFmpeg
86   // vs MSE stream parsers).
87   if (!reached_stable_state_) {
88     if (std::abs(ts_delta.InMilliseconds()) < kStableTimeGapThrsholdMsec) {
89       reached_stable_state_ = true;
90       DVLOG(3) << __func__ << " stabilized! tries:" << num_unstable_audio_tries_
91                << " offset:"
92                << audio_output_ts_helper_->base_timestamp().InMicroseconds();
93     } else {
94       base::TimeDelta orig_offset = audio_output_ts_helper_->base_timestamp();
95
96       // Save since this gets reset when we set new base time.
97       int64_t decoded_frame_count = audio_output_ts_helper_->frame_count();
98       audio_output_ts_helper_->SetBaseTimestamp(orig_offset + ts_delta);
99       audio_output_ts_helper_->AddFrames(decoded_frame_count);
100
101       DVLOG(3) << __func__
102                << " NOT stabilized. tries:" << num_unstable_audio_tries_
103                << " offset was:" << orig_offset.InMicroseconds() << " now:"
104                << audio_output_ts_helper_->base_timestamp().InMicroseconds();
105       num_unstable_audio_tries_++;
106
107       // Let developers know if their files timestamps are way off from
108       if (num_unstable_audio_tries_ > limit_unstable_audio_tries_) {
109         MEDIA_LOG(WARNING, media_log_)
110             << "Failed to reconcile encoded audio times with decoded output.";
111       }
112     }
113
114     // Don't bother with further checking until we reach stable state.
115     return;
116   }
117
118   if (std::abs(ts_delta.InMilliseconds()) > drift_warning_threshold_msec_) {
119     LIMITED_MEDIA_LOG(WARNING, media_log_, num_timestamp_gap_warnings_,
120                       kMaxTimestampGapWarnings)
121         << " Large timestamp gap detected; may cause AV sync to drift."
122         << " time:" << buffer.timestamp().InMicroseconds() << "us"
123         << " expected:" << expected_ts.InMicroseconds() << "us"
124         << " delta:" << ts_delta.InMicroseconds() << "us";
125     // Increase threshold to avoid log spam but, let us know if gap widens.
126     drift_warning_threshold_msec_ = std::abs(ts_delta.InMilliseconds());
127   }
128   DVLOG(3) << __func__ << " delta:" << ts_delta.InMicroseconds()
129            << " expected_ts:" << expected_ts.InMicroseconds()
130            << " actual_ts:" << buffer.timestamp().InMicroseconds()
131            << " audio_ts_offset:"
132            << audio_output_ts_helper_->base_timestamp().InMicroseconds();
133 }
134
135 void AudioTimestampValidator::RecordOutputDuration(
136     const AudioBuffer& audio_buffer) {
137   if (!audio_output_ts_helper_) {
138     DCHECK_NE(audio_base_ts_, kNoTimestamp);
139     // SUBTLE: deliberately creating this with output buffer sample rate because
140     // demuxer stream config is potentially stale for implicit AAC.
141     audio_output_ts_helper_ =
142         std::make_unique<AudioTimestampHelper>(audio_buffer.sample_rate());
143     audio_output_ts_helper_->SetBaseTimestamp(audio_base_ts_);
144   }
145
146   DVLOG(3) << __func__ << " " << audio_buffer.frame_count() << " frames";
147   audio_output_ts_helper_->AddFrames(audio_buffer.frame_count());
148 }
149
150 }  // namespace media