OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/base/android/media_codec_video_decoder.h" | 5 #include "media/base/android/media_codec_video_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "media/base/android/media_codec_bridge.h" | 9 #include "media/base/android/media_codec_bridge.h" |
10 #include "media/base/buffers.h" | 10 #include "media/base/buffers.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 void MediaCodecVideoDecoder::ReleaseDecoderResources() { | 68 void MediaCodecVideoDecoder::ReleaseDecoderResources() { |
69 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 69 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
70 | 70 |
71 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 71 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
72 | 72 |
73 MediaCodecDecoder::ReleaseDecoderResources(); | 73 MediaCodecDecoder::ReleaseDecoderResources(); |
74 surface_ = gfx::ScopedJavaSurface(); | 74 surface_ = gfx::ScopedJavaSurface(); |
75 delayed_buffers_.clear(); | 75 delayed_buffers_.clear(); |
76 } | 76 } |
77 | 77 |
78 void MediaCodecVideoDecoder::SetPendingSurface(gfx::ScopedJavaSurface surface) { | 78 void MediaCodecVideoDecoder::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
79 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 79 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
80 | 80 |
| 81 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
| 82 << (surface.IsEmpty() ? " empty" : " non-empty"); |
| 83 |
81 surface_ = surface.Pass(); | 84 surface_ = surface.Pass(); |
82 | 85 |
83 if (surface_.IsEmpty()) { | 86 needs_reconfigure_ = true; |
84 // Synchronously stop decoder thread and release MediaCodec | |
85 ReleaseDecoderResources(); | |
86 } | |
87 } | 87 } |
88 | 88 |
89 bool MediaCodecVideoDecoder::HasPendingSurface() const { | 89 bool MediaCodecVideoDecoder::HasVideoSurface() const { |
90 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 90 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
91 | 91 |
92 return !surface_.IsEmpty(); | 92 return !surface_.IsEmpty(); |
93 } | 93 } |
94 | 94 |
95 bool MediaCodecVideoDecoder::IsCodecReconfigureNeeded( | 95 bool MediaCodecVideoDecoder::IsCodecReconfigureNeeded( |
96 const DemuxerConfigs& curr, | 96 const DemuxerConfigs& curr, |
97 const DemuxerConfigs& next) const { | 97 const DemuxerConfigs& next) const { |
98 if (curr.video_codec != next.video_codec || | 98 if (curr.video_codec != next.video_codec || |
99 curr.is_video_encrypted != next.is_video_encrypted) { | 99 curr.is_video_encrypted != next.is_video_encrypted) { |
(...skipping 13 matching lines...) Expand all Loading... |
113 } | 113 } |
114 | 114 |
115 MediaCodecDecoder::ConfigStatus MediaCodecVideoDecoder::ConfigureInternal() { | 115 MediaCodecDecoder::ConfigStatus MediaCodecVideoDecoder::ConfigureInternal() { |
116 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 116 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
117 | 117 |
118 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 118 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
119 | 119 |
120 // If we cannot find a key frame in cache, the browser seek is needed. | 120 // If we cannot find a key frame in cache, the browser seek is needed. |
121 if (!au_queue_.RewindToLastKeyFrame()) { | 121 if (!au_queue_.RewindToLastKeyFrame()) { |
122 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " key frame required"; | 122 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " key frame required"; |
| 123 return kConfigKeyFrameRequired; |
| 124 } |
123 | 125 |
124 // The processing of CONFIG_KEY_FRAME_REQUIRED is not implemented yet, | 126 if (configs_.video_codec == kUnknownVideoCodec) { |
125 // return error for now. | 127 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
126 // TODO(timav): Replace this with the following line together with | 128 << " configuration parameters are required"; |
127 // implementing the browser seek: | 129 return kConfigFailure; |
128 // return CONFIG_KEY_FRAME_REQUIRED; | |
129 return CONFIG_FAILURE; | |
130 } | 130 } |
131 | 131 |
132 // TODO(timav): implement DRM. | 132 // TODO(timav): implement DRM. |
133 // bool is_secure = is_content_encrypted() && drm_bridge() && | 133 // bool is_secure = is_content_encrypted() && drm_bridge() && |
134 // drm_bridge()->IsProtectedSurfaceRequired(); | 134 // drm_bridge()->IsProtectedSurfaceRequired(); |
135 | 135 |
136 bool is_secure = false; // DRM is not implemented | 136 bool is_secure = false; // DRM is not implemented |
137 | 137 |
138 if (surface_.IsEmpty()) { | 138 if (surface_.IsEmpty()) { |
139 DVLOG(0) << class_name() << "::" << __FUNCTION__ << " surface required"; | 139 DVLOG(0) << class_name() << "::" << __FUNCTION__ << " surface required"; |
140 return CONFIG_FAILURE; | 140 return kConfigFailure; |
141 } | 141 } |
142 | 142 |
143 media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder( | 143 media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder( |
144 configs_.video_codec, | 144 configs_.video_codec, |
145 is_secure, | 145 is_secure, |
146 configs_.video_size, | 146 configs_.video_size, |
147 surface_.j_surface().obj(), | 147 surface_.j_surface().obj(), |
148 GetMediaCrypto().obj())); | 148 GetMediaCrypto().obj())); |
149 | 149 |
150 if (!media_codec_bridge_) { | 150 if (!media_codec_bridge_) { |
151 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " failed"; | 151 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " failed"; |
152 return CONFIG_FAILURE; | 152 return kConfigFailure; |
153 } | 153 } |
154 | 154 |
155 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " succeeded"; | 155 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " succeeded"; |
156 | 156 |
157 media_task_runner_->PostTask(FROM_HERE, codec_created_cb_); | 157 media_task_runner_->PostTask(FROM_HERE, codec_created_cb_); |
158 | 158 |
159 return CONFIG_OK; | 159 return kConfigOk; |
160 } | 160 } |
161 | 161 |
162 void MediaCodecVideoDecoder::SynchronizePTSWithTime( | 162 void MediaCodecVideoDecoder::SynchronizePTSWithTime( |
163 base::TimeDelta current_time) { | 163 base::TimeDelta current_time) { |
164 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 164 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
165 | 165 |
166 start_time_ticks_ = base::TimeTicks::Now(); | 166 start_time_ticks_ = base::TimeTicks::Now(); |
167 start_pts_ = current_time; | 167 start_pts_ = current_time; |
168 last_seen_pts_ = current_time; | 168 last_seen_pts_ = current_time; |
169 } | 169 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 size, do_render, eos_encountered), | 229 size, do_render, eos_encountered), |
230 time_to_render); | 230 time_to_render); |
231 } | 231 } |
232 | 232 |
233 int MediaCodecVideoDecoder::NumDelayedRenderTasks() const { | 233 int MediaCodecVideoDecoder::NumDelayedRenderTasks() const { |
234 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 234 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
235 | 235 |
236 return delayed_buffers_.size(); | 236 return delayed_buffers_.size(); |
237 } | 237 } |
238 | 238 |
239 void MediaCodecVideoDecoder::ReleaseDelayedBuffers() { | 239 void MediaCodecVideoDecoder::ClearDelayedBuffers(bool release) { |
240 // Media thread | 240 // Media thread |
241 // Called when there is no decoder thread | 241 // Called when there is no decoder thread |
242 for (int index : delayed_buffers_) | 242 if (release) { |
243 media_codec_bridge_->ReleaseOutputBuffer(index, false); | 243 for (int index : delayed_buffers_) |
| 244 media_codec_bridge_->ReleaseOutputBuffer(index, false); |
| 245 } |
| 246 |
244 delayed_buffers_.clear(); | 247 delayed_buffers_.clear(); |
245 } | 248 } |
246 | 249 |
247 #ifndef NDEBUG | 250 #ifndef NDEBUG |
248 void MediaCodecVideoDecoder::VerifyUnitIsKeyFrame( | 251 void MediaCodecVideoDecoder::VerifyUnitIsKeyFrame( |
249 const AccessUnit* unit) const { | 252 const AccessUnit* unit) const { |
250 // The first video frame in a sequence must be a key frame or stand-alone EOS. | 253 // The first video frame in a sequence must be a key frame or stand-alone EOS. |
251 DCHECK(unit); | 254 DCHECK(unit); |
252 bool stand_alone_eos = unit->is_end_of_stream && unit->data.empty(); | 255 bool stand_alone_eos = unit->is_end_of_stream && unit->data.empty(); |
253 DCHECK(stand_alone_eos || unit->is_key_frame); | 256 DCHECK(stand_alone_eos || unit->is_key_frame); |
(...skipping 17 matching lines...) Expand all Loading... |
271 | 274 |
272 // |update_current_time_cb_| might be null if there is audio stream. | 275 // |update_current_time_cb_| might be null if there is audio stream. |
273 // Do not update current time for stand-alone EOS frames. | 276 // Do not update current time for stand-alone EOS frames. |
274 if (!update_current_time_cb_.is_null() && !(eos_encountered && !size)) { | 277 if (!update_current_time_cb_.is_null() && !(eos_encountered && !size)) { |
275 media_task_runner_->PostTask(FROM_HERE, | 278 media_task_runner_->PostTask(FROM_HERE, |
276 base::Bind(update_current_time_cb_, pts, pts)); | 279 base::Bind(update_current_time_cb_, pts, pts)); |
277 } | 280 } |
278 } | 281 } |
279 | 282 |
280 } // namespace media | 283 } // namespace media |
OLD | NEW |