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/gpu/omx_video_decode_accelerator.h" | 5 #include "content/common/gpu/omx_video_decode_accelerator.h" |
6 | 6 |
7 #include "base/string_util.h" | |
8 #include "content/common/gpu/gles2_texture_to_egl_image_translator.h" | |
7 #include "content/common/gpu/gpu_channel.h" | 9 #include "content/common/gpu/gpu_channel.h" |
8 #include "content/common/gpu_messages.h" | |
9 #include "content/gpu/gles2_texture_to_egl_image_translator.h" | |
10 #include "media/base/bitstream_buffer.h" | 10 #include "media/base/bitstream_buffer.h" |
11 #include "media/base/data_buffer.h" | |
12 #include "media/video/picture.h" | 11 #include "media/video/picture.h" |
13 | 12 |
14 static Gles2TextureToEglImageTranslator* texture2eglImage_translator( | 13 static Gles2TextureToEglImageTranslator* texture2eglImage_translator( |
15 new Gles2TextureToEglImageTranslator(NULL, 0)); | 14 new Gles2TextureToEglImageTranslator(NULL, 0)); |
16 enum { kNumPictureBuffers = 4 }; | 15 enum { kNumPictureBuffers = 4 }; |
17 | 16 |
18 // Open the libnvomx here for now. | 17 // Open the libnvomx here for now. |
19 void* omx_handle = dlopen("libnvomx.so", RTLD_NOW); | 18 void* omx_handle = dlopen("libnvomx.so", RTLD_NOW); |
20 | 19 |
21 typedef OMX_ERRORTYPE (*OMXInit)(); | 20 typedef OMX_ERRORTYPE (*OMXInit)(); |
(...skipping 29 matching lines...) Expand all Loading... | |
51 height_(-1), | 50 height_(-1), |
52 input_buffer_count_(0), | 51 input_buffer_count_(0), |
53 input_buffer_size_(0), | 52 input_buffer_size_(0), |
54 input_port_(0), | 53 input_port_(0), |
55 input_buffers_at_component_(0), | 54 input_buffers_at_component_(0), |
56 output_buffer_count_(0), | 55 output_buffer_count_(0), |
57 output_buffer_size_(0), | 56 output_buffer_size_(0), |
58 output_port_(0), | 57 output_port_(0), |
59 output_buffers_at_component_(0), | 58 output_buffers_at_component_(0), |
60 uses_egl_image_(false), | 59 uses_egl_image_(false), |
61 client_(client), | 60 client_(client) { |
62 egl_image_(NULL) { | |
63 if (!AreOMXFunctionPointersInitialized()) { | 61 if (!AreOMXFunctionPointersInitialized()) { |
64 LOG(ERROR) << "Failed to load openmax library"; | 62 LOG(ERROR) << "Failed to load openmax library"; |
65 return; | 63 return; |
66 } | 64 } |
67 OMX_ERRORTYPE result = omx_init(); | 65 OMX_ERRORTYPE result = omx_init(); |
68 if (result != OMX_ErrorNone) | 66 if (result != OMX_ErrorNone) |
69 LOG(ERROR) << "Failed to init OpenMAX core"; | 67 LOG(ERROR) << "Failed to init OpenMAX core"; |
70 } | 68 } |
71 | 69 |
72 OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() { | 70 OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() { |
73 DCHECK(free_input_buffers_.empty()); | 71 DCHECK(free_input_buffers_.empty()); |
74 DCHECK_EQ(0, input_buffers_at_component_); | 72 DCHECK_EQ(0, input_buffers_at_component_); |
75 DCHECK_EQ(0, output_buffers_at_component_); | 73 DCHECK_EQ(0, output_buffers_at_component_); |
76 DCHECK(output_pictures_.empty()); | 74 DCHECK(output_pictures_.empty()); |
77 } | 75 } |
78 | 76 |
79 const std::vector<uint32>& OmxVideoDecodeAccelerator::GetConfig( | 77 void OmxVideoDecodeAccelerator::GetConfigs( |
80 const std::vector<uint32>& prototype_config) { | 78 const std::vector<uint32>& requested_configs, |
79 std::vector<uint32>* matched_configs) { | |
81 // TODO(vhiremath@nvidia.com) use this properly | 80 // TODO(vhiremath@nvidia.com) use this properly |
82 NOTIMPLEMENTED(); | 81 NOTIMPLEMENTED(); |
83 return component_config_; | |
84 } | 82 } |
85 | 83 |
86 // This is to initialize the OMX data structures to default values. | 84 // This is to initialize the OMX data structures to default values. |
87 template <typename T> | 85 template <typename T> |
88 static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) { | 86 static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) { |
89 memset(param, 0, sizeof(T)); | 87 memset(param, 0, sizeof(T)); |
90 param->nVersion.nVersion = 0x00000101; | 88 param->nVersion.nVersion = 0x00000101; |
91 param->nSize = sizeof(T); | 89 param->nSize = sizeof(T); |
92 } | 90 } |
93 | 91 |
94 bool OmxVideoDecodeAccelerator::Initialize(const std::vector<uint32>& config) { | 92 bool OmxVideoDecodeAccelerator::Initialize(const std::vector<uint32>& config) { |
95 // TODO(vhiremath@nvidia.com) get these acutal values from config | 93 // TODO(vhiremath@nvidia.com) get these actual values from config |
96 // Assume qvga for now | 94 // Assume qvga for now |
97 width_ = 320; | 95 width_ = 320; |
98 height_ = 240; | 96 height_ = 240; |
99 | 97 |
100 client_state_ = OMX_StateLoaded; | 98 client_state_ = OMX_StateLoaded; |
101 if (!CreateComponent()) { | 99 if (!CreateComponent()) { |
102 StopOnError(); | 100 StopOnError(); |
103 return false; | 101 return false; |
104 } | 102 } |
105 // Transition component to Idle state | 103 // Transition component to Idle state |
106 on_state_event_func_ = | 104 on_state_event_func_ = |
107 &OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle; | 105 &OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle; |
108 if (!TransitionToState(OMX_StateIdle)) | 106 if (!TransitionToState(OMX_StateIdle)) |
109 return false; | 107 return false; |
110 | 108 |
111 if (!AllocateInputBuffers()) { | 109 if (!AllocateInputBuffers()) { |
112 LOG(ERROR) << "OMX_AllocateBuffer() Input buffer error"; | 110 LOG(ERROR) << "OMX_AllocateBuffer() Input buffer error"; |
113 StopOnError(); | 111 StopOnError(); |
114 return false; | 112 return false; |
115 } | 113 } |
116 | 114 |
117 // After AllocateInputBuffers ideally this should be AllocateOutputBuffers. | 115 // After AllocateInputBuffers ideally this should be AllocateOutputBuffers. |
118 // Since in this case app provides the output buffers, | 116 // Since in this case app provides the output buffers, |
119 // we query this through ProvidePictureBuffers. | 117 // we query this through ProvidePictureBuffers. |
120 // This is call to ppapi to provide the output buffers initially. | 118 // This is call to ppapi to provide the output buffers initially. |
121 // ProvidePictureBuffers will provide | 119 // ProvidePictureBuffers will provide |
122 // - SharedMemHandle in case of decoding to system memory. | 120 // - SharedMemHandle in case of decoding to system memory. |
123 // - Textures in case of decoding to egl-images. | 121 // - Textures in case of decoding to egl-images. |
124 | 122 |
125 // Output buffers will be eventually allocated in AssignPictureBuffer(). | 123 // Output buffers will be eventually handed to us via |
126 | 124 // Assign{GLES,Sysmem}Buffers(). |
127 // TODO(vhiremath@nvidia.com) fill buffer_properties | |
128 std::vector<uint32> buffer_properties; | |
129 output_buffer_count_ = kNumPictureBuffers; | 125 output_buffer_count_ = kNumPictureBuffers; |
130 client_->ProvidePictureBuffers(output_buffer_count_, buffer_properties); | 126 client_->ProvidePictureBuffers( |
127 output_buffer_count_, gfx::Size(width_, height_), | |
128 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); | |
129 // TODO(fischman): we always ask for GLES buffers above. So why maintain the | |
130 // !uses_egl_image_ path in this class at all? Theoretically it could be | |
131 // useful for testing, but today there's no such testing. Consider ripping it | |
132 // out of this class and replacing AssignSysmemBuffers() with | |
133 // NOTIMPLEMENTED(). | |
131 return true; | 134 return true; |
132 } | 135 } |
133 | 136 |
134 bool OmxVideoDecodeAccelerator::CreateComponent() { | 137 bool OmxVideoDecodeAccelerator::CreateComponent() { |
135 OMX_CALLBACKTYPE omx_accelerator_callbacks = { | 138 OMX_CALLBACKTYPE omx_accelerator_callbacks = { |
136 &OmxVideoDecodeAccelerator::EventHandler, | 139 &OmxVideoDecodeAccelerator::EventHandler, |
137 &OmxVideoDecodeAccelerator::EmptyBufferCallback, | 140 &OmxVideoDecodeAccelerator::EmptyBufferCallback, |
138 &OmxVideoDecodeAccelerator::FillBufferCallback | 141 &OmxVideoDecodeAccelerator::FillBufferCallback |
139 }; | 142 }; |
140 OMX_ERRORTYPE result = OMX_ErrorNone; | 143 OMX_ERRORTYPE result = OMX_ErrorNone; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 // OMX_IndexParamPortDefinition on output port to be done in | 244 // OMX_IndexParamPortDefinition on output port to be done in |
242 // AllocateOutputBuffers. | 245 // AllocateOutputBuffers. |
243 // Since at this point we dont know if we will be using system memory | 246 // Since at this point we dont know if we will be using system memory |
244 // or egl-image for decoding. | 247 // or egl-image for decoding. |
245 // We get this info in AssignPictureBuffers() from plugin. | 248 // We get this info in AssignPictureBuffers() from plugin. |
246 | 249 |
247 return true; | 250 return true; |
248 } | 251 } |
249 | 252 |
250 bool OmxVideoDecodeAccelerator::Decode( | 253 bool OmxVideoDecodeAccelerator::Decode( |
251 const media::BitstreamBuffer& bitstream_buffer, | 254 const media::BitstreamBuffer& bitstream_buffer) { |
252 const media::VideoDecodeAcceleratorCallback& callback) { | |
253 DCHECK(!free_input_buffers_.empty()); | 255 DCHECK(!free_input_buffers_.empty()); |
254 DCHECK(bitstream_buffer); | |
255 | 256 |
256 if (!CanAcceptInput()) { | 257 if (!CanAcceptInput()) { |
257 return false; | 258 return false; |
258 } | 259 } |
259 | 260 |
260 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 261 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
261 free_input_buffers_.pop(); | 262 free_input_buffers_.pop(); |
262 | 263 |
263 // Setup |omx_buffer|. | 264 // Setup |omx_buffer|. |
264 scoped_ptr<base::SharedMemory> shm( | 265 scoped_ptr<base::SharedMemory> shm( |
265 new base::SharedMemory(bitstream_buffer.handle(), true)); | 266 new base::SharedMemory(bitstream_buffer.handle(), true)); |
266 if (!shm->Map(bitstream_buffer.size())) { | 267 if (!shm->Map(bitstream_buffer.size())) { |
267 LOG(ERROR) << "Failed to SharedMemory::Map()."; | 268 LOG(ERROR) << "Failed to SharedMemory::Map()."; |
268 return false; | 269 return false; |
269 } | 270 } |
270 omx_buffer->pBuffer = static_cast<OMX_U8*>(shm->memory()); | 271 omx_buffer->pBuffer = static_cast<OMX_U8*>(shm->memory()); |
271 omx_buffer->nFilledLen = bitstream_buffer->size(); | 272 omx_buffer->nFilledLen = bitstream_buffer.size(); |
272 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 273 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
273 | 274 |
274 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; | 275 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; |
275 omx_buffer->nTimeStamp = 0; | 276 omx_buffer->nTimeStamp = 0; |
276 | 277 |
277 // Give this buffer to OMX. | 278 // Give this buffer to OMX. |
278 OMX_ERRORTYPE result = OMX_ErrorNone; | 279 OMX_ERRORTYPE result = OMX_ErrorNone; |
279 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 280 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
280 if (result != OMX_ErrorNone) { | 281 if (result != OMX_ErrorNone) { |
281 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; | 282 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; |
282 StopOnError(); | 283 StopOnError(); |
283 return false; | 284 return false; |
284 } | 285 } |
285 input_buffers_at_component_++; | 286 input_buffers_at_component_++; |
286 // OMX_EmptyThisBuffer is a non blocking call and should | 287 // OMX_EmptyThisBuffer is a non blocking call and should |
287 // not make any assumptions about its completion. | 288 // not make any assumptions about its completion. |
288 omx_buff_cb_.insert(std::make_pair( | 289 omx_buff_ids_.insert(std::make_pair( |
289 omx_buffer, make_pair(shm.release(), callback))); | 290 omx_buffer, std::make_pair(shm.release(), bitstream_buffer.id()))); |
290 return true; | 291 return true; |
291 } | 292 } |
292 | 293 |
293 void OmxVideoDecodeAccelerator::AssignPictureBuffer( | 294 // NOTE: this is only partially-implemented as it only inspects the first |
294 std::vector<PictureBuffer*> picture_buffers) { | 295 // picture buffer passed in each AssignPictureBuffer call, and never unsets |
295 // NOTE: this is only partially-implemented as it only inspects the first | 296 // uses_egl_image_ once set. |
296 // picture buffer passed in each AssignPictureBuffer call, and never unsets | 297 void OmxVideoDecodeAccelerator::AssignGLESBuffers( |
297 // uses_egl_image_ once set. | 298 const std::vector<media::GLESBuffer>& buffers) { |
298 if (PictureBuffer::PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE == | 299 uses_egl_image_ = true; |
299 picture_buffers[0]->GetMemoryType()) { | 300 std::vector<media::BaseBuffer*> base_buffers(buffers.size()); |
300 uses_egl_image_ = true; | 301 for (size_t i = 0; i < buffers.size(); ++i) |
301 } | 302 base_buffers[i] = new media::GLESBuffer(buffers[i]); |
303 AssignBuffersHelper(base_buffers); | |
304 } | |
302 | 305 |
306 void OmxVideoDecodeAccelerator::AssignSysmemBuffers( | |
307 const std::vector<media::SysmemBuffer>& buffers) { | |
308 DCHECK(!uses_egl_image_); | |
309 std::vector<media::BaseBuffer*> base_buffers(buffers.size()); | |
310 for (size_t i = 0; i < buffers.size(); ++i) | |
311 base_buffers[i] = new media::SysmemBuffer(buffers[i]); | |
312 AssignBuffersHelper(base_buffers); | |
313 } | |
314 | |
315 void OmxVideoDecodeAccelerator::AssignBuffersHelper( | |
316 const std::vector<media::BaseBuffer*>& buffers) { | |
303 assigned_picture_buffers_.insert( | 317 assigned_picture_buffers_.insert( |
304 assigned_picture_buffers_.begin(), | 318 assigned_picture_buffers_.end(), buffers.begin(), buffers.end()); |
305 picture_buffers.begin(), | |
306 picture_buffers.end()); | |
307 | 319 |
308 if (assigned_picture_buffers_.size() < kNumPictureBuffers) | 320 if (assigned_picture_buffers_.size() < kNumPictureBuffers) |
309 return; // get all the buffers first. | 321 return; // get all the buffers first. |
310 | 322 |
311 // Obtain the information about the output port. | 323 // Obtain the information about the output port. |
312 OMX_PARAM_PORTDEFINITIONTYPE port_format; | 324 OMX_PARAM_PORTDEFINITIONTYPE port_format; |
313 InitParam(*this, &port_format); | 325 InitParam(*this, &port_format); |
314 port_format.nPortIndex = output_port_; | 326 port_format.nPortIndex = output_port_; |
315 OMX_ERRORTYPE result = OMX_GetParameter(component_handle_, | 327 OMX_ERRORTYPE result = OMX_GetParameter(component_handle_, |
316 OMX_IndexParamPortDefinition, | 328 OMX_IndexParamPortDefinition, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 StopOnError(); | 361 StopOnError(); |
350 } | 362 } |
351 } | 363 } |
352 | 364 |
353 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { | 365 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { |
354 // TODO(vhiremath@nvidia.com) Avoid leaking of the picture buffer. | 366 // TODO(vhiremath@nvidia.com) Avoid leaking of the picture buffer. |
355 if (!CanFillBuffer()) | 367 if (!CanFillBuffer()) |
356 return; | 368 return; |
357 | 369 |
358 for (int i = 0; i < output_buffer_count_; ++i) { | 370 for (int i = 0; i < output_buffer_count_; ++i) { |
359 if (picture_buffer_id != assigned_picture_buffers_[i]->GetId()) | 371 if (picture_buffer_id != assigned_picture_buffers_[i]->id()) |
360 continue; | 372 continue; |
361 output_buffers_at_component_++; | 373 output_buffers_at_component_++; |
362 OMX_ERRORTYPE result = | 374 OMX_ERRORTYPE result = |
363 OMX_FillThisBuffer(component_handle_, output_pictures_[i].second); | 375 OMX_FillThisBuffer(component_handle_, output_pictures_[i].second); |
364 if (result != OMX_ErrorNone) { | 376 if (result != OMX_ErrorNone) { |
365 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; | 377 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; |
366 StopOnError(); | 378 StopOnError(); |
367 } | 379 } |
368 // Sent one buffer to omx. | 380 // Sent one buffer to omx. |
369 return; | 381 return; |
(...skipping 13 matching lines...) Expand all Loading... | |
383 output_buffers_at_component_++; | 395 output_buffers_at_component_++; |
384 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); | 396 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); |
385 if (result != OMX_ErrorNone) { | 397 if (result != OMX_ErrorNone) { |
386 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; | 398 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; |
387 StopOnError(); | 399 StopOnError(); |
388 return; | 400 return; |
389 } | 401 } |
390 } | 402 } |
391 } | 403 } |
392 | 404 |
393 bool OmxVideoDecodeAccelerator::Flush( | 405 bool OmxVideoDecodeAccelerator::Flush() { |
394 const media::VideoDecodeAcceleratorCallback& callback) { | |
395 OMX_STATETYPE il_state; | 406 OMX_STATETYPE il_state; |
396 OMX_GetState(component_handle_, &il_state); | 407 OMX_GetState(component_handle_, &il_state); |
397 DCHECK_EQ(il_state, OMX_StateExecuting); | 408 DCHECK_EQ(il_state, OMX_StateExecuting); |
398 if (il_state != OMX_StateExecuting) { | 409 if (il_state != OMX_StateExecuting) { |
399 callback.Run(); | 410 client_->NotifyFlushDone(); |
400 return false; | 411 return false; |
401 } | 412 } |
402 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin; | 413 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin; |
403 flush_done_callback_ = callback; | |
404 | 414 |
405 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 415 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
406 omx_buffer->nFilledLen = 0; | 416 omx_buffer->nFilledLen = 0; |
407 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 417 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
408 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; | 418 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; |
409 omx_buffer->nTimeStamp = 0; | 419 omx_buffer->nTimeStamp = 0; |
410 // Give this buffer to OMX. | 420 // Give this buffer to OMX. |
411 OMX_ERRORTYPE result = OMX_ErrorNone; | 421 OMX_ERRORTYPE result = OMX_ErrorNone; |
412 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 422 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
413 if (result != OMX_ErrorNone) { | 423 if (result != OMX_ErrorNone) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 VLOG(1) << "Output Port had been flushed"; | 480 VLOG(1) << "Output Port had been flushed"; |
471 DCHECK_EQ(output_buffers_at_component_, 0); | 481 DCHECK_EQ(output_buffers_at_component_, 0); |
472 } | 482 } |
473 | 483 |
474 client_state_ = OMX_StatePause; | 484 client_state_ = OMX_StatePause; |
475 // So Finally call OnPortCommandFlush which should | 485 // So Finally call OnPortCommandFlush which should |
476 // internally call DismissPictureBuffer(); | 486 // internally call DismissPictureBuffer(); |
477 OnPortCommandFlush(OMX_StateExecuting); | 487 OnPortCommandFlush(OMX_StateExecuting); |
478 } | 488 } |
479 | 489 |
480 bool OmxVideoDecodeAccelerator::Abort( | 490 bool OmxVideoDecodeAccelerator::Abort() { |
481 const media::VideoDecodeAcceleratorCallback& callback) { | |
482 // TODO(vhiremath@nvidia.com) | 491 // TODO(vhiremath@nvidia.com) |
483 // Need more thinking on this to handle w.r.t OMX. | 492 // Need more thinking on this to handle w.r.t OMX. |
484 // There is no explicit UnInitialize call for this. | 493 // There is no explicit UnInitialize call for this. |
485 // Also review again for trick modes. | 494 // Also review again for trick modes. |
486 callback.Run(); | 495 client_->NotifyAbortDone(); |
487 return true; | 496 return true; |
488 } | 497 } |
489 | 498 |
490 // Event callback during initialization to handle DoneStateSet to idle | 499 // Event callback during initialization to handle DoneStateSet to idle |
491 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) { | 500 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) { |
492 DCHECK_EQ(client_state_, OMX_StateLoaded); | 501 DCHECK_EQ(client_state_, OMX_StateLoaded); |
493 DCHECK_EQ(OMX_StateIdle, state); | 502 DCHECK_EQ(OMX_StateIdle, state); |
494 VLOG(1) << "OMX video decode engine is in Idle"; | 503 VLOG(1) << "OMX video decode engine is in Idle"; |
495 | 504 |
496 on_state_event_func_ = | 505 on_state_event_func_ = |
497 &OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting; | 506 &OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting; |
498 if (!TransitionToState(OMX_StateExecuting)) | 507 if (!TransitionToState(OMX_StateExecuting)) |
499 return; | 508 return; |
500 } | 509 } |
501 | 510 |
502 // Event callback during initialization to handle DoneStateSet to executing | 511 // Event callback during initialization to handle DoneStateSet to executing |
503 void OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting( | 512 void OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting( |
504 OMX_STATETYPE state) { | 513 OMX_STATETYPE state) { |
505 DCHECK_EQ(OMX_StateExecuting, state); | 514 DCHECK_EQ(OMX_StateExecuting, state); |
506 VLOG(1) << "OMX video decode engine is in Executing"; | 515 VLOG(1) << "OMX video decode engine is in Executing"; |
507 | 516 |
508 client_state_ = OMX_StateExecuting; | 517 client_state_ = OMX_StateExecuting; |
509 on_state_event_func_ = NULL; | 518 on_state_event_func_ = NULL; |
510 // This will kickoff the actual decoding | 519 // This will kickoff the actual decoding |
511 client_->NotifyResourcesAcquired(); | |
512 InitialFillBuffer(); | 520 InitialFillBuffer(); |
513 } | 521 } |
514 | 522 |
515 // Send state transition command to component. | 523 // Send state transition command to component. |
516 bool OmxVideoDecodeAccelerator::TransitionToState(OMX_STATETYPE new_state) { | 524 bool OmxVideoDecodeAccelerator::TransitionToState(OMX_STATETYPE new_state) { |
517 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 525 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
518 OMX_CommandStateSet, | 526 OMX_CommandStateSet, |
519 new_state, 0); | 527 new_state, 0); |
520 if (result != OMX_ErrorNone) { | 528 if (result != OMX_ErrorNone) { |
521 LOG(ERROR) << "SendCommand(OMX_CommandStateSet) failed"; | 529 LOG(ERROR) << "SendCommand(OMX_CommandStateSet) failed"; |
522 StopOnError(); | 530 StopOnError(); |
523 return false; | 531 return false; |
524 } | 532 } |
525 return true; | 533 return true; |
526 } | 534 } |
527 | 535 |
528 void OmxVideoDecodeAccelerator::OnPortCommandFlush(OMX_STATETYPE state) { | 536 void OmxVideoDecodeAccelerator::OnPortCommandFlush(OMX_STATETYPE state) { |
529 DCHECK_EQ(state, OMX_StateExecuting); | 537 DCHECK_EQ(state, OMX_StateExecuting); |
530 | 538 |
531 VLOG(1) << "Deinit from Executing"; | 539 VLOG(1) << "Deinit from Executing"; |
532 on_state_event_func_ = | 540 on_state_event_func_ = |
533 &OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle; | 541 &OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle; |
534 TransitionToState(OMX_StateIdle); | 542 TransitionToState(OMX_StateIdle); |
535 for (int i = 0; i < output_buffer_count_; ++i) { | 543 for (int i = 0; i < output_buffer_count_; ++i) { |
536 OutputPicture output_picture = output_pictures_[i]; | 544 OutputPicture output_picture = output_pictures_[i]; |
537 client_->DismissPictureBuffer(output_picture.first); | 545 client_->DismissPictureBuffer(output_picture.first); |
vrk (LEFT CHROMIUM)
2011/05/23 23:35:00
(Sorry if this was asked/answered before in a prev
| |
538 } | 546 } |
539 output_pictures_.clear(); | 547 output_pictures_.clear(); |
540 } | 548 } |
541 | 549 |
542 void OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle( | 550 void OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle( |
543 OMX_STATETYPE state) { | 551 OMX_STATETYPE state) { |
544 DCHECK_EQ(state, OMX_StateIdle); | 552 DCHECK_EQ(state, OMX_StateIdle); |
545 | 553 |
546 VLOG(1) << "Deinit from Idle"; | 554 VLOG(1) << "Deinit from Idle"; |
547 on_state_event_func_ = | 555 on_state_event_func_ = |
(...skipping 14 matching lines...) Expand all Loading... | |
562 | 570 |
563 if (component_handle_) { | 571 if (component_handle_) { |
564 OMX_ERRORTYPE result = (*omx_free_handle)(component_handle_); | 572 OMX_ERRORTYPE result = (*omx_free_handle)(component_handle_); |
565 if (result != OMX_ErrorNone) | 573 if (result != OMX_ErrorNone) |
566 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; | 574 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; |
567 component_handle_ = NULL; | 575 component_handle_ = NULL; |
568 } | 576 } |
569 client_state_ = OMX_StateLoaded; | 577 client_state_ = OMX_StateLoaded; |
570 (*omx_deinit)(); | 578 (*omx_deinit)(); |
571 VLOG(1) << "OMX Deinit Clean exit done"; | 579 VLOG(1) << "OMX Deinit Clean exit done"; |
572 flush_done_callback_.Run(); | 580 client_->NotifyFlushDone(); |
573 } | 581 } |
574 | 582 |
575 void OmxVideoDecodeAccelerator::StopOnError() { | 583 void OmxVideoDecodeAccelerator::StopOnError() { |
576 OMX_STATETYPE il_state; | 584 OMX_STATETYPE il_state; |
577 OMX_GetState(component_handle_, &il_state); | 585 OMX_GetState(component_handle_, &il_state); |
578 client_state_ = OMX_StateInvalid; | 586 client_state_ = OMX_StateInvalid; |
579 switch (il_state) { | 587 switch (il_state) { |
580 case OMX_StateExecuting: | 588 case OMX_StateExecuting: |
581 OnPortCommandFlush(OMX_StateExecuting); | 589 OnPortCommandFlush(OMX_StateExecuting); |
582 return; | 590 return; |
(...skipping 21 matching lines...) Expand all Loading... | |
604 return false; | 612 return false; |
605 buffer->nInputPortIndex = input_port_; | 613 buffer->nInputPortIndex = input_port_; |
606 buffer->nOffset = 0; | 614 buffer->nOffset = 0; |
607 buffer->nFlags = 0; | 615 buffer->nFlags = 0; |
608 free_input_buffers_.push(buffer); | 616 free_input_buffers_.push(buffer); |
609 } | 617 } |
610 return true; | 618 return true; |
611 } | 619 } |
612 | 620 |
613 bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() { | 621 bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() { |
614 OMX_BUFFERHEADERTYPE* buffer; | |
615 Picture* picture; | |
616 OMX_ERRORTYPE result; | |
617 gfx::Size decoded_pixel_size(width_, height_); | 622 gfx::Size decoded_pixel_size(width_, height_); |
618 gfx::Size visible_pixel_size(width_, height_); | 623 gfx::Size visible_pixel_size(width_, height_); |
619 | 624 // TODO(fischman): remove garbage bitstream buffer id's below (42 and 24) when |
625 // the bitstream_buffer_id field is removed from Picture. | |
620 if (uses_egl_image_) { | 626 if (uses_egl_image_) { |
621 media::VideoDecodeAccelerator::PictureBuffer::DataPlaneHandle egl_ids; | |
622 std::vector<PictureBuffer::DataPlaneHandle> planes; | |
623 uint32 texture; | |
624 | |
625 for (uint32 i = 0; i < assigned_picture_buffers_.size(); i++) { | 627 for (uint32 i = 0; i < assigned_picture_buffers_.size(); i++) { |
626 picture = new media::Picture( | 628 media::GLESBuffer* gles_buffer = |
627 reinterpret_cast<media::PictureBuffer*>(assigned_picture_buffers_[i]), | 629 reinterpret_cast<media::GLESBuffer*>(assigned_picture_buffers_[i]); |
628 decoded_pixel_size, visible_pixel_size, | 630 OMX_BUFFERHEADERTYPE* omx_buffer; |
629 static_cast<void*>(component_handle_)); | 631 void* egl = texture2eglImage_translator->TranslateToEglImage( |
630 | 632 gles_buffer->texture_id()); |
631 planes = assigned_picture_buffers_[i]->GetPlaneHandles(); | 633 OMX_ERRORTYPE result = OMX_UseEGLImage( |
632 egl_ids = planes[i]; | 634 component_handle_, &omx_buffer, output_port_, gles_buffer, egl); |
633 texture = egl_ids.texture_id; | |
634 egl_image_ = texture2eglImage_translator->TranslateToEglImage(texture); | |
635 result = OMX_UseEGLImage( | |
636 component_handle_, | |
637 &buffer, | |
638 output_port_, | |
639 reinterpret_cast<media::PictureBuffer*>(assigned_picture_buffers_[i]), | |
640 egl_image_); | |
641 | |
642 if (result != OMX_ErrorNone) { | 635 if (result != OMX_ErrorNone) { |
643 LOG(ERROR) << "OMX_UseEGLImage failed"; | 636 LOG(ERROR) << "OMX_UseEGLImage failed"; |
644 return false; | 637 return false; |
645 } | 638 } |
639 omx_buffer->pAppPrivate = | |
640 new media::Picture(gles_buffer->id(), | |
641 42 /* garbage bitstreambuffer id */, | |
642 decoded_pixel_size, visible_pixel_size); | |
646 output_pictures_.push_back( | 643 output_pictures_.push_back( |
647 std::make_pair( | 644 std::make_pair(assigned_picture_buffers_[i]->id(), omx_buffer)); |
648 reinterpret_cast<media::PictureBuffer*>( | |
649 assigned_picture_buffers_[i]), | |
650 buffer)); | |
651 buffer->pAppPrivate = picture; | |
652 } | 645 } |
653 } else { | 646 } else { |
654 for (uint32 i = 0; i < assigned_picture_buffers_.size(); i++) { | 647 for (uint32 i = 0; i < assigned_picture_buffers_.size(); i++) { |
655 picture = new media::Picture( | 648 media::SysmemBuffer* sysmem_buffer = |
656 reinterpret_cast<media::PictureBuffer*>(assigned_picture_buffers_[i]), | 649 reinterpret_cast<media::SysmemBuffer*>(assigned_picture_buffers_[i]); |
657 decoded_pixel_size, visible_pixel_size, | 650 OMX_BUFFERHEADERTYPE* omx_buffer; |
658 static_cast<void*>(component_handle_)); | 651 OMX_ERRORTYPE result = OMX_AllocateBuffer( |
659 | 652 component_handle_, &omx_buffer, output_port_, NULL, |
660 result = OMX_AllocateBuffer(component_handle_, &buffer, output_port_, | 653 output_buffer_size_); |
661 NULL, output_buffer_size_); | |
662 if (result != OMX_ErrorNone) | 654 if (result != OMX_ErrorNone) |
663 return false; | 655 return false; |
656 omx_buffer->pAppPrivate = new media::Picture( | |
657 sysmem_buffer->id(), | |
658 24 /* garbage bitstreambuffer id */, | |
659 decoded_pixel_size, visible_pixel_size); | |
664 output_pictures_.push_back( | 660 output_pictures_.push_back( |
665 std::make_pair( | 661 std::make_pair(sysmem_buffer->id(), omx_buffer)); |
666 reinterpret_cast<media::PictureBuffer*>( | |
667 assigned_picture_buffers_[i]), | |
668 buffer)); | |
669 buffer->pAppPrivate = picture; | |
670 } | 662 } |
671 } | 663 } |
672 return true; | 664 return true; |
673 } | 665 } |
674 | 666 |
675 void OmxVideoDecodeAccelerator::FreeInputBuffers() { | 667 void OmxVideoDecodeAccelerator::FreeInputBuffers() { |
676 // Calls to OMX to free buffers. | 668 // Calls to OMX to free buffers. |
677 OMX_ERRORTYPE result; | 669 OMX_ERRORTYPE result; |
678 OMX_BUFFERHEADERTYPE* omx_buffer; | 670 OMX_BUFFERHEADERTYPE* omx_buffer; |
679 for (int i = 0; i < input_buffer_count_; ++i) { | 671 for (int i = 0; i < input_buffer_count_; ++i) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
712 // In this case, the component detects PortSettingsChanged | 704 // In this case, the component detects PortSettingsChanged |
713 // and sends the particular event to the IL-client. | 705 // and sends the particular event to the IL-client. |
714 // This needs to be handled in this method. | 706 // This needs to be handled in this method. |
715 return; | 707 return; |
716 } | 708 } |
717 | 709 |
718 void OmxVideoDecodeAccelerator::FillBufferDoneTask( | 710 void OmxVideoDecodeAccelerator::FillBufferDoneTask( |
719 OMX_BUFFERHEADERTYPE* buffer) { | 711 OMX_BUFFERHEADERTYPE* buffer) { |
720 DCHECK_GT(output_buffers_at_component_, 0); | 712 DCHECK_GT(output_buffers_at_component_, 0); |
721 output_buffers_at_component_--; | 713 output_buffers_at_component_--; |
722 client_->PictureReady(reinterpret_cast<Picture*>(buffer->pAppPrivate)); | 714 client_->PictureReady(*reinterpret_cast<media::Picture*>( |
715 buffer->pAppPrivate)); | |
723 } | 716 } |
724 | 717 |
725 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( | 718 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( |
726 OMX_BUFFERHEADERTYPE* buffer) { | 719 OMX_BUFFERHEADERTYPE* buffer) { |
727 DCHECK_GT(input_buffers_at_component_, 0); | 720 DCHECK_GT(input_buffers_at_component_, 0); |
728 free_input_buffers_.push(buffer); | 721 free_input_buffers_.push(buffer); |
729 input_buffers_at_component_--; | 722 input_buffers_at_component_--; |
730 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) | 723 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) |
731 return; | 724 return; |
732 // Retrieve the corresponding callback and run it. | 725 // Retrieve the corresponding BitstreamBuffer's id and notify the client of |
733 OMXBufferCallbackMap::iterator it = omx_buff_cb_.find(buffer); | 726 // its completion. |
734 if (it == omx_buff_cb_.end()) { | 727 OMXBufferIdMap::iterator it = omx_buff_ids_.find(buffer); |
735 LOG(ERROR) << "Unexpectedly failed to find a buffer callback."; | 728 if (it == omx_buff_ids_.end()) { |
729 LOG(ERROR) << "Unexpectedly failed to find a buffer id."; | |
736 StopOnError(); | 730 StopOnError(); |
737 return; | 731 return; |
738 } | 732 } |
739 delete it->second.first; | 733 delete it->second.first; |
740 it->second.second.Run(); | 734 client_->NotifyEndOfBitstreamBuffer(it->second.second); |
741 omx_buff_cb_.erase(it); | 735 omx_buff_ids_.erase(it); |
742 } | 736 } |
743 | 737 |
744 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, | 738 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, |
745 OMX_U32 data1, | 739 OMX_U32 data1, |
746 OMX_U32 data2) { | 740 OMX_U32 data2) { |
747 switch (event) { | 741 switch (event) { |
748 case OMX_EventCmdComplete: { | 742 case OMX_EventCmdComplete: { |
749 // If the last command was successful, we have completed | 743 // If the last command was successful, we have completed |
750 // a state transition. So notify that we have done it | 744 // a state transition. So notify that we have done it |
751 // accordingly. | 745 // accordingly. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
803 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, | 797 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, |
804 OMX_PTR priv_data, | 798 OMX_PTR priv_data, |
805 OMX_EVENTTYPE event, | 799 OMX_EVENTTYPE event, |
806 OMX_U32 data1, | 800 OMX_U32 data1, |
807 OMX_U32 data2, | 801 OMX_U32 data2, |
808 OMX_PTR event_data) { | 802 OMX_PTR event_data) { |
809 OmxVideoDecodeAccelerator* decoder = | 803 OmxVideoDecodeAccelerator* decoder = |
810 static_cast<OmxVideoDecodeAccelerator*>(priv_data); | 804 static_cast<OmxVideoDecodeAccelerator*>(priv_data); |
811 DCHECK_EQ(component, decoder->component_handle_); | 805 DCHECK_EQ(component, decoder->component_handle_); |
812 | 806 |
813 decoder->message_loop_->PostTask(FROM_HERE, | 807 decoder->message_loop_->PostTask( |
814 NewRunnableMethod(decoder, | 808 FROM_HERE, |
815 &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, | 809 NewRunnableMethod(decoder, |
816 event, data1, data2)); | 810 &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, |
811 event, data1, data2)); | |
817 | 812 |
818 return OMX_ErrorNone; | 813 return OMX_ErrorNone; |
819 } | 814 } |
820 | 815 |
821 // static | 816 // static |
822 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( | 817 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( |
823 OMX_HANDLETYPE component, | 818 OMX_HANDLETYPE component, |
824 OMX_PTR priv_data, | 819 OMX_PTR priv_data, |
825 OMX_BUFFERHEADERTYPE* buffer) { | 820 OMX_BUFFERHEADERTYPE* buffer) { |
826 OmxVideoDecodeAccelerator* decoder = | 821 OmxVideoDecodeAccelerator* decoder = |
(...skipping 10 matching lines...) Expand all Loading... | |
837 | 832 |
838 // static | 833 // static |
839 OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback( | 834 OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback( |
840 OMX_HANDLETYPE component, | 835 OMX_HANDLETYPE component, |
841 OMX_PTR priv_data, | 836 OMX_PTR priv_data, |
842 OMX_BUFFERHEADERTYPE* buffer) { | 837 OMX_BUFFERHEADERTYPE* buffer) { |
843 OmxVideoDecodeAccelerator* decoder = | 838 OmxVideoDecodeAccelerator* decoder = |
844 static_cast<OmxVideoDecodeAccelerator*>(priv_data); | 839 static_cast<OmxVideoDecodeAccelerator*>(priv_data); |
845 DCHECK_EQ(component, decoder->component_handle_); | 840 DCHECK_EQ(component, decoder->component_handle_); |
846 | 841 |
847 decoder->message_loop_->PostTask(FROM_HERE, | 842 decoder->message_loop_->PostTask( |
843 FROM_HERE, | |
848 NewRunnableMethod( | 844 NewRunnableMethod( |
849 decoder, | 845 decoder, |
850 &OmxVideoDecodeAccelerator::FillBufferDoneTask, buffer)); | 846 &OmxVideoDecodeAccelerator::FillBufferDoneTask, buffer)); |
851 return OMX_ErrorNone; | 847 return OMX_ErrorNone; |
852 } | 848 } |
853 | 849 |
854 bool OmxVideoDecodeAccelerator::CanAcceptInput() { | 850 bool OmxVideoDecodeAccelerator::CanAcceptInput() { |
855 // We can't take input buffer when in error state. | 851 // We can't take input buffer when in error state. |
856 return (client_state_ != OMX_StateInvalid && | 852 return (client_state_ != OMX_StateInvalid && |
857 client_state_ != OMX_StatePause && | 853 client_state_ != OMX_StatePause && |
(...skipping 20 matching lines...) Expand all Loading... | |
878 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 874 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
879 cmd, port_index, 0); | 875 cmd, port_index, 0); |
880 if (result != OMX_ErrorNone) { | 876 if (result != OMX_ErrorNone) { |
881 LOG(ERROR) << "SendCommand(OMX_CommandPortDisable) failed"; | 877 LOG(ERROR) << "SendCommand(OMX_CommandPortDisable) failed"; |
882 StopOnError(); | 878 StopOnError(); |
883 return; | 879 return; |
884 } | 880 } |
885 } | 881 } |
886 | 882 |
887 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); | 883 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); |
OLD | NEW |