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,
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, std::move(init_cb), output_cb,
78 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
79 DemuxerStream* stream) {
81 // Stream is likely being seeked to a new timestamp, so make new validator to
82 // build new timestamp expectations.
83 audio_ts_validator_.reset(
84 new AudioTimestampValidator(stream->audio_decoder_config(), media_log_));
87 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
88 const DecoderBuffer& buffer) {
89 audio_ts_validator_->CheckForTimestampGap(buffer);
92 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
94 audio_ts_validator_->RecordOutputDuration(*buffer);
95 return PostDecodeAction::DELIVER;
98 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnConfigChanged(
99 const DecoderConfigType& config) {
100 // Reset validator with the latest config. Also ensures that we do not attempt
101 // to match timestamps across config boundaries.
102 audio_ts_validator_.reset(new AudioTimestampValidator(config, media_log_));
105 // Video decoder stream traits implementation.
108 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
113 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
114 DecoderType* decoder) {
115 return decoder->NeedsBitstreamConversion();
119 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
120 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
121 return OutputType::CreateEOSFrame();
124 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
126 // Randomly selected number of samples to keep.
127 : keyframe_distance_average_(16) {}
129 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
130 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
131 DemuxerStream* stream) {
132 return stream->video_decoder_config();
135 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
136 const StatisticsCB& statistics_cb,
138 stats_.video_bytes_decoded = bytes_decoded;
140 if (keyframe_distance_average_.count()) {
141 stats_.video_keyframe_distance_average =
142 keyframe_distance_average_.Average();
144 // Before we have enough keyframes to calculate the average distance, we
145 // will assume the average keyframe distance is infinitely large.
146 stats_.video_keyframe_distance_average = base::TimeDelta::Max();
149 statistics_cb.Run(stats_);
152 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
153 DecoderType* decoder,
154 const DecoderConfigType& config,
156 CdmContext* cdm_context,
158 const OutputCB& output_cb,
159 const WaitingCB& waiting_cb) {
160 DCHECK(config.IsValidConfig());
161 stats_.video_decoder_name = decoder->GetDisplayName();
162 DVLOG(2) << stats_.video_decoder_name;
163 decoder->Initialize(config, low_delay, cdm_context, std::move(init_cb),
164 output_cb, waiting_cb);
167 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
168 DemuxerStream* stream) {
170 last_keyframe_timestamp_ = base::TimeDelta();
171 frame_metadata_.clear();
174 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
175 const DecoderBuffer& buffer) {
176 if (buffer.end_of_stream()) {
177 last_keyframe_timestamp_ = base::TimeDelta();
181 frame_metadata_[buffer.timestamp()] = {
182 buffer.discard_padding().first == kInfiniteDuration, // should_drop
183 buffer.duration(), // duration
186 if (!buffer.is_key_frame())
189 base::TimeDelta current_frame_timestamp = buffer.timestamp();
190 if (last_keyframe_timestamp_.is_zero()) {
191 last_keyframe_timestamp_ = current_frame_timestamp;
195 const base::TimeDelta frame_distance =
196 current_frame_timestamp - last_keyframe_timestamp_;
197 last_keyframe_timestamp_ = current_frame_timestamp;
198 keyframe_distance_average_.AddSample(frame_distance);
201 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
202 OutputType* buffer) {
203 // Add a timestamp here (after decoding completed) to enable buffering delay
204 // measurements down the line.
205 buffer->metadata()->SetTimeTicks(media::VideoFrameMetadata::DECODE_TIME,
206 base::TimeTicks::Now());
208 auto it = frame_metadata_.find(buffer->timestamp());
210 // If the frame isn't in |frame_metadata_| it probably was erased below on a
211 // previous cycle. We could drop these, but today our video algorithm will put
212 // them back into sorted order or drop the frame if a later frame has already
214 if (it == frame_metadata_.end())
215 return PostDecodeAction::DELIVER;
217 auto action = it->second.should_drop ? PostDecodeAction::DROP
218 : PostDecodeAction::DELIVER;
220 // Provide duration information to help the rendering algorithm on the very
221 // first and very last frames.
222 if (it->second.duration != kNoTimestamp) {
223 buffer->metadata()->SetTimeDelta(VideoFrameMetadata::FRAME_DURATION,
224 it->second.duration);
227 // We erase from the beginning onward to our target frame since frames should
228 // be returned in presentation order. It's possible to accumulate entries in
229 // this queue if playback begins at a non-keyframe; those frames may never be
230 // returned from the decoder.
231 frame_metadata_.erase(frame_metadata_.begin(), it + 1);