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