Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / decoder_stream_traits.cc
1 // Copyright 2014 The Chromium Authors
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     SampleFormat initial_hw_sample_format)
58     : media_log_(media_log),
59       initial_hw_layout_(initial_hw_layout),
60       initial_hw_sample_format_(initial_hw_sample_format) {
61   weak_this_ = weak_factory_.GetWeakPtr();
62 }
63
64 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderConfigType
65 DecoderStreamTraits<DemuxerStream::AUDIO>::GetDecoderConfig(
66     DemuxerStream* stream) {
67   auto config = stream->audio_decoder_config();
68   // Demuxer is not aware of hw layout, so we set it here.
69   config.set_target_output_channel_layout(initial_hw_layout_);
70   config.set_target_output_sample_format(initial_hw_sample_format_);
71   return config;
72 }
73
74 void DecoderStreamTraits<DemuxerStream::AUDIO>::ReportStatistics(
75     const StatisticsCB& statistics_cb,
76     int bytes_decoded) {
77   stats_.audio_bytes_decoded = bytes_decoded;
78   statistics_cb.Run(stats_);
79 }
80
81 void DecoderStreamTraits<DemuxerStream::AUDIO>::InitializeDecoder(
82     DecoderType* decoder,
83     const DecoderConfigType& config,
84     bool /* low_delay */,
85     CdmContext* cdm_context,
86     InitCB init_cb,
87     const OutputCB& output_cb,
88     const WaitingCB& waiting_cb) {
89   DCHECK(config.IsValidConfig());
90
91   if (config_.IsValidConfig() && !config_.Matches(config))
92     OnConfigChanged(config);
93   config_ = config;
94
95   stats_.audio_pipeline_info.decoder_type = AudioDecoderType::kUnknown;
96   // Both |this| and |decoder| are owned by a DecoderSelector and will stay
97   // alive at least until |init_cb| is finished executing.
98   decoder->Initialize(
99       config, cdm_context,
100       base::BindOnce(
101           &DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecoderInitialized,
102           weak_this_, base::Unretained(decoder), std::move(init_cb)),
103       output_cb, waiting_cb);
104 }
105
106 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecoderInitialized(
107     DecoderType* decoder,
108     InitCB cb,
109     DecoderStatus result) {
110   if (result.is_ok())
111     stats_.audio_pipeline_info.decoder_type = decoder->GetDecoderType();
112   std::move(cb).Run(result);
113 }
114
115 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
116     DemuxerStream* stream) {
117   DCHECK(stream);
118   // Stream is likely being seeked to a new timestamp, so make new validator to
119   // build new timestamp expectations.
120   audio_ts_validator_ = std::make_unique<AudioTimestampValidator>(
121       stream->audio_decoder_config(), media_log_);
122 }
123
124 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
125     const DecoderBuffer& buffer) {
126   audio_ts_validator_->CheckForTimestampGap(buffer);
127 }
128
129 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
130     OutputType* buffer) {
131   audio_ts_validator_->RecordOutputDuration(*buffer);
132   return PostDecodeAction::DELIVER;
133 }
134
135 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnConfigChanged(
136     const DecoderConfigType& config) {
137   // Reset validator with the latest config. Also ensures that we do not attempt
138   // to match timestamps across config boundaries.
139   audio_ts_validator_ =
140       std::make_unique<AudioTimestampValidator>(config, media_log_);
141 }
142
143 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnOutputReady(
144     OutputType* buffer) {}
145
146 // Video decoder stream traits implementation.
147
148 // static
149 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
150   return "video";
151 }
152
153 // static
154 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
155     DecoderType* decoder) {
156   return decoder->NeedsBitstreamConversion();
157 }
158
159 // static
160 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
161 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
162   return OutputType::CreateEOSFrame();
163 }
164
165 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsPlatformDecoder(
166     bool is_platform_decoder) {
167   stats_.video_pipeline_info.is_platform_decoder = is_platform_decoder;
168 }
169
170 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsDecryptingDemuxerStream(
171     bool is_dds) {
172   stats_.video_pipeline_info.has_decrypting_demuxer_stream = is_dds;
173 }
174
175 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetEncryptionType(
176     EncryptionType encryption_type) {
177   stats_.video_pipeline_info.encryption_type = encryption_type;
178 }
179
180 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
181     MediaLog* media_log)
182     // Randomly selected number of samples to keep.
183     : keyframe_distance_average_(16) {
184   weak_this_ = weak_factory_.GetWeakPtr();
185 }
186
187 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
188 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
189     DemuxerStream* stream) {
190   return stream->video_decoder_config();
191 }
192
193 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
194     const StatisticsCB& statistics_cb,
195     int bytes_decoded) {
196   stats_.video_bytes_decoded = bytes_decoded;
197
198   if (keyframe_distance_average_.count()) {
199     stats_.video_keyframe_distance_average =
200         keyframe_distance_average_.Average();
201   } else {
202     // Before we have enough keyframes to calculate the average distance, we
203     // will assume the average keyframe distance is infinitely large.
204     stats_.video_keyframe_distance_average = base::TimeDelta::Max();
205   }
206
207   statistics_cb.Run(stats_);
208 }
209
210 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
211     DecoderType* decoder,
212     const DecoderConfigType& config,
213     bool low_delay,
214     CdmContext* cdm_context,
215     InitCB init_cb,
216     const OutputCB& output_cb,
217     const WaitingCB& waiting_cb) {
218   DCHECK(config.IsValidConfig());
219   stats_.video_pipeline_info.decoder_type = VideoDecoderType::kUnknown;
220   transform_ = config.video_transformation();
221   // |decoder| is owned by a DecoderSelector and will stay
222   // alive at least until |init_cb| is finished executing.
223   decoder->Initialize(
224       config, low_delay, cdm_context,
225       base::BindOnce(
226           &DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized,
227           weak_this_, base::Unretained(decoder), std::move(init_cb)),
228       output_cb, waiting_cb);
229 }
230
231 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized(
232     DecoderType* decoder,
233     InitCB cb,
234     DecoderStatus result) {
235   if (result.is_ok()) {
236     stats_.video_pipeline_info.decoder_type = decoder->GetDecoderType();
237     DVLOG(2) << stats_.video_pipeline_info.decoder_type;
238   } else {
239     DVLOG(2) << "Decoder initialization failed.";
240   }
241   std::move(cb).Run(result);
242 }
243
244 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
245     DemuxerStream* stream) {
246   DCHECK(stream);
247   last_keyframe_timestamp_ = base::TimeDelta();
248   frame_metadata_.clear();
249 }
250
251 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
252     const DecoderBuffer& buffer) {
253   if (buffer.end_of_stream()) {
254     last_keyframe_timestamp_ = base::TimeDelta();
255     return;
256   }
257
258   frame_metadata_[buffer.timestamp()] = {
259       buffer.discard_padding().first == kInfiniteDuration,  // should_drop
260       buffer.duration(),                                    // duration
261       base::TimeTicks::Now(),                               // decode_begin_time
262   };
263
264   if (!buffer.is_key_frame())
265     return;
266
267   base::TimeDelta current_frame_timestamp = buffer.timestamp();
268   if (last_keyframe_timestamp_.is_zero()) {
269     last_keyframe_timestamp_ = current_frame_timestamp;
270     return;
271   }
272
273   const base::TimeDelta frame_distance =
274       current_frame_timestamp - last_keyframe_timestamp_;
275   last_keyframe_timestamp_ = current_frame_timestamp;
276   keyframe_distance_average_.AddSample(frame_distance);
277 }
278
279 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
280     OutputType* buffer) {
281   auto it = frame_metadata_.find(buffer->timestamp());
282
283   // If the frame isn't in |frame_metadata_| it probably was erased below on a
284   // previous cycle. We could drop these, but today our video algorithm will put
285   // them back into sorted order or drop the frame if a later frame has already
286   // been rendered.
287   if (it == frame_metadata_.end())
288     return PostDecodeAction::DELIVER;
289
290   // Add a timestamp here to enable buffering delay measurements down the line.
291   buffer->metadata().decode_begin_time = it->second.decode_begin_time;
292   buffer->metadata().decode_end_time = base::TimeTicks::Now();
293
294   auto action = it->second.should_drop ? PostDecodeAction::DROP
295                                        : PostDecodeAction::DELIVER;
296
297   // Provide duration information to help the rendering algorithm on the very
298   // first and very last frames.
299   if (it->second.duration != kNoTimestamp)
300     buffer->metadata().frame_duration = it->second.duration;
301
302   // We erase from the beginning onward to our target frame since frames should
303   // be returned in presentation order. It's possible to accumulate entries in
304   // this queue if playback begins at a non-keyframe; those frames may never be
305   // returned from the decoder.
306   frame_metadata_.erase(frame_metadata_.begin(), it + 1);
307   return action;
308 }
309
310 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnOutputReady(
311     OutputType* buffer) {
312   buffer->metadata().transformation = transform_;
313
314   if (!buffer->metadata().decode_begin_time.has_value())
315     return;
316
317   // Tag buffer with elapsed time since creation.
318   buffer->metadata().processing_time =
319       base::TimeTicks::Now() - *buffer->metadata().decode_begin_time;
320 }
321
322 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetPreferNonPlatformDecoders(
323     bool prefer) {
324   prefer_non_platform_decoders_ = prefer;
325 }
326
327 bool DecoderStreamTraits<DemuxerStream::VIDEO>::GetPreferNonPlatformDecoders()
328     const {
329   return prefer_non_platform_decoders_;
330 }
331
332 }  // namespace media