Upload upstream chromium 76.0.3809.146
[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 DecoderStreamTraits<DemuxerStream::AUDIO>::DecoderStreamTraits(
39     MediaLog* media_log,
40     ChannelLayout initial_hw_layout)
41     : media_log_(media_log), initial_hw_layout_(initial_hw_layout) {}
42
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_);
49   return config;
50 }
51
52 void DecoderStreamTraits<DemuxerStream::AUDIO>::ReportStatistics(
53     const StatisticsCB& statistics_cb,
54     int bytes_decoded) {
55   stats_.audio_bytes_decoded = bytes_decoded;
56   statistics_cb.Run(stats_);
57 }
58
59 void DecoderStreamTraits<DemuxerStream::AUDIO>::InitializeDecoder(
60     DecoderType* decoder,
61     const DecoderConfigType& config,
62     bool /* low_delay */,
63     CdmContext* cdm_context,
64     InitCB init_cb,
65     const OutputCB& output_cb,
66     const WaitingCB& waiting_cb) {
67   DCHECK(config.IsValidConfig());
68
69   if (config_.IsValidConfig() && !config_.Matches(config))
70     OnConfigChanged(config);
71   config_ = config;
72
73   stats_.audio_decoder_name = decoder->GetDisplayName();
74   decoder->Initialize(config, cdm_context, std::move(init_cb), output_cb,
75                       waiting_cb);
76 }
77
78 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
79     DemuxerStream* stream) {
80   DCHECK(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_));
85 }
86
87 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
88     const DecoderBuffer& buffer) {
89   audio_ts_validator_->CheckForTimestampGap(buffer);
90 }
91
92 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
93     OutputType* buffer) {
94   audio_ts_validator_->RecordOutputDuration(*buffer);
95   return PostDecodeAction::DELIVER;
96 }
97
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_));
103 }
104
105 // Video decoder stream traits implementation.
106
107 // static
108 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
109   return "video";
110 }
111
112 // static
113 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
114     DecoderType* decoder) {
115   return decoder->NeedsBitstreamConversion();
116 }
117
118 // static
119 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
120 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
121   return OutputType::CreateEOSFrame();
122 }
123
124 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
125     MediaLog* media_log)
126     // Randomly selected number of samples to keep.
127     : keyframe_distance_average_(16) {}
128
129 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
130 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
131     DemuxerStream* stream) {
132   return stream->video_decoder_config();
133 }
134
135 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
136     const StatisticsCB& statistics_cb,
137     int bytes_decoded) {
138   stats_.video_bytes_decoded = bytes_decoded;
139
140   if (keyframe_distance_average_.count()) {
141     stats_.video_keyframe_distance_average =
142         keyframe_distance_average_.Average();
143   } else {
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();
147   }
148
149   statistics_cb.Run(stats_);
150 }
151
152 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
153     DecoderType* decoder,
154     const DecoderConfigType& config,
155     bool low_delay,
156     CdmContext* cdm_context,
157     InitCB init_cb,
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);
165 }
166
167 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
168     DemuxerStream* stream) {
169   DCHECK(stream);
170   last_keyframe_timestamp_ = base::TimeDelta();
171   frame_metadata_.clear();
172 }
173
174 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
175     const DecoderBuffer& buffer) {
176   if (buffer.end_of_stream()) {
177     last_keyframe_timestamp_ = base::TimeDelta();
178     return;
179   }
180
181   frame_metadata_[buffer.timestamp()] = {
182       buffer.discard_padding().first == kInfiniteDuration,  // should_drop
183       buffer.duration(),                                    // duration
184   };
185
186   if (!buffer.is_key_frame())
187     return;
188
189   base::TimeDelta current_frame_timestamp = buffer.timestamp();
190   if (last_keyframe_timestamp_.is_zero()) {
191     last_keyframe_timestamp_ = current_frame_timestamp;
192     return;
193   }
194
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);
199 }
200
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());
207
208   auto it = frame_metadata_.find(buffer->timestamp());
209
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
213   // been rendered.
214   if (it == frame_metadata_.end())
215     return PostDecodeAction::DELIVER;
216
217   auto action = it->second.should_drop ? PostDecodeAction::DROP
218                                        : PostDecodeAction::DELIVER;
219
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);
225   }
226
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);
232   return action;
233 }
234
235 }  // namespace media