Upload upstream chromium 73.0.3683.0
[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     const 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, init_cb, output_cb, waiting_cb);
75 }
76
77 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnStreamReset(
78     DemuxerStream* stream) {
79   DCHECK(stream);
80   // Stream is likely being seeked to a new timestamp, so make new validator to
81   // build new timestamp expectations.
82   audio_ts_validator_.reset(
83       new AudioTimestampValidator(stream->audio_decoder_config(), media_log_));
84 }
85
86 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecode(
87     const DecoderBuffer& buffer) {
88   audio_ts_validator_->CheckForTimestampGap(buffer);
89 }
90
91 PostDecodeAction DecoderStreamTraits<DemuxerStream::AUDIO>::OnDecodeDone(
92     const scoped_refptr<OutputType>& buffer) {
93   audio_ts_validator_->RecordOutputDuration(buffer);
94   return PostDecodeAction::DELIVER;
95 }
96
97 void DecoderStreamTraits<DemuxerStream::AUDIO>::OnConfigChanged(
98     const DecoderConfigType& config) {
99   // Reset validator with the latest config. Also ensures that we do not attempt
100   // to match timestamps across config boundaries.
101   audio_ts_validator_.reset(new AudioTimestampValidator(config, media_log_));
102 }
103
104 // Video decoder stream traits implementation.
105
106 // static
107 std::string DecoderStreamTraits<DemuxerStream::VIDEO>::ToString() {
108   return "video";
109 }
110
111 // static
112 bool DecoderStreamTraits<DemuxerStream::VIDEO>::NeedsBitstreamConversion(
113     DecoderType* decoder) {
114   return decoder->NeedsBitstreamConversion();
115 }
116
117 // static
118 scoped_refptr<DecoderStreamTraits<DemuxerStream::VIDEO>::OutputType>
119 DecoderStreamTraits<DemuxerStream::VIDEO>::CreateEOSOutput() {
120   return OutputType::CreateEOSFrame();
121 }
122
123 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderStreamTraits(
124     MediaLog* media_log)
125     // Randomly selected number of samples to keep.
126     : keyframe_distance_average_(16) {}
127
128 DecoderStreamTraits<DemuxerStream::VIDEO>::DecoderConfigType
129 DecoderStreamTraits<DemuxerStream::VIDEO>::GetDecoderConfig(
130     DemuxerStream* stream) {
131   return stream->video_decoder_config();
132 }
133
134 void DecoderStreamTraits<DemuxerStream::VIDEO>::ReportStatistics(
135     const StatisticsCB& statistics_cb,
136     int bytes_decoded) {
137   stats_.video_bytes_decoded = bytes_decoded;
138
139   if (keyframe_distance_average_.count()) {
140     stats_.video_keyframe_distance_average =
141         keyframe_distance_average_.Average();
142   } else {
143     // Before we have enough keyframes to calculate the average distance, we
144     // will assume the average keyframe distance is infinitely large.
145     stats_.video_keyframe_distance_average = base::TimeDelta::Max();
146   }
147
148   statistics_cb.Run(stats_);
149 }
150
151 void DecoderStreamTraits<DemuxerStream::VIDEO>::InitializeDecoder(
152     DecoderType* decoder,
153     const DecoderConfigType& config,
154     bool low_delay,
155     CdmContext* cdm_context,
156     const InitCB& init_cb,
157     const OutputCB& output_cb,
158     const WaitingCB& waiting_cb) {
159   DCHECK(config.IsValidConfig());
160   stats_.video_decoder_name = decoder->GetDisplayName();
161   DVLOG(2) << stats_.video_decoder_name;
162   decoder->Initialize(config, low_delay, cdm_context, init_cb, output_cb,
163                       waiting_cb);
164 }
165
166 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnStreamReset(
167     DemuxerStream* stream) {
168   DCHECK(stream);
169   last_keyframe_timestamp_ = base::TimeDelta();
170   frames_to_drop_.clear();
171 }
172
173 void DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecode(
174     const DecoderBuffer& buffer) {
175   if (buffer.end_of_stream()) {
176     last_keyframe_timestamp_ = base::TimeDelta();
177     return;
178   }
179
180   if (buffer.discard_padding().first == kInfiniteDuration)
181     frames_to_drop_.insert(buffer.timestamp());
182
183   if (!buffer.is_key_frame())
184     return;
185
186   base::TimeDelta current_frame_timestamp = buffer.timestamp();
187   if (last_keyframe_timestamp_.is_zero()) {
188     last_keyframe_timestamp_ = current_frame_timestamp;
189     return;
190   }
191
192   const base::TimeDelta frame_distance =
193       current_frame_timestamp - last_keyframe_timestamp_;
194   last_keyframe_timestamp_ = current_frame_timestamp;
195   keyframe_distance_average_.AddSample(frame_distance);
196 }
197
198 PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone(
199     const scoped_refptr<OutputType>& buffer) {
200   auto it = frames_to_drop_.find(buffer->timestamp());
201   if (it != frames_to_drop_.end()) {
202     // We erase from the beginning onward to our target frame since frames
203     // should be returned in presentation order. It's possible to accumulate
204     // entries in this queue if playback begins at a non-keyframe; those frames
205     // may never be returned from the decoder.
206     frames_to_drop_.erase(frames_to_drop_.begin(), it + 1);
207     return PostDecodeAction::DROP;
208   }
209
210   return PostDecodeAction::DELIVER;
211 }
212
213 }  // namespace media