Revert "[M120 Migration]Fix for crash during chrome exit"
[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 = keyframe_distance_average_.Mean();
200   } else {
201     // Before we have enough keyframes to calculate the average distance, we
202     // will assume the average keyframe distance is infinitely large.
203     stats_.video_keyframe_distance_average = base::TimeDelta::Max();
204   }
205
206   statistics_cb.Run(stats_);
207 }
208
209 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
210     DecoderType* decoder,
211     const DecoderConfigType& config,
212     bool low_delay,
213     CdmContext* cdm_context,
214     InitCB init_cb,
215     const OutputCB& output_cb,
216     const WaitingCB& waiting_cb) {
217   DCHECK(config.IsValidConfig());
218   stats_.video_pipeline_info.decoder_type = VideoDecoderType::kUnknown;
219   transform_ = config.video_transformation();
220   // |decoder| is owned by a DecoderSelector and will stay
221   // alive at least until |init_cb| is finished executing.
222   decoder->Initialize(
223       config, low_delay, cdm_context,
224       base::BindOnce(
225           &DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized,
226           weak_this_, base::Unretained(decoder), std::move(init_cb)),
227       output_cb, waiting_cb);
228 }
229
230 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecoderInitialized(
231     DecoderType* decoder,
232     InitCB cb,
233     DecoderStatus result) {
234   if (result.is_ok()) {
235     stats_.video_pipeline_info.decoder_type = decoder->GetDecoderType();
236     DVLOG(2) << stats_.video_pipeline_info.decoder_type;
237   } else {
238     DVLOG(2) << "Decoder initialization failed.";
239   }
240   std::move(cb).Run(result);
241 }
242
243 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
244     DemuxerStream* stream) {
245   DCHECK(stream);
246   last_keyframe_timestamp_ = base::TimeDelta();
247   frame_metadata_.clear();
248 }
249
250 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
251     const DecoderBuffer& buffer) {
252   if (buffer.end_of_stream()) {
253     last_keyframe_timestamp_ = base::TimeDelta();
254     return;
255   }
256
257   frame_metadata_[buffer.timestamp()] = {
258       buffer.discard_padding().first == kInfiniteDuration,  // should_drop
259       buffer.duration(),                                    // duration
260       base::TimeTicks::Now(),                               // decode_begin_time
261   };
262
263   if (!buffer.is_key_frame())
264     return;
265
266   base::TimeDelta current_frame_timestamp = buffer.timestamp();
267   if (last_keyframe_timestamp_.is_zero()) {
268     last_keyframe_timestamp_ = current_frame_timestamp;
269     return;
270   }
271
272   const base::TimeDelta frame_distance =
273       current_frame_timestamp - last_keyframe_timestamp_;
274   last_keyframe_timestamp_ = current_frame_timestamp;
275   keyframe_distance_average_.AddSample(frame_distance);
276 }
277
278 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
279     OutputType* buffer) {
280   auto it = frame_metadata_.find(buffer->timestamp());
281
282   // If the frame isn't in |frame_metadata_| it probably was erased below on a
283   // previous cycle. We could drop these, but today our video algorithm will put
284   // them back into sorted order or drop the frame if a later frame has already
285   // been rendered.
286   if (it == frame_metadata_.end())
287     return PostDecodeAction::DELIVER;
288
289   // Add a timestamp here to enable buffering delay measurements down the line.
290   buffer->metadata().decode_begin_time = it->second.decode_begin_time;
291   buffer->metadata().decode_end_time = base::TimeTicks::Now();
292
293   auto action = it->second.should_drop ? PostDecodeAction::DROP
294                                        : PostDecodeAction::DELIVER;
295
296   // Provide duration information to help the rendering algorithm on the very
297   // first and very last frames.
298   if (it->second.duration != kNoTimestamp)
299     buffer->metadata().frame_duration = it->second.duration;
300
301   // We erase from the beginning onward to our target frame since frames should
302   // be returned in presentation order. It's possible to accumulate entries in
303   // this queue if playback begins at a non-keyframe; those frames may never be
304   // returned from the decoder.
305   frame_metadata_.erase(frame_metadata_.begin(), it + 1);
306   return action;
307 }
308
309 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnOutputReady(
310     OutputType* buffer) {
311   buffer->metadata().transformation = transform_;
312
313   if (!buffer->metadata().decode_begin_time.has_value())
314     return;
315
316   // Tag buffer with elapsed time since creation.
317   buffer->metadata().processing_time =
318       base::TimeTicks::Now() - *buffer->metadata().decode_begin_time;
319 }
320
321 void DecoderStreamTraits<DemuxerStream::VIDEO>::SetPreferNonPlatformDecoders(
322     bool prefer) {
323   prefer_non_platform_decoders_ = prefer;
324 }
325
326 bool DecoderStreamTraits<DemuxerStream::VIDEO>::GetPreferNonPlatformDecoders()
327     const {
328   return prefer_non_platform_decoders_;
329 }
330
331 }  // namespace media