Upload upstream chromium 94.0.4606.31
[platform/framework/web/chromium-efl.git] / media / filters / decoder_stream_traits.cc
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.
4
5 #include "media/filters/decoder_stream_traits.h"
6
7 #include <limits>
8 #include <memory>
9
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"
17
18 namespace media {
19
20 // Audio decoder stream traits implementation.
21
22 // static
23 std::string DecoderStreamTraits<DemuxerStream::AUDIO>::ToString() {
24   return "audio";
25 }
26
27 // static
28 bool DecoderStreamTraits<DemuxerStream::AUDIO>::NeedsBitstreamConversion(
29     DecoderType* decoder) {
30   return decoder->NeedsBitstreamConversion();
31 }
32
33 // static
34 scoped_refptr<DecoderStreamTraits<DemuxerStream::AUDIO>::OutputType>
35 DecoderStreamTraits<DemuxerStream::AUDIO>::CreateEOSOutput() {
36   return OutputType::CreateEOSBuffer();
37 }
38
39 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsPlatformDecoder(
40     bool is_platform_decoder) {
41   stats_.audio_pipeline_info.is_platform_decoder = is_platform_decoder;
42 }
43
44 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsDecryptingDemuxerStream(
45     bool is_dds) {
46   stats_.audio_pipeline_info.has_decrypting_demuxer_stream = is_dds;
47 }
48
49 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetEncryptionType(
50     EncryptionType encryption_type) {
51   stats_.audio_pipeline_info.encryption_type = encryption_type;
52 }
53
54 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderStreamTraits(
55     MediaLog* media_log,
56     ChannelLayout initial_hw_layout)
57     : media_log_(media_log), initial_hw_layout_(initial_hw_layout) {
58   weak_this_ = weak_factory_.GetWeakPtr();
59 }
60
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_);
67   return config;
68 }
69
70 void DecoderStreamTraits<DemuxerStream::AUDIO>::ReportStatistics(
71     const StatisticsCB& statistics_cb,
72     int bytes_decoded) {
73   stats_.audio_bytes_decoded = bytes_decoded;
74   statistics_cb.Run(stats_);
75 }
76
77 void DecoderStreamTraits<DemuxerStream::AUDIO>::InitializeDecoder(
78     DecoderType* decoder,
79     const DecoderConfigType& config,
80     bool /* low_delay */,
81     CdmContext* cdm_context,
82     InitCB init_cb,
83     const OutputCB& output_cb,
84     const WaitingCB& waiting_cb) {
85   DCHECK(config.IsValidConfig());
86
87   if (config_.IsValidConfig() && !config_.Matches(config))
88     OnConfigChanged(config);
89   config_ = config;
90
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.
94   decoder->Initialize(
95       config, cdm_context,
96       base::BindOnce(
97           &DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecoderInitialized,
98           weak_this_, base::Unretained(decoder), std::move(init_cb)),
99       output_cb, waiting_cb);
100 }
101
102 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecoderInitialized(
103     DecoderType* decoder,
104     InitCB cb,
105     Status result) {
106   if (result.is_ok())
107     stats_.audio_pipeline_info.decoder_type = decoder->GetDecoderType();
108   std::move(cb).Run(result);
109 }
110
111 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
112     DemuxerStream* stream) {
113   DCHECK(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_);
118 }
119
120 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
121     const DecoderBuffer& buffer) {
122   audio_ts_validator_->CheckForTimestampGap(buffer);
123 }
124
125 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
126     OutputType* buffer) {
127   audio_ts_validator_->RecordOutputDuration(*buffer);
128   return PostDecodeAction::DELIVER;
129 }
130
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_);
137 }
138
139 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnOutputReady(
140     OutputType* buffer) {}
141
142 // Video decoder stream traits implementation.
143
144 // static
145 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
146   return "video";
147 }
148
149 // static
150 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
151     DecoderType* decoder) {
152   return decoder->NeedsBitstreamConversion();
153 }
154
155 // static
156 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
157 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
158   return OutputType::CreateEOSFrame();
159 }
160
161 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsPlatformDecoder(
162     bool is_platform_decoder) {
163   stats_.video_pipeline_info.is_platform_decoder = is_platform_decoder;
164 }
165
166 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsDecryptingDemuxerStream(
167     bool is_dds) {
168   stats_.video_pipeline_info.has_decrypting_demuxer_stream = is_dds;
169 }
170
171 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetEncryptionType(
172     EncryptionType encryption_type) {
173   stats_.video_pipeline_info.encryption_type = encryption_type;
174 }
175
176 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
177     MediaLog* media_log)
178     // Randomly selected number of samples to keep.
179     : keyframe_distance_average_(16) {
180   weak_this_ = weak_factory_.GetWeakPtr();
181 }
182
183 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
184 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
185     DemuxerStream* stream) {
186   return stream->video_decoder_config();
187 }
188
189 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
190     const StatisticsCB& statistics_cb,
191     int bytes_decoded) {
192   stats_.video_bytes_decoded = bytes_decoded;
193
194   if (keyframe_distance_average_.count()) {
195     stats_.video_keyframe_distance_average =
196         keyframe_distance_average_.Average();
197   } else {
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();
201   }
202
203   statistics_cb.Run(stats_);
204 }
205
206 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
207     DecoderType* decoder,
208     const DecoderConfigType& config,
209     bool low_delay,
210     CdmContext* cdm_context,
211     InitCB init_cb,
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.
219   decoder->Initialize(
220       config, low_delay, cdm_context,
221       base::BindOnce(
222           &DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized,
223           weak_this_, base::Unretained(decoder), std::move(init_cb)),
224       output_cb, waiting_cb);
225 }
226
227 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized(
228     DecoderType* decoder,
229     InitCB cb,
230     Status result) {
231   if (result.is_ok()) {
232     stats_.video_pipeline_info.decoder_type = decoder->GetDecoderType();
233     DVLOG(2) << stats_.video_pipeline_info.decoder_type;
234   } else {
235     DVLOG(2) << "Decoder initialization failed.";
236   }
237   std::move(cb).Run(result);
238 }
239
240 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
241     DemuxerStream* stream) {
242   DCHECK(stream);
243   last_keyframe_timestamp_ = base::TimeDelta();
244   frame_metadata_.clear();
245 }
246
247 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
248     const DecoderBuffer& buffer) {
249   if (buffer.end_of_stream()) {
250     last_keyframe_timestamp_ = base::TimeDelta();
251     return;
252   }
253
254   frame_metadata_[buffer.timestamp()] = {
255       buffer.discard_padding().first == kInfiniteDuration,  // should_drop
256       buffer.duration(),                                    // duration
257       base::TimeTicks::Now(),                               // decode_begin_time
258   };
259
260   if (!buffer.is_key_frame())
261     return;
262
263   base::TimeDelta current_frame_timestamp = buffer.timestamp();
264   if (last_keyframe_timestamp_.is_zero()) {
265     last_keyframe_timestamp_ = current_frame_timestamp;
266     return;
267   }
268
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);
273 }
274
275 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
276     OutputType* buffer) {
277   auto it = frame_metadata_.find(buffer->timestamp());
278
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
282   // been rendered.
283   if (it == frame_metadata_.end())
284     return PostDecodeAction::DELIVER;
285
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();
289
290   auto action = it->second.should_drop ? PostDecodeAction::DROP
291                                        : PostDecodeAction::DELIVER;
292
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;
297
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);
303   return action;
304 }
305
306 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnOutputReady(
307     OutputType* buffer) {
308   buffer->metadata().transformation = transform_;
309
310   if (!buffer->metadata().decode_begin_time.has_value())
311     return;
312
313   // Tag buffer with elapsed time since creation.
314   buffer->metadata().processing_time =
315       base::TimeTicks::Now() - *buffer->metadata().decode_begin_time;
316 }
317
318 }  // namespace media