OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/common/gpu/media/omx_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/omx_video_decode_accelerator.h" |
6 | 6 |
7 #include "base/stl_util-inl.h" | 7 #include "base/stl_util-inl.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "content/common/gpu/gpu_channel.h" | 9 #include "content/common/gpu/gpu_channel.h" |
10 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" | 10 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 } | 328 } |
329 buffer->pAppPrivate = NULL; | 329 buffer->pAppPrivate = NULL; |
330 buffer->nTimeStamp = 0; | 330 buffer->nTimeStamp = 0; |
331 buffer->nOutputPortIndex = output_port_; | 331 buffer->nOutputPortIndex = output_port_; |
332 CHECK(fake_output_buffers_.insert(buffer).second); | 332 CHECK(fake_output_buffers_.insert(buffer).second); |
333 } | 333 } |
334 | 334 |
335 return true; | 335 return true; |
336 } | 336 } |
337 | 337 |
338 bool OmxVideoDecodeAccelerator::Decode( | 338 void OmxVideoDecodeAccelerator::Decode( |
339 const media::BitstreamBuffer& bitstream_buffer) { | 339 const media::BitstreamBuffer& bitstream_buffer) { |
340 DCHECK(!free_input_buffers_.empty()); | 340 DCHECK(!free_input_buffers_.empty()); |
341 | 341 |
342 if (!CanAcceptInput()) | 342 if (!CanAcceptInput()) |
343 return false; | 343 return; |
344 | 344 |
345 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 345 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
346 free_input_buffers_.pop(); | 346 free_input_buffers_.pop(); |
347 | 347 |
348 // Setup |omx_buffer|. | 348 // Setup |omx_buffer|. |
349 scoped_ptr<base::SharedMemory> shm( | 349 scoped_ptr<base::SharedMemory> shm( |
350 new base::SharedMemory(bitstream_buffer.handle(), true)); | 350 new base::SharedMemory(bitstream_buffer.handle(), true)); |
351 if (!shm->Map(bitstream_buffer.size())) { | 351 if (!shm->Map(bitstream_buffer.size())) { |
352 LOG(ERROR) << "Failed to SharedMemory::Map()."; | 352 LOG(ERROR) << "Failed to SharedMemory::Map()."; |
353 return false; | 353 return; |
354 } | 354 } |
355 SharedMemoryAndId* input_buffer_details = new SharedMemoryAndId(); | 355 SharedMemoryAndId* input_buffer_details = new SharedMemoryAndId(); |
356 input_buffer_details->first.reset(shm.release()); | 356 input_buffer_details->first.reset(shm.release()); |
357 input_buffer_details->second = bitstream_buffer.id(); | 357 input_buffer_details->second = bitstream_buffer.id(); |
358 DCHECK(!omx_buffer->pAppPrivate); | 358 DCHECK(!omx_buffer->pAppPrivate); |
359 omx_buffer->pAppPrivate = input_buffer_details; | 359 omx_buffer->pAppPrivate = input_buffer_details; |
360 omx_buffer->pBuffer = | 360 omx_buffer->pBuffer = |
361 static_cast<OMX_U8*>(input_buffer_details->first->memory()); | 361 static_cast<OMX_U8*>(input_buffer_details->first->memory()); |
362 omx_buffer->nFilledLen = bitstream_buffer.size(); | 362 omx_buffer->nFilledLen = bitstream_buffer.size(); |
363 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 363 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
364 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; | 364 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; |
365 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to | 365 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to |
366 // the output buffer's nTimeStamp field, so we can report it back to the | 366 // the output buffer's nTimeStamp field, so we can report it back to the |
367 // client in PictureReady(). | 367 // client in PictureReady(). |
368 omx_buffer->nTimeStamp = bitstream_buffer.id(); | 368 omx_buffer->nTimeStamp = bitstream_buffer.id(); |
369 | 369 |
370 // Give this buffer to OMX. | 370 // Give this buffer to OMX. |
371 OMX_ERRORTYPE result = OMX_ErrorNone; | 371 OMX_ERRORTYPE result = OMX_ErrorNone; |
372 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 372 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
373 if (result != OMX_ErrorNone) { | 373 if (result != OMX_ErrorNone) { |
374 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; | 374 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; |
375 StopOnError(); | 375 StopOnError(); |
376 return false; | 376 return; |
377 } | 377 } |
378 input_buffers_at_component_++; | 378 input_buffers_at_component_++; |
379 return true; | |
380 } | 379 } |
381 | 380 |
382 void OmxVideoDecodeAccelerator::AssignGLESBuffers( | 381 void OmxVideoDecodeAccelerator::AssignGLESBuffers( |
383 const std::vector<media::GLESBuffer>& buffers) { | 382 const std::vector<media::GLESBuffer>& buffers) { |
384 if (!CanFillBuffer()) { | 383 if (!CanFillBuffer()) { |
385 StopOnError(); | 384 StopOnError(); |
386 return; | 385 return; |
387 } | 386 } |
388 CHECK_EQ(output_buffers_at_component_, 0); | 387 CHECK_EQ(output_buffers_at_component_, 0); |
389 CHECK_EQ(fake_output_buffers_.size(), 0U); | 388 CHECK_EQ(fake_output_buffers_.size(), 0U); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 ++output_buffers_at_component_; | 432 ++output_buffers_at_component_; |
434 OMX_ERRORTYPE result = | 433 OMX_ERRORTYPE result = |
435 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); | 434 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); |
436 if (result != OMX_ErrorNone) { | 435 if (result != OMX_ErrorNone) { |
437 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; | 436 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; |
438 StopOnError(); | 437 StopOnError(); |
439 return; | 438 return; |
440 } | 439 } |
441 } | 440 } |
442 | 441 |
443 bool OmxVideoDecodeAccelerator::Flush() { | 442 void OmxVideoDecodeAccelerator::Flush() { |
444 OMX_STATETYPE il_state; | 443 OMX_STATETYPE il_state; |
445 OMX_GetState(component_handle_, &il_state); | 444 OMX_GetState(component_handle_, &il_state); |
446 DCHECK_EQ(il_state, OMX_StateExecuting); | 445 DCHECK_EQ(il_state, OMX_StateExecuting); |
447 // Decode the pending data first. Then flush I/O ports. | 446 // Decode the pending data first. Then flush I/O ports. |
448 if (il_state != OMX_StateExecuting) { | 447 if (il_state != OMX_StateExecuting) { |
449 client_->NotifyFlushDone(); | 448 client_->NotifyFlushDone(); |
450 return false; | 449 return; |
451 } | 450 } |
452 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin; | 451 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin; |
453 | 452 |
454 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 453 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
455 free_input_buffers_.pop(); | 454 free_input_buffers_.pop(); |
456 | 455 |
457 omx_buffer->nFilledLen = 0; | 456 omx_buffer->nFilledLen = 0; |
458 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 457 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
459 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; | 458 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; |
460 omx_buffer->nTimeStamp = 0; | 459 omx_buffer->nTimeStamp = 0; |
461 // Give this buffer to OMX. | 460 // Give this buffer to OMX. |
462 OMX_ERRORTYPE result = OMX_ErrorNone; | 461 OMX_ERRORTYPE result = OMX_ErrorNone; |
463 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 462 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
464 if (result != OMX_ErrorNone) { | 463 if (result != OMX_ErrorNone) { |
465 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; | 464 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; |
466 StopOnError(); | 465 StopOnError(); |
467 return false; | 466 return; |
468 } | 467 } |
469 input_buffers_at_component_++; | 468 input_buffers_at_component_++; |
470 return true; | |
471 } | 469 } |
472 | 470 |
473 void OmxVideoDecodeAccelerator::FlushBegin() { | 471 void OmxVideoDecodeAccelerator::FlushBegin() { |
474 VLOG(1) << "Starting actual flush for EOS"; | 472 VLOG(1) << "Starting actual flush for EOS"; |
475 DCHECK(!on_state_event_func_); | 473 DCHECK(!on_state_event_func_); |
476 on_state_event_func_ = &OmxVideoDecodeAccelerator::PauseFromExecuting; | 474 on_state_event_func_ = &OmxVideoDecodeAccelerator::PauseFromExecuting; |
477 TransitionToState(OMX_StatePause); | 475 TransitionToState(OMX_StatePause); |
478 } | 476 } |
479 | 477 |
480 void OmxVideoDecodeAccelerator::PauseFromExecuting(OMX_STATETYPE ignored) { | 478 void OmxVideoDecodeAccelerator::PauseFromExecuting(OMX_STATETYPE ignored) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 516 |
519 void OmxVideoDecodeAccelerator::OutputPortFlushDone(int port) { | 517 void OmxVideoDecodeAccelerator::OutputPortFlushDone(int port) { |
520 DCHECK_EQ(port, output_port_); | 518 DCHECK_EQ(port, output_port_); |
521 | 519 |
522 VLOG(1) << "Output Port has been flushed"; | 520 VLOG(1) << "Output Port has been flushed"; |
523 DCHECK_EQ(output_buffers_at_component_, 0); | 521 DCHECK_EQ(output_buffers_at_component_, 0); |
524 client_state_ = OMX_StatePause; | 522 client_state_ = OMX_StatePause; |
525 client_->NotifyFlushDone(); | 523 client_->NotifyFlushDone(); |
526 } | 524 } |
527 | 525 |
528 bool OmxVideoDecodeAccelerator::Abort() { | 526 void OmxVideoDecodeAccelerator::Abort() { |
529 CHECK_EQ(message_loop_, MessageLoop::current()); | 527 CHECK_EQ(message_loop_, MessageLoop::current()); |
530 // Abort() implies immediacy but Flush() actually decodes pending data first. | 528 // Abort() implies immediacy but Flush() actually decodes pending data first. |
531 // TODO(vhiremath@nvidia.com) Fix the Abort to handle this immediacy. | 529 // TODO(vhiremath@nvidia.com) Fix the Abort to handle this immediacy. |
532 ShutDownOMXFromExecuting(); | 530 ShutDownOMXFromExecuting(); |
533 return true; | 531 return; |
534 } | 532 } |
535 | 533 |
536 // Event callback during initialization to handle DoneStateSet to idle | 534 // Event callback during initialization to handle DoneStateSet to idle |
537 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) { | 535 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) { |
538 DCHECK(!on_state_event_func_); | 536 DCHECK(!on_state_event_func_); |
539 DCHECK_EQ(client_state_, OMX_StateLoaded); | 537 DCHECK_EQ(client_state_, OMX_StateLoaded); |
540 DCHECK_EQ(OMX_StateIdle, state); | 538 DCHECK_EQ(OMX_StateIdle, state); |
541 | 539 |
542 VLOG(1) << "OMX video decode engine is in Idle"; | 540 VLOG(1) << "OMX video decode engine is in Idle"; |
543 | 541 |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 1020 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
1023 cmd, port_index, 0); | 1021 cmd, port_index, 0); |
1024 if (result != OMX_ErrorNone) { | 1022 if (result != OMX_ErrorNone) { |
1025 LOG(ERROR) << "SendCommand() failed" << cmd << ":" << result; | 1023 LOG(ERROR) << "SendCommand() failed" << cmd << ":" << result; |
1026 StopOnError(); | 1024 StopOnError(); |
1027 return; | 1025 return; |
1028 } | 1026 } |
1029 } | 1027 } |
1030 | 1028 |
1031 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); | 1029 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); |
OLD | NEW |