OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_decoder_job.h" | 5 #include "media/base/android/media_decoder_job.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 | 21 |
22 MediaDecoderJob::MediaDecoderJob( | 22 MediaDecoderJob::MediaDecoderJob( |
23 const scoped_refptr<base::MessageLoopProxy>& decoder_loop, | 23 const scoped_refptr<base::MessageLoopProxy>& decoder_loop, |
24 MediaCodecBridge* media_codec_bridge, | 24 MediaCodecBridge* media_codec_bridge, |
25 const base::Closure& request_data_cb) | 25 const base::Closure& request_data_cb) |
26 : ui_loop_(base::MessageLoopProxy::current()), | 26 : ui_loop_(base::MessageLoopProxy::current()), |
27 decoder_loop_(decoder_loop), | 27 decoder_loop_(decoder_loop), |
28 media_codec_bridge_(media_codec_bridge), | 28 media_codec_bridge_(media_codec_bridge), |
29 needs_flush_(false), | 29 needs_flush_(false), |
30 input_eos_encountered_(false), | 30 input_eos_encountered_(false), |
| 31 output_eos_encountered_(false), |
31 skip_eos_enqueue_(true), | 32 skip_eos_enqueue_(true), |
32 prerolling_(true), | 33 prerolling_(true), |
33 weak_this_(this), | 34 weak_this_(this), |
34 request_data_cb_(request_data_cb), | 35 request_data_cb_(request_data_cb), |
35 access_unit_index_(0), | 36 access_unit_index_(0), |
36 input_buf_index_(-1), | 37 input_buf_index_(-1), |
37 stop_decode_pending_(false), | 38 stop_decode_pending_(false), |
38 destroy_pending_(false) { | 39 destroy_pending_(false) { |
39 } | 40 } |
40 | 41 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 const base::TimeDelta& start_presentation_timestamp, | 269 const base::TimeDelta& start_presentation_timestamp, |
269 bool needs_flush, | 270 bool needs_flush, |
270 const MediaDecoderJob::DecoderCallback& callback) { | 271 const MediaDecoderJob::DecoderCallback& callback) { |
271 DVLOG(1) << __FUNCTION__; | 272 DVLOG(1) << __FUNCTION__; |
272 DCHECK(decoder_loop_->BelongsToCurrentThread()); | 273 DCHECK(decoder_loop_->BelongsToCurrentThread()); |
273 TRACE_EVENT0("media", __FUNCTION__); | 274 TRACE_EVENT0("media", __FUNCTION__); |
274 | 275 |
275 if (needs_flush) { | 276 if (needs_flush) { |
276 DVLOG(1) << "DecodeInternal needs flush."; | 277 DVLOG(1) << "DecodeInternal needs flush."; |
277 input_eos_encountered_ = false; | 278 input_eos_encountered_ = false; |
| 279 output_eos_encountered_ = false; |
278 MediaCodecStatus reset_status = media_codec_bridge_->Reset(); | 280 MediaCodecStatus reset_status = media_codec_bridge_->Reset(); |
279 if (MEDIA_CODEC_OK != reset_status) { | 281 if (MEDIA_CODEC_OK != reset_status) { |
280 callback.Run(reset_status, kNoTimestamp(), 0); | 282 callback.Run(reset_status, kNoTimestamp(), 0); |
281 return; | 283 return; |
282 } | 284 } |
283 } | 285 } |
284 | 286 |
| 287 // Once output EOS has occurred, we should not be asked to decode again. |
| 288 // MediaCodec has undefined behavior if similarly asked to decode after output |
| 289 // EOS. |
| 290 DCHECK(!output_eos_encountered_); |
| 291 |
285 // For aborted access unit, just skip it and inform the player. | 292 // For aborted access unit, just skip it and inform the player. |
286 if (unit.status == DemuxerStream::kAborted) { | 293 if (unit.status == DemuxerStream::kAborted) { |
287 // TODO(qinmin): use a new enum instead of MEDIA_CODEC_STOPPED. | 294 // TODO(qinmin): use a new enum instead of MEDIA_CODEC_STOPPED. |
288 callback.Run(MEDIA_CODEC_STOPPED, kNoTimestamp(), 0); | 295 callback.Run(MEDIA_CODEC_STOPPED, kNoTimestamp(), 0); |
289 return; | 296 return; |
290 } | 297 } |
291 | 298 |
292 if (skip_eos_enqueue_) { | 299 if (skip_eos_enqueue_) { |
293 if (unit.end_of_stream || unit.data.empty()) { | 300 if (unit.end_of_stream || unit.data.empty()) { |
294 input_eos_encountered_ = true; | 301 input_eos_encountered_ = true; |
| 302 output_eos_encountered_ = true; |
295 callback.Run(MEDIA_CODEC_OUTPUT_END_OF_STREAM, kNoTimestamp(), 0); | 303 callback.Run(MEDIA_CODEC_OUTPUT_END_OF_STREAM, kNoTimestamp(), 0); |
296 return; | 304 return; |
297 } | 305 } |
298 | 306 |
299 skip_eos_enqueue_ = false; | 307 skip_eos_enqueue_ = false; |
300 } | 308 } |
301 | 309 |
302 | |
303 MediaCodecStatus input_status = MEDIA_CODEC_INPUT_END_OF_STREAM; | 310 MediaCodecStatus input_status = MEDIA_CODEC_INPUT_END_OF_STREAM; |
304 if (!input_eos_encountered_) { | 311 if (!input_eos_encountered_) { |
305 input_status = QueueInputBuffer(unit); | 312 input_status = QueueInputBuffer(unit); |
306 if (input_status == MEDIA_CODEC_INPUT_END_OF_STREAM) { | 313 if (input_status == MEDIA_CODEC_INPUT_END_OF_STREAM) { |
307 input_eos_encountered_ = true; | 314 input_eos_encountered_ = true; |
308 } else if (input_status != MEDIA_CODEC_OK) { | 315 } else if (input_status != MEDIA_CODEC_OK) { |
309 callback.Run(input_status, kNoTimestamp(), 0); | 316 callback.Run(input_status, kNoTimestamp(), 0); |
310 return; | 317 return; |
311 } | 318 } |
312 } | 319 } |
313 | 320 |
314 int buffer_index = 0; | 321 int buffer_index = 0; |
315 size_t offset = 0; | 322 size_t offset = 0; |
316 size_t size = 0; | 323 size_t size = 0; |
317 base::TimeDelta presentation_timestamp; | 324 base::TimeDelta presentation_timestamp; |
318 bool output_eos_encountered = false; | |
319 | 325 |
320 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds( | 326 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds( |
321 kMediaCodecTimeoutInMilliseconds); | 327 kMediaCodecTimeoutInMilliseconds); |
322 | 328 |
323 MediaCodecStatus status = | 329 MediaCodecStatus status = |
324 media_codec_bridge_->DequeueOutputBuffer(timeout, | 330 media_codec_bridge_->DequeueOutputBuffer(timeout, |
325 &buffer_index, | 331 &buffer_index, |
326 &offset, | 332 &offset, |
327 &size, | 333 &size, |
328 &presentation_timestamp, | 334 &presentation_timestamp, |
329 &output_eos_encountered, | 335 &output_eos_encountered_, |
330 NULL); | 336 NULL); |
331 | 337 |
332 if (status != MEDIA_CODEC_OK) { | 338 if (status != MEDIA_CODEC_OK) { |
333 if (status == MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED && | 339 if (status == MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED && |
334 !media_codec_bridge_->GetOutputBuffers()) { | 340 !media_codec_bridge_->GetOutputBuffers()) { |
335 status = MEDIA_CODEC_ERROR; | 341 status = MEDIA_CODEC_ERROR; |
336 } | 342 } |
337 callback.Run(status, kNoTimestamp(), 0); | 343 callback.Run(status, kNoTimestamp(), 0); |
338 return; | 344 return; |
339 } | 345 } |
340 | 346 |
341 // TODO(xhwang/qinmin): This logic is correct but strange. Clean it up. | 347 // TODO(xhwang/qinmin): This logic is correct but strange. Clean it up. |
342 if (output_eos_encountered) | 348 if (output_eos_encountered_) |
343 status = MEDIA_CODEC_OUTPUT_END_OF_STREAM; | 349 status = MEDIA_CODEC_OUTPUT_END_OF_STREAM; |
344 else if (input_status == MEDIA_CODEC_INPUT_END_OF_STREAM) | 350 else if (input_status == MEDIA_CODEC_INPUT_END_OF_STREAM) |
345 status = MEDIA_CODEC_INPUT_END_OF_STREAM; | 351 status = MEDIA_CODEC_INPUT_END_OF_STREAM; |
346 | 352 |
347 // Check whether we need to render the output. | 353 // Check whether we need to render the output. |
348 // TODO(qinmin): comparing most recently queued input's |unit.timestamp| with | 354 // TODO(qinmin): comparing most recently queued input's |unit.timestamp| with |
349 // |preroll_timestamp_| is not accurate due to data reordering and possible | 355 // |preroll_timestamp_| is not accurate due to data reordering and possible |
350 // input queueing without immediate dequeue when |input_status| != | 356 // input queueing without immediate dequeue when |input_status| != |
351 // |MEDIA_CODEC_OK|. Need to use the |presentation_timestamp| for video, and | 357 // |MEDIA_CODEC_OK|. Need to use the |presentation_timestamp| for video, and |
352 // use |size| to calculate the timestamp for audio. See | 358 // use |size| to calculate the timestamp for audio. See |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 // Do nothing. | 429 // Do nothing. |
424 break; | 430 break; |
425 }; | 431 }; |
426 | 432 |
427 stop_decode_pending_ = false; | 433 stop_decode_pending_ = false; |
428 base::ResetAndReturn(&decode_cb_).Run(status, presentation_timestamp, | 434 base::ResetAndReturn(&decode_cb_).Run(status, presentation_timestamp, |
429 audio_output_bytes); | 435 audio_output_bytes); |
430 } | 436 } |
431 | 437 |
432 } // namespace media | 438 } // namespace media |
OLD | NEW |