Upload upstream chromium 85.0.4183.84
[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
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"
16
17 namespace media {
18
19 // Audio decoder stream traits implementation.
20
21 // static
22 std::string DecoderStreamTraits<DemuxerStream::AUDIO>::ToString() {
23   return "audio";
24 }
25
26 // static
27 bool DecoderStreamTraits<DemuxerStream::AUDIO>::NeedsBitstreamConversion(
28     DecoderType* decoder) {
29   return decoder->NeedsBitstreamConversion();
30 }
31
32 // static
33 scoped_refptr<DecoderStreamTraits<DemuxerStream::AUDIO>::OutputType>
34 DecoderStreamTraits<DemuxerStream::AUDIO>::CreateEOSOutput() {
35   return OutputType::CreateEOSBuffer();
36 }
37
38 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsPlatformDecoder(
39     bool is_platform_decoder) {
40   stats_.audio_decoder_info.is_platform_decoder = is_platform_decoder;
41 }
42
43 void DecoderStreamTraits<DemuxerStream::AUDIO>::SetIsDecryptingDemuxerStream(
44     bool is_dds) {
45   stats_.audio_decoder_info.has_decrypting_demuxer_stream = is_dds;
46 }
47
48 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderStreamTraits(
49     MediaLog* media_log,
50     ChannelLayout initial_hw_layout)
51     : media_log_(media_log), initial_hw_layout_(initial_hw_layout) {}
52
53 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderConfigType
54 DecoderStreamTraits<DemuxerStream::AUDIO>::GetDecoderConfig(
55     DemuxerStream* stream) {
56   auto config = stream->audio_decoder_config();
57   // Demuxer is not aware of hw layout, so we set it here.
58   config.set_target_output_channel_layout(initial_hw_layout_);
59   return config;
60 }
61
62 void DecoderStreamTraits<DemuxerStream::AUDIO>::ReportStatistics(
63     const StatisticsCB& statistics_cb,
64     int bytes_decoded) {
65   stats_.audio_bytes_decoded = bytes_decoded;
66   statistics_cb.Run(stats_);
67 }
68
69 void DecoderStreamTraits<DemuxerStream::AUDIO>::InitializeDecoder(
70     DecoderType* decoder,
71     const DecoderConfigType& config,
72     bool /* low_delay */,
73     CdmContext* cdm_context,
74     InitCB init_cb,
75     const OutputCB& output_cb,
76     const WaitingCB& waiting_cb) {
77   DCHECK(config.IsValidConfig());
78
79   if (config_.IsValidConfig() && !config_.Matches(config))
80     OnConfigChanged(config);
81   config_ = config;
82
83   stats_.audio_decoder_info.decoder_name = decoder->GetDisplayName();
84   decoder->Initialize(config, cdm_context, std::move(init_cb), output_cb,
85                       waiting_cb);
86 }
87
88 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
89     DemuxerStream* stream) {
90   DCHECK(stream);
91   // Stream is likely being seeked to a new timestamp, so make new validator to
92   // build new timestamp expectations.
93   audio_ts_validator_.reset(
94       new AudioTimestampValidator(stream->audio_decoder_config(), media_log_));
95 }
96
97 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
98     const DecoderBuffer& buffer) {
99   audio_ts_validator_->CheckForTimestampGap(buffer);
100 }
101
102 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
103     OutputType* buffer) {
104   audio_ts_validator_->RecordOutputDuration(*buffer);
105   return PostDecodeAction::DELIVER;
106 }
107
108 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnConfigChanged(
109     const DecoderConfigType& config) {
110   // Reset validator with the latest config. Also ensures that we do not attempt
111   // to match timestamps across config boundaries.
112   audio_ts_validator_.reset(new AudioTimestampValidator(config, media_log_));
113 }
114
115 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnOutputReady(
116     OutputType* buffer) {}
117
118 // Video decoder stream traits implementation.
119
120 // static
121 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
122   return "video";
123 }
124
125 // static
126 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
127     DecoderType* decoder) {
128   return decoder->NeedsBitstreamConversion();
129 }
130
131 // static
132 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
133 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
134   return OutputType::CreateEOSFrame();
135 }
136
137 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsPlatformDecoder(
138     bool is_platform_decoder) {
139   stats_.video_decoder_info.is_platform_decoder = is_platform_decoder;
140 }
141
142 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetIsDecryptingDemuxerStream(
143     bool is_dds) {
144   stats_.video_decoder_info.has_decrypting_demuxer_stream = is_dds;
145 }
146
147 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
148     MediaLog* media_log)
149     // Randomly selected number of samples to keep.
150     : keyframe_distance_average_(16) {}
151
152 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
153 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
154     DemuxerStream* stream) {
155   return stream->video_decoder_config();
156 }
157
158 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
159     const StatisticsCB& statistics_cb,
160     int bytes_decoded) {
161   stats_.video_bytes_decoded = bytes_decoded;
162
163   if (keyframe_distance_average_.count()) {
164     stats_.video_keyframe_distance_average =
165         keyframe_distance_average_.Average();
166   } else {
167     // Before we have enough keyframes to calculate the average distance, we
168     // will assume the average keyframe distance is infinitely large.
169     stats_.video_keyframe_distance_average = base::TimeDelta::Max();
170   }
171
172   statistics_cb.Run(stats_);
173 }
174
175 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
176     DecoderType* decoder,
177     const DecoderConfigType& config,
178     bool low_delay,
179     CdmContext* cdm_context,
180     InitCB init_cb,
181     const OutputCB& output_cb,
182     const WaitingCB& waiting_cb) {
183   DCHECK(config.IsValidConfig());
184   stats_.video_decoder_info.decoder_name = decoder->GetDisplayName();
185   DVLOG(2) << stats_.video_decoder_info.decoder_name;
186   decoder->Initialize(config, low_delay, cdm_context, std::move(init_cb),
187                       output_cb, waiting_cb);
188 }
189
190 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
191     DemuxerStream* stream) {
192   DCHECK(stream);
193   last_keyframe_timestamp_ = base::TimeDelta();
194   frame_metadata_.clear();
195 }
196
197 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
198     const DecoderBuffer& buffer) {
199   if (buffer.end_of_stream()) {
200     last_keyframe_timestamp_ = base::TimeDelta();
201     return;
202   }
203
204   frame_metadata_[buffer.timestamp()] = {
205       buffer.discard_padding().first == kInfiniteDuration,  // should_drop
206       buffer.duration(),                                    // duration
207       base::TimeTicks::Now(),                               // decode_begin_time
208   };
209
210   if (!buffer.is_key_frame())
211     return;
212
213   base::TimeDelta current_frame_timestamp = buffer.timestamp();
214   if (last_keyframe_timestamp_.is_zero()) {
215     last_keyframe_timestamp_ = current_frame_timestamp;
216     return;
217   }
218
219   const base::TimeDelta frame_distance =
220       current_frame_timestamp - last_keyframe_timestamp_;
221   last_keyframe_timestamp_ = current_frame_timestamp;
222   keyframe_distance_average_.AddSample(frame_distance);
223 }
224
225 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
226     OutputType* buffer) {
227   auto it = frame_metadata_.find(buffer->timestamp());
228
229   // If the frame isn't in |frame_metadata_| it probably was erased below on a
230   // previous cycle. We could drop these, but today our video algorithm will put
231   // them back into sorted order or drop the frame if a later frame has already
232   // been rendered.
233   if (it == frame_metadata_.end())
234     return PostDecodeAction::DELIVER;
235
236   // Add a timestamp here to enable buffering delay measurements down the line.
237   buffer->metadata()->decode_begin_time = it->second.decode_begin_time;
238   buffer->metadata()->decode_end_time = base::TimeTicks::Now();
239
240   auto action = it->second.should_drop ? PostDecodeAction::DROP
241                                        : PostDecodeAction::DELIVER;
242
243   // Provide duration information to help the rendering algorithm on the very
244   // first and very last frames.
245   if (it->second.duration != kNoTimestamp)
246     buffer->metadata()->frame_duration = it->second.duration;
247
248   // We erase from the beginning onward to our target frame since frames should
249   // be returned in presentation order. It's possible to accumulate entries in
250   // this queue if playback begins at a non-keyframe; those frames may never be
251   // returned from the decoder.
252   frame_metadata_.erase(frame_metadata_.begin(), it + 1);
253   return action;
254 }
255
256 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnOutputReady(
257     OutputType* buffer) {
258   if (!buffer->metadata()->decode_begin_time.has_value())
259     return;
260
261   // Tag buffer with elapsed time since creation.
262   buffer->metadata()->processing_time =
263       base::TimeTicks::Now() - *buffer->metadata()->decode_begin_time;
264 }
265
266 }  // namespace media