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