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_decoder.h" | 5 #include "media/base/android/media_codec_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 const base::Closure& error_cb, | 39 const base::Closure& error_cb, |
40 const char* decoder_thread_name) | 40 const char* decoder_thread_name) |
41 : media_task_runner_(media_task_runner), | 41 : media_task_runner_(media_task_runner), |
42 decoder_thread_(decoder_thread_name), | 42 decoder_thread_(decoder_thread_name), |
43 needs_reconfigure_(false), | 43 needs_reconfigure_(false), |
44 external_request_data_cb_(external_request_data_cb), | 44 external_request_data_cb_(external_request_data_cb), |
45 starvation_cb_(starvation_cb), | 45 starvation_cb_(starvation_cb), |
46 stop_done_cb_(stop_done_cb), | 46 stop_done_cb_(stop_done_cb), |
47 error_cb_(error_cb), | 47 error_cb_(error_cb), |
48 state_(kStopped), | 48 state_(kStopped), |
| 49 needs_preroll_(true), |
49 eos_enqueued_(false), | 50 eos_enqueued_(false), |
50 completed_(false), | 51 completed_(false), |
51 last_frame_posted_(false), | 52 last_frame_posted_(false), |
52 is_data_request_in_progress_(false), | 53 is_data_request_in_progress_(false), |
53 is_incoming_data_invalid_(false), | 54 is_incoming_data_invalid_(false), |
54 #ifndef NDEBUG | 55 #ifndef NDEBUG |
55 verify_next_frame_is_key_(false), | 56 verify_next_frame_is_key_(false), |
56 #endif | 57 #endif |
57 weak_factory_(this) { | 58 weak_factory_(this) { |
58 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 59 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
59 | 60 |
60 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; | 61 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; |
61 | 62 |
62 internal_error_cb_ = | 63 internal_error_cb_ = |
63 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); | 64 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); |
| 65 internal_preroll_done_cb_ = |
| 66 base::Bind(&MediaCodecDecoder::OnPrerollDone, weak_factory_.GetWeakPtr()); |
64 request_data_cb_ = | 67 request_data_cb_ = |
65 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); | 68 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); |
66 } | 69 } |
67 | 70 |
68 MediaCodecDecoder::~MediaCodecDecoder() { | 71 MediaCodecDecoder::~MediaCodecDecoder() { |
69 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 72 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
70 | 73 |
71 DVLOG(1) << "Decoder::~Decoder()"; | 74 DVLOG(1) << "Decoder::~Decoder()"; |
72 | 75 |
73 // NB: ReleaseDecoderResources() is virtual | 76 // NB: ReleaseDecoderResources() is virtual |
74 ReleaseDecoderResources(); | 77 ReleaseDecoderResources(); |
75 } | 78 } |
76 | 79 |
77 const char* MediaCodecDecoder::class_name() const { | 80 const char* MediaCodecDecoder::class_name() const { |
78 return "Decoder"; | 81 return "Decoder"; |
79 } | 82 } |
80 | 83 |
81 void MediaCodecDecoder::ReleaseDecoderResources() { | 84 void MediaCodecDecoder::ReleaseDecoderResources() { |
82 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 85 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
83 | 86 |
84 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 87 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
85 | 88 |
86 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). | 89 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). |
87 SetState(kInEmergencyStop); | 90 SetState(kInEmergencyStop); |
88 | 91 |
89 decoder_thread_.Stop(); // synchronous | 92 decoder_thread_.Stop(); // synchronous |
90 | 93 |
91 SetState(kStopped); | 94 SetState(kStopped); |
92 media_codec_bridge_.reset(); | 95 ReleaseMediaCodec(); |
| 96 |
| 97 needs_preroll_ = true; |
93 } | 98 } |
94 | 99 |
95 void MediaCodecDecoder::Flush() { | 100 void MediaCodecDecoder::Flush() { |
96 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 101 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
97 | 102 |
98 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 103 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
99 | 104 |
100 DCHECK_EQ(GetState(), kStopped); | 105 DCHECK_EQ(GetState(), kStopped); |
101 | 106 |
102 // Flush() is a part of the Seek request. Whenever we request a seek we need | 107 // Flush() is a part of the Seek request. Whenever we request a seek we need |
103 // to invalidate the current data request. | 108 // to invalidate the current data request. |
104 if (is_data_request_in_progress_) | 109 if (is_data_request_in_progress_) |
105 is_incoming_data_invalid_ = true; | 110 is_incoming_data_invalid_ = true; |
106 | 111 |
107 eos_enqueued_ = false; | 112 eos_enqueued_ = false; |
108 completed_ = false; | 113 completed_ = false; |
109 au_queue_.Flush(); | 114 au_queue_.Flush(); |
110 | 115 |
111 #ifndef NDEBUG | 116 #ifndef NDEBUG |
112 // We check and reset |verify_next_frame_is_key_| on Decoder thread. | 117 // We check and reset |verify_next_frame_is_key_| on Decoder thread. |
113 // This DCHECK ensures we won't need to lock this variable. | 118 // This DCHECK ensures we won't need to lock this variable. |
114 DCHECK(!decoder_thread_.IsRunning()); | 119 DCHECK(!decoder_thread_.IsRunning()); |
115 | 120 |
116 // For video the first frame after flush must be key frame. | 121 // For video the first frame after flush must be key frame. |
117 verify_next_frame_is_key_ = true; | 122 verify_next_frame_is_key_ = true; |
118 #endif | 123 #endif |
119 | 124 |
| 125 needs_preroll_ = true; |
| 126 |
120 if (media_codec_bridge_) { | 127 if (media_codec_bridge_) { |
121 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush() | 128 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush() |
122 MediaCodecStatus flush_status = media_codec_bridge_->Reset(); | 129 MediaCodecStatus flush_status = media_codec_bridge_->Reset(); |
123 if (flush_status != MEDIA_CODEC_OK) { | 130 if (flush_status != MEDIA_CODEC_OK) { |
124 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 131 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
125 << "MediaCodecBridge::Reset() failed"; | 132 << "MediaCodecBridge::Reset() failed"; |
126 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); | 133 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); |
127 } | 134 } |
128 } | 135 } |
129 } | 136 } |
130 | 137 |
131 void MediaCodecDecoder::ReleaseMediaCodec() { | 138 void MediaCodecDecoder::ReleaseMediaCodec() { |
132 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 139 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
133 | 140 |
134 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 141 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
135 | 142 |
136 media_codec_bridge_.reset(); | 143 media_codec_bridge_.reset(); |
137 } | 144 } |
138 | 145 |
139 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { | 146 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { |
140 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 147 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
141 | 148 |
| 149 // Whether decoder needs to be stopped. |
142 base::AutoLock lock(state_lock_); | 150 base::AutoLock lock(state_lock_); |
143 return state_ == kPrefetching || state_ == kRunning; | 151 switch (state_) { |
| 152 case kPrefetching: |
| 153 case kPrefetched: |
| 154 case kPrerolling: |
| 155 case kPrerolled: |
| 156 case kRunning: |
| 157 return true; |
| 158 case kStopped: |
| 159 case kStopping: |
| 160 case kInEmergencyStop: |
| 161 case kError: |
| 162 return false; |
| 163 } |
| 164 NOTREACHED(); |
| 165 return false; |
144 } | 166 } |
145 | 167 |
146 bool MediaCodecDecoder::IsStopped() const { | 168 bool MediaCodecDecoder::IsStopped() const { |
147 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 169 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
148 | 170 |
149 return GetState() == kStopped; | 171 return GetState() == kStopped; |
150 } | 172 } |
151 | 173 |
152 bool MediaCodecDecoder::IsCompleted() const { | 174 bool MediaCodecDecoder::IsCompleted() const { |
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 175 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
154 | 176 |
155 return completed_; | 177 return completed_; |
156 } | 178 } |
157 | 179 |
| 180 bool MediaCodecDecoder::NeedsPreroll() const { |
| 181 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 182 |
| 183 return HasStream() && needs_preroll_ && !completed_; |
| 184 } |
| 185 |
158 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { | 186 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { |
159 base::android::ScopedJavaLocalRef<jobject> media_crypto; | 187 base::android::ScopedJavaLocalRef<jobject> media_crypto; |
160 | 188 |
161 // TODO(timav): implement DRM. | 189 // TODO(timav): implement DRM. |
162 // drm_bridge_ is not implemented | 190 // drm_bridge_ is not implemented |
163 // if (drm_bridge_) | 191 // if (drm_bridge_) |
164 // media_crypto = drm_bridge_->GetMediaCrypto(); | 192 // media_crypto = drm_bridge_->GetMediaCrypto(); |
165 return media_crypto; | 193 return media_crypto; |
166 } | 194 } |
167 | 195 |
(...skipping 17 matching lines...) Expand all Loading... |
185 | 213 |
186 if (GetState() == kError) { | 214 if (GetState() == kError) { |
187 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; | 215 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; |
188 return kConfigFailure; | 216 return kConfigFailure; |
189 } | 217 } |
190 | 218 |
191 if (needs_reconfigure_) { | 219 if (needs_reconfigure_) { |
192 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 220 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
193 << ": needs reconfigure, deleting MediaCodec"; | 221 << ": needs reconfigure, deleting MediaCodec"; |
194 needs_reconfigure_ = false; | 222 needs_reconfigure_ = false; |
195 media_codec_bridge_.reset(); | 223 ReleaseMediaCodec(); |
196 | |
197 // No need to release these buffers since the MediaCodec is deleted, just | |
198 // remove their indexes from |delayed_buffers_|. | |
199 | |
200 ClearDelayedBuffers(false); | |
201 } | 224 } |
202 | 225 |
203 MediaCodecDecoder::ConfigStatus result; | 226 MediaCodecDecoder::ConfigStatus result; |
204 if (media_codec_bridge_) { | 227 if (media_codec_bridge_) { |
205 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 228 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
206 << ": reconfiguration is not required, ignoring"; | 229 << ": reconfiguration is not required, ignoring"; |
207 result = kConfigOk; | 230 result = kConfigOk; |
208 } else { | 231 } else { |
209 result = ConfigureInternal(); | 232 result = ConfigureInternal(); |
210 | 233 |
211 #ifndef NDEBUG | 234 #ifndef NDEBUG |
212 // We check and reset |verify_next_frame_is_key_| on Decoder thread. | 235 // We check and reset |verify_next_frame_is_key_| on Decoder thread. |
213 // This DCHECK ensures we won't need to lock this variable. | 236 // This DCHECK ensures we won't need to lock this variable. |
214 DCHECK(!decoder_thread_.IsRunning()); | 237 DCHECK(!decoder_thread_.IsRunning()); |
215 | 238 |
216 // For video the first frame after reconfiguration must be key frame. | 239 // For video the first frame after reconfiguration must be key frame. |
217 if (result == kConfigOk) | 240 if (result == kConfigOk) |
218 verify_next_frame_is_key_ = true; | 241 verify_next_frame_is_key_ = true; |
219 #endif | 242 #endif |
220 } | 243 } |
221 | 244 |
222 return result; | 245 return result; |
223 } | 246 } |
224 | 247 |
225 bool MediaCodecDecoder::Start(base::TimeDelta current_time) { | 248 bool MediaCodecDecoder::Preroll(base::TimeDelta preroll_timestamp, |
| 249 const base::Closure& preroll_done_cb) { |
226 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 250 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
227 | 251 |
228 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 252 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
229 << " current_time:" << current_time; | 253 << " preroll_timestamp:" << preroll_timestamp; |
230 | 254 |
231 DecoderState state = GetState(); | 255 DecoderState state = GetState(); |
232 if (state == kRunning) { | |
233 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started"; | |
234 return true; // already started | |
235 } | |
236 | |
237 if (state != kPrefetched) { | 256 if (state != kPrefetched) { |
238 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " | 257 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " |
239 << AsString(state) << ", ignoring"; | 258 << AsString(state) << ", ignoring"; |
240 return false; | 259 return false; |
241 } | 260 } |
242 | 261 |
243 if (!media_codec_bridge_) { | 262 if (!media_codec_bridge_) { |
244 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 263 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
245 << ": not configured, ignoring"; | 264 << ": not configured, ignoring"; |
246 return false; | 265 return false; |
247 } | 266 } |
248 | 267 |
249 DCHECK(!decoder_thread_.IsRunning()); | 268 DCHECK(!decoder_thread_.IsRunning()); |
| 269 DCHECK(needs_preroll_); |
| 270 |
| 271 preroll_done_cb_ = preroll_done_cb; |
250 | 272 |
251 // We only synchronize video stream. | 273 // We only synchronize video stream. |
252 // When audio is present, the |current_time| is audio time. | 274 DissociatePTSFromTime(); // associaton will happen after preroll is done. |
253 SynchronizePTSWithTime(current_time); | 275 preroll_timestamp_ = preroll_timestamp; |
254 | 276 |
255 last_frame_posted_ = false; | 277 last_frame_posted_ = false; |
256 | 278 |
257 // Start the decoder thread | 279 // Start the decoder thread |
258 if (!decoder_thread_.Start()) { | 280 if (!decoder_thread_.Start()) { |
259 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 281 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
260 << ": cannot start decoder thread"; | 282 << ": cannot start decoder thread"; |
261 return false; | 283 return false; |
262 } | 284 } |
263 | 285 |
264 DVLOG(0) << class_name() << "::" << __FUNCTION__ << " decoder thread started"; | 286 SetState(kPrerolling); |
| 287 |
| 288 decoder_thread_.task_runner()->PostTask( |
| 289 FROM_HERE, |
| 290 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); |
| 291 |
| 292 return true; |
| 293 } |
| 294 |
| 295 bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) { |
| 296 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 297 |
| 298 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
| 299 << " start_timestamp:" << start_timestamp; |
| 300 |
| 301 DecoderState state = GetState(); |
| 302 |
| 303 if (state != kPrefetched && state != kPrerolled) { |
| 304 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " |
| 305 << AsString(state) << ", ignoring"; |
| 306 return false; |
| 307 } |
| 308 |
| 309 if (!media_codec_bridge_) { |
| 310 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
| 311 << ": not configured, ignoring"; |
| 312 return false; |
| 313 } |
| 314 |
| 315 // We only synchronize video stream. |
| 316 AssociateCurrentTimeWithPTS(start_timestamp); |
| 317 preroll_timestamp_ = base::TimeDelta(); |
| 318 |
| 319 // Start the decoder thread |
| 320 if (!decoder_thread_.IsRunning()) { |
| 321 last_frame_posted_ = false; |
| 322 if (!decoder_thread_.Start()) { |
| 323 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
| 324 << ": cannot start decoder thread"; |
| 325 return false; |
| 326 } |
| 327 } |
265 | 328 |
266 SetState(kRunning); | 329 SetState(kRunning); |
267 | 330 |
268 decoder_thread_.task_runner()->PostTask( | 331 decoder_thread_.task_runner()->PostTask( |
269 FROM_HERE, | 332 FROM_HERE, |
270 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); | 333 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); |
271 | 334 |
272 return true; | 335 return true; |
273 } | 336 } |
274 | 337 |
(...skipping 10 matching lines...) Expand all Loading... |
285 | 348 |
286 // After this method returns, decoder thread will not be running. | 349 // After this method returns, decoder thread will not be running. |
287 | 350 |
288 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). | 351 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). |
289 SetState(kInEmergencyStop); | 352 SetState(kInEmergencyStop); |
290 | 353 |
291 decoder_thread_.Stop(); // synchronous | 354 decoder_thread_.Stop(); // synchronous |
292 | 355 |
293 SetState(kStopped); | 356 SetState(kStopped); |
294 | 357 |
295 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|. | 358 ReleaseDelayedBuffers(); |
296 } | 359 } |
297 | 360 |
298 void MediaCodecDecoder::RequestToStop() { | 361 void MediaCodecDecoder::RequestToStop() { |
299 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 362 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
300 | 363 |
301 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 364 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
302 | 365 |
303 DecoderState state = GetState(); | 366 DecoderState state = GetState(); |
304 switch (state) { | 367 switch (state) { |
305 case kError: | 368 case kError: |
306 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 369 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
307 << ": wrong state kError, ignoring"; | 370 << ": wrong state kError, ignoring"; |
308 break; | 371 break; |
309 case kRunning: | 372 case kRunning: |
310 SetState(kStopping); | 373 SetState(kStopping); |
311 break; | 374 break; |
| 375 case kPrerolling: |
| 376 case kPrerolled: |
| 377 DCHECK(decoder_thread_.IsRunning()); |
| 378 // Synchronous stop. |
| 379 decoder_thread_.Stop(); |
| 380 SetState(kStopped); |
| 381 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
| 382 break; |
312 case kStopping: | 383 case kStopping: |
313 break; // ignore | 384 break; // ignore |
314 case kStopped: | 385 case kStopped: |
315 case kPrefetching: | 386 case kPrefetching: |
316 case kPrefetched: | 387 case kPrefetched: |
317 // There is nothing to wait for, we can sent nofigication right away. | 388 // There is nothing to wait for, we can sent nofigication right away. |
318 DCHECK(!decoder_thread_.IsRunning()); | 389 DCHECK(!decoder_thread_.IsRunning()); |
319 SetState(kStopped); | 390 SetState(kStopped); |
320 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 391 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
321 break; | 392 break; |
322 default: | 393 default: |
323 NOTREACHED(); | 394 NOTREACHED(); |
324 break; | 395 break; |
325 } | 396 } |
326 } | 397 } |
327 | 398 |
328 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { | 399 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { |
329 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 400 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
330 | 401 |
331 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 402 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
332 << " completed:" << completed; | 403 << " completed:" << completed; |
333 | 404 |
334 decoder_thread_.Stop(); // synchronous | 405 decoder_thread_.Stop(); // synchronous |
335 | 406 |
336 SetState(kStopped); | 407 SetState(kStopped); |
337 completed_ = completed; | 408 completed_ = completed; |
338 | 409 |
| 410 if (completed_ && !preroll_done_cb_.is_null()) |
| 411 media_task_runner_->PostTask(FROM_HERE, |
| 412 base::ResetAndReturn(&preroll_done_cb_)); |
| 413 |
339 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 414 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
340 } | 415 } |
341 | 416 |
| 417 void MediaCodecDecoder::OnPrerollDone() { |
| 418 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 419 |
| 420 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
| 421 |
| 422 if (GetState() == kPrerolling) { |
| 423 SetState(kPrerolled); |
| 424 needs_preroll_ = false; |
| 425 media_task_runner_->PostTask(FROM_HERE, |
| 426 base::ResetAndReturn(&preroll_done_cb_)); |
| 427 } |
| 428 } |
| 429 |
342 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { | 430 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { |
343 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 431 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
344 | 432 |
345 // If |data| contains an aborted data, the last AU will have kAborted status. | 433 // If |data| contains an aborted data, the last AU will have kAborted status. |
346 bool aborted_data = | 434 bool aborted_data = |
347 !data.access_units.empty() && | 435 !data.access_units.empty() && |
348 data.access_units.back().status == DemuxerStream::kAborted; | 436 data.access_units.back().status == DemuxerStream::kAborted; |
349 | 437 |
350 #ifndef NDEBUG | 438 #ifndef NDEBUG |
351 const char* explain_if_skipped = | 439 const char* explain_if_skipped = |
(...skipping 12 matching lines...) Expand all Loading... |
364 | 452 |
365 is_incoming_data_invalid_ = false; | 453 is_incoming_data_invalid_ = false; |
366 is_data_request_in_progress_ = false; | 454 is_data_request_in_progress_ = false; |
367 | 455 |
368 // Do not request data if we got kAborted. There is no point to request the | 456 // Do not request data if we got kAborted. There is no point to request the |
369 // data after kAborted and before the OnDemuxerSeekDone. | 457 // data after kAborted and before the OnDemuxerSeekDone. |
370 if (GetState() == kPrefetching && !aborted_data) | 458 if (GetState() == kPrefetching && !aborted_data) |
371 PrefetchNextChunk(); | 459 PrefetchNextChunk(); |
372 } | 460 } |
373 | 461 |
| 462 bool MediaCodecDecoder::IsPrerollingForTests() const { |
| 463 // UI task runner. |
| 464 return GetState() == kPrerolling; |
| 465 } |
| 466 |
374 int MediaCodecDecoder::NumDelayedRenderTasks() const { | 467 int MediaCodecDecoder::NumDelayedRenderTasks() const { |
375 return 0; | 468 return 0; |
376 } | 469 } |
377 | 470 |
378 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, | 471 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, |
379 bool has_delayed_tasks) { | 472 bool has_delayed_tasks) { |
380 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 473 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
381 | 474 |
382 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; | 475 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; |
383 | 476 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 request_data_cb_.Run(); | 526 request_data_cb_.Run(); |
434 } | 527 } |
435 | 528 |
436 void MediaCodecDecoder::ProcessNextFrame() { | 529 void MediaCodecDecoder::ProcessNextFrame() { |
437 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 530 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
438 | 531 |
439 DVLOG(2) << class_name() << "::" << __FUNCTION__; | 532 DVLOG(2) << class_name() << "::" << __FUNCTION__; |
440 | 533 |
441 DecoderState state = GetState(); | 534 DecoderState state = GetState(); |
442 | 535 |
443 if (state != kRunning && state != kStopping) { | 536 if (state != kPrerolling && state != kRunning && state != kStopping) { |
444 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; | 537 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; |
445 return; | 538 return; |
446 } | 539 } |
447 | 540 |
448 if (state == kStopping) { | 541 if (state == kStopping) { |
449 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { | 542 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { |
450 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 543 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
451 << ": kStopping, posting OnLastFrameRendered"; | 544 << ": kStopping, posting OnLastFrameRendered"; |
452 media_task_runner_->PostTask( | 545 media_task_runner_->PostTask( |
453 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, | 546 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, |
454 weak_factory_.GetWeakPtr(), false)); | 547 weak_factory_.GetWeakPtr(), false)); |
455 last_frame_posted_ = true; | 548 last_frame_posted_ = true; |
456 } | 549 } |
457 | 550 |
458 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. | 551 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. |
459 // We only need to let finish the delayed rendering tasks. | 552 // We only need to let finish the delayed rendering tasks. |
460 return; | 553 return; |
461 } | 554 } |
462 | 555 |
463 DCHECK(state == kRunning); | 556 DCHECK(state == kPrerolling || state == kRunning); |
464 | 557 |
465 if (!EnqueueInputBuffer()) | 558 if (!EnqueueInputBuffer()) |
466 return; | 559 return; |
467 | 560 |
468 if (!DepleteOutputBufferQueue()) | 561 if (!DepleteOutputBufferQueue()) |
469 return; | 562 return; |
470 | 563 |
471 // We need a small delay if we want to stop this thread by | 564 // We need a small delay if we want to stop this thread by |
472 // decoder_thread_.Stop() reliably. | 565 // decoder_thread_.Stop() reliably. |
473 // The decoder thread message loop processes all pending | 566 // The decoder thread message loop processes all pending |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 | 691 |
599 DVLOG(2) << class_name() << "::" << __FUNCTION__; | 692 DVLOG(2) << class_name() << "::" << __FUNCTION__; |
600 | 693 |
601 int buffer_index = 0; | 694 int buffer_index = 0; |
602 size_t offset = 0; | 695 size_t offset = 0; |
603 size_t size = 0; | 696 size_t size = 0; |
604 base::TimeDelta pts; | 697 base::TimeDelta pts; |
605 MediaCodecStatus status; | 698 MediaCodecStatus status; |
606 bool eos_encountered = false; | 699 bool eos_encountered = false; |
607 | 700 |
| 701 RenderMode render_mode; |
| 702 |
608 base::TimeDelta timeout = | 703 base::TimeDelta timeout = |
609 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); | 704 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); |
610 | 705 |
611 // Extract all output buffers that are available. | 706 // Extract all output buffers that are available. |
612 // Usually there will be only one, but sometimes it is preceeded by | 707 // Usually there will be only one, but sometimes it is preceeded by |
613 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. | 708 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. |
614 do { | 709 do { |
615 status = media_codec_bridge_->DequeueOutputBuffer( | 710 status = media_codec_bridge_->DequeueOutputBuffer( |
616 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, | 711 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, |
617 nullptr); | 712 nullptr); |
618 | 713 |
619 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls | 714 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls |
620 // to quickly break the loop after we got all currently available buffers. | 715 // to quickly break the loop after we got all currently available buffers. |
621 timeout = base::TimeDelta::FromMilliseconds(0); | 716 timeout = base::TimeDelta::FromMilliseconds(0); |
622 | 717 |
623 switch (status) { | 718 switch (status) { |
624 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 719 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
625 // Output buffers are replaced in MediaCodecBridge, nothing to do. | 720 // Output buffers are replaced in MediaCodecBridge, nothing to do. |
626 break; | 721 break; |
627 | 722 |
628 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: | 723 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
629 DVLOG(2) << class_name() << "::" << __FUNCTION__ | 724 DVLOG(2) << class_name() << "::" << __FUNCTION__ |
630 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; | 725 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; |
631 OnOutputFormatChanged(); | 726 OnOutputFormatChanged(); |
632 break; | 727 break; |
633 | 728 |
634 case MEDIA_CODEC_OK: | 729 case MEDIA_CODEC_OK: |
635 // We got the decoded frame | 730 // We got the decoded frame. |
636 Render(buffer_index, size, true, pts, eos_encountered); | 731 |
| 732 if (pts < preroll_timestamp_) |
| 733 render_mode = kRenderSkip; |
| 734 else if (GetState() == kPrerolling) |
| 735 render_mode = kRenderAfterPreroll; |
| 736 else |
| 737 render_mode = kRenderNow; |
| 738 |
| 739 Render(buffer_index, size, render_mode, pts, eos_encountered); |
| 740 |
| 741 if (render_mode == kRenderAfterPreroll) { |
| 742 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts:" << pts |
| 743 << " preroll done, stopping frame processing"; |
| 744 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_); |
| 745 return false; |
| 746 } |
637 break; | 747 break; |
638 | 748 |
639 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 749 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
640 // Nothing to do. | 750 // Nothing to do. |
641 break; | 751 break; |
642 | 752 |
643 case MEDIA_CODEC_ERROR: | 753 case MEDIA_CODEC_ERROR: |
644 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 754 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
645 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; | 755 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; |
646 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); | 756 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 | 789 |
680 base::AutoLock lock(state_lock_); | 790 base::AutoLock lock(state_lock_); |
681 state_ = state; | 791 state_ = state; |
682 } | 792 } |
683 | 793 |
684 #undef RETURN_STRING | 794 #undef RETURN_STRING |
685 #define RETURN_STRING(x) \ | 795 #define RETURN_STRING(x) \ |
686 case x: \ | 796 case x: \ |
687 return #x; | 797 return #x; |
688 | 798 |
| 799 const char* MediaCodecDecoder::AsString(RenderMode render_mode) { |
| 800 switch (render_mode) { |
| 801 RETURN_STRING(kRenderSkip); |
| 802 RETURN_STRING(kRenderAfterPreroll); |
| 803 RETURN_STRING(kRenderNow); |
| 804 } |
| 805 return nullptr; // crash early |
| 806 } |
| 807 |
689 const char* MediaCodecDecoder::AsString(DecoderState state) { | 808 const char* MediaCodecDecoder::AsString(DecoderState state) { |
690 switch (state) { | 809 switch (state) { |
691 RETURN_STRING(kStopped); | 810 RETURN_STRING(kStopped); |
692 RETURN_STRING(kPrefetching); | 811 RETURN_STRING(kPrefetching); |
693 RETURN_STRING(kPrefetched); | 812 RETURN_STRING(kPrefetched); |
| 813 RETURN_STRING(kPrerolling); |
| 814 RETURN_STRING(kPrerolled); |
694 RETURN_STRING(kRunning); | 815 RETURN_STRING(kRunning); |
695 RETURN_STRING(kStopping); | 816 RETURN_STRING(kStopping); |
696 RETURN_STRING(kInEmergencyStop); | 817 RETURN_STRING(kInEmergencyStop); |
697 RETURN_STRING(kError); | 818 RETURN_STRING(kError); |
698 default: | |
699 return "Unknown DecoderState"; | |
700 } | 819 } |
| 820 return nullptr; // crash early |
701 } | 821 } |
702 | 822 |
703 #undef RETURN_STRING | 823 #undef RETURN_STRING |
704 | 824 |
705 } // namespace media | 825 } // namespace media |
OLD | NEW |