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"
10 #include "base/logging.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "media/base/audio_buffer.h"
13 #include "media/base/audio_decoder.h"
14 #include "media/base/audio_decoder_config.h"
15 #include "media/base/video_decoder.h"
16 #include "media/base/video_frame.h"
20 // Audio decoder stream traits implementation.
23 std::string DecoderStreamTraits<DemuxerStream::AUDIO>::ToString() {
28 bool DecoderStreamTraits<DemuxerStream::AUDIO>::NeedsBitstreamConversion(
29 DecoderType* decoder) {
30 return decoder->NeedsBitstreamConversion();
34 scoped_refptr<DecoderStreamTraits<DemuxerStream::AUDIO>::OutputType>
35 DecoderStreamTraits<DemuxerStream::AUDIO>::CreateEOSOutput() {
36 return OutputType::CreateEOSBuffer();
39 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsPlatformDecoder(
40 bool is_platform_decoder) {
41 stats_.audio_pipeline_info.is_platform_decoder = is_platform_decoder;
44 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsDecryptingDemuxerStream(
46 stats_.audio_pipeline_info.has_decrypting_demuxer_stream = is_dds;
49 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetEncryptionType(
50 EncryptionType encryption_type) {
51 stats_.audio_pipeline_info.encryption_type = encryption_type;
54 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderStreamTraits(
56 ChannelLayout initial_hw_layout)
57 : media_log_(media_log), initial_hw_layout_(initial_hw_layout) {
58 weak_this_ = weak_factory_.GetWeakPtr();
61 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderConfigType
62 DecoderStreamTraits<DemuxerStream::AUDIO>::GetDecoderConfig(
63 DemuxerStream* stream) {
64 auto config = stream->audio_decoder_config();
65 // Demuxer is not aware of hw layout, so we set it here.
66 config.set_target_output_channel_layout(initial_hw_layout_);
70 void DecoderStreamTraits<DemuxerStream::AUDIO>::ReportStatistics(
71 const StatisticsCB& statistics_cb,
73 stats_.audio_bytes_decoded = bytes_decoded;
74 statistics_cb.Run(stats_);
77 void DecoderStreamTraits<DemuxerStream::AUDIO>::InitializeDecoder(
79 const DecoderConfigType& config,
81 CdmContext* cdm_context,
83 const OutputCB& output_cb,
84 const WaitingCB& waiting_cb) {
85 DCHECK(config.IsValidConfig());
87 if (config_.IsValidConfig() && !config_.Matches(config))
88 OnConfigChanged(config);
91 stats_.audio_pipeline_info.decoder_type = AudioDecoderType::kUnknown;
92 // Both |this| and |decoder| are owned by a DecoderSelector and will stay
93 // alive at least until |init_cb| is finished executing.
97 &DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecoderInitialized,
98 weak_this_, base::Unretained(decoder), std::move(init_cb)),
99 output_cb, waiting_cb);
102 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecoderInitialized(
103 DecoderType* decoder,
107 stats_.audio_pipeline_info.decoder_type = decoder->GetDecoderType();
108 std::move(cb).Run(result);
111 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
112 DemuxerStream* stream) {
114 // Stream is likely being seeked to a new timestamp, so make new validator to
115 // build new timestamp expectations.
116 audio_ts_validator_ = std::make_unique<AudioTimestampValidator>(
117 stream->audio_decoder_config(), media_log_);
120 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
121 const DecoderBuffer& buffer) {
122 audio_ts_validator_->CheckForTimestampGap(buffer);
125 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
126 OutputType* buffer) {
127 audio_ts_validator_->RecordOutputDuration(*buffer);
128 return PostDecodeAction::DELIVER;
131 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnConfigChanged(
132 const DecoderConfigType& config) {
133 // Reset validator with the latest config. Also ensures that we do not attempt
134 // to match timestamps across config boundaries.
135 audio_ts_validator_ =
136 std::make_unique<AudioTimestampValidator>(config, media_log_);
139 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnOutputReady(
140 OutputType* buffer) {}
142 // Video decoder stream traits implementation.
145 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
150 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
151 DecoderType* decoder) {
152 return decoder->NeedsBitstreamConversion();
156 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
157 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
158 return OutputType::CreateEOSFrame();
161 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsPlatformDecoder(
162 bool is_platform_decoder) {
163 stats_.video_pipeline_info.is_platform_decoder = is_platform_decoder;
166 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsDecryptingDemuxerStream(
168 stats_.video_pipeline_info.has_decrypting_demuxer_stream = is_dds;
171 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetEncryptionType(
172 EncryptionType encryption_type) {
173 stats_.video_pipeline_info.encryption_type = encryption_type;
176 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
178 // Randomly selected number of samples to keep.
179 : keyframe_distance_average_(16) {
180 weak_this_ = weak_factory_.GetWeakPtr();
183 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
184 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
185 DemuxerStream* stream) {
186 return stream->video_decoder_config();
189 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
190 const StatisticsCB& statistics_cb,
192 stats_.video_bytes_decoded = bytes_decoded;
194 if (keyframe_distance_average_.count()) {
195 stats_.video_keyframe_distance_average =
196 keyframe_distance_average_.Average();
198 // Before we have enough keyframes to calculate the average distance, we
199 // will assume the average keyframe distance is infinitely large.
200 stats_.video_keyframe_distance_average = base::TimeDelta::Max();
203 statistics_cb.Run(stats_);
206 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
207 DecoderType* decoder,
208 const DecoderConfigType& config,
210 CdmContext* cdm_context,
212 const OutputCB& output_cb,
213 const WaitingCB& waiting_cb) {
214 DCHECK(config.IsValidConfig());
215 stats_.video_pipeline_info.decoder_type = VideoDecoderType::kUnknown;
216 transform_ = config.video_transformation();
217 // |decoder| is owned by a DecoderSelector and will stay
218 // alive at least until |init_cb| is finished executing.
220 config, low_delay, cdm_context,
222 &DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized,
223 weak_this_, base::Unretained(decoder), std::move(init_cb)),
224 output_cb, waiting_cb);
227 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized(
228 DecoderType* decoder,
231 if (result.is_ok()) {
232 stats_.video_pipeline_info.decoder_type = decoder->GetDecoderType();
233 DVLOG(2) << stats_.video_pipeline_info.decoder_type;
235 DVLOG(2) << "Decoder initialization failed.";
237 std::move(cb).Run(result);
240 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
241 DemuxerStream* stream) {
243 last_keyframe_timestamp_ = base::TimeDelta();
244 frame_metadata_.clear();
247 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
248 const DecoderBuffer& buffer) {
249 if (buffer.end_of_stream()) {
250 last_keyframe_timestamp_ = base::TimeDelta();
254 frame_metadata_[buffer.timestamp()] = {
255 buffer.discard_padding().first == kInfiniteDuration, // should_drop
256 buffer.duration(), // duration
257 base::TimeTicks::Now(), // decode_begin_time
260 if (!buffer.is_key_frame())
263 base::TimeDelta current_frame_timestamp = buffer.timestamp();
264 if (last_keyframe_timestamp_.is_zero()) {
265 last_keyframe_timestamp_ = current_frame_timestamp;
269 const base::TimeDelta frame_distance =
270 current_frame_timestamp - last_keyframe_timestamp_;
271 last_keyframe_timestamp_ = current_frame_timestamp;
272 keyframe_distance_average_.AddSample(frame_distance);
275 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
276 OutputType* buffer) {
277 auto it = frame_metadata_.find(buffer->timestamp());
279 // If the frame isn't in |frame_metadata_| it probably was erased below on a
280 // previous cycle. We could drop these, but today our video algorithm will put
281 // them back into sorted order or drop the frame if a later frame has already
283 if (it == frame_metadata_.end())
284 return PostDecodeAction::DELIVER;
286 // Add a timestamp here to enable buffering delay measurements down the line.
287 buffer->metadata().decode_begin_time = it->second.decode_begin_time;
288 buffer->metadata().decode_end_time = base::TimeTicks::Now();
290 auto action = it->second.should_drop ? PostDecodeAction::DROP
291 : PostDecodeAction::DELIVER;
293 // Provide duration information to help the rendering algorithm on the very
294 // first and very last frames.
295 if (it->second.duration != kNoTimestamp)
296 buffer->metadata().frame_duration = it->second.duration;
298 // We erase from the beginning onward to our target frame since frames should
299 // be returned in presentation order. It's possible to accumulate entries in
300 // this queue if playback begins at a non-keyframe; those frames may never be
301 // returned from the decoder.
302 frame_metadata_.erase(frame_metadata_.begin(), it + 1);
306 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnOutputReady(
307 OutputType* buffer) {
308 buffer->metadata().transformation = transform_;
310 if (!buffer->metadata().decode_begin_time.has_value())
313 // Tag buffer with elapsed time since creation.
314 buffer->metadata().processing_time =
315 base::TimeTicks::Now() - *buffer->metadata().decode_begin_time;