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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
50 #define RETURN_ON_FAILURE(result, log, error, ret_val) \ | 50 #define RETURN_ON_FAILURE(result, log, error, ret_val) \ |
51 do { \ | 51 do { \ |
52 if (!(result)) { \ | 52 if (!(result)) { \ |
53 LOG(ERROR) << log; \ | 53 LOG(ERROR) << log; \ |
54 StopOnError(error); \ | 54 StopOnError(error); \ |
55 return ret_val; \ | 55 return ret_val; \ |
56 } \ | 56 } \ |
57 } while (0) | 57 } while (0) |
58 | 58 |
59 // OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone. | 59 // OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone. |
60 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \ | 60 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \ |
61 RETURN_ON_FAILURE( \ | 61 RETURN_ON_FAILURE( \ |
62 ((omx_result) == OMX_ErrorNone), \ | 62 ((omx_result) == OMX_ErrorNone), \ |
63 log << ", OMX result: " << std::hex << std::showbase << omx_result, \ | 63 log << ", OMX result: 0x" << std::hex << omx_result, \ |
64 error, ret_val) | 64 error, ret_val) |
65 | 65 |
66 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator( | 66 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator( |
67 media::VideoDecodeAccelerator::Client* client) | 67 media::VideoDecodeAccelerator::Client* client) |
68 : message_loop_(MessageLoop::current()), | 68 : message_loop_(MessageLoop::current()), |
69 component_handle_(NULL), | 69 component_handle_(NULL), |
70 client_state_(OMX_StateMax), | 70 client_state_(OMX_StateMax), |
71 current_state_change_(NO_TRANSITION), | 71 current_state_change_(NO_TRANSITION), |
72 saw_eos_during_flush_(false), | 72 saw_eos_during_flush_(false), |
73 input_buffer_count_(0), | 73 input_buffer_count_(0), |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]); | 175 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]); |
176 OMX_ERRORTYPE result = omx_get_components_of_role( | 176 OMX_ERRORTYPE result = omx_get_components_of_role( |
177 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component)); | 177 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component)); |
178 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name, | 178 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name, |
179 VIDEODECODERERROR_UNSUPPORTED, false); | 179 VIDEODECODERERROR_UNSUPPORTED, false); |
180 RETURN_ON_FAILURE(num_components == 1, | 180 RETURN_ON_FAILURE(num_components == 1, |
181 "No components for: " << role_name, | 181 "No components for: " << role_name, |
182 VIDEODECODERERROR_UNSUPPORTED, false); | 182 VIDEODECODERERROR_UNSUPPORTED, false); |
183 | 183 |
184 // Get the handle to the component. | 184 // Get the handle to the component. |
185 AddRef(); // To reflect passing |this| to OMX_GetHandle below. | |
185 result = omx_gethandle( | 186 result = omx_gethandle( |
186 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()), | 187 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()), |
187 this, &omx_accelerator_callbacks); | 188 this, &omx_accelerator_callbacks); |
188 RETURN_ON_OMX_FAILURE(result, | 189 RETURN_ON_OMX_FAILURE(result, |
189 "Failed to OMX_GetHandle on: " << component.get(), | 190 "Failed to OMX_GetHandle on: " << component.get(), |
190 VIDEODECODERERROR_INSUFFICIENT_RESOURCES, false); | 191 VIDEODECODERERROR_INSUFFICIENT_RESOURCES, false); |
191 client_state_ = OMX_StateLoaded; | 192 client_state_ = OMX_StateLoaded; |
192 | 193 |
193 // Get the port information. This will obtain information about the number of | 194 // Get the port information. This will obtain information about the number of |
194 // ports and index of the first port. | 195 // ports and index of the first port. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
258 RETURN_ON_OMX_FAILURE(result, | 259 RETURN_ON_OMX_FAILURE(result, |
259 "SetParameter(OMX_IndexParamPortDefinition) failed", | 260 "SetParameter(OMX_IndexParamPortDefinition) failed", |
260 VIDEODECODERERROR_INVALIDINPUT, false); | 261 VIDEODECODERERROR_INVALIDINPUT, false); |
261 | 262 |
262 // Fill the component with fake output buffers. This seems to be required for | 263 // Fill the component with fake output buffers. This seems to be required for |
263 // the component to move from Loaded to Idle. How bogus. | 264 // the component to move from Loaded to Idle. How bogus. |
264 for (int i = 0; i < kNumPictureBuffers; ++i) { | 265 for (int i = 0; i < kNumPictureBuffers; ++i) { |
265 OMX_BUFFERHEADERTYPE* buffer; | 266 OMX_BUFFERHEADERTYPE* buffer; |
266 result = OMX_UseBuffer(component_handle_, &buffer, output_port_, | 267 result = OMX_UseBuffer(component_handle_, &buffer, output_port_, |
267 NULL, 0, reinterpret_cast<OMX_U8*>(0x1)); | 268 NULL, 0, reinterpret_cast<OMX_U8*>(0x1)); |
268 RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer failed with: " << result, | 269 RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer failed", |
269 VIDEODECODERERROR_INVALIDINPUT, false); | 270 VIDEODECODERERROR_INVALIDINPUT, false); |
270 buffer->pAppPrivate = NULL; | 271 buffer->pAppPrivate = NULL; |
271 buffer->nTimeStamp = -1; | 272 buffer->nTimeStamp = -1; |
272 buffer->nOutputPortIndex = output_port_; | 273 buffer->nOutputPortIndex = output_port_; |
273 CHECK(fake_output_buffers_.insert(buffer).second); | 274 CHECK(fake_output_buffers_.insert(buffer).second); |
274 } | 275 } |
275 | 276 |
276 return true; | 277 return true; |
277 } | 278 } |
278 | 279 |
279 void OmxVideoDecodeAccelerator::Decode( | 280 void OmxVideoDecodeAccelerator::Decode( |
280 const media::BitstreamBuffer& bitstream_buffer) { | 281 const media::BitstreamBuffer& bitstream_buffer) { |
281 DCHECK_EQ(message_loop_, MessageLoop::current()); | 282 DCHECK_EQ(message_loop_, MessageLoop::current()); |
282 DCHECK(!free_input_buffers_.empty()); | 283 DCHECK(!free_input_buffers_.empty()); |
283 | 284 |
284 RETURN_ON_FAILURE(current_state_change_ == NO_TRANSITION && | 285 RETURN_ON_FAILURE(current_state_change_ == NO_TRANSITION && |
285 (client_state_ == OMX_StateIdle || | 286 (client_state_ == OMX_StateIdle || |
286 client_state_ == OMX_StateExecuting), | 287 client_state_ == OMX_StateExecuting), |
287 "Call to Decode() during invalid state or transition:" | 288 "Call to Decode() during invalid state or transition: " |
288 << current_state_change_ << ", " << client_state_, | 289 << current_state_change_ << ", " << client_state_, |
289 VIDEODECODERERROR_UNSUPPORTED,); | 290 VIDEODECODERERROR_UNSUPPORTED,); |
290 | 291 |
291 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 292 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
292 free_input_buffers_.pop(); | 293 free_input_buffers_.pop(); |
293 | 294 |
294 // Setup |omx_buffer|. | 295 // Setup |omx_buffer|. |
295 scoped_ptr<base::SharedMemory> shm( | 296 scoped_ptr<base::SharedMemory> shm( |
296 new base::SharedMemory(bitstream_buffer.handle(), true)); | 297 new base::SharedMemory(bitstream_buffer.handle(), true)); |
297 RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()), | 298 RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()), |
(...skipping 10 matching lines...) Expand all Loading... | |
308 omx_buffer->nFilledLen = bitstream_buffer.size(); | 309 omx_buffer->nFilledLen = bitstream_buffer.size(); |
309 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 310 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
310 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; | 311 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; |
311 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to | 312 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to |
312 // the output buffer's nTimeStamp field, so we can report it back to the | 313 // the output buffer's nTimeStamp field, so we can report it back to the |
313 // client in PictureReady(). | 314 // client in PictureReady(). |
314 omx_buffer->nTimeStamp = bitstream_buffer.id(); | 315 omx_buffer->nTimeStamp = bitstream_buffer.id(); |
315 | 316 |
316 // Give this buffer to OMX. | 317 // Give this buffer to OMX. |
317 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 318 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
318 RETURN_ON_OMX_FAILURE(result, | 319 RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed", |
319 "OMX_EmptyThisBuffer() failed with result " << result, | |
320 VIDEODECODERERROR_INVALIDINPUT,); | 320 VIDEODECODERERROR_INVALIDINPUT,); |
321 | 321 |
322 input_buffers_at_component_++; | 322 input_buffers_at_component_++; |
323 } | 323 } |
324 | 324 |
325 void OmxVideoDecodeAccelerator::AssignGLESBuffers( | 325 void OmxVideoDecodeAccelerator::AssignGLESBuffers( |
326 const std::vector<media::GLESBuffer>& buffers) { | 326 const std::vector<media::GLESBuffer>& buffers) { |
327 DCHECK_EQ(message_loop_, MessageLoop::current()); | 327 DCHECK_EQ(message_loop_, MessageLoop::current()); |
328 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", | 328 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", |
329 VIDEODECODERERROR_UNSUPPORTED,); | 329 VIDEODECODERERROR_UNSUPPORTED,); |
(...skipping 28 matching lines...) Expand all Loading... | |
358 | 358 |
359 OutputPictureById::iterator it = pictures_.find(picture_buffer_id); | 359 OutputPictureById::iterator it = pictures_.find(picture_buffer_id); |
360 RETURN_ON_FAILURE(it != pictures_.end(), | 360 RETURN_ON_FAILURE(it != pictures_.end(), |
361 "Missing picture buffer id: " << picture_buffer_id, | 361 "Missing picture buffer id: " << picture_buffer_id, |
362 VIDEODECODERERROR_UNSUPPORTED,); | 362 VIDEODECODERERROR_UNSUPPORTED,); |
363 OutputPicture& output_picture = it->second; | 363 OutputPicture& output_picture = it->second; |
364 | 364 |
365 ++output_buffers_at_component_; | 365 ++output_buffers_at_component_; |
366 OMX_ERRORTYPE result = | 366 OMX_ERRORTYPE result = |
367 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); | 367 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); |
368 RETURN_ON_OMX_FAILURE(result, | 368 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed", |
369 "OMX_FillThisBuffer() failed with result " << result, | |
370 VIDEODECODERERROR_INVALIDINPUT,); | 369 VIDEODECODERERROR_INVALIDINPUT,); |
371 } | 370 } |
372 | 371 |
373 void OmxVideoDecodeAccelerator::Flush() { | 372 void OmxVideoDecodeAccelerator::Flush() { |
374 DCHECK_EQ(message_loop_, MessageLoop::current()); | 373 DCHECK_EQ(message_loop_, MessageLoop::current()); |
375 DCHECK_EQ(current_state_change_, NO_TRANSITION); | 374 DCHECK_EQ(current_state_change_, NO_TRANSITION); |
376 DCHECK_EQ(client_state_, OMX_StateExecuting); | 375 DCHECK_EQ(client_state_, OMX_StateExecuting); |
377 current_state_change_ = FLUSHING; | 376 current_state_change_ = FLUSHING; |
378 | 377 |
379 // Cook up an empty buffer w/ EOS set and feed it to OMX. | 378 // Cook up an empty buffer w/ EOS set and feed it to OMX. |
380 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 379 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
381 free_input_buffers_.pop(); | 380 free_input_buffers_.pop(); |
382 omx_buffer->nFilledLen = 0; | 381 omx_buffer->nFilledLen = 0; |
383 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 382 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
384 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; | 383 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; |
385 omx_buffer->nTimeStamp = -2; | 384 omx_buffer->nTimeStamp = -2; |
386 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 385 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
387 RETURN_ON_OMX_FAILURE(result, | 386 RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed", |
388 "OMX_EmptyThisBuffer() failed with result " << result, | |
389 VIDEODECODERERROR_INVALIDINPUT,); | 387 VIDEODECODERERROR_INVALIDINPUT,); |
390 input_buffers_at_component_++; | 388 input_buffers_at_component_++; |
391 } | 389 } |
392 | 390 |
393 void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() { | 391 void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() { |
394 DCHECK_EQ(message_loop_, MessageLoop::current()); | 392 DCHECK_EQ(message_loop_, MessageLoop::current()); |
395 BeginTransitionToState(OMX_StatePause); | 393 BeginTransitionToState(OMX_StatePause); |
396 } | 394 } |
397 | 395 |
398 void OmxVideoDecodeAccelerator::FlushIOPorts() { | 396 void OmxVideoDecodeAccelerator::FlushIOPorts() { |
(...skipping 21 matching lines...) Expand all Loading... | |
420 DCHECK_EQ(message_loop_, MessageLoop::current()); | 418 DCHECK_EQ(message_loop_, MessageLoop::current()); |
421 DCHECK_EQ(current_state_change_, NO_TRANSITION); | 419 DCHECK_EQ(current_state_change_, NO_TRANSITION); |
422 DCHECK_EQ(client_state_, OMX_StateExecuting); | 420 DCHECK_EQ(client_state_, OMX_StateExecuting); |
423 current_state_change_ = RESETTING; | 421 current_state_change_ = RESETTING; |
424 BeginTransitionToState(OMX_StatePause); | 422 BeginTransitionToState(OMX_StatePause); |
425 } | 423 } |
426 | 424 |
427 void OmxVideoDecodeAccelerator::Destroy() { | 425 void OmxVideoDecodeAccelerator::Destroy() { |
428 DCHECK_EQ(message_loop_, MessageLoop::current()); | 426 DCHECK_EQ(message_loop_, MessageLoop::current()); |
429 DCHECK_EQ(current_state_change_, NO_TRANSITION); | 427 DCHECK_EQ(current_state_change_, NO_TRANSITION); |
428 // If we were never initializeed there's no teardown to do. | |
429 if (client_state_ == OMX_StateMax) | |
430 return; | |
431 // If we can already call OMX_FreeHandle, simply do so. | |
432 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) { | |
433 ShutdownComponent(); | |
434 return; | |
435 } | |
430 DCHECK_EQ(client_state_, OMX_StateExecuting); | 436 DCHECK_EQ(client_state_, OMX_StateExecuting); |
431 current_state_change_ = DESTROYING; | 437 current_state_change_ = DESTROYING; |
438 client_ = NULL; | |
vhiremath
2011/07/14 14:29:15
Do we really want to do it here ?
What if OVDA has
Ami GONE FROM CHROMIUM
2011/07/14 16:23:03
It is incorrect to call Destroy() while a Reset()
| |
432 BeginTransitionToState(OMX_StateIdle); | 439 BeginTransitionToState(OMX_StateIdle); |
440 BusyLoopInDestroying(); | |
433 } | 441 } |
434 | 442 |
435 void OmxVideoDecodeAccelerator::BeginTransitionToState( | 443 void OmxVideoDecodeAccelerator::BeginTransitionToState( |
436 OMX_STATETYPE new_state) { | 444 OMX_STATETYPE new_state) { |
437 DCHECK_EQ(message_loop_, MessageLoop::current()); | 445 DCHECK_EQ(message_loop_, MessageLoop::current()); |
438 DCHECK_NE(current_state_change_, NO_TRANSITION); | 446 DCHECK_NE(current_state_change_, NO_TRANSITION); |
447 DCHECK_NE(current_state_change_, ERRORING); | |
448 if (current_state_change_ == NO_TRANSITION || | |
449 current_state_change_ == ERRORING) { | |
450 return; | |
451 } | |
439 OMX_ERRORTYPE result = OMX_SendCommand( | 452 OMX_ERRORTYPE result = OMX_SendCommand( |
440 component_handle_, OMX_CommandStateSet, new_state, 0); | 453 component_handle_, OMX_CommandStateSet, new_state, 0); |
441 RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed", | 454 RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed", |
442 VIDEODECODERERROR_INVALIDINPUT,); | 455 VIDEODECODERERROR_INVALIDINPUT,); |
443 } | 456 } |
444 | 457 |
445 void OmxVideoDecodeAccelerator::OnReachedIdleInInitializing() { | 458 void OmxVideoDecodeAccelerator::OnReachedIdleInInitializing() { |
446 DCHECK_EQ(client_state_, OMX_StateLoaded); | 459 DCHECK_EQ(client_state_, OMX_StateLoaded); |
447 client_state_ = OMX_StateIdle; | 460 client_state_ = OMX_StateIdle; |
448 BeginTransitionToState(OMX_StateExecuting); | 461 BeginTransitionToState(OMX_StateExecuting); |
449 } | 462 } |
450 | 463 |
451 void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() { | 464 void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() { |
452 DCHECK_EQ(client_state_, OMX_StateIdle); | 465 DCHECK_EQ(client_state_, OMX_StateIdle); |
453 client_state_ = OMX_StateExecuting; | 466 client_state_ = OMX_StateExecuting; |
454 current_state_change_ = NO_TRANSITION; | 467 current_state_change_ = NO_TRANSITION; |
455 | 468 |
456 // Request filling of our fake buffers to trigger decode processing. In | 469 // Request filling of our fake buffers to trigger decode processing. In |
457 // reality as soon as any data is decoded these will get dismissed due to | 470 // reality as soon as any data is decoded these will get dismissed due to |
458 // dimension mismatch. | 471 // dimension mismatch. |
459 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = | 472 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = |
460 fake_output_buffers_.begin(); | 473 fake_output_buffers_.begin(); |
461 it != fake_output_buffers_.end(); ++it) { | 474 it != fake_output_buffers_.end(); ++it) { |
462 OMX_BUFFERHEADERTYPE* buffer = *it; | 475 OMX_BUFFERHEADERTYPE* buffer = *it; |
463 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer); | 476 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer); |
464 RETURN_ON_OMX_FAILURE(result, | 477 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer()", |
465 "OMX_FillThisBuffer() failed with: " << result, | |
466 VIDEODECODERERROR_INVALIDINPUT,); | 478 VIDEODECODERERROR_INVALIDINPUT,); |
467 ++output_buffers_at_component_; | 479 ++output_buffers_at_component_; |
468 } | 480 } |
469 | 481 |
470 client_->NotifyInitializeDone(); | 482 if (client_) |
483 client_->NotifyInitializeDone(); | |
471 } | 484 } |
472 | 485 |
473 void OmxVideoDecodeAccelerator::OnReachedPauseInFlushing() { | 486 void OmxVideoDecodeAccelerator::OnReachedPauseInFlushing() { |
474 DCHECK_EQ(client_state_, OMX_StateExecuting); | 487 DCHECK_EQ(client_state_, OMX_StateExecuting); |
475 client_state_ = OMX_StatePause; | 488 client_state_ = OMX_StatePause; |
476 FlushIOPorts(); | 489 FlushIOPorts(); |
477 } | 490 } |
478 | 491 |
479 void OmxVideoDecodeAccelerator::OnReachedExecutingInFlushing() { | 492 void OmxVideoDecodeAccelerator::OnReachedExecutingInFlushing() { |
480 DCHECK_EQ(client_state_, OMX_StatePause); | 493 DCHECK_EQ(client_state_, OMX_StatePause); |
481 client_state_ = OMX_StateExecuting; | 494 client_state_ = OMX_StateExecuting; |
482 DCHECK(saw_eos_during_flush_); | 495 DCHECK(saw_eos_during_flush_); |
483 saw_eos_during_flush_ = false; | 496 saw_eos_during_flush_ = false; |
484 current_state_change_ = NO_TRANSITION; | 497 current_state_change_ = NO_TRANSITION; |
485 client_->NotifyFlushDone(); | 498 if (client_) |
499 client_->NotifyFlushDone(); | |
486 } | 500 } |
487 | 501 |
488 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() { | 502 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() { |
489 DCHECK_EQ(client_state_, OMX_StateExecuting); | 503 DCHECK_EQ(client_state_, OMX_StateExecuting); |
490 client_state_ = OMX_StatePause; | 504 client_state_ = OMX_StatePause; |
491 FlushIOPorts(); | 505 FlushIOPorts(); |
492 } | 506 } |
493 | 507 |
494 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() { | 508 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() { |
495 DCHECK_EQ(client_state_, OMX_StatePause); | 509 DCHECK_EQ(client_state_, OMX_StatePause); |
496 client_state_ = OMX_StateExecuting; | 510 client_state_ = OMX_StateExecuting; |
497 current_state_change_ = NO_TRANSITION; | 511 current_state_change_ = NO_TRANSITION; |
498 client_->NotifyResetDone(); | 512 if (client_) |
513 client_->NotifyResetDone(); | |
514 } | |
515 | |
516 // Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients | |
517 // enjoy the fire-and-forget nature of a synchronous Destroy() call that | |
518 // ensures no further callbacks are made. Since the interface between OMX | |
519 // callbacks and this class is a MessageLoop, we need to ensure the loop | |
520 // outlives the shutdown dance, even during process shutdown. We do this by | |
521 // repeatedly enqueuing a no-op task until shutdown is complete, since | |
522 // MessageLoop's shutdown drains pending tasks. | |
523 void OmxVideoDecodeAccelerator::BusyLoopInDestroying() { | |
524 if (!component_handle_) return; | |
525 // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed | |
526 // tasks. Instead we sleep for 5ms. Really. | |
527 base::PlatformThread::Sleep(5); | |
vhiremath
2011/07/14 14:29:15
Why do we want to delay PostTask here ?
May cause
Ami GONE FROM CHROMIUM
2011/07/14 16:23:03
To reduce the CPU load of what otherwise would be
| |
528 message_loop_->PostTask( | |
529 FROM_HERE, NewRunnableMethod( | |
530 this, &OmxVideoDecodeAccelerator::BusyLoopInDestroying)); | |
499 } | 531 } |
vhiremath
2011/07/14 14:29:15
Please explain how this logic works.
Note: We have
Ami GONE FROM CHROMIUM
2011/07/14 16:23:03
I think so.
The purpose of this method is simple:
| |
500 | 532 |
501 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() { | 533 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() { |
502 DCHECK_EQ(client_state_, OMX_StateExecuting); | 534 DCHECK_EQ(client_state_, OMX_StateExecuting); |
503 client_state_ = OMX_StateIdle; | 535 client_state_ = OMX_StateIdle; |
504 | 536 |
505 // Note that during the Executing -> Idle transition, the OMX spec guarantees | 537 // Note that during the Executing -> Idle transition, the OMX spec guarantees |
506 // buffers have been returned to the client, so we don't need to do an | 538 // buffers have been returned to the client, so we don't need to do an |
507 // explicit FlushIOPorts(). | 539 // explicit FlushIOPorts(). |
508 | 540 |
509 BeginTransitionToState(OMX_StateLoaded); | 541 BeginTransitionToState(OMX_StateLoaded); |
510 | 542 |
511 // TODO(fischman): evaluate what these conditionals are doing. What happens | 543 // TODO(fischman): evaluate what these conditionals are doing. What happens |
512 // if they're false?? | 544 // if they're false?? |
513 if (!input_buffers_at_component_) | 545 if (!input_buffers_at_component_) |
514 FreeInputBuffers(); | 546 FreeInputBuffers(); |
515 if (!output_buffers_at_component_) | 547 if (!output_buffers_at_component_) |
516 FreeOutputBuffers(); | 548 FreeOutputBuffers(); |
517 } | |
518 | 549 |
519 void OmxVideoDecodeAccelerator::ShutdownComponent() { | 550 BusyLoopInDestroying(); |
520 OMX_ERRORTYPE result = omx_free_handle(component_handle_); | |
521 if (result != OMX_ErrorNone) | |
522 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; | |
523 component_handle_ = NULL; | |
524 omx_deinit(); | |
525 client_state_ = OMX_StateMax; | |
526 } | 551 } |
527 | 552 |
528 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() { | 553 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() { |
529 DCHECK_EQ(client_state_, OMX_StateIdle); | 554 DCHECK_EQ(client_state_, OMX_StateIdle); |
530 client_state_ = OMX_StateLoaded; | 555 client_state_ = OMX_StateLoaded; |
531 current_state_change_ = NO_TRANSITION; | 556 current_state_change_ = NO_TRANSITION; |
532 ShutdownComponent(); | 557 ShutdownComponent(); |
533 client_->NotifyDestroyDone(); | |
534 } | 558 } |
535 | 559 |
536 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() { | 560 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() { |
537 client_state_ = OMX_StateInvalid; | 561 client_state_ = OMX_StateInvalid; |
538 ShutdownComponent(); | 562 ShutdownComponent(); |
539 } | 563 } |
540 | 564 |
565 void OmxVideoDecodeAccelerator::ShutdownComponent() { | |
566 OMX_ERRORTYPE result = omx_free_handle(component_handle_); | |
567 if (result != OMX_ErrorNone) | |
568 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; | |
569 component_handle_ = NULL; | |
570 client_state_ = OMX_StateMax; | |
571 // This Release() call must happen *after* any access to |*this| because it | |
572 // might result in |this| being deleted. | |
573 Release(); // Since OMX no longer has |this| to call back to. | |
574 omx_deinit(); | |
575 } | |
576 | |
541 void OmxVideoDecodeAccelerator::StopOnError( | 577 void OmxVideoDecodeAccelerator::StopOnError( |
542 media::VideoDecodeAccelerator::Error error) { | 578 media::VideoDecodeAccelerator::Error error) { |
543 DCHECK_EQ(message_loop_, MessageLoop::current()); | 579 DCHECK_EQ(message_loop_, MessageLoop::current()); |
544 current_state_change_ = ERRORING; | |
545 | 580 |
546 client_->NotifyError(error); | 581 if (client_) |
582 client_->NotifyError(error); | |
547 | 583 |
548 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax) | 584 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax) |
549 return; | 585 return; |
550 | 586 |
551 BeginTransitionToState(OMX_StateInvalid); | 587 BeginTransitionToState(OMX_StateInvalid); |
588 current_state_change_ = ERRORING; | |
552 } | 589 } |
553 | 590 |
554 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() { | 591 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() { |
555 DCHECK_EQ(message_loop_, MessageLoop::current()); | 592 DCHECK_EQ(message_loop_, MessageLoop::current()); |
556 for (int i = 0; i < input_buffer_count_; ++i) { | 593 for (int i = 0; i < input_buffer_count_; ++i) { |
557 OMX_BUFFERHEADERTYPE* buffer; | 594 OMX_BUFFERHEADERTYPE* buffer; |
558 // While registering the buffer header we use fake buffer information | 595 // While registering the buffer header we use fake buffer information |
559 // (length 0, at memory address 0x1) to fake out the "safety" check in | 596 // (length 0, at memory address 0x1) to fake out the "safety" check in |
560 // OMX_UseBuffer. When it comes time to actually use this header in Decode | 597 // OMX_UseBuffer. When it comes time to actually use this header in Decode |
561 // we set these fields to their real values (for the duration of that | 598 // we set these fields to their real values (for the duration of that |
(...skipping 20 matching lines...) Expand all Loading... | |
582 gfx::Size decoded_pixel_size(pictures_.begin()->second.gles_buffer.size()); | 619 gfx::Size decoded_pixel_size(pictures_.begin()->second.gles_buffer.size()); |
583 gfx::Size visible_pixel_size(pictures_.begin()->second.gles_buffer.size()); | 620 gfx::Size visible_pixel_size(pictures_.begin()->second.gles_buffer.size()); |
584 for (OutputPictureById::iterator it = pictures_.begin(); | 621 for (OutputPictureById::iterator it = pictures_.begin(); |
585 it != pictures_.end(); ++it) { | 622 it != pictures_.end(); ++it) { |
586 media::GLESBuffer& gles_buffer = it->second.gles_buffer; | 623 media::GLESBuffer& gles_buffer = it->second.gles_buffer; |
587 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header; | 624 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header; |
588 DCHECK(!*omx_buffer); | 625 DCHECK(!*omx_buffer); |
589 OMX_ERRORTYPE result = OMX_UseEGLImage( | 626 OMX_ERRORTYPE result = OMX_UseEGLImage( |
590 component_handle_, omx_buffer, output_port_, &gles_buffer, | 627 component_handle_, omx_buffer, output_port_, &gles_buffer, |
591 it->second.egl_image); | 628 it->second.egl_image); |
592 RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage failed with: " << result, | 629 RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage", |
593 VIDEODECODERERROR_MEMFAILURE, false); | 630 VIDEODECODERERROR_MEMFAILURE, false); |
594 // Here we set a garbage bitstream buffer id, and then overwrite it before | 631 // Here we set a garbage bitstream buffer id, and then overwrite it before |
595 // passing to PictureReady. | 632 // passing to PictureReady. |
596 int garbage_bitstream_buffer_id = -1; | 633 int garbage_bitstream_buffer_id = -1; |
597 (*omx_buffer)->pAppPrivate = | 634 (*omx_buffer)->pAppPrivate = |
598 new media::Picture(gles_buffer.id(), garbage_bitstream_buffer_id, | 635 new media::Picture(gles_buffer.id(), garbage_bitstream_buffer_id, |
599 decoded_pixel_size, visible_pixel_size); | 636 decoded_pixel_size, visible_pixel_size); |
600 } | 637 } |
601 return true; | 638 return true; |
602 } | 639 } |
603 | 640 |
604 void OmxVideoDecodeAccelerator::FreeInputBuffers() { | 641 void OmxVideoDecodeAccelerator::FreeInputBuffers() { |
605 DCHECK_EQ(message_loop_, MessageLoop::current()); | 642 DCHECK_EQ(message_loop_, MessageLoop::current()); |
606 // Calls to OMX to free buffers. | 643 // Calls to OMX to free buffers. |
607 OMX_ERRORTYPE result; | 644 OMX_ERRORTYPE result; |
608 OMX_BUFFERHEADERTYPE* omx_buffer; | 645 OMX_BUFFERHEADERTYPE* omx_buffer; |
609 while (!free_input_buffers_.empty()) { | 646 while (!free_input_buffers_.empty()) { |
610 omx_buffer = free_input_buffers_.front(); | 647 omx_buffer = free_input_buffers_.front(); |
611 free_input_buffers_.pop(); | 648 free_input_buffers_.pop(); |
612 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer); | 649 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer); |
613 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, | 650 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", |
614 VIDEODECODERERROR_INVALIDINPUT,); | 651 VIDEODECODERERROR_INVALIDINPUT,); |
615 } | 652 } |
616 VLOG(1) << "Input buffers freed."; | |
617 } | 653 } |
618 | 654 |
619 void OmxVideoDecodeAccelerator::FreeOutputBuffers() { | 655 void OmxVideoDecodeAccelerator::FreeOutputBuffers() { |
620 DCHECK_EQ(message_loop_, MessageLoop::current()); | 656 DCHECK_EQ(message_loop_, MessageLoop::current()); |
621 // Calls to OMX to free buffers. | 657 // Calls to OMX to free buffers. |
622 OMX_ERRORTYPE result; | 658 OMX_ERRORTYPE result; |
623 static Gles2TextureToEglImageTranslator texture2eglImage_translator; | 659 static Gles2TextureToEglImageTranslator texture2eglImage_translator; |
624 for (OutputPictureById::iterator it = pictures_.begin(); | 660 for (OutputPictureById::iterator it = pictures_.begin(); |
625 it != pictures_.end(); ++it) { | 661 it != pictures_.end(); ++it) { |
626 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; | 662 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; |
627 CHECK(omx_buffer); | 663 CHECK(omx_buffer); |
628 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); | 664 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); |
629 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); | 665 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); |
630 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, | 666 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", |
631 VIDEODECODERERROR_INVALIDINPUT,); | 667 VIDEODECODERERROR_INVALIDINPUT,); |
632 texture2eglImage_translator.DestroyEglImage(egl_display_, | 668 texture2eglImage_translator.DestroyEglImage(egl_display_, |
633 it->second.egl_image); | 669 it->second.egl_image); |
634 client_->DismissPictureBuffer(it->first); | 670 if (client_) |
671 client_->DismissPictureBuffer(it->first); | |
635 } | 672 } |
636 pictures_.clear(); | 673 pictures_.clear(); |
637 } | 674 } |
638 | 675 |
639 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { | 676 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { |
640 DCHECK_EQ(message_loop_, MessageLoop::current()); | 677 DCHECK_EQ(message_loop_, MessageLoop::current()); |
641 OMX_PARAM_PORTDEFINITIONTYPE port_format; | 678 OMX_PARAM_PORTDEFINITIONTYPE port_format; |
642 InitParam(*this, &port_format); | 679 InitParam(*this, &port_format); |
643 port_format.nPortIndex = output_port_; | 680 port_format.nPortIndex = output_port_; |
644 OMX_ERRORTYPE result = OMX_GetParameter( | 681 OMX_ERRORTYPE result = OMX_GetParameter( |
645 component_handle_, OMX_IndexParamPortDefinition, &port_format); | 682 component_handle_, OMX_IndexParamPortDefinition, &port_format); |
646 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter failed with: " << result, | 683 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", |
647 VIDEODECODERERROR_UNSUPPORTED,); | 684 VIDEODECODERERROR_UNSUPPORTED,); |
648 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); | 685 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); |
649 | 686 |
650 // TODO(fischman): to support mid-stream resize, need to free/dismiss any | 687 // TODO(fischman): to support mid-stream resize, need to free/dismiss any |
651 // |pictures_| we already have. Make sure that the shutdown-path agrees with | 688 // |pictures_| we already have. Make sure that the shutdown-path agrees with |
652 // this (there's already freeing logic there, which should not be duplicated). | 689 // this (there's already freeing logic there, which should not be duplicated). |
653 | 690 |
654 // Request picture buffers to be handed to the component. | 691 // Request picture buffers to be handed to the component. |
655 // ProvidePictureBuffers() will trigger AssignGLESBuffers, which ultimately | 692 // ProvidePictureBuffers() will trigger AssignGLESBuffers, which ultimately |
656 // assigns the textures to the component and re-enables the port. | 693 // assigns the textures to the component and re-enables the port. |
657 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; | 694 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; |
658 client_->ProvidePictureBuffers( | 695 if (client_) { |
659 kNumPictureBuffers, | 696 client_->ProvidePictureBuffers( |
660 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), | 697 kNumPictureBuffers, |
661 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); | 698 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), |
699 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); | |
700 } | |
662 } | 701 } |
663 | 702 |
664 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { | 703 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { |
665 DCHECK_EQ(message_loop_, MessageLoop::current()); | 704 DCHECK_EQ(message_loop_, MessageLoop::current()); |
666 | 705 |
667 if (!CanFillBuffer()) { | 706 if (!CanFillBuffer()) { |
668 StopOnError(VIDEODECODERERROR_UNSUPPORTED); // Should be STATE_ERROR. | 707 StopOnError(VIDEODECODERERROR_UNSUPPORTED); // Should be STATE_ERROR. |
669 return; | 708 return; |
670 } | 709 } |
671 | 710 |
672 // Provide output buffers to decoder. | 711 // Provide output buffers to decoder. |
673 for (OutputPictureById::iterator it = pictures_.begin(); | 712 for (OutputPictureById::iterator it = pictures_.begin(); |
674 it != pictures_.end(); ++it) { | 713 it != pictures_.end(); ++it) { |
675 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; | 714 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; |
676 DCHECK(omx_buffer); | 715 DCHECK(omx_buffer); |
677 // Clear EOS flag. | 716 // Clear EOS flag. |
678 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; | 717 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; |
679 omx_buffer->nOutputPortIndex = output_port_; | 718 omx_buffer->nOutputPortIndex = output_port_; |
680 ++output_buffers_at_component_; | 719 ++output_buffers_at_component_; |
681 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); | 720 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); |
682 RETURN_ON_OMX_FAILURE(result, | 721 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed", |
683 "OMX_FillThisBuffer() failed with result " << result, | |
684 VIDEODECODERERROR_INSUFFICIENT_BUFFERS,); | 722 VIDEODECODERERROR_INSUFFICIENT_BUFFERS,); |
685 } | 723 } |
686 } | 724 } |
687 | 725 |
688 void OmxVideoDecodeAccelerator::FillBufferDoneTask( | 726 void OmxVideoDecodeAccelerator::FillBufferDoneTask( |
689 OMX_BUFFERHEADERTYPE* buffer) { | 727 OMX_BUFFERHEADERTYPE* buffer) { |
690 DCHECK_EQ(message_loop_, MessageLoop::current()); | 728 DCHECK_EQ(message_loop_, MessageLoop::current()); |
691 DCHECK_GT(output_buffers_at_component_, 0); | 729 DCHECK_GT(output_buffers_at_component_, 0); |
692 --output_buffers_at_component_; | 730 --output_buffers_at_component_; |
693 | 731 |
694 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) { | 732 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) { |
695 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U); | 733 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U); |
696 OMX_ERRORTYPE result = | 734 OMX_ERRORTYPE result = |
697 OMX_FreeBuffer(component_handle_, output_port_, buffer); | 735 OMX_FreeBuffer(component_handle_, output_port_, buffer); |
698 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, | 736 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed", |
699 VIDEODECODERERROR_INVALIDINPUT,); | 737 VIDEODECODERERROR_INVALIDINPUT,); |
700 return; | 738 return; |
701 } | 739 } |
702 CHECK(!fake_output_buffers_.size()); | 740 CHECK(!fake_output_buffers_.size()); |
703 | 741 |
704 if (current_state_change_ == FLUSHING && | 742 if (current_state_change_ == FLUSHING && |
705 buffer->nFlags & OMX_BUFFERFLAG_EOS) { | 743 buffer->nFlags & OMX_BUFFERFLAG_EOS) { |
706 DCHECK(!saw_eos_during_flush_); | 744 DCHECK(!saw_eos_during_flush_); |
707 saw_eos_during_flush_ = true; | 745 saw_eos_during_flush_ = true; |
708 } | 746 } |
709 | 747 |
710 // During the transition from Executing to Idle, and during port-flushing, all | 748 // During the transition from Executing to Idle, and during port-flushing, all |
711 // pictures are sent back through here. Avoid giving them to the client. | 749 // pictures are sent back through here. Avoid giving them to the client. |
712 // Also avoid sending the (fake) EOS buffer to the client. | 750 // Also avoid sending the (fake) EOS buffer to the client. |
713 if ((current_state_change_ != NO_TRANSITION && | 751 if ((current_state_change_ != NO_TRANSITION && |
714 current_state_change_ != FLUSHING) || | 752 current_state_change_ != FLUSHING) || |
715 saw_eos_during_flush_) { | 753 saw_eos_during_flush_) { |
716 return; | 754 return; |
717 } | 755 } |
718 | 756 |
719 CHECK(buffer->pAppPrivate); | 757 CHECK(buffer->pAppPrivate); |
720 media::Picture* picture = | 758 media::Picture* picture = |
721 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); | 759 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); |
722 // See Decode() for an explanation of this abuse of nTimeStamp. | 760 // See Decode() for an explanation of this abuse of nTimeStamp. |
723 picture->set_bitstream_buffer_id(buffer->nTimeStamp); | 761 picture->set_bitstream_buffer_id(buffer->nTimeStamp); |
724 client_->PictureReady(*picture); | 762 if (client_) |
763 client_->PictureReady(*picture); | |
725 } | 764 } |
726 | 765 |
727 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( | 766 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( |
728 OMX_BUFFERHEADERTYPE* buffer) { | 767 OMX_BUFFERHEADERTYPE* buffer) { |
729 DCHECK_EQ(message_loop_, MessageLoop::current()); | 768 DCHECK_EQ(message_loop_, MessageLoop::current()); |
730 DCHECK_GT(input_buffers_at_component_, 0); | 769 DCHECK_GT(input_buffers_at_component_, 0); |
731 free_input_buffers_.push(buffer); | 770 free_input_buffers_.push(buffer); |
732 input_buffers_at_component_--; | 771 input_buffers_at_component_--; |
733 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) | 772 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) |
734 return; | 773 return; |
735 | 774 |
736 // Retrieve the corresponding BitstreamBuffer's id and notify the client of | 775 // Retrieve the corresponding BitstreamBuffer's id and notify the client of |
737 // its completion. | 776 // its completion. |
738 SharedMemoryAndId* input_buffer_details = | 777 SharedMemoryAndId* input_buffer_details = |
739 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate); | 778 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate); |
740 DCHECK(input_buffer_details); | 779 DCHECK(input_buffer_details); |
741 buffer->pAppPrivate = NULL; | 780 buffer->pAppPrivate = NULL; |
742 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); | 781 if (client_) |
782 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); | |
743 delete input_buffer_details; | 783 delete input_buffer_details; |
744 } | 784 } |
745 | 785 |
746 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) { | 786 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) { |
747 DCHECK_EQ(message_loop_, MessageLoop::current()); | 787 DCHECK_EQ(message_loop_, MessageLoop::current()); |
748 switch (current_state_change_) { | 788 switch (current_state_change_) { |
749 case INITIALIZING: | 789 case INITIALIZING: |
750 switch (reached) { | 790 switch (reached) { |
751 case OMX_StateIdle: | 791 case OMX_StateIdle: |
752 OnReachedIdleInInitializing(); | 792 OnReachedIdleInInitializing(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
794 NOTREACHED() << "Unexpected state in " << current_state_change_ | 834 NOTREACHED() << "Unexpected state in " << current_state_change_ |
795 << ": " << reached; | 835 << ": " << reached; |
796 } | 836 } |
797 } | 837 } |
798 | 838 |
799 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, | 839 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, |
800 OMX_U32 data1, | 840 OMX_U32 data1, |
801 OMX_U32 data2) { | 841 OMX_U32 data2) { |
802 DCHECK_EQ(message_loop_, MessageLoop::current()); | 842 DCHECK_EQ(message_loop_, MessageLoop::current()); |
803 switch (event) { | 843 switch (event) { |
804 case OMX_EventCmdComplete: { | 844 case OMX_EventCmdComplete: |
805 // If the last command was successful, we have completed | 845 switch (data1) { |
806 // a state transition. So notify that we have done it | |
807 // accordingly. | |
808 OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(data1); | |
809 switch (cmd) { | |
810 case OMX_CommandPortDisable: | 846 case OMX_CommandPortDisable: |
811 DCHECK_EQ(data2, output_port_); | 847 DCHECK_EQ(data2, output_port_); |
812 OnOutputPortDisabled(); | 848 OnOutputPortDisabled(); |
813 break; | 849 return; |
814 case OMX_CommandPortEnable: | 850 case OMX_CommandPortEnable: |
815 DCHECK_EQ(data2, output_port_); | 851 DCHECK_EQ(data2, output_port_); |
816 OnOutputPortEnabled(); | 852 OnOutputPortEnabled(); |
817 break; | 853 return; |
818 case OMX_CommandStateSet: | 854 case OMX_CommandStateSet: |
819 DispatchStateReached(static_cast<OMX_STATETYPE>(data2)); | 855 DispatchStateReached(static_cast<OMX_STATETYPE>(data2)); |
820 break; | 856 return; |
821 case OMX_CommandFlush: | 857 case OMX_CommandFlush: |
822 DCHECK(current_state_change_ == FLUSHING || | 858 DCHECK(current_state_change_ == FLUSHING || |
823 current_state_change_ == RESETTING || | 859 current_state_change_ == RESETTING || |
824 current_state_change_ == DESTROYING); | 860 current_state_change_ == DESTROYING); |
825 if (data2 == input_port_) | 861 if (data2 == input_port_) |
826 InputPortFlushDone(); | 862 InputPortFlushDone(); |
827 else if (data2 == output_port_) | 863 else if (data2 == output_port_) |
828 OutputPortFlushDone(); | 864 OutputPortFlushDone(); |
829 else | 865 else |
830 NOTREACHED() << "Unexpected port flushed: " << data2; | 866 NOTREACHED() << "Unexpected port flushed: " << data2; |
831 break; | 867 return; |
832 default: | 868 default: |
833 RETURN_ON_FAILURE(false, "Unknown command completed: " << data1, | 869 RETURN_ON_FAILURE(false, "Unknown command completed: " << data1, |
834 VIDEODECODERERROR_HARDWARE,); | 870 VIDEODECODERERROR_HARDWARE,); |
835 } | 871 } |
836 break; | 872 return; |
837 } | |
838 case OMX_EventError: | 873 case OMX_EventError: |
839 RETURN_ON_FAILURE(false, "EventError: " << data1, | 874 if (current_state_change_ != DESTROYING && |
840 VIDEODECODERERROR_HARDWARE,); | 875 current_state_change_ != ERRORING) { |
876 RETURN_ON_FAILURE(false, "EventError: 0x" << std::hex << data1, | |
877 VIDEODECODERERROR_HARDWARE,); | |
878 } | |
879 return; | |
841 case OMX_EventPortSettingsChanged: | 880 case OMX_EventPortSettingsChanged: |
842 if (data2 == OMX_IndexParamPortDefinition) { | 881 if (data2 == OMX_IndexParamPortDefinition) { |
843 DCHECK_EQ(data1, output_port_); | 882 DCHECK_EQ(data1, output_port_); |
844 // This event is only used for output resize; kick off handling that by | 883 // This event is only used for output resize; kick off handling that by |
845 // pausing the output port. | 884 // pausing the output port. |
846 SendCommandToPort(OMX_CommandPortDisable, output_port_); | 885 SendCommandToPort(OMX_CommandPortDisable, output_port_); |
847 } else if (data1 == output_port_ && | 886 } else if (data1 == output_port_ && |
848 data2 == OMX_IndexConfigCommonOutputCrop) { | 887 data2 == OMX_IndexConfigCommonOutputCrop) { |
849 // TODO(vjain): Handle video crop rect. | 888 // TODO(vjain): Handle video crop rect. |
850 } else { | 889 } else { |
851 RETURN_ON_FAILURE(false, | 890 RETURN_ON_FAILURE(false, |
852 "Unexpected EventPortSettingsChanged: " | 891 "Unexpected EventPortSettingsChanged: " |
853 << data1 << ", " << data2, | 892 << data1 << ", " << data2, |
854 VIDEODECODERERROR_HARDWARE,); | 893 VIDEODECODERERROR_HARDWARE,); |
855 } | 894 } |
856 break; | 895 return; |
857 case OMX_EventBufferFlag: | 896 case OMX_EventBufferFlag: |
858 if (data1 == output_port_) { | 897 if (data1 == output_port_) { |
859 DCHECK_EQ(current_state_change_, FLUSHING); | 898 DCHECK_EQ(current_state_change_, FLUSHING); |
860 OnReachedEOSInFlushing(); | 899 OnReachedEOSInFlushing(); |
861 } else { | 900 } else { |
862 RETURN_ON_FAILURE(false, | 901 RETURN_ON_FAILURE(false, |
863 "Unexpected OMX_EventBufferFlag: " | 902 "Unexpected OMX_EventBufferFlag: " |
864 << data1 << ", " << data2, | 903 << data1 << ", " << data2, |
865 VIDEODECODERERROR_HARDWARE,); | 904 VIDEODECODERERROR_HARDWARE,); |
866 } | 905 } |
867 break; | 906 return; |
868 default: | 907 default: |
869 RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event, | 908 RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event, |
870 VIDEODECODERERROR_HARDWARE,); | 909 VIDEODECODERERROR_HARDWARE,); |
871 } | 910 } |
872 } | 911 } |
873 | 912 |
874 // static | 913 // static |
875 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, | 914 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, |
876 OMX_PTR priv_data, | 915 OMX_PTR priv_data, |
877 OMX_EVENTTYPE event, | 916 OMX_EVENTTYPE event, |
878 OMX_U32 data1, | 917 OMX_U32 data1, |
879 OMX_U32 data2, | 918 OMX_U32 data2, |
880 OMX_PTR event_data) { | 919 OMX_PTR event_data) { |
881 // Called on the OMX thread. | 920 // Called on the OMX thread. |
882 OmxVideoDecodeAccelerator* decoder = | 921 OmxVideoDecodeAccelerator* decoder = |
883 static_cast<OmxVideoDecodeAccelerator*>(priv_data); | 922 static_cast<OmxVideoDecodeAccelerator*>(priv_data); |
884 DCHECK_EQ(component, decoder->component_handle_); | 923 DCHECK_EQ(component, decoder->component_handle_); |
885 decoder->message_loop_->PostTask( | 924 decoder->message_loop_->PostTask( |
886 FROM_HERE, | 925 FROM_HERE, NewRunnableMethod( |
887 NewRunnableMethod(decoder, | 926 decoder, &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, |
888 &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, | 927 event, data1, data2)); |
889 event, data1, data2)); | |
890 return OMX_ErrorNone; | 928 return OMX_ErrorNone; |
891 } | 929 } |
892 | 930 |
893 // static | 931 // static |
894 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( | 932 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( |
895 OMX_HANDLETYPE component, | 933 OMX_HANDLETYPE component, |
896 OMX_PTR priv_data, | 934 OMX_PTR priv_data, |
897 OMX_BUFFERHEADERTYPE* buffer) { | 935 OMX_BUFFERHEADERTYPE* buffer) { |
898 // Called on the OMX thread. | 936 // Called on the OMX thread. |
899 OmxVideoDecodeAccelerator* decoder = | 937 OmxVideoDecodeAccelerator* decoder = |
(...skipping 19 matching lines...) Expand all Loading... | |
919 decoder->message_loop_->PostTask( | 957 decoder->message_loop_->PostTask( |
920 FROM_HERE, | 958 FROM_HERE, |
921 NewRunnableMethod(decoder, | 959 NewRunnableMethod(decoder, |
922 &OmxVideoDecodeAccelerator::FillBufferDoneTask, | 960 &OmxVideoDecodeAccelerator::FillBufferDoneTask, |
923 buffer)); | 961 buffer)); |
924 return OMX_ErrorNone; | 962 return OMX_ErrorNone; |
925 } | 963 } |
926 | 964 |
927 bool OmxVideoDecodeAccelerator::CanFillBuffer() { | 965 bool OmxVideoDecodeAccelerator::CanFillBuffer() { |
928 DCHECK_EQ(message_loop_, MessageLoop::current()); | 966 DCHECK_EQ(message_loop_, MessageLoop::current()); |
967 if (current_state_change_ == DESTROYING || | |
968 current_state_change_ == ERRORING) { | |
969 return false; | |
970 } | |
929 return client_state_ == OMX_StateIdle || | 971 return client_state_ == OMX_StateIdle || |
930 client_state_ == OMX_StateExecuting || | 972 client_state_ == OMX_StateExecuting || |
931 client_state_ == OMX_StatePause; | 973 client_state_ == OMX_StatePause; |
932 } | 974 } |
933 | 975 |
934 bool OmxVideoDecodeAccelerator::SendCommandToPort( | 976 bool OmxVideoDecodeAccelerator::SendCommandToPort( |
935 OMX_COMMANDTYPE cmd, int port_index) { | 977 OMX_COMMANDTYPE cmd, int port_index) { |
936 DCHECK_EQ(message_loop_, MessageLoop::current()); | 978 DCHECK_EQ(message_loop_, MessageLoop::current()); |
937 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 979 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
938 cmd, port_index, 0); | 980 cmd, port_index, 0); |
939 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd << ":" << result, | 981 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, |
940 VIDEODECODERERROR_INVALIDINPUT, false); | 982 VIDEODECODERERROR_INVALIDINPUT, false); |
941 return true; | 983 return true; |
942 } | 984 } |
943 | |
944 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); | |
OLD | NEW |