1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/decoder_stream_traits.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "media/base/audio_buffer.h"
12 #include "media/base/audio_decoder.h"
13 #include "media/base/audio_decoder_config.h"
14 #include "media/base/video_decoder.h"
15 #include "media/base/video_frame.h"
19 // Audio decoder stream traits implementation.
22 std::string DecoderStreamTraits<DemuxerStream::AUDIO>::ToString() {
27 bool DecoderStreamTraits<DemuxerStream::AUDIO>::NeedsBitstreamConversion(
28 DecoderType* decoder) {
29 return decoder->NeedsBitstreamConversion();
33 scoped_refptr<DecoderStreamTraits<DemuxerStream::AUDIO>::OutputType>
34 DecoderStreamTraits<DemuxerStream::AUDIO>::CreateEOSOutput() {
35 return OutputType::CreateEOSBuffer();
38 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsPlatformDecoder(
39 bool is_platform_decoder) {
40 stats_.audio_decoder_info.is_platform_decoder = is_platform_decoder;
43 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsDecryptingDemuxerStream(
45 stats_.audio_decoder_info.has_decrypting_demuxer_stream = is_dds;
48 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderStreamTraits(
50 ChannelLayout initial_hw_layout)
51 : media_log_(media_log), initial_hw_layout_(initial_hw_layout) {}
53 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderConfigType
54 DecoderStreamTraits<DemuxerStream::AUDIO>::GetDecoderConfig(
55 DemuxerStream* stream) {
56 auto config = stream->audio_decoder_config();
57 // Demuxer is not aware of hw layout, so we set it here.
58 config.set_target_output_channel_layout(initial_hw_layout_);
62 void DecoderStreamTraits<DemuxerStream::AUDIO>::ReportStatistics(
63 const StatisticsCB& statistics_cb,
65 stats_.audio_bytes_decoded = bytes_decoded;
66 statistics_cb.Run(stats_);
69 void DecoderStreamTraits<DemuxerStream::AUDIO>::InitializeDecoder(
71 const DecoderConfigType& config,
73 CdmContext* cdm_context,
75 const OutputCB& output_cb,
76 const WaitingCB& waiting_cb) {
77 DCHECK(config.IsValidConfig());
79 if (config_.IsValidConfig() && !config_.Matches(config))
80 OnConfigChanged(config);
83 stats_.audio_decoder_info.decoder_name = decoder->GetDisplayName();
84 decoder->Initialize(config, cdm_context, std::move(init_cb), output_cb,
88 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
89 DemuxerStream* stream) {
91 // Stream is likely being seeked to a new timestamp, so make new validator to
92 // build new timestamp expectations.
93 audio_ts_validator_.reset(
94 new AudioTimestampValidator(stream->audio_decoder_config(), media_log_));
97 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
98 const DecoderBuffer& buffer) {
99 audio_ts_validator_->CheckForTimestampGap(buffer);
102 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
103 OutputType* buffer) {
104 audio_ts_validator_->RecordOutputDuration(*buffer);
105 return PostDecodeAction::DELIVER;
108 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnConfigChanged(
109 const DecoderConfigType& config) {
110 // Reset validator with the latest config. Also ensures that we do not attempt
111 // to match timestamps across config boundaries.
112 audio_ts_validator_.reset(new AudioTimestampValidator(config, media_log_));
115 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnOutputReady(
116 OutputType* buffer) {}
118 // Video decoder stream traits implementation.
121 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
126 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
127 DecoderType* decoder) {
128 return decoder->NeedsBitstreamConversion();
132 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
133 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
134 return OutputType::CreateEOSFrame();
137 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsPlatformDecoder(
138 bool is_platform_decoder) {
139 stats_.video_decoder_info.is_platform_decoder = is_platform_decoder;
142 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsDecryptingDemuxerStream(
144 stats_.video_decoder_info.has_decrypting_demuxer_stream = is_dds;
147 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
149 // Randomly selected number of samples to keep.
150 : keyframe_distance_average_(16) {}
152 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
153 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
154 DemuxerStream* stream) {
155 return stream->video_decoder_config();
158 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
159 const StatisticsCB& statistics_cb,
161 stats_.video_bytes_decoded = bytes_decoded;
163 if (keyframe_distance_average_.count()) {
164 stats_.video_keyframe_distance_average =
165 keyframe_distance_average_.Average();
167 // Before we have enough keyframes to calculate the average distance, we
168 // will assume the average keyframe distance is infinitely large.
169 stats_.video_keyframe_distance_average = base::TimeDelta::Max();
172 statistics_cb.Run(stats_);
175 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
176 DecoderType* decoder,
177 const DecoderConfigType& config,
179 CdmContext* cdm_context,
181 const OutputCB& output_cb,
182 const WaitingCB& waiting_cb) {
183 DCHECK(config.IsValidConfig());
184 stats_.video_decoder_info.decoder_name = decoder->GetDisplayName();
185 DVLOG(2) << stats_.video_decoder_info.decoder_name;
186 decoder->Initialize(config, low_delay, cdm_context, std::move(init_cb),
187 output_cb, waiting_cb);
190 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
191 DemuxerStream* stream) {
193 last_keyframe_timestamp_ = base::TimeDelta();
194 frame_metadata_.clear();
197 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
198 const DecoderBuffer& buffer) {
199 if (buffer.end_of_stream()) {
200 last_keyframe_timestamp_ = base::TimeDelta();
204 frame_metadata_[buffer.timestamp()] = {
205 buffer.discard_padding().first == kInfiniteDuration, // should_drop
206 buffer.duration(), // duration
207 base::TimeTicks::Now(), // decode_begin_time
210 if (!buffer.is_key_frame())
213 base::TimeDelta current_frame_timestamp = buffer.timestamp();
214 if (last_keyframe_timestamp_.is_zero()) {
215 last_keyframe_timestamp_ = current_frame_timestamp;
219 const base::TimeDelta frame_distance =
220 current_frame_timestamp - last_keyframe_timestamp_;
221 last_keyframe_timestamp_ = current_frame_timestamp;
222 keyframe_distance_average_.AddSample(frame_distance);
225 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
226 OutputType* buffer) {
227 auto it = frame_metadata_.find(buffer->timestamp());
229 // If the frame isn't in |frame_metadata_| it probably was erased below on a
230 // previous cycle. We could drop these, but today our video algorithm will put
231 // them back into sorted order or drop the frame if a later frame has already
233 if (it == frame_metadata_.end())
234 return PostDecodeAction::DELIVER;
236 // Add a timestamp here to enable buffering delay measurements down the line.
237 buffer->metadata()->decode_begin_time = it->second.decode_begin_time;
238 buffer->metadata()->decode_end_time = base::TimeTicks::Now();
240 auto action = it->second.should_drop ? PostDecodeAction::DROP
241 : PostDecodeAction::DELIVER;
243 // Provide duration information to help the rendering algorithm on the very
244 // first and very last frames.
245 if (it->second.duration != kNoTimestamp)
246 buffer->metadata()->frame_duration = it->second.duration;
248 // We erase from the beginning onward to our target frame since frames should
249 // be returned in presentation order. It's possible to accumulate entries in
250 // this queue if playback begins at a non-keyframe; those frames may never be
251 // returned from the decoder.
252 frame_metadata_.erase(frame_metadata_.begin(), it + 1);
256 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnOutputReady(
257 OutputType* buffer) {
258 if (!buffer->metadata()->decode_begin_time.has_value())
261 // Tag buffer with elapsed time since creation.
262 buffer->metadata()->processing_time =
263 base::TimeTicks::Now() - *buffer->metadata()->decode_begin_time;