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 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderStreamTraits(
40 ChannelLayout initial_hw_layout)
41 : media_log_(media_log), initial_hw_layout_(initial_hw_layout) {}
43 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderConfigType
44 DecoderStreamTraits<DemuxerStream::AUDIO>::GetDecoderConfig(
45 DemuxerStream* stream) {
46 auto config = stream->audio_decoder_config();
47 // Demuxer is not aware of hw layout, so we set it here.
48 config.set_target_output_channel_layout(initial_hw_layout_);
52 void DecoderStreamTraits<DemuxerStream::AUDIO>::ReportStatistics(
53 const StatisticsCB& statistics_cb,
55 stats_.audio_bytes_decoded = bytes_decoded;
56 statistics_cb.Run(stats_);
59 void DecoderStreamTraits<DemuxerStream::AUDIO>::InitializeDecoder(
61 const DecoderConfigType& config,
63 CdmContext* cdm_context,
64 const InitCB& init_cb,
65 const OutputCB& output_cb,
66 const WaitingCB& waiting_cb) {
67 DCHECK(config.IsValidConfig());
69 if (config_.IsValidConfig() && !config_.Matches(config))
70 OnConfigChanged(config);
73 stats_.audio_decoder_name = decoder->GetDisplayName();
74 decoder->Initialize(config, cdm_context, init_cb, output_cb, waiting_cb);
77 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
78 DemuxerStream* stream) {
80 // Stream is likely being seeked to a new timestamp, so make new validator to
81 // build new timestamp expectations.
82 audio_ts_validator_.reset(
83 new AudioTimestampValidator(stream->audio_decoder_config(), media_log_));
86 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
87 const DecoderBuffer& buffer) {
88 audio_ts_validator_->CheckForTimestampGap(buffer);
91 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
92 const scoped_refptr<OutputType>& buffer) {
93 audio_ts_validator_->RecordOutputDuration(buffer);
94 return PostDecodeAction::DELIVER;
97 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnConfigChanged(
98 const DecoderConfigType& config) {
99 // Reset validator with the latest config. Also ensures that we do not attempt
100 // to match timestamps across config boundaries.
101 audio_ts_validator_.reset(new AudioTimestampValidator(config, media_log_));
104 // Video decoder stream traits implementation.
107 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
112 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
113 DecoderType* decoder) {
114 return decoder->NeedsBitstreamConversion();
118 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
119 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
120 return OutputType::CreateEOSFrame();
123 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
125 // Randomly selected number of samples to keep.
126 : keyframe_distance_average_(16) {}
128 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
129 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
130 DemuxerStream* stream) {
131 return stream->video_decoder_config();
134 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
135 const StatisticsCB& statistics_cb,
137 stats_.video_bytes_decoded = bytes_decoded;
139 if (keyframe_distance_average_.count()) {
140 stats_.video_keyframe_distance_average =
141 keyframe_distance_average_.Average();
143 // Before we have enough keyframes to calculate the average distance, we
144 // will assume the average keyframe distance is infinitely large.
145 stats_.video_keyframe_distance_average = base::TimeDelta::Max();
148 statistics_cb.Run(stats_);
151 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
152 DecoderType* decoder,
153 const DecoderConfigType& config,
155 CdmContext* cdm_context,
156 const InitCB& init_cb,
157 const OutputCB& output_cb,
158 const WaitingCB& waiting_cb) {
159 DCHECK(config.IsValidConfig());
160 stats_.video_decoder_name = decoder->GetDisplayName();
161 DVLOG(2) << stats_.video_decoder_name;
162 decoder->Initialize(config, low_delay, cdm_context, init_cb, output_cb,
166 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
167 DemuxerStream* stream) {
169 last_keyframe_timestamp_ = base::TimeDelta();
170 frames_to_drop_.clear();
173 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
174 const DecoderBuffer& buffer) {
175 if (buffer.end_of_stream()) {
176 last_keyframe_timestamp_ = base::TimeDelta();
180 if (buffer.discard_padding().first == kInfiniteDuration)
181 frames_to_drop_.insert(buffer.timestamp());
183 if (!buffer.is_key_frame())
186 base::TimeDelta current_frame_timestamp = buffer.timestamp();
187 if (last_keyframe_timestamp_.is_zero()) {
188 last_keyframe_timestamp_ = current_frame_timestamp;
192 const base::TimeDelta frame_distance =
193 current_frame_timestamp - last_keyframe_timestamp_;
194 last_keyframe_timestamp_ = current_frame_timestamp;
195 keyframe_distance_average_.AddSample(frame_distance);
198 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
199 const scoped_refptr<OutputType>& buffer) {
200 auto it = frames_to_drop_.find(buffer->timestamp());
201 if (it != frames_to_drop_.end()) {
202 // We erase from the beginning onward to our target frame since frames
203 // should be returned in presentation order. It's possible to accumulate
204 // entries in this queue if playback begins at a non-keyframe; those frames
205 // may never be returned from the decoder.
206 frames_to_drop_.erase(frames_to_drop_.begin(), it + 1);
207 return PostDecodeAction::DROP;
210 return PostDecodeAction::DELIVER;