1 /**
2 * @copyright
3 *
4 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of The Linux Foundation nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28 * DAMAGE.
29 *
30 * @file
31 *
32 * omx_swvdec.cpp
33 *
34 * @brief
35 *
36 * OMX software video decoder component source.
37 */
38
39 #include <assert.h>
40 #include <fcntl.h>
41 #include <sys/mman.h>
42
43 #include <media/hardware/HardwareAPI.h>
44 #include <gralloc_priv.h>
45
46 #include "OMX_QCOMExtns.h"
47
48 #include "omx_swvdec.h"
49
50 #include "swvdec_api.h"
51
52 /**
53 * ----------------
54 * PUBLIC FUNCTIONS
55 * ----------------
56 */
57
58 /**
59 * @brief Create & return component class instance.
60 *
61 * @retval Pointer to new component class instance.
62 */
get_omx_component_factory_fn(void)63 void *get_omx_component_factory_fn(void)
64 {
65 return new omx_swvdec;
66 }
67
68 /**
69 * @brief Component constructor.
70 */
omx_swvdec()71 omx_swvdec::omx_swvdec():
72 m_state(OMX_StateInvalid),
73 m_status_flags(0),
74 m_swvdec_codec(SWVDEC_CODEC_INVALID),
75 m_swvdec_handle(NULL),
76 m_swvdec_created(false),
77 m_omx_video_codingtype(OMX_VIDEO_CodingUnused),
78 m_omx_color_formattype(OMX_COLOR_FormatUnused),
79 m_sync_frame_decoding_mode(false),
80 m_android_native_buffers(false),
81 m_meta_buffer_mode(false),
82 m_port_reconfig_inprogress(false),
83 m_buffer_array_ip(NULL),
84 m_buffer_array_op(NULL),
85 m_meta_buffer_array(NULL)
86 {
87 // memset all member variables that are composite structures
88 memset(&m_cmp, 0, sizeof(m_cmp)); // part of base class
89 memset(&m_cmp_name[0], 0, sizeof(m_cmp_name));
90 memset(&m_role_name[0], 0, sizeof(m_role_name));
91 memset(&m_frame_rate, 0, sizeof(m_frame_rate));
92 memset(&m_frame_dimensions, 0, sizeof(m_frame_dimensions));
93 memset(&m_frame_attributes, 0, sizeof(m_frame_attributes));
94 memset(&m_async_thread, 0, sizeof(m_async_thread));
95 memset(&m_port_ip, 0, sizeof(m_port_ip));
96 memset(&m_port_op, 0, sizeof(m_port_op));
97 memset(&m_callback, 0, sizeof(m_callback));
98 memset(&m_app_data, 0, sizeof(m_app_data));
99 memset(&m_prio_mgmt, 0, sizeof(m_prio_mgmt));
100 memset(&m_sem_cmd, 0, sizeof(m_sem_cmd));
101 memset(&m_meta_buffer_array_mutex, 0, sizeof(m_meta_buffer_array_mutex));
102
103 // null-terminate component name & role name strings
104 m_cmp_name[0] = '\0';
105 m_role_name[0] = '\0';
106
107 // ports are enabled & unpopulated by default
108 m_port_ip.enabled = OMX_TRUE;
109 m_port_op.enabled = OMX_TRUE;
110 m_port_ip.unpopulated = OMX_TRUE;
111 m_port_op.unpopulated = OMX_TRUE;
112 }
113
114 /**
115 * @brief Component destructor.
116 */
~omx_swvdec()117 omx_swvdec::~omx_swvdec()
118 {
119 }
120
121 /**
122 * @brief Initialize component.
123 *
124 * @param[in] cmp_name: Component name string.
125 *
126 * @retval OMX_ERRORTYPE
127 */
component_init(OMX_STRING cmp_name)128 OMX_ERRORTYPE omx_swvdec::component_init(OMX_STRING cmp_name)
129 {
130 OMX_ERRORTYPE retval = OMX_ErrorNone;
131
132 OMX_SWVDEC_LOG_API("'%s', version date: %s",
133 cmp_name,
134 OMX_SWVDEC_VERSION_DATE);
135
136 omx_swvdec_log_init();
137
138 if (m_state != OMX_StateInvalid)
139 {
140 OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
141 OMX_STATETYPE_STRING(m_state));
142 retval = OMX_ErrorIncorrectStateOperation;
143 goto component_init_exit;
144 }
145
146 // set up codec type variables based on component name string
147
148 if (!strncmp(cmp_name,
149 "OMX.qti.video.decoder.mpeg4sw",
150 OMX_MAX_STRINGNAME_SIZE))
151 {
152 OMX_SWVDEC_LOG_LOW("'video_decoder.mpeg4'");
153
154 strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE);
155 strlcpy(m_role_name, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
156
157 m_swvdec_codec = SWVDEC_CODEC_MPEG4;
158 m_omx_video_codingtype = OMX_VIDEO_CodingMPEG4;
159 }
160 else if (!strncmp(cmp_name,
161 "OMX.qti.video.decoder.h263sw",
162 OMX_MAX_STRINGNAME_SIZE))
163 {
164 OMX_SWVDEC_LOG_LOW("video_decoder.h263");
165
166 strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE);
167 strlcpy(m_role_name, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
168
169 m_swvdec_codec = SWVDEC_CODEC_H263;
170 m_omx_video_codingtype = OMX_VIDEO_CodingH263;
171 }
172 else if (((!strncmp(cmp_name,
173 "OMX.qti.video.decoder.divxsw",
174 OMX_MAX_STRINGNAME_SIZE))) ||
175 ((!strncmp(cmp_name,
176 "OMX.qti.video.decoder.divx4sw",
177 OMX_MAX_STRINGNAME_SIZE))))
178 {
179 OMX_SWVDEC_LOG_LOW("video_decoder.divx");
180
181 strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE);
182 strlcpy(m_role_name, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
183
184 m_swvdec_codec = SWVDEC_CODEC_MPEG4;
185 m_omx_video_codingtype = ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx);
186 }
187 else
188 {
189 OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name);
190 retval = OMX_ErrorInvalidComponentName;
191 goto component_init_exit;
192 }
193
194 m_omx_color_formattype =
195 (OMX_COLOR_FORMATTYPE) OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m;
196
197 m_frame_rate.fps_numerator = DEFAULT_FPS_NUMERATOR;
198 m_frame_rate.fps_denominator = DEFAULT_FPS_DENOMINATOR;
199
200 {
201 SWVDEC_CALLBACK callback;
202
203 SWVDEC_STATUS retval_swvdec;
204
205 // initialize SwVdec core library
206
207 callback.pfn_empty_buffer_done = swvdec_empty_buffer_done_callback;
208 callback.pfn_fill_buffer_done = swvdec_fill_buffer_done_callback;
209 callback.pfn_event_notification = swvdec_event_handler_callback;
210 callback.p_client = this;
211
212 if ((retval_swvdec = swvdec_init(&m_swvdec_handle,
213 m_swvdec_codec,
214 &callback)) !=
215 SWVDEC_STATUS_SUCCESS)
216 {
217 retval = retval_swvdec2omx(retval_swvdec);
218 goto component_init_exit;
219 }
220
221 m_swvdec_created = true;
222
223 // set frame dimensions for OMX component & SwVdec core
224 if ((retval = set_frame_dimensions(DEFAULT_FRAME_WIDTH,
225 DEFAULT_FRAME_HEIGHT)) !=
226 OMX_ErrorNone)
227 {
228 goto component_init_exit;
229 }
230
231 // set frame attributes for OMX component & SwVdec core
232 if ((retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
233 DEFAULT_ALIGNMENT_SCANLINES_Y,
234 DEFAULT_ALIGNMENT_SCANLINES_UV,
235 DEFAULT_ALIGNMENT_SIZE)) !=
236 OMX_ErrorNone)
237 {
238 goto component_init_exit;
239 }
240 }
241
242 // get SwVdec buffer requirements for input port; set m_port_ip
243 if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) !=
244 OMX_ErrorNone)
245 {
246 goto component_init_exit;
247 }
248
249 // get SwVdec buffer requirements for output port; set m_port_op
250 if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) !=
251 OMX_ErrorNone)
252 {
253 goto component_init_exit;
254 }
255
256 // create callback thread's mutex & condition variable
257 if ((retval = async_thread_create()) != OMX_ErrorNone)
258 {
259 goto component_init_exit;
260 }
261
262 // create semaphore for command processing
263 if (sem_init(&m_sem_cmd, 0, 0))
264 {
265 OMX_SWVDEC_LOG_ERROR("failed to create command processing semaphore");
266 retval = OMX_ErrorInsufficientResources;
267 goto component_init_exit;
268 }
269
270 // create mutex for meta buffer info array
271 if (pthread_mutex_init(&m_meta_buffer_array_mutex, NULL))
272 {
273 OMX_SWVDEC_LOG_ERROR("failed to create meta buffer info array mutex");
274 retval = OMX_ErrorInsufficientResources;
275 goto component_init_exit;
276 }
277
278 // move to 'loaded' state
279 OMX_SWVDEC_LOG_HIGH("OMX_StateInvalid -> OMX_StateLoaded");
280 m_state = OMX_StateLoaded;
281
282 component_init_exit:
283 return retval;
284 }
285
286 /**
287 * @brief De-initialize component.
288 *
289 * @param[in] cmp_handle: Component handle.
290 *
291 * @retval OMX_ERRORTYPE
292 */
component_deinit(OMX_HANDLETYPE cmp_handle)293 OMX_ERRORTYPE omx_swvdec::component_deinit(OMX_HANDLETYPE cmp_handle)
294 {
295 OMX_SWVDEC_LOG_API("");
296
297 if (cmp_handle == NULL)
298 {
299 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
300 }
301
302 pthread_mutex_destroy(&m_meta_buffer_array_mutex);
303
304 sem_destroy(&m_sem_cmd);
305
306 async_thread_destroy();
307
308 if (m_swvdec_created)
309 {
310 swvdec_deinit(m_swvdec_handle);
311 m_swvdec_handle = NULL;
312 }
313
314 OMX_SWVDEC_LOG_HIGH("all done, goodbye!");
315
316 return OMX_ErrorNone;
317 }
318
319 /**
320 * @brief Get component version.
321 *
322 * @param[in] cmp_handle: Component handle.
323 * @param[in] cmp_name: Component name string.
324 * @param[in,out] p_cmp_version: Pointer to component version variable.
325 * @param[in,out] p_spec_version: Pointer to OMX spec version variable.
326 * @param[in,out] p_cmp_UUID: Pointer to component UUID variable.
327 *
328 * @retval OMX_ERRORTYPE
329 */
get_component_version(OMX_HANDLETYPE cmp_handle,OMX_STRING cmp_name,OMX_VERSIONTYPE * p_cmp_version,OMX_VERSIONTYPE * p_spec_version,OMX_UUIDTYPE * p_cmp_UUID)330 OMX_ERRORTYPE omx_swvdec::get_component_version(OMX_HANDLETYPE cmp_handle,
331 OMX_STRING cmp_name,
332 OMX_VERSIONTYPE *p_cmp_version,
333 OMX_VERSIONTYPE *p_spec_version,
334 OMX_UUIDTYPE *p_cmp_UUID)
335 {
336 OMX_ERRORTYPE retval = OMX_ErrorNone;
337
338 (void) p_cmp_UUID;
339
340 OMX_SWVDEC_LOG_API("");
341
342 if (m_state == OMX_StateInvalid)
343 {
344 OMX_SWVDEC_LOG_ERROR("in invalid state");
345 retval = OMX_ErrorInvalidState;
346 }
347 else if (cmp_handle == NULL)
348 {
349 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
350 retval = OMX_ErrorInvalidComponent;
351 }
352 else if (strncmp(cmp_name, m_cmp_name, sizeof(m_cmp_name)))
353 {
354 OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name);
355 retval = OMX_ErrorInvalidComponentName;
356 }
357 else if (p_cmp_version == NULL)
358 {
359 OMX_SWVDEC_LOG_ERROR("p_cmp_version = NULL");
360 retval = OMX_ErrorBadParameter;
361 }
362 else if (p_spec_version == NULL)
363 {
364 OMX_SWVDEC_LOG_ERROR("p_spec_version = NULL");
365 retval = OMX_ErrorBadParameter;
366 }
367 else
368 {
369 p_spec_version->nVersion = OMX_SPEC_VERSION;
370 }
371
372 get_component_version_exit:
373 return retval;
374 }
375
376 /**
377 * @brief Send command to component.
378 *
379 * @param[in] cmp_handle: Component handle.
380 * @param[in] cmd: Command.
381 * @param[in] param: Command parameter.
382 * @param[in] p_cmd_data: Pointer to command data.
383 *
384 * @retval OMX_ERRORTYPE
385 */
send_command(OMX_HANDLETYPE cmp_handle,OMX_COMMANDTYPE cmd,OMX_U32 param,OMX_PTR p_cmd_data)386 OMX_ERRORTYPE omx_swvdec::send_command(OMX_HANDLETYPE cmp_handle,
387 OMX_COMMANDTYPE cmd,
388 OMX_U32 param,
389 OMX_PTR p_cmd_data)
390 {
391 OMX_ERRORTYPE retval = OMX_ErrorNone;
392
393 (void) p_cmd_data; // prevent warning for unused function argument
394
395 if (m_state == OMX_StateInvalid)
396 {
397 OMX_SWVDEC_LOG_ERROR("in invalid state");
398 retval = OMX_ErrorInvalidState;
399 goto send_command_exit;
400 }
401 else if (cmp_handle == NULL)
402 {
403 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
404 retval = OMX_ErrorInvalidComponent;
405 goto send_command_exit;
406 }
407
408 switch (cmd)
409 {
410
411 case OMX_CommandStateSet:
412 {
413 OMX_SWVDEC_LOG_API("%s, %s",
414 OMX_COMMANDTYPE_STRING(cmd),
415 OMX_STATETYPE_STRING((OMX_STATETYPE) param));
416 break;
417 }
418
419 case OMX_CommandFlush:
420 case OMX_CommandPortDisable:
421 case OMX_CommandPortEnable:
422 {
423 OMX_SWVDEC_LOG_API("%s, port index %d",
424 OMX_COMMANDTYPE_STRING(cmd),
425 param);
426
427 if ((param != OMX_CORE_PORT_INDEX_IP) &&
428 (param != OMX_CORE_PORT_INDEX_OP) &&
429 (param != OMX_ALL))
430 {
431 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", param);
432 retval = OMX_ErrorBadPortIndex;
433 }
434 break;
435 }
436
437 default:
438 {
439 OMX_SWVDEC_LOG_API("cmd %d, param %d", cmd, param);
440
441 OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", cmd);
442 retval = OMX_ErrorBadParameter;
443 break;
444 }
445
446 } // switch (cmd)
447
448 if (retval == OMX_ErrorNone)
449 {
450 if (cmp_handle == NULL)
451 {
452 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
453 retval = OMX_ErrorInvalidComponent;
454 }
455 else if (m_state == OMX_StateInvalid)
456 {
457 OMX_SWVDEC_LOG_ERROR("in invalid state");
458 retval = OMX_ErrorInvalidState;
459 }
460 }
461
462 if (retval != OMX_ErrorNone)
463 {
464 // command not processed; return error code via event handler callback
465 async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
466 }
467 else
468 {
469 // post command event
470 async_post_event(OMX_SWVDEC_EVENT_CMD, cmd, param);
471
472 // wait on command semaphore
473 sem_wait(&m_sem_cmd);
474 }
475
476 send_command_exit:
477 return retval;
478 }
479
480 /**
481 * @brief Get a parameter from component.
482 *
483 * @param[in] cmp_handle: Component handle.
484 * @param[in] param_index: Parameter index.
485 * @param[in,out] p_param_data: Pointer to parameter data.
486 *
487 * @retval OMX_ERRORTYPE
488 */
get_parameter(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE param_index,OMX_PTR p_param_data)489 OMX_ERRORTYPE omx_swvdec::get_parameter(OMX_HANDLETYPE cmp_handle,
490 OMX_INDEXTYPE param_index,
491 OMX_PTR p_param_data)
492 {
493 OMX_ERRORTYPE retval = OMX_ErrorNone;
494
495 if (m_state == OMX_StateInvalid)
496 {
497 OMX_SWVDEC_LOG_ERROR("in invalid state");
498 retval = OMX_ErrorInvalidState;
499 }
500 else if (cmp_handle == NULL)
501 {
502 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
503 retval = OMX_ErrorInvalidComponent;
504 }
505 else if (p_param_data == NULL)
506 {
507 OMX_SWVDEC_LOG_ERROR("p_param_data = NULL");
508 retval = OMX_ErrorBadParameter;
509 }
510
511 if (retval != OMX_ErrorNone)
512 {
513 goto get_parameter_exit;
514 }
515
516 switch (param_index)
517 {
518
519 case OMX_IndexParamAudioInit:
520 {
521 OMX_PORT_PARAM_TYPE *p_port_param =
522 (OMX_PORT_PARAM_TYPE *) p_param_data;
523
524 p_port_param->nPorts = 0;
525 p_port_param->nStartPortNumber = 0;
526
527 OMX_SWVDEC_LOG_API("OMX_IndexParamAudioInit: "
528 "%d port(s), start port %d",
529 p_port_param->nPorts,
530 p_port_param->nStartPortNumber);
531 break;
532 }
533
534 case OMX_IndexParamImageInit:
535 {
536 OMX_PORT_PARAM_TYPE *p_port_param =
537 (OMX_PORT_PARAM_TYPE *) p_param_data;
538
539 p_port_param->nPorts = 0;
540 p_port_param->nStartPortNumber = 0;
541
542 OMX_SWVDEC_LOG_API("OMX_IndexParamImageInit: "
543 "%d port(s), start port %d",
544 p_port_param->nPorts,
545 p_port_param->nStartPortNumber);
546 break;
547 }
548
549 case OMX_IndexParamVideoInit:
550 {
551 OMX_PORT_PARAM_TYPE *p_port_param =
552 (OMX_PORT_PARAM_TYPE *) p_param_data;
553
554 p_port_param->nPorts = 2;
555 p_port_param->nStartPortNumber = 0;
556
557 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoInit: "
558 "%d port(s), start port %d",
559 p_port_param->nPorts,
560 p_port_param->nStartPortNumber);
561 break;
562 }
563
564 case OMX_IndexParamOtherInit:
565 {
566 OMX_PORT_PARAM_TYPE *p_port_param =
567 (OMX_PORT_PARAM_TYPE *) p_param_data;
568
569 p_port_param->nPorts = 0;
570 p_port_param->nStartPortNumber = 0;
571
572 OMX_SWVDEC_LOG_API("OMX_IndexParamOtherInit: "
573 "%d port(s), start port %d",
574 p_port_param->nPorts,
575 p_port_param->nStartPortNumber);
576 break;
577 }
578
579 case OMX_IndexConfigPriorityMgmt:
580 {
581 OMX_PRIORITYMGMTTYPE *p_prio_mgmt =
582 (OMX_PRIORITYMGMTTYPE *) p_param_data;
583
584 OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt");
585
586 memcpy(p_prio_mgmt, &m_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE));
587 break;
588 }
589
590 case OMX_IndexParamStandardComponentRole:
591 {
592 OMX_PARAM_COMPONENTROLETYPE *p_cmp_role =
593 (OMX_PARAM_COMPONENTROLETYPE *) p_param_data;
594
595 strlcpy((char *) p_cmp_role->cRole,
596 m_role_name,
597 OMX_MAX_STRINGNAME_SIZE);
598
599 OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole: %s",
600 p_cmp_role->cRole);
601 break;
602 }
603
604 case OMX_IndexParamPortDefinition:
605 {
606 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def =
607 (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data;
608
609 OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d",
610 p_port_def->nPortIndex);
611
612 retval = get_port_definition(p_port_def);
613 break;
614 }
615
616 case OMX_IndexParamCompBufferSupplier:
617 {
618 OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier =
619 (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data;
620
621 OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier, port index %d",
622 p_buffer_supplier->nPortIndex);
623
624 if ((p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_IP) ||
625 (p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_OP))
626 {
627 p_buffer_supplier->eBufferSupplier = OMX_BufferSupplyUnspecified;
628 }
629 else
630 {
631 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
632 p_buffer_supplier->nPortIndex);
633 retval = OMX_ErrorBadPortIndex;
634 }
635
636 break;
637 }
638
639 case OMX_IndexParamVideoPortFormat:
640 {
641 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format =
642 (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data;
643
644 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, "
645 "port index %d, index %d",
646 p_port_format->nPortIndex,
647 p_port_format->nIndex);
648
649 retval = get_video_port_format(p_port_format);
650 break;
651 }
652
653 case OMX_IndexParamVideoMpeg2:
654 {
655 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2: unsupported");
656 retval = OMX_ErrorUnsupportedIndex;
657 break;
658 }
659
660 case OMX_IndexParamVideoMpeg4:
661 {
662 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4: unsupported");
663 retval = OMX_ErrorUnsupportedIndex;
664 break;
665 }
666
667 case OMX_IndexParamVideoAvc:
668 {
669 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc: unsupported");
670 retval = OMX_ErrorUnsupportedIndex;
671 break;
672 }
673
674 case OMX_IndexParamVideoH263:
675 {
676 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263: unsupported");
677 retval = OMX_ErrorUnsupportedIndex;
678 break;
679 }
680
681 case OMX_IndexParamVideoProfileLevelQuerySupported:
682 {
683 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel =
684 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) p_param_data;
685
686 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoProfileLevelQuerySupported, "
687 "port index %d, profile index %d",
688 p_profilelevel->nPortIndex,
689 p_profilelevel->nProfileIndex);
690
691 retval = get_supported_profilelevel(p_profilelevel);
692 break;
693 }
694
695 default:
696 {
697 /**
698 * Vendor-specific extension indices checked here since they are not
699 * part of the OMX_INDEXTYPE enumerated type.
700 */
701
702 switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
703 {
704
705 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
706 {
707 GetAndroidNativeBufferUsageParams *p_buffer_usage =
708 (GetAndroidNativeBufferUsageParams *) p_param_data;
709
710 OMX_SWVDEC_LOG_API(
711 "OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage, "
712 "port index %d", p_buffer_usage->nPortIndex);
713
714 if (p_buffer_usage->nPortIndex == OMX_CORE_PORT_INDEX_OP)
715 {
716 p_buffer_usage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
717 GRALLOC_USAGE_SW_READ_OFTEN |
718 GRALLOC_USAGE_SW_WRITE_OFTEN);
719 }
720 else
721 {
722 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
723 p_buffer_usage->nPortIndex);
724 retval = OMX_ErrorBadPortIndex;
725 }
726 break;
727 }
728
729 case OMX_QcomIndexFlexibleYUVDescription:
730 {
731 OMX_SWVDEC_LOG_API("OMX_QcomIndexFlexibleYUVDescription");
732
733 retval = describe_color_format((DescribeColorFormatParams *)
734 p_param_data);
735 break;
736 }
737
738 default:
739 {
740 OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid");
741 retval = OMX_ErrorBadParameter;
742 break;
743 }
744
745 } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
746
747 } // default case
748
749 } // switch (param_index)
750
751 get_parameter_exit:
752 return retval;
753 }
754
755 /**
756 * @brief Set a parameter to component.
757 *
758 * @param[in] cmp_handle: Component handle.
759 * @param[in] param_index: Parameter index.
760 * @param[in] p_param_data: Pointer to parameter data.
761 *
762 * @retval OMX_ERRORTYPE
763 */
set_parameter(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE param_index,OMX_PTR p_param_data)764 OMX_ERRORTYPE omx_swvdec::set_parameter(OMX_HANDLETYPE cmp_handle,
765 OMX_INDEXTYPE param_index,
766 OMX_PTR p_param_data)
767 {
768 OMX_ERRORTYPE retval = OMX_ErrorNone;
769
770 if (m_state == OMX_StateInvalid)
771 {
772 OMX_SWVDEC_LOG_ERROR("in invalid state");
773 retval = OMX_ErrorInvalidState;
774 }
775 else if (cmp_handle == NULL)
776 {
777 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
778 retval = OMX_ErrorInvalidComponent;
779 }
780 else if (p_param_data == NULL)
781 {
782 OMX_SWVDEC_LOG_ERROR("p_param_data = NULL");
783 retval = OMX_ErrorBadParameter;
784 }
785 else if ((m_state != OMX_StateLoaded) &&
786 (m_port_reconfig_inprogress == false))
787 {
788 OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
789 OMX_STATETYPE_STRING(m_state));
790 retval = OMX_ErrorIncorrectStateOperation;
791 }
792
793 if (retval != OMX_ErrorNone)
794 {
795 goto set_parameter_exit;
796 }
797
798 switch (param_index)
799 {
800
801 case OMX_IndexParamPriorityMgmt:
802 {
803 OMX_PRIORITYMGMTTYPE *p_prio_mgmt =
804 (OMX_PRIORITYMGMTTYPE *) p_param_data;
805
806 OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt: "
807 "group ID %d, group priority %d",
808 p_prio_mgmt->nGroupID,
809 p_prio_mgmt->nGroupPriority);
810
811 if (m_state != OMX_StateLoaded)
812 {
813 OMX_SWVDEC_LOG_ERROR("'%d' state invalid; "
814 "should be in loaded state",
815 m_state);
816 retval = OMX_ErrorIncorrectStateOperation;
817 }
818 else
819 {
820 memcpy(&m_prio_mgmt, p_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE));
821 }
822
823 break;
824 }
825
826 case OMX_IndexParamStandardComponentRole:
827 {
828 OMX_PARAM_COMPONENTROLETYPE *p_cmp_role =
829 (OMX_PARAM_COMPONENTROLETYPE *) p_param_data;
830
831 OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole '%s'",
832 p_cmp_role->cRole);
833
834 if (m_state != OMX_StateLoaded)
835 {
836 OMX_SWVDEC_LOG_ERROR("'%d' state invalid; "
837 "should be in loaded state",
838 m_state);
839 retval = OMX_ErrorIncorrectStateOperation;
840 }
841 else
842 {
843 if (strncmp((char *) p_cmp_role->cRole,
844 m_role_name,
845 OMX_MAX_STRINGNAME_SIZE))
846 {
847 OMX_SWVDEC_LOG_ERROR("'%s': invalid component role name",
848 p_cmp_role->cRole);
849 retval = OMX_ErrorBadParameter;
850 }
851 }
852
853 break;
854 }
855
856 case OMX_IndexParamPortDefinition:
857 {
858 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def =
859 (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data;
860
861 OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d",
862 p_port_def->nPortIndex);
863
864 if ((m_state != OMX_StateLoaded) &&
865 (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
866 (m_port_ip.enabled == OMX_TRUE) &&
867 (m_port_ip.populated == OMX_TRUE)) ||
868 ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
869 (m_port_op.enabled == OMX_TRUE) &&
870 (m_port_op.populated == OMX_TRUE))))
871 {
872 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamPortDefinition "
873 "disallowed in state %s "
874 "while port %d is enabled & populated",
875 OMX_STATETYPE_STRING(m_state),
876 p_port_def->nPortIndex);
877
878 retval = OMX_ErrorIncorrectStateOperation;
879 }
880 else
881 {
882 retval = set_port_definition(p_port_def);
883 }
884
885 break;
886 }
887
888 case OMX_IndexParamCompBufferSupplier:
889 {
890 OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier =
891 (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data;
892
893 OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier: "
894 "port index %d, buffer supplier %d",
895 p_buffer_supplier->nPortIndex,
896 (int) p_buffer_supplier->eBufferSupplier);
897
898 if ((p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_IP) &&
899 (p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_OP))
900 {
901 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
902 p_buffer_supplier->nPortIndex);
903 retval = OMX_ErrorBadPortIndex;
904 }
905
906 break;
907 }
908
909 case OMX_IndexParamVideoPortFormat:
910 {
911 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format =
912 (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data;
913
914 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, port index %d",
915 p_port_format->nPortIndex);
916
917 if ((m_state != OMX_StateLoaded) &&
918 (((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
919 (m_port_ip.enabled == OMX_TRUE) &&
920 (m_port_ip.populated == OMX_TRUE)) ||
921 ((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
922 (m_port_op.enabled == OMX_TRUE) &&
923 (m_port_op.populated == OMX_TRUE))))
924 {
925 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoPortFormat "
926 "disallowed in state %s "
927 "while port %d is enabled & populated",
928 OMX_STATETYPE_STRING(m_state),
929 p_port_format->nPortIndex);
930
931 retval = OMX_ErrorIncorrectStateOperation;
932 }
933 else
934 {
935 retval = set_video_port_format(p_port_format);
936 }
937
938 break;
939 }
940
941 case OMX_IndexParamVideoMpeg2:
942 {
943 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2 unsupported");
944 retval = OMX_ErrorUnsupportedIndex;
945 break;
946 }
947
948 case OMX_IndexParamVideoMpeg4:
949 {
950 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4 unsupported");
951 retval = OMX_ErrorUnsupportedIndex;
952 break;
953 }
954
955 case OMX_IndexParamVideoAvc:
956 {
957 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc unsupported");
958 retval = OMX_ErrorUnsupportedIndex;
959 break;
960 }
961
962 case OMX_IndexParamVideoH263:
963 {
964 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263 unsupported");
965 retval = OMX_ErrorUnsupportedIndex;
966 break;
967 }
968
969 default:
970 {
971 /**
972 * Vendor-specific extension indices checked here since they are not
973 * part of the OMX_INDEXTYPE enumerated type.
974 */
975
976 switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
977 {
978
979 case OMX_QcomIndexPortDefn:
980 {
981 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def =
982 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) p_param_data;
983
984 OMX_SWVDEC_LOG_API("OMX_QcomIndexPortDefn, port index %d",
985 p_port_def->nPortIndex);
986
987 if ((m_state != OMX_StateLoaded) &&
988 (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
989 (m_port_ip.enabled == OMX_TRUE) &&
990 (m_port_ip.populated == OMX_TRUE)) ||
991 ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
992 (m_port_op.enabled == OMX_TRUE) &&
993 (m_port_op.populated == OMX_TRUE))))
994 {
995 OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexPortDefn "
996 "disallowed in state %s "
997 "while port %d is enabled & populated",
998 OMX_STATETYPE_STRING(m_state),
999 p_port_def->nPortIndex);
1000
1001 retval = OMX_ErrorIncorrectStateOperation;
1002 }
1003 else
1004 {
1005 retval = set_port_definition_qcom(p_port_def);
1006 }
1007
1008 break;
1009 }
1010
1011 case OMX_QcomIndexParamVideoDivx:
1012 {
1013 OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoDivx");
1014 OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexParamVideoDivx unsupported");
1015 retval = OMX_ErrorUnsupportedIndex;
1016 break;
1017 }
1018
1019 case OMX_QcomIndexParamVideoSyncFrameDecodingMode:
1020 {
1021 OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoSyncFrameDecodingMode");
1022 m_sync_frame_decoding_mode = true;
1023 break;
1024 }
1025
1026 case OMX_QcomIndexParamVideoDecoderPictureOrder:
1027 {
1028 QOMX_VIDEO_DECODER_PICTURE_ORDER *p_picture_order =
1029 (QOMX_VIDEO_DECODER_PICTURE_ORDER *) p_param_data;
1030
1031 switch (p_picture_order->eOutputPictureOrder)
1032 {
1033
1034 case QOMX_VIDEO_DISPLAY_ORDER:
1035 {
1036 OMX_SWVDEC_LOG_API(
1037 "OMX_QcomIndexParamVideoDecoderPictureOrder, "
1038 "QOMX_VIDEO_DISPLAY_ORDER");
1039 break;
1040 }
1041
1042 case QOMX_VIDEO_DECODE_ORDER:
1043 {
1044 OMX_SWVDEC_LOG_ERROR(
1045 "OMX_QcomIndexParamVideoDecoderPictureOrder, "
1046 "QOMX_VIDEO_DECODE_ORDER; unsupported");
1047
1048 retval = OMX_ErrorUnsupportedSetting;
1049 break;
1050 }
1051
1052 default:
1053 {
1054 OMX_SWVDEC_LOG_ERROR(
1055 "OMX_QcomIndexParamVideoDecoderPictureOrder, %d; invalid");
1056
1057 retval = OMX_ErrorBadParameter;
1058 break;
1059 }
1060
1061 }
1062 break;
1063 }
1064
1065 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
1066 {
1067 OMX_SWVDEC_LOG_API(
1068 "OMX_GoogleAndroidIndexEnableAndroidNativeBuffers, %s",
1069 (((EnableAndroidNativeBuffersParams *) p_param_data)->enable ?
1070 "enable" :
1071 "disable"));
1072
1073 m_android_native_buffers =
1074 (bool) (((EnableAndroidNativeBuffersParams *)
1075 p_param_data)->enable);
1076
1077 break;
1078 }
1079
1080 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
1081 {
1082 OMX_SWVDEC_LOG_ERROR("OMX_GoogleAndroidIndexUseAndroidNativeBuffer "
1083 "unsupported");
1084
1085 retval = OMX_ErrorUnsupportedIndex;
1086 break;
1087 }
1088
1089 case OMX_QcomIndexParamEnableTimeStampReorder:
1090 {
1091 OMX_SWVDEC_LOG_API(
1092 "OMX_QcomIndexParamEnableTimeStampReorder, %s",
1093 (((QOMX_INDEXTIMESTAMPREORDER *) p_param_data)->bEnable ?
1094 "enable" :
1095 "disable"));
1096
1097 break;
1098 }
1099
1100 case OMX_QcomIndexParamVideoMetaBufferMode:
1101 {
1102 StoreMetaDataInBuffersParams *p_meta_data =
1103 (StoreMetaDataInBuffersParams *) p_param_data;
1104
1105 OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoMetaBufferMode, "
1106 "port index %d, %s",
1107 p_meta_data->nPortIndex,
1108 (p_meta_data->bStoreMetaData ?
1109 "enabled" :
1110 "disabled"));
1111
1112 if (p_meta_data->nPortIndex == OMX_CORE_PORT_INDEX_OP)
1113 {
1114 m_meta_buffer_mode = (bool) p_meta_data->bStoreMetaData;
1115 }
1116 else
1117 {
1118 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1119 p_meta_data->nPortIndex);
1120 retval = OMX_ErrorBadPortIndex;
1121 }
1122
1123 break;
1124 }
1125
1126 default:
1127 {
1128 OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid");
1129 retval = OMX_ErrorBadParameter;
1130 break;
1131 }
1132
1133 } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
1134
1135 break;
1136 } // default case
1137
1138 } // switch (param_index)
1139
1140 set_parameter_exit:
1141 return retval;
1142 }
1143
1144 /**
1145 * @brief Get a configuration from component.
1146 *
1147 * @param[in] cmp_handle: Component handle.
1148 * @param[in] config_index: Configuration index.
1149 * @param[in] p_config_data: Pointer to configuration data.
1150 *
1151 * @retval OMX_ERRORTYPE
1152 */
get_config(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE config_index,OMX_PTR p_config_data)1153 OMX_ERRORTYPE omx_swvdec::get_config(OMX_HANDLETYPE cmp_handle,
1154 OMX_INDEXTYPE config_index,
1155 OMX_PTR p_config_data)
1156 {
1157 OMX_ERRORTYPE retval = OMX_ErrorNone;
1158
1159 if (m_state == OMX_StateInvalid)
1160 {
1161 OMX_SWVDEC_LOG_ERROR("in invalid state");
1162 retval = OMX_ErrorInvalidState;
1163 goto get_config_exit;
1164 }
1165 else if (cmp_handle == NULL)
1166 {
1167 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1168 retval = OMX_ErrorInvalidComponent;
1169 goto get_config_exit;
1170 }
1171 else if (p_config_data == NULL)
1172 {
1173 OMX_SWVDEC_LOG_ERROR("p_config_data = NULL");
1174 retval = OMX_ErrorBadParameter;
1175 goto get_config_exit;
1176 }
1177
1178 switch (config_index)
1179 {
1180
1181 case OMX_IndexConfigCommonOutputCrop:
1182 {
1183 OMX_CONFIG_RECTTYPE *p_recttype = (OMX_CONFIG_RECTTYPE *) p_config_data;
1184
1185 OMX_SWVDEC_LOG_API("OMX_IndexConfigCommonOutputCrop, port index %d",
1186 p_recttype->nPortIndex);
1187
1188 if (p_recttype->nPortIndex == OMX_CORE_PORT_INDEX_OP)
1189 {
1190 p_recttype->nLeft = 0;
1191 p_recttype->nTop = 0;
1192 p_recttype->nWidth = m_frame_dimensions.width;
1193 p_recttype->nHeight = m_frame_dimensions.height;
1194 }
1195 else
1196 {
1197 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1198 p_recttype->nPortIndex);
1199 retval = OMX_ErrorBadPortIndex;
1200 }
1201
1202 break;
1203 }
1204
1205 default:
1206 {
1207 switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index)
1208 {
1209
1210 case OMX_QcomIndexConfigInterlaced:
1211 {
1212 OMX_QCOM_CONFIG_INTERLACETYPE *p_config_interlacetype =
1213 (OMX_QCOM_CONFIG_INTERLACETYPE *) p_config_data;
1214
1215 OMX_SWVDEC_LOG_API("OMX_QcomIndexConfigInterlaced, "
1216 "port index %d, index %d",
1217 p_config_interlacetype->nPortIndex,
1218 p_config_interlacetype->nIndex);
1219
1220 if (p_config_interlacetype->nPortIndex == OMX_CORE_PORT_INDEX_OP)
1221 {
1222 if (p_config_interlacetype->nIndex == 0)
1223 {
1224 p_config_interlacetype->eInterlaceType =
1225 OMX_QCOM_InterlaceFrameProgressive;
1226 }
1227 else if (p_config_interlacetype->nIndex == 1)
1228 {
1229 p_config_interlacetype->eInterlaceType =
1230 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
1231 }
1232 else if (p_config_interlacetype->nIndex == 2)
1233 {
1234 p_config_interlacetype->eInterlaceType =
1235 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
1236 }
1237 else
1238 {
1239 OMX_SWVDEC_LOG_ERROR("index '%d' unsupported; "
1240 "no more interlaced types",
1241 p_config_interlacetype->nIndex);
1242 retval = OMX_ErrorNoMore;
1243 }
1244 }
1245 else
1246 {
1247 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1248 p_config_interlacetype->nPortIndex);
1249 retval = OMX_ErrorBadPortIndex;
1250 }
1251
1252 break;
1253 }
1254
1255 case OMX_QcomIndexQueryNumberOfVideoDecInstance:
1256 {
1257 QOMX_VIDEO_QUERY_DECODER_INSTANCES *p_decoder_instances =
1258 (QOMX_VIDEO_QUERY_DECODER_INSTANCES *) p_config_data;
1259
1260 OMX_SWVDEC_LOG_API("OMX_QcomIndexQueryNumberOfVideoDecInstance");
1261
1262 p_decoder_instances->nNumOfInstances = OMX_SWVDEC_NUM_INSTANCES;
1263 break;
1264 }
1265
1266 case OMX_QcomIndexConfigVideoFramePackingArrangement:
1267 {
1268 OMX_SWVDEC_LOG_API(
1269 "OMX_QcomIndexConfigVideoFramePackingArrangement");
1270
1271 OMX_SWVDEC_LOG_ERROR(
1272 "OMX_QcomIndexConfigVideoFramePackingArrangement unsupported");
1273
1274 retval = OMX_ErrorUnsupportedIndex;
1275 break;
1276 }
1277
1278 default:
1279 {
1280 OMX_SWVDEC_LOG_ERROR("config index '%d' invalid", config_index);
1281 retval = OMX_ErrorBadParameter;
1282 break;
1283 }
1284
1285 } // switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index)
1286
1287 break;
1288 }
1289
1290 } // switch (config_index)
1291
1292 get_config_exit:
1293 return retval;
1294 }
1295
1296 /**
1297 * @brief Set a configuration to component.
1298 *
1299 * @retval OMX_ERRORTYPE
1300 */
set_config(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE config_index,OMX_PTR p_config_data)1301 OMX_ERRORTYPE omx_swvdec::set_config(OMX_HANDLETYPE cmp_handle,
1302 OMX_INDEXTYPE config_index,
1303 OMX_PTR p_config_data)
1304 {
1305 (void) cmp_handle;
1306 (void) config_index;
1307 (void) p_config_data;
1308
1309 OMX_SWVDEC_LOG_ERROR("not implemented");
1310
1311 return OMX_ErrorNotImplemented;
1312 }
1313
1314 /**
1315 * @brief Translate a vendor-specific extension string to a standard index type.
1316 *
1317 * @param[in] cmp_handle: Component handle.
1318 * @param[in] param_name: Parameter name (extension string).
1319 * @param[in,out] p_index_type: Pointer to extension string's index type.
1320 *
1321 * @retval OMX_ERRORTYPE
1322 */
get_extension_index(OMX_HANDLETYPE cmp_handle,OMX_STRING param_name,OMX_INDEXTYPE * p_index_type)1323 OMX_ERRORTYPE omx_swvdec::get_extension_index(OMX_HANDLETYPE cmp_handle,
1324 OMX_STRING param_name,
1325 OMX_INDEXTYPE *p_index_type)
1326 {
1327 OMX_ERRORTYPE retval = OMX_ErrorNone;
1328
1329 if (m_state == OMX_StateInvalid)
1330 {
1331 OMX_SWVDEC_LOG_ERROR("in invalid state");
1332 retval = OMX_ErrorInvalidState;
1333 }
1334 else if (cmp_handle == NULL)
1335 {
1336 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1337 retval = OMX_ErrorInvalidComponent;
1338 }
1339 else if (p_index_type == NULL)
1340 {
1341 OMX_SWVDEC_LOG_ERROR("p_index_type = NULL");
1342 retval = OMX_ErrorBadParameter;
1343 }
1344
1345 if (retval != OMX_ErrorNone)
1346 goto get_extension_index_exit;
1347
1348 OMX_SWVDEC_LOG_API("'%s'", param_name);
1349
1350 if (!strncmp(param_name,
1351 "OMX.QCOM.index.param.video.SyncFrameDecodingMode",
1352 OMX_MAX_STRINGNAME_SIZE))
1353 {
1354 *p_index_type =
1355 (OMX_INDEXTYPE) OMX_QcomIndexParamVideoSyncFrameDecodingMode;
1356 }
1357 else if (!strncmp(param_name,
1358 "OMX.QCOM.index.param.IndexExtraData",
1359 OMX_MAX_STRINGNAME_SIZE))
1360 {
1361 *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamIndexExtraDataType;
1362 }
1363 else if (!strncmp(param_name,
1364 "OMX.google.android.index.enableAndroidNativeBuffers",
1365 OMX_MAX_STRINGNAME_SIZE))
1366 {
1367 *p_index_type =
1368 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
1369 }
1370 else if (!strncmp(param_name,
1371 "OMX.google.android.index.useAndroidNativeBuffer2",
1372 OMX_MAX_STRINGNAME_SIZE))
1373 {
1374 *p_index_type =
1375 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
1376 }
1377 else if (!strncmp(param_name,
1378 "OMX.google.android.index.useAndroidNativeBuffer",
1379 OMX_MAX_STRINGNAME_SIZE))
1380 {
1381 *p_index_type =
1382 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
1383 }
1384 else if (!strncmp(param_name,
1385 "OMX.google.android.index.getAndroidNativeBufferUsage",
1386 OMX_MAX_STRINGNAME_SIZE))
1387 {
1388 *p_index_type =
1389 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
1390 }
1391 else if (!strncmp(param_name,
1392 "OMX.google.android.index.storeMetaDataInBuffers",
1393 OMX_MAX_STRINGNAME_SIZE))
1394 {
1395 *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamVideoMetaBufferMode;
1396 }
1397 else if (!strncmp(param_name,
1398 "OMX.google.android.index.describeColorFormat",
1399 OMX_MAX_STRINGNAME_SIZE))
1400 {
1401 *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexFlexibleYUVDescription;
1402 }
1403 else
1404 {
1405 OMX_SWVDEC_LOG_ERROR("'%s': not implemented", param_name);
1406 retval = OMX_ErrorNotImplemented;
1407 }
1408
1409 get_extension_index_exit:
1410 return retval;
1411 }
1412
1413 /**
1414 * @brief Get component state.
1415 *
1416 * @param[in] cmp_handle: Component handle.
1417 * @param[in,out] p_state: Pointer to state variable.
1418 *
1419 * @retval OMX_ERRORTYPE
1420 */
get_state(OMX_HANDLETYPE cmp_handle,OMX_STATETYPE * p_state)1421 OMX_ERRORTYPE omx_swvdec::get_state(OMX_HANDLETYPE cmp_handle,
1422 OMX_STATETYPE *p_state)
1423 {
1424 OMX_ERRORTYPE retval = OMX_ErrorNone;
1425
1426 if (cmp_handle == NULL)
1427 {
1428 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1429 retval = OMX_ErrorInvalidComponent;
1430 }
1431 else
1432 {
1433 OMX_SWVDEC_LOG_API("%s", OMX_STATETYPE_STRING(m_state));
1434 *p_state = m_state;
1435 }
1436
1437 return retval;
1438 }
1439
1440 /**
1441 * @brief Component tunnel request.
1442 *
1443 * @retval OMX_ErrorNotImplemented
1444 */
component_tunnel_request(OMX_HANDLETYPE cmp_handle,OMX_U32 port,OMX_HANDLETYPE peer_component,OMX_U32 peer_port,OMX_TUNNELSETUPTYPE * p_tunnel_setup)1445 OMX_ERRORTYPE omx_swvdec::component_tunnel_request(
1446 OMX_HANDLETYPE cmp_handle,
1447 OMX_U32 port,
1448 OMX_HANDLETYPE peer_component,
1449 OMX_U32 peer_port,
1450 OMX_TUNNELSETUPTYPE *p_tunnel_setup)
1451 {
1452 (void) cmp_handle;
1453 (void) port;
1454 (void) peer_component;
1455 (void) peer_port;
1456 (void) p_tunnel_setup;
1457
1458 OMX_SWVDEC_LOG_API("");
1459
1460 OMX_SWVDEC_LOG_ERROR("not implemented");
1461
1462 return OMX_ErrorNotImplemented;
1463 }
1464
1465 /**
1466 * @brief Use buffer.
1467 *
1468 * @param[in] cmp_handle: Component handle.
1469 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
1470 * structure.
1471 * @param[in] port: Port index.
1472 * @param[in] p_app_data: Pointer to IL client app data.
1473 * @param[in] bytes: Size of buffer to be allocated in bytes.
1474 * @param[in] p_buffer: Pointer to buffer to be used.
1475 *
1476 * @retval OMX_ERRORTYPE
1477 */
use_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_U32 port,OMX_PTR p_app_data,OMX_U32 bytes,OMX_U8 * p_buffer)1478 OMX_ERRORTYPE omx_swvdec::use_buffer(OMX_HANDLETYPE cmp_handle,
1479 OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
1480 OMX_U32 port,
1481 OMX_PTR p_app_data,
1482 OMX_U32 bytes,
1483 OMX_U8 *p_buffer)
1484 {
1485 OMX_ERRORTYPE retval = OMX_ErrorNone;
1486
1487 if (m_state == OMX_StateInvalid)
1488 {
1489 OMX_SWVDEC_LOG_ERROR("in invalid state");
1490 retval = OMX_ErrorInvalidState;
1491 }
1492 else if (cmp_handle == NULL)
1493 {
1494 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1495 retval = OMX_ErrorInvalidComponent;
1496 }
1497 else if (pp_buffer_hdr == NULL)
1498 {
1499 OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL");
1500 retval = OMX_ErrorBadParameter;
1501 }
1502 else
1503 {
1504 OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer);
1505
1506 if (port == OMX_CORE_PORT_INDEX_OP)
1507 {
1508 retval = buffer_use_op(pp_buffer_hdr, p_app_data, bytes, p_buffer);
1509
1510 if (retval == OMX_ErrorNone)
1511 {
1512 SWVDEC_STATUS retval_swvdec;
1513
1514 if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) &&
1515 (m_port_ip.populated == OMX_TRUE) &&
1516 (m_port_op.populated == OMX_TRUE))
1517 {
1518 // start SwVdec
1519 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1520 SWVDEC_STATUS_SUCCESS)
1521 {
1522 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1523 retval = retval_swvdec2omx(retval_swvdec);
1524 goto use_buffer_exit;
1525 }
1526
1527 m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE);
1528
1529 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1530 OMX_CommandStateSet,
1531 OMX_StateIdle);
1532 }
1533
1534 if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) &&
1535 (m_port_op.populated == OMX_TRUE))
1536 {
1537 if (m_port_reconfig_inprogress)
1538 {
1539 // start SwVdec
1540 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1541 SWVDEC_STATUS_SUCCESS)
1542 {
1543 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1544 retval = retval_swvdec2omx(retval_swvdec);
1545 }
1546 }
1547
1548 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP);
1549
1550 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1551 OMX_CommandPortEnable,
1552 OMX_CORE_PORT_INDEX_OP);
1553 }
1554 }
1555 }
1556 else
1557 {
1558 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port);
1559 retval = OMX_ErrorBadPortIndex;
1560 }
1561 }
1562
1563 use_buffer_exit:
1564 return retval;
1565 }
1566
1567 /**
1568 * @brief Allocate new buffer & associated header.
1569 *
1570 * @param[in] cmp_handle: Component handle.
1571 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
1572 * structure.
1573 * @param[in] port: Port index.
1574 * @param[in] p_app_data: Pointer to IL client app data.
1575 * @param[in] bytes: Size of buffer to be allocated in bytes.
1576 *
1577 * @retval OMX_ERRORTYPE
1578 */
allocate_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_U32 port,OMX_PTR p_app_data,OMX_U32 bytes)1579 OMX_ERRORTYPE omx_swvdec::allocate_buffer(OMX_HANDLETYPE cmp_handle,
1580 OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
1581 OMX_U32 port,
1582 OMX_PTR p_app_data,
1583 OMX_U32 bytes)
1584 {
1585 OMX_ERRORTYPE retval = OMX_ErrorNone;
1586
1587 if (m_state == OMX_StateInvalid)
1588 {
1589 OMX_SWVDEC_LOG_ERROR("in invalid state");
1590 retval = OMX_ErrorInvalidState;
1591 }
1592 else if (cmp_handle == NULL)
1593 {
1594 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1595 retval = OMX_ErrorInvalidComponent;
1596 }
1597 else if (pp_buffer_hdr == NULL)
1598 {
1599 OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL");
1600 retval = OMX_ErrorBadParameter;
1601 }
1602 else
1603 {
1604 OMX_SWVDEC_LOG_API("port index %d, %d bytes", port, bytes);
1605
1606 if (port == OMX_CORE_PORT_INDEX_IP)
1607 {
1608 retval = buffer_allocate_ip(pp_buffer_hdr,
1609 p_app_data,
1610 bytes);
1611 }
1612 else if (port == OMX_CORE_PORT_INDEX_OP)
1613 {
1614 if (m_meta_buffer_mode == true)
1615 {
1616 OMX_SWVDEC_LOG_ERROR("'meta buffer mode' enabled");
1617 retval = OMX_ErrorBadParameter;
1618 }
1619 else if (m_android_native_buffers == true)
1620 {
1621 OMX_SWVDEC_LOG_ERROR("'android native buffers' enabled");
1622 retval = OMX_ErrorBadParameter;
1623 }
1624 else
1625 {
1626 retval = buffer_allocate_op(pp_buffer_hdr,
1627 p_app_data,
1628 bytes);
1629 }
1630 }
1631 else
1632 {
1633 OMX_SWVDEC_LOG_ERROR("port index %d invalid", port);
1634 retval = OMX_ErrorBadPortIndex;
1635 }
1636
1637 if (retval == OMX_ErrorNone)
1638 {
1639 SWVDEC_STATUS retval_swvdec;
1640
1641 if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) &&
1642 (m_port_ip.populated == OMX_TRUE) &&
1643 (m_port_op.populated == OMX_TRUE))
1644 {
1645 // start SwVdec
1646 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1647 SWVDEC_STATUS_SUCCESS)
1648 {
1649 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1650 retval = retval_swvdec2omx(retval_swvdec);
1651 goto allocate_buffer_exit;
1652 }
1653
1654 m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE);
1655
1656 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1657 OMX_CommandStateSet,
1658 OMX_StateIdle);
1659 }
1660
1661 if ((m_status_flags & (1 << PENDING_PORT_ENABLE_IP)) &&
1662 (m_port_ip.populated == OMX_TRUE))
1663 {
1664 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_IP);
1665
1666 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1667 OMX_CommandPortEnable,
1668 OMX_CORE_PORT_INDEX_IP);
1669 }
1670
1671 if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) &&
1672 (m_port_op.populated == OMX_TRUE))
1673 {
1674 if (m_port_reconfig_inprogress)
1675 {
1676 // start SwVdec
1677 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1678 SWVDEC_STATUS_SUCCESS)
1679 {
1680 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1681 retval = retval_swvdec2omx(retval_swvdec);
1682 }
1683 }
1684
1685 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP);
1686
1687 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1688 OMX_CommandPortEnable,
1689 OMX_CORE_PORT_INDEX_OP);
1690 }
1691 }
1692 }
1693
1694 allocate_buffer_exit:
1695 return retval;
1696 }
1697
1698 /**
1699 * @brief Release buffer & associated header.
1700 *
1701 * @param[in] cmp_handle: Component handle.
1702 * @param[in] port: Port index.
1703 * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
1704 *
1705 * @retval OMX_ERRORTYPE
1706 */
free_buffer(OMX_HANDLETYPE cmp_handle,OMX_U32 port,OMX_BUFFERHEADERTYPE * p_buffer_hdr)1707 OMX_ERRORTYPE omx_swvdec::free_buffer(OMX_HANDLETYPE cmp_handle,
1708 OMX_U32 port,
1709 OMX_BUFFERHEADERTYPE *p_buffer_hdr)
1710 {
1711 OMX_ERRORTYPE retval = OMX_ErrorNone;
1712
1713 if (cmp_handle == NULL)
1714 {
1715 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1716 retval = OMX_ErrorInvalidComponent;
1717 }
1718 else if (p_buffer_hdr == NULL)
1719 {
1720 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
1721 retval = OMX_ErrorBadParameter;
1722 }
1723 else if ((port != OMX_CORE_PORT_INDEX_IP) &&
1724 (port != OMX_CORE_PORT_INDEX_OP))
1725 {
1726 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port);
1727 retval = OMX_ErrorBadPortIndex;
1728 }
1729 else if (m_state != OMX_StateIdle)
1730 {
1731 if (m_state != OMX_StateExecuting)
1732 {
1733 OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
1734 OMX_STATETYPE_STRING(m_state));
1735 retval = OMX_ErrorIncorrectStateOperation;
1736 }
1737 else
1738 {
1739 if (((port == OMX_CORE_PORT_INDEX_IP) && m_port_ip.enabled) ||
1740 ((port == OMX_CORE_PORT_INDEX_OP) && m_port_op.enabled))
1741 {
1742 OMX_SWVDEC_LOG_ERROR("port index %d not disabled", port);
1743 retval = OMX_ErrorBadPortIndex;
1744 }
1745 }
1746 }
1747
1748 if (retval == OMX_ErrorNone)
1749 {
1750 OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer_hdr);
1751
1752 if (port == OMX_CORE_PORT_INDEX_IP)
1753 {
1754 retval = buffer_deallocate_ip(p_buffer_hdr);
1755 }
1756 else
1757 {
1758 retval = buffer_deallocate_op(p_buffer_hdr);
1759 }
1760 }
1761
1762 if ((retval == OMX_ErrorNone) &&
1763 (m_status_flags & (1 << PENDING_STATE_IDLE_TO_LOADED)))
1764 {
1765 if ((m_port_ip.unpopulated == OMX_TRUE) &&
1766 (m_port_op.unpopulated == OMX_TRUE))
1767 {
1768 SWVDEC_STATUS retval_swvdec;
1769
1770 // stop SwVdec
1771 if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
1772 SWVDEC_STATUS_SUCCESS)
1773 {
1774 m_status_flags &= ~(1 << PENDING_STATE_IDLE_TO_LOADED);
1775
1776 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1777 OMX_CommandStateSet,
1778 OMX_StateLoaded);
1779 }
1780 else
1781 {
1782 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
1783 retval = retval_swvdec2omx(retval_swvdec);
1784 }
1785 }
1786 }
1787
1788 if ((retval == OMX_ErrorNone) &&
1789 (m_status_flags & (1 << PENDING_PORT_DISABLE_IP)) &&
1790 m_port_ip.unpopulated)
1791 {
1792 m_status_flags &= ~(1 << PENDING_PORT_DISABLE_IP);
1793
1794 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1795 OMX_CommandPortDisable,
1796 OMX_CORE_PORT_INDEX_IP);
1797 }
1798
1799 if ((retval == OMX_ErrorNone) &&
1800 (m_status_flags & (1 << PENDING_PORT_DISABLE_OP)) &&
1801 m_port_op.unpopulated)
1802 {
1803 if (m_port_reconfig_inprogress)
1804 {
1805 SWVDEC_STATUS retval_swvdec;
1806
1807 if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) !=
1808 SWVDEC_STATUS_SUCCESS)
1809 {
1810 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
1811 retval = retval_swvdec2omx(retval_swvdec);
1812 }
1813 }
1814
1815 m_status_flags &= ~(1 << PENDING_PORT_DISABLE_OP);
1816
1817 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1818 OMX_CommandPortDisable,
1819 OMX_CORE_PORT_INDEX_OP);
1820 }
1821
1822 return retval;
1823 }
1824
1825 /**
1826 * @brief Send a buffer to component's input port to be emptied.
1827 *
1828 * @param[in] cmp_handle: Component handle.
1829 * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
1830 *
1831 * @retval OMX_ERRORTYPE
1832 */
empty_this_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE * p_buffer_hdr)1833 OMX_ERRORTYPE omx_swvdec::empty_this_buffer(OMX_HANDLETYPE cmp_handle,
1834 OMX_BUFFERHEADERTYPE *p_buffer_hdr)
1835 {
1836 OMX_ERRORTYPE retval = OMX_ErrorNone;
1837
1838 unsigned int ii;
1839
1840 if (m_state == OMX_StateInvalid)
1841 {
1842 OMX_SWVDEC_LOG_ERROR("in invalid state");
1843 retval = OMX_ErrorInvalidState;
1844 }
1845 else if (cmp_handle == NULL)
1846 {
1847 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1848 retval = OMX_ErrorInvalidComponent;
1849 }
1850 else if (p_buffer_hdr == NULL)
1851 {
1852 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
1853 retval = OMX_ErrorBadParameter;
1854 }
1855 else if (p_buffer_hdr->pBuffer == NULL)
1856 {
1857 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL");
1858 retval = OMX_ErrorBadParameter;
1859 }
1860 else if (p_buffer_hdr->pInputPortPrivate == NULL)
1861 {
1862 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pInputPortPrivate = NULL");
1863 retval = OMX_ErrorBadParameter;
1864 }
1865 else if (m_port_ip.enabled == OMX_FALSE)
1866 {
1867 OMX_SWVDEC_LOG_ERROR("ip port disabled");
1868 retval = OMX_ErrorIncorrectStateOperation;
1869 }
1870 else if (p_buffer_hdr->nInputPortIndex != OMX_CORE_PORT_INDEX_IP)
1871 {
1872 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1873 p_buffer_hdr->nInputPortIndex);
1874 retval = OMX_ErrorBadPortIndex;
1875 }
1876
1877 if (retval != OMX_ErrorNone)
1878 {
1879 goto empty_this_buffer_exit;
1880 }
1881
1882 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
1883 {
1884 if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
1885 {
1886 OMX_SWVDEC_LOG_LOW("ip buffer %p has index %d",
1887 p_buffer_hdr->pBuffer,
1888 ii);
1889 break;
1890 }
1891 }
1892
1893 if (ii == m_port_ip.def.nBufferCountActual)
1894 {
1895 OMX_SWVDEC_LOG_ERROR("ip buffer %p not found",
1896 p_buffer_hdr->pBuffer);
1897 retval = OMX_ErrorBadParameter;
1898 goto empty_this_buffer_exit;
1899 }
1900
1901 if (m_sync_frame_decoding_mode &&
1902 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
1903 {
1904 p_buffer_hdr->nFlags |= OMX_BUFFERFLAG_EOS;
1905 }
1906
1907 OMX_SWVDEC_LOG_API("%p: buffer %p, flags 0x%08x, filled length %d, "
1908 "timestamp %lld",
1909 p_buffer_hdr,
1910 p_buffer_hdr->pBuffer,
1911 p_buffer_hdr->nFlags,
1912 p_buffer_hdr->nFilledLen,
1913 p_buffer_hdr->nTimeStamp);
1914
1915 async_post_event(OMX_SWVDEC_EVENT_ETB,
1916 (unsigned long) p_buffer_hdr,
1917 (unsigned long) ii);
1918
1919 empty_this_buffer_exit:
1920 return retval;
1921 }
1922
1923 /**
1924 * @brief Send a buffer to component's output port to be filled.
1925 *
1926 * @param[in] cmp_handle: Component handle.
1927 * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
1928 *
1929 * @retval OMX_ERRORTYPE
1930 */
fill_this_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE * p_buffer_hdr)1931 OMX_ERRORTYPE omx_swvdec::fill_this_buffer(OMX_HANDLETYPE cmp_handle,
1932 OMX_BUFFERHEADERTYPE *p_buffer_hdr)
1933 {
1934 OMX_ERRORTYPE retval = OMX_ErrorNone;
1935
1936 unsigned int ii;
1937
1938 SWVDEC_BUFFER *p_buffer_swvdec;
1939
1940 if (m_state == OMX_StateInvalid)
1941 {
1942 OMX_SWVDEC_LOG_ERROR("in invalid state");
1943 retval = OMX_ErrorInvalidState;
1944 }
1945 else if (cmp_handle == NULL)
1946 {
1947 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1948 retval = OMX_ErrorInvalidComponent;
1949 }
1950 else if (p_buffer_hdr == NULL)
1951 {
1952 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
1953 retval = OMX_ErrorBadParameter;
1954 }
1955 else if (p_buffer_hdr->pBuffer == NULL)
1956 {
1957 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL");
1958 retval = OMX_ErrorBadParameter;
1959 }
1960 else if (p_buffer_hdr->pOutputPortPrivate == NULL)
1961 {
1962 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pOutputPortPrivate = NULL");
1963 retval = OMX_ErrorBadParameter;
1964 }
1965 else if (m_port_op.enabled == OMX_FALSE)
1966 {
1967 OMX_SWVDEC_LOG_ERROR("op port disabled");
1968 retval = OMX_ErrorIncorrectStateOperation;
1969 }
1970 else if (p_buffer_hdr->nOutputPortIndex != OMX_CORE_PORT_INDEX_OP)
1971 {
1972 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1973 p_buffer_hdr->nOutputPortIndex);
1974 retval = OMX_ErrorBadPortIndex;
1975 }
1976
1977 if (retval != OMX_ErrorNone)
1978 {
1979 goto fill_this_buffer_exit;
1980 }
1981
1982 OMX_SWVDEC_LOG_API("%p", p_buffer_hdr);
1983
1984 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
1985 {
1986 if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
1987 {
1988 OMX_SWVDEC_LOG_LOW("op buffer %p has index %d",
1989 p_buffer_hdr->pBuffer,
1990 ii);
1991 break;
1992 }
1993 }
1994
1995 if (ii == m_port_op.def.nBufferCountActual)
1996 {
1997 OMX_SWVDEC_LOG_ERROR("op buffer %p not found",
1998 p_buffer_hdr->pBuffer);
1999 retval = OMX_ErrorBadParameter;
2000 goto fill_this_buffer_exit;
2001 }
2002
2003 p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec;
2004
2005 if (m_meta_buffer_mode)
2006 {
2007 struct VideoDecoderOutputMetaData *p_meta_data;
2008
2009 private_handle_t *p_private_handle;
2010
2011 struct vdec_bufferpayload *p_buffer_payload;
2012
2013 p_meta_data =
2014 (struct VideoDecoderOutputMetaData *) p_buffer_hdr->pBuffer;
2015
2016 p_private_handle = (private_handle_t *) (p_meta_data->pHandle);
2017
2018 p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
2019
2020 if (p_private_handle == NULL)
2021 {
2022 OMX_SWVDEC_LOG_ERROR(
2023 "p_buffer_hdr->pBuffer->pHandle = NULL");
2024
2025 retval = OMX_ErrorBadParameter;
2026 goto fill_this_buffer_exit;
2027 }
2028
2029 pthread_mutex_lock(&m_meta_buffer_array_mutex);
2030
2031 if (m_meta_buffer_array[ii].ref_count == 0)
2032 {
2033 unsigned char *bufferaddr;
2034
2035 bufferaddr = (unsigned char *) mmap(NULL,
2036 m_port_op.def.nBufferSize,
2037 PROT_READ | PROT_WRITE,
2038 MAP_SHARED,
2039 p_private_handle->fd,
2040 0);
2041
2042 if (bufferaddr == MAP_FAILED)
2043 {
2044 OMX_SWVDEC_LOG_ERROR("mmap() failed for "
2045 "fd %d of size %d",
2046 p_private_handle->fd,
2047 m_port_op.def.nBufferSize);
2048
2049 retval = OMX_ErrorInsufficientResources;
2050 goto fill_this_buffer_exit;
2051 }
2052
2053 p_buffer_payload->bufferaddr = bufferaddr;
2054 p_buffer_payload->pmem_fd = p_private_handle->fd;
2055 p_buffer_payload->buffer_len = m_port_op.def.nBufferSize;
2056 p_buffer_payload->mmaped_size = m_port_op.def.nBufferSize;
2057
2058 p_buffer_swvdec->p_buffer = bufferaddr;
2059 p_buffer_swvdec->size = m_port_op.def.nBufferSize;
2060 p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
2061 }
2062
2063 pthread_mutex_unlock(&m_meta_buffer_array_mutex);
2064
2065 meta_buffer_ref_add(ii,
2066 p_buffer_payload->pmem_fd,
2067 p_buffer_payload->offset);
2068 }
2069
2070 OMX_SWVDEC_LOG_LOW("%p: buffer %p",
2071 p_buffer_hdr,
2072 p_buffer_swvdec->p_buffer);
2073
2074 async_post_event(OMX_SWVDEC_EVENT_FTB,
2075 (unsigned long) p_buffer_hdr,
2076 (unsigned long) ii);
2077
2078 fill_this_buffer_exit:
2079 return retval;
2080 }
2081
2082 /**
2083 * @brief Set component's callback structure.
2084 *
2085 * @param[in] cmp_handle: Component handle.
2086 * @param[in] p_callbacks: Pointer to callback structure.
2087 * @param[in] p_app_data: Pointer to IL client app data.
2088 *
2089 * @retval OMX_ERRORTYPE
2090 */
set_callbacks(OMX_HANDLETYPE cmp_handle,OMX_CALLBACKTYPE * p_callbacks,OMX_PTR p_app_data)2091 OMX_ERRORTYPE omx_swvdec::set_callbacks(OMX_HANDLETYPE cmp_handle,
2092 OMX_CALLBACKTYPE *p_callbacks,
2093 OMX_PTR p_app_data)
2094 {
2095 OMX_ERRORTYPE retval = OMX_ErrorNone;
2096
2097 OMX_SWVDEC_LOG_API("");
2098
2099 if (m_state == OMX_StateInvalid)
2100 {
2101 OMX_SWVDEC_LOG_ERROR("in invalid state");
2102 retval = OMX_ErrorInvalidState;
2103 }
2104 else if (cmp_handle == NULL)
2105 {
2106 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
2107 retval = OMX_ErrorInvalidComponent;
2108 }
2109 else if (p_callbacks->EventHandler == NULL)
2110 {
2111 OMX_SWVDEC_LOG_ERROR("p_callbacks->EventHandler = NULL");
2112 retval = OMX_ErrorBadParameter;
2113 }
2114 else if (p_callbacks->EmptyBufferDone == NULL)
2115 {
2116 OMX_SWVDEC_LOG_ERROR("p_callbacks->EmptyBufferDone = NULL");
2117 retval = OMX_ErrorBadParameter;
2118 }
2119 else if (p_callbacks->FillBufferDone == NULL)
2120 {
2121 OMX_SWVDEC_LOG_ERROR("p_callbacks->FillBufferDone = NULL");
2122 retval = OMX_ErrorBadParameter;
2123 }
2124 else
2125 {
2126 m_callback = *p_callbacks;
2127 m_app_data = p_app_data;
2128 }
2129
2130 return retval;
2131 }
2132
2133 /**
2134 * @brief Use EGL image.
2135 *
2136 * @retval OMX_ErrorNotImplemented
2137 */
use_EGL_image(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_U32 port,OMX_PTR p_app_data,void * egl_image)2138 OMX_ERRORTYPE omx_swvdec::use_EGL_image(OMX_HANDLETYPE cmp_handle,
2139 OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
2140 OMX_U32 port,
2141 OMX_PTR p_app_data,
2142 void *egl_image)
2143 {
2144 (void) cmp_handle;
2145 (void) pp_buffer_hdr;
2146 (void) port;
2147 (void) p_app_data;
2148 (void) egl_image;
2149
2150 OMX_SWVDEC_LOG_API("");
2151
2152 OMX_SWVDEC_LOG_ERROR("not implemented");
2153
2154 return OMX_ErrorNotImplemented;
2155 }
2156
2157 /**
2158 * @brief Enumerate component role.
2159 *
2160 * @param[in] cmp_handle: Component handle.
2161 * @param[in,out] p_role: Pointer to component role string.
2162 * @param[in] index: Role index being queried.
2163 *
2164 * @retval OMX_ERRORTYPE
2165 */
component_role_enum(OMX_HANDLETYPE cmp_handle,OMX_U8 * p_role,OMX_U32 index)2166 OMX_ERRORTYPE omx_swvdec::component_role_enum(OMX_HANDLETYPE cmp_handle,
2167 OMX_U8 *p_role,
2168 OMX_U32 index)
2169 {
2170 OMX_ERRORTYPE retval = OMX_ErrorNone;
2171
2172 if (m_state == OMX_StateInvalid)
2173 {
2174 OMX_SWVDEC_LOG_ERROR("in invalid state");
2175 retval = OMX_ErrorInvalidState;
2176 }
2177 else if (cmp_handle == NULL)
2178 {
2179 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
2180 retval = OMX_ErrorInvalidComponent;
2181 }
2182 else if (index > 0)
2183 {
2184 OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more roles", index);
2185 retval = OMX_ErrorNoMore;
2186 }
2187 else
2188 {
2189 memcpy(p_role, m_role_name, OMX_MAX_STRINGNAME_SIZE);
2190 OMX_SWVDEC_LOG_API("index '%d': '%s'", index, p_role);
2191 }
2192
2193 return retval;
2194 }
2195
2196 /**
2197 * -------------------------
2198 * SwVdec callback functions
2199 * -------------------------
2200 */
2201
2202 /**
2203 * @brief SwVdec empty buffer done callback.
2204 *
2205 * @param[in] swvdec_handle: SwVdec handle.
2206 * @param[in] p_buffer_ip: Pointer to input buffer structure.
2207 * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2208 *
2209 * @retval SWVDEC_STATUS_SUCCESS
2210 * @retval SWVDEC_STATUS_NULL_POINTER
2211 * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2212 */
swvdec_empty_buffer_done_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_BUFFER * p_buffer_ip,void * p_client_handle)2213 SWVDEC_STATUS omx_swvdec::swvdec_empty_buffer_done_callback(
2214 SWVDEC_HANDLE swvdec_handle,
2215 SWVDEC_BUFFER *p_buffer_ip,
2216 void *p_client_handle)
2217 {
2218 SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2219
2220 if (p_buffer_ip == NULL)
2221 {
2222 OMX_SWVDEC_LOG_ERROR("p_buffer_ip = NULL");
2223 retval = SWVDEC_STATUS_NULL_POINTER;
2224 }
2225 else if (p_client_handle == NULL)
2226 {
2227 OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2228 retval = SWVDEC_STATUS_NULL_POINTER;
2229 }
2230 else
2231 {
2232 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2233
2234 if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2235 {
2236 OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2237 retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2238 }
2239 else
2240 {
2241 p_omx_swvdec->swvdec_empty_buffer_done(p_buffer_ip);
2242 }
2243 }
2244
2245 return retval;
2246 }
2247
2248 /**
2249 * @brief SwVdec fill buffer done callback.
2250 *
2251 * @param[in] swvdec_handle: SwVdec handle.
2252 * @param[in] p_buffer_op: Pointer to output buffer structure.
2253 * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2254 *
2255 * @retval SWVDEC_STATUS_SUCCESS
2256 * @retval SWVDEC_STATUS_NULL_POINTER
2257 * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2258 */
swvdec_fill_buffer_done_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_BUFFER * p_buffer_op,void * p_client_handle)2259 SWVDEC_STATUS omx_swvdec::swvdec_fill_buffer_done_callback(
2260 SWVDEC_HANDLE swvdec_handle,
2261 SWVDEC_BUFFER *p_buffer_op,
2262 void *p_client_handle)
2263 {
2264 SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2265
2266 if (p_buffer_op == NULL)
2267 {
2268 OMX_SWVDEC_LOG_ERROR("p_buffer_op = NULL");
2269 retval = SWVDEC_STATUS_NULL_POINTER;
2270 }
2271 else if (p_client_handle == NULL)
2272 {
2273 OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2274 retval = SWVDEC_STATUS_NULL_POINTER;
2275 }
2276 else
2277 {
2278 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2279
2280 if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2281 {
2282 OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2283 retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2284 }
2285 else
2286 {
2287 p_omx_swvdec->swvdec_fill_buffer_done(p_buffer_op);
2288 }
2289 }
2290
2291 return retval;
2292 }
2293
2294 /**
2295 * @brief SwVdec event handler callback.
2296 *
2297 * @param[in] swvdec_handle: SwVdec handle.
2298 * @param[in] event: Event.
2299 * @param[in] p_data: Pointer to event-specific data.
2300 * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2301 *
2302 * @retval SWVDEC_STATUS_SUCCESS
2303 * @retval SWVDEC_STATUS_NULL_POINTER
2304 * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2305 */
swvdec_event_handler_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_EVENT event,void * p_data,void * p_client_handle)2306 SWVDEC_STATUS omx_swvdec::swvdec_event_handler_callback(
2307 SWVDEC_HANDLE swvdec_handle,
2308 SWVDEC_EVENT event,
2309 void *p_data,
2310 void *p_client_handle)
2311 {
2312 SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2313
2314 if ((event == SWVDEC_EVENT_RELEASE_REFERENCE) && (p_data == NULL))
2315 {
2316 OMX_SWVDEC_LOG_ERROR("p_data = NULL");
2317 retval = SWVDEC_STATUS_NULL_POINTER;
2318 }
2319 else if (p_client_handle == NULL)
2320 {
2321 OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2322 retval = SWVDEC_STATUS_NULL_POINTER;
2323 }
2324 else
2325 {
2326 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2327
2328 if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2329 {
2330 OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2331 retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2332 }
2333 else
2334 {
2335 p_omx_swvdec->swvdec_event_handler(event, p_data);
2336 }
2337 }
2338
2339 return retval;
2340 }
2341
2342 /**
2343 * -----------------
2344 * PRIVATE FUNCTIONS
2345 * -----------------
2346 */
2347
2348 /**
2349 * @brief Set frame dimensions for OMX component & SwVdec core.
2350 *
2351 * @param[in] width: Frame width.
2352 * @param[in] height: Frame height.
2353 *
2354 * @retval OMX_ERRORTYPE
2355 */
set_frame_dimensions(unsigned int width,unsigned int height)2356 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions(unsigned int width,
2357 unsigned int height)
2358 {
2359 OMX_ERRORTYPE retval;
2360
2361 m_frame_dimensions.width = width;
2362 m_frame_dimensions.height = height;
2363
2364 OMX_SWVDEC_LOG_HIGH("%d x %d",
2365 m_frame_dimensions.width,
2366 m_frame_dimensions.height);
2367
2368 retval = set_frame_dimensions_swvdec();
2369
2370 return retval;
2371 }
2372
2373 /**
2374 * @brief Set frame attributes for OMX component & SwVdec core, based on
2375 * frame dimensions & alignment factors.
2376 *
2377 * @param[in] alignment_stride: Frame stride alignment factor.
2378 * @param[in] alignment_scanlines_y: Frame luma scanlines alignment factor.
2379 * @param[in] alignment_scanlines_uv: Frame chroma scanlines alignment factor.
2380 * @param[in] alignment_size: Frame size alignment factor.
2381 *
2382 * @retval OMX_ERRORTYPE
2383 */
set_frame_attributes(unsigned int alignment_stride,unsigned int alignment_scanlines_y,unsigned int alignment_scanlines_uv,unsigned int alignment_size)2384 OMX_ERRORTYPE omx_swvdec::set_frame_attributes(
2385 unsigned int alignment_stride,
2386 unsigned int alignment_scanlines_y,
2387 unsigned int alignment_scanlines_uv,
2388 unsigned int alignment_size)
2389 {
2390 OMX_ERRORTYPE retval;
2391
2392 unsigned int width = m_frame_dimensions.width;
2393 unsigned int height = m_frame_dimensions.height;
2394
2395 unsigned int scanlines_uv;
2396
2397 unsigned int plane_size_y;
2398 unsigned int plane_size_uv;
2399
2400 m_frame_attributes.stride = ALIGN(width, alignment_stride);
2401 m_frame_attributes.scanlines = ALIGN(height, alignment_scanlines_y);
2402
2403 scanlines_uv = ALIGN(height / 2, alignment_scanlines_uv);
2404
2405 plane_size_y = m_frame_attributes.stride * m_frame_attributes.scanlines;
2406 plane_size_uv = m_frame_attributes.stride * scanlines_uv;
2407
2408 m_frame_attributes.size =
2409 ALIGN(plane_size_y + plane_size_uv, alignment_size);
2410
2411 OMX_SWVDEC_LOG_HIGH("stride %d, scanlines %d, size %d",
2412 m_frame_attributes.stride,
2413 m_frame_attributes.scanlines,
2414 m_frame_attributes.size);
2415
2416 retval = set_frame_attributes_swvdec();
2417
2418 return retval;
2419 }
2420
2421 /**
2422 * @brief Get video port format for input or output port.
2423 *
2424 * @param[in,out] p_port_format: Pointer to video port format type.
2425 *
2426 * @retval OMX_ERRORTYPE
2427 */
get_video_port_format(OMX_VIDEO_PARAM_PORTFORMATTYPE * p_port_format)2428 OMX_ERRORTYPE omx_swvdec::get_video_port_format(
2429 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
2430 {
2431 OMX_ERRORTYPE retval = OMX_ErrorNone;
2432
2433 if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2434 {
2435 if (p_port_format->nIndex == 0)
2436 {
2437 p_port_format->eColorFormat = OMX_COLOR_FormatUnused;
2438 p_port_format->eCompressionFormat = m_omx_video_codingtype;
2439
2440 OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2441 "compression format 0x%08x",
2442 p_port_format->eColorFormat,
2443 p_port_format->eCompressionFormat);
2444 }
2445 else
2446 {
2447 OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; "
2448 "no more compression formats",
2449 p_port_format->nIndex);
2450 retval = OMX_ErrorNoMore;
2451 }
2452 }
2453 else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2454 {
2455 if (p_port_format->nIndex == 0)
2456 {
2457 p_port_format->eColorFormat =
2458 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m;
2459 p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
2460
2461 OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2462 "compression format 0x%08x",
2463 p_port_format->eColorFormat,
2464 p_port_format->eCompressionFormat);
2465 }
2466 else if (p_port_format->nIndex == 1)
2467 {
2468 p_port_format->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
2469 p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
2470
2471 OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2472 "compression format 0x%08x",
2473 p_port_format->eColorFormat,
2474 p_port_format->eCompressionFormat);
2475 }
2476 // Here, add additional supported color formats as necessary.
2477 else
2478 {
2479 OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more color formats",
2480 p_port_format->nIndex);
2481 retval = OMX_ErrorNoMore;
2482 }
2483 }
2484 else
2485 {
2486 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2487 p_port_format->nPortIndex);
2488 retval = OMX_ErrorBadPortIndex;
2489 }
2490
2491 return retval;
2492 }
2493
2494 /**
2495 * @brief Set video port format for input or output port.
2496 *
2497 * @param[in] p_port_format: Pointer to video port format type.
2498 *
2499 * @retval OMX_ERRORTYPE
2500 */
set_video_port_format(OMX_VIDEO_PARAM_PORTFORMATTYPE * p_port_format)2501 OMX_ERRORTYPE omx_swvdec::set_video_port_format(
2502 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
2503 {
2504 OMX_ERRORTYPE retval = OMX_ErrorNone;
2505
2506 if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2507 {
2508 // do nothing
2509 OMX_SWVDEC_LOG_HIGH("OMX_IndexParamVideoPortFormat, port index 0; "
2510 "doing nothing");
2511 }
2512 else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2513 {
2514 /**
2515 * If color format specified by IL client is different from default,
2516 * set alignment factors for new color format and call
2517 * set_frame_attributes().
2518 */
2519 switch (p_port_format->eColorFormat)
2520 {
2521
2522 case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m:
2523 {
2524 // do nothing; this is the default color format
2525 OMX_SWVDEC_LOG_HIGH(
2526 "'0x%08x': OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m",
2527 p_port_format->eColorFormat);
2528 break;
2529 }
2530
2531 case OMX_COLOR_FormatYUV420SemiPlanar:
2532 {
2533 OMX_SWVDEC_LOG_HIGH("'0x%08x': OMX_COLOR_FormatYUV420SemiPlanar",
2534 p_port_format->eColorFormat);
2535
2536 retval = set_frame_attributes(16, // stride alignment
2537 1, // Y scanlines alignment
2538 1, // UV scanlines alignment
2539 4096); // size alignment
2540 break;
2541 }
2542
2543 default:
2544 {
2545 OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid or unsupported",
2546 p_port_format->eColorFormat);
2547 retval = OMX_ErrorBadParameter;
2548 break;
2549 }
2550
2551 }
2552 }
2553 else
2554 {
2555 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2556 p_port_format->nPortIndex);
2557 retval = OMX_ErrorBadPortIndex;
2558 }
2559
2560 set_video_port_format_exit:
2561 return retval;
2562 }
2563
2564 /**
2565 * @brief Get port definition for input or output port.
2566 *
2567 * @param[in,out] p_port_def: Pointer to port definition type.
2568 *
2569 * @retval OMX_ERRORTYPE
2570 */
get_port_definition(OMX_PARAM_PORTDEFINITIONTYPE * p_port_def)2571 OMX_ERRORTYPE omx_swvdec::get_port_definition(
2572 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
2573 {
2574 OMX_ERRORTYPE retval = OMX_ErrorNone;
2575
2576 p_port_def->eDomain = OMX_PortDomainVideo;
2577
2578 if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2579 {
2580 if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) !=
2581 OMX_ErrorNone)
2582 {
2583 goto get_port_definition_exit;
2584 }
2585
2586 p_port_def->eDir = OMX_DirInput;
2587 p_port_def->nBufferCountActual = m_port_ip.def.nBufferCountActual;
2588 p_port_def->nBufferCountMin = m_port_ip.def.nBufferCountMin;
2589 p_port_def->nBufferSize = m_port_ip.def.nBufferSize;
2590 p_port_def->bEnabled = m_port_ip.enabled;
2591 p_port_def->bPopulated = m_port_ip.populated;
2592
2593 OMX_SWVDEC_LOG_HIGH("port index %d: "
2594 "count actual %d, count min %d, size %d",
2595 p_port_def->nPortIndex,
2596 p_port_def->nBufferCountActual,
2597 p_port_def->nBufferCountMin,
2598 p_port_def->nBufferSize);
2599
2600 // frame dimensions & attributes don't apply to input port
2601
2602 p_port_def->format.video.eColorFormat = OMX_COLOR_FormatUnused;
2603 p_port_def->format.video.eCompressionFormat = m_omx_video_codingtype;
2604 }
2605 else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2606 {
2607 unsigned int frame_width = m_frame_dimensions.width;
2608 unsigned int frame_height = m_frame_dimensions.height;
2609
2610 if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone)
2611 {
2612 goto get_port_definition_exit;
2613 }
2614
2615 p_port_def->format.video.nFrameWidth = m_frame_dimensions.width;
2616 p_port_def->format.video.nFrameHeight = m_frame_dimensions.height;
2617
2618 // if frame dimensions have changed, update frame attributes
2619 if ((frame_width != m_frame_dimensions.width) ||
2620 (frame_height != m_frame_dimensions.height))
2621 {
2622 if ((retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
2623 DEFAULT_ALIGNMENT_SCANLINES_Y,
2624 DEFAULT_ALIGNMENT_SCANLINES_UV,
2625 DEFAULT_ALIGNMENT_SIZE)) !=
2626 OMX_ErrorNone)
2627 {
2628 goto get_port_definition_exit;
2629 }
2630 }
2631
2632 if ((retval = get_frame_attributes_swvdec()) != OMX_ErrorNone)
2633 {
2634 goto get_port_definition_exit;
2635 }
2636
2637 p_port_def->format.video.nStride = m_frame_attributes.stride;
2638 p_port_def->format.video.nSliceHeight = m_frame_attributes.scanlines;
2639
2640 OMX_SWVDEC_LOG_HIGH("port index %d: "
2641 "%d x %d, stride %d, sliceheight %d",
2642 p_port_def->nPortIndex,
2643 p_port_def->format.video.nFrameWidth,
2644 p_port_def->format.video.nFrameHeight,
2645 p_port_def->format.video.nStride,
2646 p_port_def->format.video.nSliceHeight);
2647
2648 /**
2649 * Query to SwVdec core for buffer requirements is not allowed in
2650 * executing state since it will overwrite the component's buffer
2651 * requirements updated via the most recent set_parameter().
2652 *
2653 * Buffer requirements communicated to component via set_parameter() are
2654 * not propagated to SwVdec core.
2655 *
2656 * The only execption is if port reconfiguration is in progress, in
2657 * which case the query to SwVdec core is required since buffer
2658 * requirements can change based on new dimensions.
2659 */
2660 if ((m_state != OMX_StateExecuting) || m_port_reconfig_inprogress)
2661 {
2662 if ((retval =
2663 get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) !=
2664 OMX_ErrorNone)
2665 {
2666 goto get_port_definition_exit;
2667 }
2668 }
2669
2670 p_port_def->eDir = OMX_DirOutput;
2671 p_port_def->nBufferCountActual = m_port_op.def.nBufferCountActual;
2672 p_port_def->nBufferCountMin = m_port_op.def.nBufferCountMin;
2673 p_port_def->nBufferSize = m_port_op.def.nBufferSize;
2674 p_port_def->bEnabled = m_port_op.enabled;
2675 p_port_def->bPopulated = m_port_op.populated;
2676
2677 OMX_SWVDEC_LOG_HIGH("port index %d: "
2678 "count actual %d, count min %d, size %d",
2679 p_port_def->nPortIndex,
2680 p_port_def->nBufferCountActual,
2681 p_port_def->nBufferCountMin,
2682 p_port_def->nBufferSize);
2683
2684 p_port_def->format.video.eColorFormat = m_omx_color_formattype;
2685 p_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
2686 }
2687 else
2688 {
2689 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
2690 retval = OMX_ErrorBadPortIndex;
2691 }
2692
2693 get_port_definition_exit:
2694 return retval;
2695 }
2696
2697 /**
2698 * @brief Set port definition for input or output port.
2699 *
2700 * @param[in] p_port_def: Pointer to port definition type.
2701 *
2702 * @retval OMX_ERRORTYPE
2703 */
set_port_definition(OMX_PARAM_PORTDEFINITIONTYPE * p_port_def)2704 OMX_ERRORTYPE omx_swvdec::set_port_definition(
2705 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
2706 {
2707 OMX_ERRORTYPE retval = OMX_ErrorNone;
2708
2709 OMX_SWVDEC_LOG_HIGH("port index %d: "
2710 "count actual %d, count min %d, size %d",
2711 p_port_def->nPortIndex,
2712 p_port_def->nBufferCountActual,
2713 p_port_def->nBufferCountMin,
2714 p_port_def->nBufferSize);
2715
2716 if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2717 {
2718 m_port_ip.def.nBufferCountActual = p_port_def->nBufferCountActual;
2719 m_port_ip.def.nBufferCountMin = p_port_def->nBufferCountMin;
2720 m_port_ip.def.nBufferSize = p_port_def->nBufferSize;
2721 }
2722 else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2723 {
2724 OMX_SWVDEC_LOG_HIGH("port index %d: %d x %d",
2725 p_port_def->nPortIndex,
2726 p_port_def->format.video.nFrameWidth,
2727 p_port_def->format.video.nFrameHeight);
2728
2729 m_port_op.def.nBufferCountActual = p_port_def->nBufferCountActual;
2730 m_port_op.def.nBufferCountMin = p_port_def->nBufferCountMin;
2731 m_port_op.def.nBufferSize = p_port_def->nBufferSize;
2732
2733 retval = set_frame_dimensions(p_port_def->format.video.nFrameWidth,
2734 p_port_def->format.video.nFrameHeight);
2735 if (retval != OMX_ErrorNone)
2736 goto set_port_definition_exit;
2737
2738 m_frame_attributes.stride = p_port_def->format.video.nStride;
2739 m_frame_attributes.scanlines = p_port_def->format.video.nSliceHeight;
2740 m_frame_attributes.size = p_port_def->nBufferSize;
2741
2742 retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
2743 DEFAULT_ALIGNMENT_SCANLINES_Y,
2744 DEFAULT_ALIGNMENT_SCANLINES_UV,
2745 DEFAULT_ALIGNMENT_SIZE);
2746 }
2747 else
2748 {
2749 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
2750 retval = OMX_ErrorBadPortIndex;
2751 }
2752
2753 set_port_definition_exit:
2754 return retval;
2755 }
2756
2757 /**
2758 * @brief Get supported profile & level.
2759 *
2760 * The supported profiles & levels are not queried from SwVdec core, but
2761 * hard-coded. This should ideally be replaced with a query to SwVdec core.
2762 *
2763 * @param[in,out] p_profilelevel: Pointer to video profile & level type.
2764 *
2765 * @retval OMX_ERRORTYPE
2766 */
get_supported_profilelevel(OMX_VIDEO_PARAM_PROFILELEVELTYPE * p_profilelevel)2767 OMX_ERRORTYPE omx_swvdec::get_supported_profilelevel(
2768 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel)
2769 {
2770 OMX_ERRORTYPE retval = OMX_ErrorNone;
2771
2772 if (p_profilelevel == NULL)
2773 {
2774 OMX_SWVDEC_LOG_ERROR("p_profilelevel = NULL");
2775 retval = OMX_ErrorBadParameter;
2776 goto get_supported_profilelevel_exit;
2777 }
2778
2779 if (p_profilelevel->nPortIndex != OMX_CORE_PORT_INDEX_IP)
2780 {
2781 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2782 p_profilelevel->nPortIndex);
2783 retval = OMX_ErrorBadPortIndex;
2784 goto get_supported_profilelevel_exit;
2785 }
2786
2787 if (m_omx_video_codingtype == OMX_VIDEO_CodingH263)
2788 {
2789 if (p_profilelevel->nProfileIndex == 0)
2790 {
2791 p_profilelevel->eProfile = OMX_VIDEO_H263ProfileBaseline;
2792 p_profilelevel->eLevel = OMX_VIDEO_H263Level70;
2793 OMX_SWVDEC_LOG_HIGH("H.263 baseline profile, level 70");
2794 }
2795 else
2796 {
2797 OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
2798 "no more profiles",
2799 p_profilelevel->nProfileIndex);
2800 retval = OMX_ErrorNoMore;
2801 }
2802 }
2803 else if ((m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4) ||
2804 (m_omx_video_codingtype ==
2805 ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)))
2806 {
2807 if (p_profilelevel->nProfileIndex == 0)
2808 {
2809 p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2810 p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level5;
2811 OMX_SWVDEC_LOG_HIGH("MPEG-4 simple profile, level 5");
2812 }
2813 else if (p_profilelevel->nProfileIndex == 1)
2814 {
2815 p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2816 p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level5;
2817 OMX_SWVDEC_LOG_HIGH("MPEG-4 advanced simple profile, level 5");
2818 }
2819 else
2820 {
2821 OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
2822 "no more profiles",
2823 p_profilelevel->nProfileIndex);
2824 retval = OMX_ErrorNoMore;
2825 }
2826 }
2827 else
2828 {
2829 assert(0);
2830 retval = OMX_ErrorUndefined;
2831 }
2832
2833 get_supported_profilelevel_exit:
2834 return retval;
2835 }
2836
2837 /**
2838 * @brief Describe color format.
2839 *
2840 * @param[in,out] p_params: Pointer to 'DescribeColorFormatParams' structure.
2841 *
2842 * @retval OMX_ERRORTYPE
2843 */
describe_color_format(DescribeColorFormatParams * p_params)2844 OMX_ERRORTYPE omx_swvdec::describe_color_format(
2845 DescribeColorFormatParams *p_params)
2846 {
2847 OMX_ERRORTYPE retval = OMX_ErrorNone;
2848
2849 if (p_params == NULL)
2850 {
2851 OMX_SWVDEC_LOG_ERROR("p_params = NULL");
2852 retval = OMX_ErrorBadParameter;
2853 }
2854 else
2855 {
2856 MediaImage *p_img = &p_params->sMediaImage;
2857
2858 switch (p_params->eColorFormat)
2859 {
2860
2861 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
2862 {
2863 size_t stride, scanlines;
2864
2865 p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
2866 p_img->mNumPlanes = 3;
2867
2868 p_img->mWidth = p_params->nFrameWidth;
2869 p_img->mHeight = p_params->nFrameHeight;
2870
2871 stride = ALIGN(p_img->mWidth, DEFAULT_ALIGNMENT_STRIDE);
2872 scanlines = ALIGN(p_img->mHeight, DEFAULT_ALIGNMENT_SCANLINES_Y);
2873
2874 p_img->mBitDepth = 8;
2875
2876 // plane 0 (Y)
2877 p_img->mPlane[MediaImage::Y].mOffset = 0;
2878 p_img->mPlane[MediaImage::Y].mColInc = 1;
2879 p_img->mPlane[MediaImage::Y].mRowInc = stride;
2880 p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
2881 p_img->mPlane[MediaImage::Y].mVertSubsampling = 1;
2882
2883 // plane 1 (U)
2884 p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines;
2885 p_img->mPlane[MediaImage::Y].mColInc = 2;
2886 p_img->mPlane[MediaImage::Y].mRowInc = stride;
2887 p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2888 p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
2889
2890 // plane 2 (V)
2891 p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines + 1;
2892 p_img->mPlane[MediaImage::Y].mColInc = 2;
2893 p_img->mPlane[MediaImage::Y].mRowInc = stride;
2894 p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2895 p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
2896
2897 break;
2898 }
2899
2900 case OMX_COLOR_FormatYUV420SemiPlanar:
2901 {
2902 size_t stride, scanlines;
2903
2904 p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
2905 p_img->mNumPlanes = 3;
2906
2907 p_img->mWidth = p_params->nFrameWidth;
2908 p_img->mHeight = p_params->nFrameHeight;
2909
2910 stride = ALIGN(p_img->mWidth, 16);
2911 scanlines = ALIGN(p_img->mHeight, 1);
2912
2913 p_img->mBitDepth = 8;
2914
2915 // plane 0 (Y)
2916 p_img->mPlane[MediaImage::Y].mOffset = 0;
2917 p_img->mPlane[MediaImage::Y].mColInc = 1;
2918 p_img->mPlane[MediaImage::Y].mRowInc = stride;
2919 p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
2920 p_img->mPlane[MediaImage::Y].mVertSubsampling = 1;
2921
2922 // plane 1 (U)
2923 p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines;
2924 p_img->mPlane[MediaImage::Y].mColInc = 2;
2925 p_img->mPlane[MediaImage::Y].mRowInc = stride;
2926 p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2927 p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
2928
2929 // plane 2 (V)
2930 p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines + 1;
2931 p_img->mPlane[MediaImage::Y].mColInc = 2;
2932 p_img->mPlane[MediaImage::Y].mRowInc = stride;
2933 p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2934 p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
2935
2936 break;
2937 }
2938
2939 default:
2940 {
2941 OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid/unsupported",
2942 p_params->eColorFormat);
2943
2944 p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
2945
2946 retval = OMX_ErrorBadParameter;
2947 break;
2948 }
2949
2950 } // switch (p_params->eColorFormat)
2951 }
2952
2953 return retval;
2954 }
2955
2956 /**
2957 * @brief Set QTI vendor-specific port definition for input or output port.
2958 *
2959 * @param[in] p_port_def: Pointer to QTI vendor-specific port definition type.
2960 *
2961 * @retval OMX_ERRORTYPE
2962 */
set_port_definition_qcom(OMX_QCOM_PARAM_PORTDEFINITIONTYPE * p_port_def)2963 OMX_ERRORTYPE omx_swvdec::set_port_definition_qcom(
2964 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def)
2965 {
2966 OMX_ERRORTYPE retval = OMX_ErrorNone;
2967
2968 if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2969 {
2970 switch (p_port_def->nFramePackingFormat)
2971 {
2972
2973 case OMX_QCOM_FramePacking_Arbitrary:
2974 {
2975 OMX_SWVDEC_LOG_ERROR("OMX_QCOM_FramePacking_Arbitrary unsupported");
2976 retval = OMX_ErrorUnsupportedSetting;
2977 break;
2978 }
2979
2980 case OMX_QCOM_FramePacking_OnlyOneCompleteFrame:
2981 {
2982 OMX_SWVDEC_LOG_HIGH(
2983 "OMX_QCOM_FramePacking_OnlyOneCompleteFrame");
2984 break;
2985 }
2986
2987 default:
2988 {
2989 OMX_SWVDEC_LOG_ERROR(
2990 "frame packing format '%d' unsupported");
2991 retval = OMX_ErrorUnsupportedSetting;
2992 break;
2993 }
2994
2995 }
2996 }
2997 else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2998 {
2999 OMX_SWVDEC_LOG_HIGH("nMemRegion %d, nCacheAttr %d",
3000 p_port_def->nMemRegion,
3001 p_port_def->nCacheAttr);
3002 }
3003 else
3004 {
3005 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
3006 p_port_def->nPortIndex);
3007 retval = OMX_ErrorBadPortIndex;
3008 }
3009
3010 return retval;
3011 }
3012
3013 /**
3014 * @brief Set SwVdec frame dimensions based on OMX component frame dimensions.
3015 *
3016 * @retval OMX_ERRORTYPE
3017 */
set_frame_dimensions_swvdec()3018 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions_swvdec()
3019 {
3020 OMX_ERRORTYPE retval = OMX_ErrorNone;
3021
3022 SWVDEC_PROPERTY property;
3023
3024 SWVDEC_STATUS retval_swvdec;
3025
3026 property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
3027
3028 property.info.frame_dimensions.width = m_frame_dimensions.width;
3029 property.info.frame_dimensions.height = m_frame_dimensions.height;
3030
3031 if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3032 SWVDEC_STATUS_SUCCESS)
3033 {
3034 retval = retval_swvdec2omx(retval_swvdec);
3035 }
3036
3037 return retval;
3038 }
3039
3040 /**
3041 * @brief Set SwVdec frame attributes based on OMX component frame attributes.
3042 *
3043 * @retval OMX_ERRORTYPE
3044 */
set_frame_attributes_swvdec()3045 OMX_ERRORTYPE omx_swvdec::set_frame_attributes_swvdec()
3046 {
3047 OMX_ERRORTYPE retval = OMX_ErrorNone;
3048
3049 SWVDEC_FRAME_ATTRIBUTES *p_frame_attributes;
3050
3051 SWVDEC_PROPERTY property;
3052
3053 SWVDEC_STATUS retval_swvdec;
3054
3055 p_frame_attributes = &property.info.frame_attributes;
3056
3057 property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
3058
3059 p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12;
3060
3061 p_frame_attributes->semiplanar.stride = m_frame_attributes.stride;
3062 p_frame_attributes->semiplanar.offset_uv = (m_frame_attributes.stride *
3063 m_frame_attributes.scanlines);
3064
3065 p_frame_attributes->size = m_frame_attributes.size;
3066
3067 if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3068 SWVDEC_STATUS_SUCCESS)
3069 {
3070 retval = retval_swvdec2omx(retval_swvdec);
3071 }
3072
3073 return retval;
3074 }
3075
3076 /**
3077 * @brief Get SwVdec frame dimensions and set OMX component frame dimensions.
3078 *
3079 * @retval OMX_ERRORTYPE
3080 */
get_frame_dimensions_swvdec()3081 OMX_ERRORTYPE omx_swvdec::get_frame_dimensions_swvdec()
3082 {
3083 OMX_ERRORTYPE retval = OMX_ErrorNone;
3084
3085 SWVDEC_PROPERTY property;
3086
3087 SWVDEC_STATUS retval_swvdec;
3088
3089 property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
3090
3091 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3092 SWVDEC_STATUS_SUCCESS)
3093 {
3094 retval = retval_swvdec2omx(retval_swvdec);
3095 }
3096 else
3097 {
3098 m_frame_dimensions.width = property.info.frame_dimensions.width;
3099 m_frame_dimensions.height = property.info.frame_dimensions.height;
3100 }
3101
3102 return retval;
3103 }
3104
3105 /**
3106 * @brief Get SwVdec frame attributes and set OMX component frame attributes.
3107 *
3108 * @retval OMX_ERRORTYPE
3109 */
get_frame_attributes_swvdec()3110 OMX_ERRORTYPE omx_swvdec::get_frame_attributes_swvdec()
3111 {
3112 OMX_ERRORTYPE retval = OMX_ErrorNone;
3113
3114 SWVDEC_PROPERTY property;
3115
3116 SWVDEC_STATUS retval_swvdec;
3117
3118 property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
3119
3120 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3121 SWVDEC_STATUS_SUCCESS)
3122 {
3123 retval = retval_swvdec2omx(retval_swvdec);
3124 }
3125 else
3126 {
3127 m_frame_attributes.stride =
3128 property.info.frame_attributes.semiplanar.stride;
3129
3130 m_frame_attributes.scanlines =
3131 (property.info.frame_attributes.semiplanar.offset_uv /
3132 property.info.frame_attributes.semiplanar.stride);
3133
3134 m_frame_attributes.size = property.info.frame_attributes.size;
3135 }
3136
3137 return retval;
3138 }
3139
3140 /**
3141 * @brief Get SwVdec buffer requirements; set input or output port definitions.
3142 *
3143 * @param[in] port_index: Port index.
3144 *
3145 * @retval OMX_ERRORTYPE
3146 */
get_buffer_requirements_swvdec(unsigned int port_index)3147 OMX_ERRORTYPE omx_swvdec::get_buffer_requirements_swvdec(
3148 unsigned int port_index)
3149 {
3150 OMX_ERRORTYPE retval = OMX_ErrorNone;
3151
3152 SWVDEC_PROPERTY property;
3153
3154 SWVDEC_STATUS retval_swvdec;
3155
3156 SWVDEC_BUFFER_REQ *p_buffer_req;
3157
3158 if (port_index == OMX_CORE_PORT_INDEX_IP)
3159 {
3160 property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_IP;
3161
3162 p_buffer_req = &property.info.buffer_req_ip;
3163
3164 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3165 SWVDEC_STATUS_SUCCESS)
3166 {
3167 retval = retval_swvdec2omx(retval_swvdec);
3168 goto get_buffer_requirements_swvdec_exit;
3169 }
3170
3171 m_port_ip.def.nBufferSize = p_buffer_req->size;
3172 m_port_ip.def.nBufferCountMin = p_buffer_req->mincount;
3173 m_port_ip.def.nBufferCountActual = MAX(p_buffer_req->mincount,
3174 OMX_SWVDEC_IP_BUFFER_COUNT);
3175 m_port_ip.def.nBufferAlignment = p_buffer_req->alignment;
3176
3177 OMX_SWVDEC_LOG_HIGH("ip port: %d bytes x %d, %d-byte aligned",
3178 m_port_ip.def.nBufferSize,
3179 m_port_ip.def.nBufferCountActual,
3180 m_port_ip.def.nBufferAlignment);
3181 }
3182 else if (port_index == OMX_CORE_PORT_INDEX_OP)
3183 {
3184 property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_OP;
3185
3186 p_buffer_req = &property.info.buffer_req_op;
3187
3188 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3189 SWVDEC_STATUS_SUCCESS)
3190 {
3191 retval = retval_swvdec2omx(retval_swvdec);
3192 goto get_buffer_requirements_swvdec_exit;
3193 }
3194
3195 if (m_sync_frame_decoding_mode)
3196 {
3197 // only 1 output buffer for sync frame decoding mode
3198 p_buffer_req->mincount = 1;
3199 }
3200
3201 m_port_op.def.nBufferSize = p_buffer_req->size;
3202 m_port_op.def.nBufferCountMin = p_buffer_req->mincount;
3203 m_port_op.def.nBufferCountActual = p_buffer_req->mincount;
3204 m_port_op.def.nBufferAlignment = p_buffer_req->alignment;
3205
3206 OMX_SWVDEC_LOG_HIGH("op port: %d bytes x %d, %d-byte aligned",
3207 m_port_op.def.nBufferSize,
3208 m_port_op.def.nBufferCountActual,
3209 m_port_op.def.nBufferAlignment);
3210 }
3211 else
3212 {
3213 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port_index);
3214 retval = OMX_ErrorBadPortIndex;
3215 }
3216
3217 get_buffer_requirements_swvdec_exit:
3218 return retval;
3219 }
3220
3221 /**
3222 * @brief Allocate input buffer, and input buffer info array if ncessary.
3223 *
3224 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3225 * structure.
3226 * @param[in] p_app_data: Pointer to IL client app data.
3227 * @param[in] size: Size of buffer to be allocated in bytes.
3228 *
3229 * @retval OMX_ERRORTYPE
3230 */
buffer_allocate_ip(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3231 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip(
3232 OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3233 OMX_PTR p_app_data,
3234 OMX_U32 size)
3235 {
3236 OMX_ERRORTYPE retval = OMX_ErrorNone;
3237
3238 unsigned int ii;
3239
3240 if (size != m_port_ip.def.nBufferSize)
3241 {
3242 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3243 "configured size (%d bytes)",
3244 size,
3245 m_port_ip.def.nBufferSize);
3246 retval = OMX_ErrorBadParameter;
3247 goto buffer_allocate_ip_exit;
3248 }
3249
3250 if (m_buffer_array_ip == NULL)
3251 {
3252 // input buffer info array not allocated; allocate here
3253
3254 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3255 m_port_ip.def.nBufferCountActual,
3256 (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3257
3258 if ((retval = buffer_allocate_ip_info_array()) != OMX_ErrorNone)
3259 {
3260 goto buffer_allocate_ip_exit;
3261 }
3262 }
3263
3264 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3265 {
3266 if (m_buffer_array_ip[ii].buffer_populated == false)
3267 {
3268 OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3269 break;
3270 }
3271 }
3272
3273 if (ii < m_port_ip.def.nBufferCountActual)
3274 {
3275 int pmem_fd = -1;
3276
3277 unsigned char *bufferaddr;
3278
3279 OMX_SWVDEC_LOG_HIGH("ip buffer %d: %d bytes being allocated",
3280 ii,
3281 size);
3282
3283 m_buffer_array_ip[ii].ion_info.ion_fd_device =
3284 ion_memory_alloc_map(&m_buffer_array_ip[ii].ion_info.ion_alloc_data,
3285 &m_buffer_array_ip[ii].ion_info.ion_fd_data,
3286 size,
3287 m_port_ip.def.nBufferAlignment);
3288
3289 if (m_buffer_array_ip[ii].ion_info.ion_fd_device < 0)
3290 {
3291 retval = OMX_ErrorInsufficientResources;
3292 goto buffer_allocate_ip_exit;
3293 }
3294
3295 pmem_fd = m_buffer_array_ip[ii].ion_info.ion_fd_data.fd;
3296
3297 bufferaddr = (unsigned char *) mmap(NULL,
3298 size,
3299 PROT_READ | PROT_WRITE,
3300 MAP_SHARED,
3301 pmem_fd,
3302 0);
3303
3304 if (bufferaddr == MAP_FAILED)
3305 {
3306 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3307 pmem_fd,
3308 size);
3309 close(pmem_fd);
3310 ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3311 retval = OMX_ErrorInsufficientResources;
3312 goto buffer_allocate_ip_exit;
3313 }
3314
3315 *pp_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3316
3317 m_buffer_array_ip[ii].buffer_payload.bufferaddr = bufferaddr;
3318 m_buffer_array_ip[ii].buffer_payload.pmem_fd = pmem_fd;
3319 m_buffer_array_ip[ii].buffer_payload.buffer_len = size;
3320 m_buffer_array_ip[ii].buffer_payload.mmaped_size = size;
3321 m_buffer_array_ip[ii].buffer_payload.offset = 0;
3322
3323 m_buffer_array_ip[ii].buffer_swvdec.p_buffer = bufferaddr;
3324 m_buffer_array_ip[ii].buffer_swvdec.size = size;
3325 m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3326 (void *) ((unsigned long) ii);
3327
3328 m_buffer_array_ip[ii].buffer_populated = true;
3329
3330 OMX_SWVDEC_LOG_HIGH("ip buffer %d: %p, %d bytes",
3331 ii,
3332 bufferaddr,
3333 size);
3334
3335 (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr;
3336 (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
3337 (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION;
3338 (*pp_buffer_hdr)->nAllocLen = size;
3339 (*pp_buffer_hdr)->pAppPrivate = p_app_data;
3340 (*pp_buffer_hdr)->nInputPortIndex = OMX_CORE_PORT_INDEX_IP;
3341 (*pp_buffer_hdr)->pInputPortPrivate =
3342 (void *) &(m_buffer_array_ip[ii].buffer_payload);
3343
3344 m_port_ip.populated = port_ip_populated();
3345 m_port_ip.unpopulated = OMX_FALSE;
3346 }
3347 else
3348 {
3349 OMX_SWVDEC_LOG_ERROR("all %d ip buffers allocated",
3350 m_port_ip.def.nBufferCountActual);
3351 retval = OMX_ErrorInsufficientResources;
3352 }
3353
3354 buffer_allocate_ip_exit:
3355 return retval;
3356 }
3357
3358 /**
3359 * @brief Allocate output buffer, and output buffer info array if necessary.
3360 *
3361 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3362 * structure.
3363 * @param[in] p_app_data: Pointer to IL client app data.
3364 * @param[in] size: Size of buffer to be allocated in bytes.
3365 *
3366 * @retval OMX_ERRORTYPE
3367 */
buffer_allocate_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3368 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op(
3369 OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3370 OMX_PTR p_app_data,
3371 OMX_U32 size)
3372 {
3373 OMX_ERRORTYPE retval = OMX_ErrorNone;
3374
3375 unsigned int ii;
3376
3377 if (size != m_port_op.def.nBufferSize)
3378 {
3379 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3380 "configured size (%d bytes)",
3381 size,
3382 m_port_op.def.nBufferSize);
3383 retval = OMX_ErrorBadParameter;
3384 goto buffer_allocate_op_exit;
3385 }
3386
3387 if (m_buffer_array_op == NULL)
3388 {
3389 // output buffer info array not allocated; allocate here
3390
3391 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3392 m_port_op.def.nBufferCountActual,
3393 (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3394
3395 if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
3396 {
3397 goto buffer_allocate_op_exit;
3398 }
3399 }
3400
3401 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3402 {
3403 if (m_buffer_array_op[ii].buffer_populated == false)
3404 {
3405 OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3406 break;
3407 }
3408 }
3409
3410 if (ii < m_port_op.def.nBufferCountActual)
3411 {
3412 int pmem_fd = -1;
3413
3414 unsigned char *bufferaddr;
3415
3416 OMX_SWVDEC_LOG_HIGH("op buffer %d: %d bytes being allocated",
3417 ii,
3418 size);
3419
3420 m_buffer_array_op[ii].ion_info.ion_fd_device =
3421 ion_memory_alloc_map(&m_buffer_array_op[ii].ion_info.ion_alloc_data,
3422 &m_buffer_array_op[ii].ion_info.ion_fd_data,
3423 size,
3424 m_port_op.def.nBufferAlignment);
3425
3426 if (m_buffer_array_op[ii].ion_info.ion_fd_device < 0)
3427 {
3428 retval = OMX_ErrorInsufficientResources;
3429 goto buffer_allocate_op_exit;
3430 }
3431
3432 pmem_fd = m_buffer_array_op[ii].ion_info.ion_fd_data.fd;
3433
3434 bufferaddr = (unsigned char *) mmap(NULL,
3435 size,
3436 PROT_READ | PROT_WRITE,
3437 MAP_SHARED,
3438 pmem_fd,
3439 0);
3440
3441 if (bufferaddr == MAP_FAILED)
3442 {
3443 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3444 pmem_fd,
3445 size);
3446 close(pmem_fd);
3447 ion_memory_free(&m_buffer_array_op[ii].ion_info);
3448 retval = OMX_ErrorInsufficientResources;
3449 goto buffer_allocate_op_exit;
3450 }
3451
3452 *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3453
3454 m_buffer_array_op[ii].buffer_payload.bufferaddr = bufferaddr;
3455 m_buffer_array_op[ii].buffer_payload.pmem_fd = pmem_fd;
3456 m_buffer_array_op[ii].buffer_payload.buffer_len = size;
3457 m_buffer_array_op[ii].buffer_payload.mmaped_size = size;
3458 m_buffer_array_op[ii].buffer_payload.offset = 0;
3459
3460 m_buffer_array_op[ii].buffer_swvdec.p_buffer = bufferaddr;
3461 m_buffer_array_op[ii].buffer_swvdec.size = size;
3462 m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3463 (void *) ((unsigned long) ii);
3464
3465 m_buffer_array_op[ii].buffer_populated = true;
3466
3467 OMX_SWVDEC_LOG_HIGH("op buffer %d: %p, %d bytes",
3468 ii,
3469 bufferaddr,
3470 size);
3471
3472 (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr;
3473 (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
3474 (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION;
3475 (*pp_buffer_hdr)->nAllocLen = size;
3476 (*pp_buffer_hdr)->pAppPrivate = p_app_data;
3477 (*pp_buffer_hdr)->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP;
3478 (*pp_buffer_hdr)->pOutputPortPrivate =
3479 (void *) &(m_buffer_array_op[ii].buffer_payload);
3480
3481 m_port_op.populated = port_op_populated();
3482 m_port_op.unpopulated = OMX_FALSE;
3483 }
3484 else
3485 {
3486 OMX_SWVDEC_LOG_ERROR("all %d op buffers allocated",
3487 m_port_op.def.nBufferCountActual);
3488 retval = OMX_ErrorInsufficientResources;
3489 }
3490
3491 buffer_allocate_op_exit:
3492 return retval;
3493 }
3494
3495 /**
3496 * @brief Allocate input buffer info array.
3497 */
buffer_allocate_ip_info_array()3498 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip_info_array()
3499 {
3500 OMX_ERRORTYPE retval = OMX_ErrorNone;
3501
3502 unsigned int ii;
3503
3504 OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3505
3506 if (m_buffer_array_ip != NULL)
3507 {
3508 OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3509 retval = OMX_ErrorInsufficientResources;
3510 goto buffer_allocate_ip_hdr_exit;
3511 }
3512
3513 // input buffer info array not allocated; allocate here
3514
3515 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3516 m_port_ip.def.nBufferCountActual,
3517 (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3518
3519 m_buffer_array_ip =
3520 (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3521 m_port_ip.def.nBufferCountActual);
3522
3523 if (m_buffer_array_ip == NULL)
3524 {
3525 OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3526 "%d element%s, %d bytes requested",
3527 m_port_ip.def.nBufferCountActual,
3528 (m_port_ip.def.nBufferCountActual > 1) ? "s" : "",
3529 sizeof(OMX_SWVDEC_BUFFER_INFO) *
3530 m_port_ip.def.nBufferCountActual);
3531 retval = OMX_ErrorInsufficientResources;
3532 goto buffer_allocate_ip_hdr_exit;
3533 }
3534
3535 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3536 {
3537 p_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3538
3539 // reset file descriptors
3540
3541 m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
3542 m_buffer_array_ip[ii].ion_info.ion_fd_device = -1;
3543
3544 m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3545 (void *) ((unsigned long) ii);
3546
3547 p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
3548 p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION;
3549 p_buffer_hdr->nOutputPortIndex = OMX_CORE_PORT_INDEX_IP;
3550 p_buffer_hdr->pOutputPortPrivate =
3551 (void *) &(m_buffer_array_ip[ii].buffer_payload);
3552 }
3553
3554 buffer_allocate_ip_hdr_exit:
3555 return retval;
3556 }
3557
3558 /**
3559 * @brief Allocate output buffer info array.
3560 */
buffer_allocate_op_info_array()3561 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op_info_array()
3562 {
3563 OMX_ERRORTYPE retval = OMX_ErrorNone;
3564
3565 unsigned int ii;
3566
3567 OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3568
3569 if (m_buffer_array_op != NULL)
3570 {
3571 OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3572 retval = OMX_ErrorInsufficientResources;
3573 goto buffer_allocate_op_hdr_exit;
3574 }
3575
3576 // output buffer info array not allocated; allocate here
3577
3578 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3579 m_port_op.def.nBufferCountActual,
3580 (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3581
3582 m_buffer_array_op =
3583 (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3584 m_port_op.def.nBufferCountActual);
3585
3586 if (m_buffer_array_op == NULL)
3587 {
3588 OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3589 "%d element%s, %d bytes requested",
3590 m_port_op.def.nBufferCountActual,
3591 (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
3592 sizeof(OMX_SWVDEC_BUFFER_INFO) *
3593 m_port_op.def.nBufferCountActual);
3594 retval = OMX_ErrorInsufficientResources;
3595 goto buffer_allocate_op_hdr_exit;
3596 }
3597
3598 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3599 {
3600 p_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3601
3602 // reset file descriptors
3603
3604 m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3605 m_buffer_array_op[ii].ion_info.ion_fd_device = -1;
3606
3607 m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3608 (void *) ((unsigned long) ii);
3609
3610 p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
3611 p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION;
3612 p_buffer_hdr->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP;
3613 p_buffer_hdr->pOutputPortPrivate =
3614 (void *) &(m_buffer_array_op[ii].buffer_payload);
3615 }
3616
3617 buffer_allocate_op_hdr_exit:
3618 return retval;
3619 }
3620
3621 /**
3622 * @brief Use buffer allocated by IL client; allocate output buffer info array
3623 * if necessary.
3624 *
3625 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3626 * structure.
3627 * @param[in] p_app_data: Pointer to IL client app data.
3628 * @param[in] size: Size of buffer to be allocated in bytes.
3629 * @param[in] p_buffer: Pointer to buffer to be used.
3630 *
3631 * @retval OMX_ERRORTYPE
3632 */
buffer_use_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size,OMX_U8 * p_buffer)3633 OMX_ERRORTYPE omx_swvdec::buffer_use_op(
3634 OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3635 OMX_PTR p_app_data,
3636 OMX_U32 size,
3637 OMX_U8 *p_buffer)
3638 {
3639 OMX_ERRORTYPE retval = OMX_ErrorNone;
3640
3641 unsigned int ii;
3642
3643 (void) size;
3644
3645 if (m_buffer_array_op == NULL)
3646 {
3647 // output buffer info array not allocated; allocate here
3648
3649 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3650 m_port_op.def.nBufferCountActual,
3651 (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3652
3653 if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
3654 {
3655 goto buffer_use_op_exit;
3656 }
3657 }
3658
3659 if (m_meta_buffer_mode && (m_meta_buffer_array == NULL))
3660 {
3661 // meta buffer info array not allocated; allocate here
3662
3663 OMX_SWVDEC_LOG_HIGH("allocating meta buffer info array, %d element%s",
3664 m_port_op.def.nBufferCountActual,
3665 (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3666
3667 if ((retval = meta_buffer_array_allocate()) != OMX_ErrorNone)
3668 {
3669 goto buffer_use_op_exit;
3670 }
3671 }
3672
3673 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3674 {
3675 if (m_buffer_array_op[ii].buffer_populated == false)
3676 {
3677 OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3678 break;
3679 }
3680 }
3681
3682 if (ii < m_port_op.def.nBufferCountActual)
3683 {
3684 struct vdec_bufferpayload *p_buffer_payload;
3685
3686 SWVDEC_BUFFER *p_buffer_swvdec;
3687
3688 *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3689 p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
3690 p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec;
3691
3692 if (m_meta_buffer_mode)
3693 {
3694 p_buffer_swvdec->size = m_port_op.def.nBufferSize;
3695 p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
3696
3697 m_buffer_array_op[ii].buffer_populated = true;
3698
3699 (*pp_buffer_hdr)->pBuffer = p_buffer;
3700 (*pp_buffer_hdr)->pAppPrivate = p_app_data;
3701 (*pp_buffer_hdr)->nAllocLen =
3702 sizeof(struct VideoDecoderOutputMetaData);
3703
3704 OMX_SWVDEC_LOG_HIGH("op buffer %d: %p (meta buffer)",
3705 ii,
3706 *pp_buffer_hdr);
3707
3708 m_port_op.populated = port_op_populated();
3709 m_port_op.unpopulated = OMX_FALSE;
3710 }
3711 else if (m_android_native_buffers)
3712 {
3713 private_handle_t *p_handle;
3714
3715 OMX_U8 *p_buffer_mapped;
3716
3717 p_handle = (private_handle_t *) p_buffer;
3718
3719 if (((OMX_U32) p_handle->size) < m_port_op.def.nBufferSize)
3720 {
3721 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3722 "configured size (%d bytes)",
3723 p_handle->size,
3724 m_port_op.def.nBufferSize);
3725
3726 retval = OMX_ErrorBadParameter;
3727 goto buffer_use_op_exit;
3728 }
3729
3730 m_port_op.def.nBufferSize = p_handle->size;
3731
3732 p_buffer_mapped = (OMX_U8 *) mmap(NULL,
3733 p_handle->size,
3734 PROT_READ | PROT_WRITE,
3735 MAP_SHARED,
3736 p_handle->fd,
3737 0);
3738
3739 if (p_buffer_mapped == MAP_FAILED)
3740 {
3741 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3742 p_handle->fd,
3743 p_handle->size);
3744
3745 retval = OMX_ErrorInsufficientResources;
3746 goto buffer_use_op_exit;
3747 }
3748
3749 p_buffer_payload->bufferaddr = p_buffer_mapped;
3750 p_buffer_payload->pmem_fd = p_handle->fd;
3751 p_buffer_payload->buffer_len = p_handle->size;
3752 p_buffer_payload->mmaped_size = p_handle->size;
3753 p_buffer_payload->offset = 0;
3754
3755 p_buffer_swvdec->p_buffer = p_buffer_mapped;
3756 p_buffer_swvdec->size = m_port_op.def.nBufferSize;
3757 p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
3758
3759 m_buffer_array_op[ii].buffer_populated = true;
3760
3761 (*pp_buffer_hdr)->pBuffer = (m_android_native_buffers ?
3762 ((OMX_U8 *) p_handle) :
3763 p_buffer_mapped);
3764 (*pp_buffer_hdr)->pAppPrivate = p_app_data;
3765 (*pp_buffer_hdr)->nAllocLen = m_port_op.def.nBufferSize;
3766
3767 m_buffer_array_op[ii].ion_info.ion_fd_data.fd = p_handle->fd;
3768
3769 OMX_SWVDEC_LOG_HIGH("op buffer %d: %p",
3770 ii,
3771 *pp_buffer_hdr);
3772
3773 m_port_op.populated = port_op_populated();
3774 m_port_op.unpopulated = OMX_FALSE;
3775 }
3776 else
3777 {
3778 OMX_SWVDEC_LOG_ERROR("neither 'meta buffer mode' nor "
3779 "'android native buffers' enabled");
3780 retval = OMX_ErrorBadParameter;
3781 }
3782 }
3783 else
3784 {
3785 OMX_SWVDEC_LOG_ERROR("all %d op buffers populated",
3786 m_port_op.def.nBufferCountActual);
3787 retval = OMX_ErrorInsufficientResources;
3788 }
3789
3790 buffer_use_op_exit:
3791 return retval;
3792 }
3793
3794 /**
3795 * @brief De-allocate input buffer.
3796 *
3797 * @param[in] p_buffer_hdr: Pointer to buffer header structure.
3798 *
3799 * @retval OMX_ERRORTYPE
3800 */
buffer_deallocate_ip(OMX_BUFFERHEADERTYPE * p_buffer_hdr)3801 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_ip(
3802 OMX_BUFFERHEADERTYPE *p_buffer_hdr)
3803 {
3804 OMX_ERRORTYPE retval = OMX_ErrorNone;
3805
3806 unsigned int ii;
3807
3808 if (p_buffer_hdr == NULL)
3809 {
3810 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
3811 retval = OMX_ErrorBadParameter;
3812 goto buffer_deallocate_ip_exit;
3813 }
3814 else if (m_buffer_array_ip == NULL)
3815 {
3816 OMX_SWVDEC_LOG_ERROR("ip buffer array not allocated");
3817 retval = OMX_ErrorBadParameter;
3818 goto buffer_deallocate_ip_exit;
3819 }
3820
3821 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3822 {
3823 if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
3824 {
3825 OMX_SWVDEC_LOG_LOW("%p has index %d",
3826 p_buffer_hdr->pBuffer,
3827 ii);
3828 break;
3829 }
3830 }
3831
3832 if (ii < m_port_ip.def.nBufferCountActual)
3833 {
3834 if (m_buffer_array_ip[ii].buffer_payload.pmem_fd > 0)
3835 {
3836 m_buffer_array_ip[ii].buffer_populated = false;
3837
3838 m_port_ip.populated = OMX_FALSE;
3839
3840 munmap(m_buffer_array_ip[ii].buffer_payload.bufferaddr,
3841 m_buffer_array_ip[ii].buffer_payload.mmaped_size);
3842
3843 close(m_buffer_array_ip[ii].buffer_payload.pmem_fd);
3844 m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
3845
3846 ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3847
3848 // check if all buffers are unpopulated
3849 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3850 {
3851 if (m_buffer_array_ip[ii].buffer_populated)
3852 break;
3853 }
3854
3855 // if no buffers are populated, de-allocate input buffer info array
3856 if (ii == m_port_ip.def.nBufferCountActual)
3857 {
3858 buffer_deallocate_ip_info_array();
3859 m_port_ip.unpopulated = OMX_TRUE;
3860 }
3861 }
3862 else
3863 {
3864 OMX_SWVDEC_LOG_ERROR("%p: pmem_fd %d",
3865 p_buffer_hdr->pBuffer,
3866 m_buffer_array_ip[ii].buffer_payload.pmem_fd);
3867 }
3868 }
3869 else
3870 {
3871 OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
3872 retval = OMX_ErrorBadParameter;
3873 }
3874
3875 buffer_deallocate_ip_exit:
3876 return retval;
3877 }
3878
3879 /**
3880 * @brief De-allocate output buffer.
3881 *
3882 * @param[in] p_buffer_hdr: Pointer to buffer header structure.
3883 *
3884 * @retval OMX_ERRORTYPE
3885 */
buffer_deallocate_op(OMX_BUFFERHEADERTYPE * p_buffer_hdr)3886 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_op(
3887 OMX_BUFFERHEADERTYPE *p_buffer_hdr)
3888 {
3889 OMX_ERRORTYPE retval = OMX_ErrorNone;
3890
3891 unsigned int ii;
3892
3893 if (p_buffer_hdr == NULL)
3894 {
3895 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
3896 retval = OMX_ErrorBadParameter;
3897 goto buffer_deallocate_op_exit;
3898 }
3899 else if (m_buffer_array_op == NULL)
3900 {
3901 OMX_SWVDEC_LOG_ERROR("op buffer array not allocated");
3902 retval = OMX_ErrorBadParameter;
3903 goto buffer_deallocate_op_exit;
3904 }
3905
3906 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3907 {
3908 if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
3909 {
3910 OMX_SWVDEC_LOG_LOW("%p has index %d",
3911 p_buffer_hdr->pBuffer,
3912 ii);
3913 break;
3914 }
3915 }
3916
3917 if (ii < m_port_op.def.nBufferCountActual)
3918 {
3919 assert(m_buffer_array_op[ii].buffer_payload.pmem_fd > 0);
3920
3921 if (m_meta_buffer_mode)
3922 {
3923 // do nothing; munmap() & close() done in FBD or RR
3924 }
3925 else if (m_android_native_buffers)
3926 {
3927 munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
3928 m_buffer_array_op[ii].buffer_payload.mmaped_size);
3929 m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3930 }
3931 else if (m_sync_frame_decoding_mode)
3932 {
3933 munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
3934 m_buffer_array_op[ii].buffer_payload.mmaped_size);
3935 close(m_buffer_array_op[ii].buffer_payload.pmem_fd);
3936 m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3937 ion_memory_free(&m_buffer_array_op[ii].ion_info);
3938 }
3939 else
3940 {
3941 assert(0);
3942 }
3943
3944 m_buffer_array_op[ii].buffer_populated = false;
3945
3946 m_port_op.populated = OMX_FALSE;
3947
3948 // check if all buffers are unpopulated
3949 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3950 {
3951 if (m_buffer_array_op[ii].buffer_populated)
3952 break;
3953 }
3954
3955 // if no buffers are populated, de-allocate output buffer info array
3956 if (ii == m_port_op.def.nBufferCountActual)
3957 {
3958 buffer_deallocate_op_info_array();
3959 m_port_op.unpopulated = OMX_TRUE;
3960
3961 if (m_meta_buffer_mode)
3962 {
3963 meta_buffer_array_deallocate();
3964 }
3965 }
3966 }
3967 else
3968 {
3969 OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
3970 retval = OMX_ErrorBadParameter;
3971 }
3972
3973 buffer_deallocate_op_exit:
3974 return retval;
3975 }
3976
3977 /**
3978 * @brief De-allocate input buffer info array.
3979 */
buffer_deallocate_ip_info_array()3980 void omx_swvdec::buffer_deallocate_ip_info_array()
3981 {
3982 assert(m_buffer_array_ip != NULL);
3983
3984 free(m_buffer_array_ip);
3985 m_buffer_array_ip = NULL;
3986 }
3987
3988 /**
3989 * @brief De-allocate output buffer info array.
3990 */
buffer_deallocate_op_info_array()3991 void omx_swvdec::buffer_deallocate_op_info_array()
3992 {
3993 assert(m_buffer_array_op != NULL);
3994
3995 free(m_buffer_array_op);
3996 m_buffer_array_op = NULL;
3997 }
3998
3999 /**
4000 * @brief Allocate meta buffer info array.
4001 *
4002 * @retval OMX_ERRORTYPE
4003 */
meta_buffer_array_allocate()4004 OMX_ERRORTYPE omx_swvdec::meta_buffer_array_allocate()
4005 {
4006 OMX_ERRORTYPE retval = OMX_ErrorNone;
4007
4008 m_meta_buffer_array = ((OMX_SWVDEC_META_BUFFER_INFO *)
4009 calloc(sizeof(OMX_SWVDEC_META_BUFFER_INFO),
4010 m_port_op.def.nBufferCountActual));
4011
4012 if (m_meta_buffer_array == NULL)
4013 {
4014 OMX_SWVDEC_LOG_ERROR("failed to allocate meta_buffer info array; "
4015 "%d element%s, %d bytes requested",
4016 m_port_op.def.nBufferCountActual,
4017 (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
4018 sizeof(OMX_SWVDEC_META_BUFFER_INFO) *
4019 m_port_op.def.nBufferCountActual);
4020
4021 retval = OMX_ErrorInsufficientResources;
4022 }
4023
4024 return retval;
4025 }
4026
4027 /**
4028 * @brief De-allocate meta buffer info array.
4029 */
meta_buffer_array_deallocate()4030 void omx_swvdec::meta_buffer_array_deallocate()
4031 {
4032 assert(m_meta_buffer_array != NULL);
4033
4034 free(m_meta_buffer_array);
4035 m_meta_buffer_array = NULL;
4036 }
4037
4038 /**
4039 * @brief Add meta buffer reference.
4040 *
4041 * @param[in] index:
4042 * @param[in] fd:
4043 * @param[in] offset:
4044 */
meta_buffer_ref_add(unsigned int index,unsigned int fd,unsigned int offset)4045 void omx_swvdec::meta_buffer_ref_add(unsigned int index,
4046 unsigned int fd,
4047 unsigned int offset)
4048 {
4049 pthread_mutex_lock(&m_meta_buffer_array_mutex);
4050
4051 if ((m_meta_buffer_array[index].dup_fd != 0) &&
4052 (m_meta_buffer_array[index].fd != fd) &&
4053 (m_meta_buffer_array[index].offset != offset))
4054 {
4055 OMX_SWVDEC_LOG_LOW("index %d taken by fd %d, offset %d",
4056 index,
4057 m_meta_buffer_array[index].fd,
4058 m_meta_buffer_array[index].offset);
4059 }
4060 else
4061 {
4062 if (m_meta_buffer_array[index].dup_fd == 0)
4063 {
4064 m_meta_buffer_array[index].fd = fd;
4065 m_meta_buffer_array[index].dup_fd = dup(fd);
4066 m_meta_buffer_array[index].offset = offset;
4067 }
4068
4069 m_meta_buffer_array[index].ref_count++;
4070 }
4071
4072 pthread_mutex_unlock(&m_meta_buffer_array_mutex);
4073 }
4074
4075 /**
4076 * @brief Remove meta buffer reference.
4077 *
4078 * @param[in] fd:
4079 * @param[in] offset:
4080 */
meta_buffer_ref_remove(unsigned int fd,unsigned int offset)4081 void omx_swvdec::meta_buffer_ref_remove(unsigned int fd,
4082 unsigned int offset)
4083 {
4084 unsigned int ii;
4085
4086 pthread_mutex_lock(&m_meta_buffer_array_mutex);
4087
4088 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4089 {
4090 if ((m_meta_buffer_array[ii].fd == fd) &&
4091 (m_meta_buffer_array[ii].offset == offset))
4092 {
4093 m_meta_buffer_array[ii].ref_count--;
4094
4095 if (m_meta_buffer_array[ii].ref_count == 0)
4096 {
4097 close(m_meta_buffer_array[ii].dup_fd);
4098
4099 m_meta_buffer_array[ii].fd = 0;
4100 m_meta_buffer_array[ii].dup_fd = 0;
4101 m_meta_buffer_array[ii].offset = 0;
4102
4103 munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
4104 m_buffer_array_op[ii].buffer_payload.mmaped_size);
4105
4106 m_buffer_array_op[ii].buffer_payload.bufferaddr = NULL;
4107 m_buffer_array_op[ii].buffer_payload.offset = 0;
4108 m_buffer_array_op[ii].buffer_payload.mmaped_size = 0;
4109
4110 m_buffer_array_op[ii].buffer_swvdec.p_buffer = NULL;
4111 m_buffer_array_op[ii].buffer_swvdec.size = 0;
4112 }
4113
4114 break;
4115 }
4116 }
4117
4118 assert(ii < m_port_op.def.nBufferCountActual);
4119
4120 pthread_mutex_unlock(&m_meta_buffer_array_mutex);
4121 }
4122
4123 /**
4124 * @brief Check if ip port is populated, i.e., if all ip buffers are populated.
4125 *
4126 * @retval true
4127 * @retval false
4128 */
port_ip_populated()4129 OMX_BOOL omx_swvdec::port_ip_populated()
4130 {
4131 OMX_BOOL retval = OMX_FALSE;
4132
4133 if (m_buffer_array_ip != NULL)
4134 {
4135 unsigned int ii;
4136
4137 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4138 {
4139 if (m_buffer_array_ip[ii].buffer_populated == false)
4140 {
4141 break;
4142 }
4143 }
4144
4145 if (ii == m_port_ip.def.nBufferCountActual)
4146 {
4147 retval = OMX_TRUE;
4148 }
4149 }
4150
4151 return retval;
4152 }
4153
4154 /**
4155 * @brief Check if op port is populated, i.e., if all op buffers are populated.
4156 *
4157 * @retval true
4158 * @retval false
4159 */
port_op_populated()4160 OMX_BOOL omx_swvdec::port_op_populated()
4161 {
4162 OMX_BOOL retval = OMX_FALSE;
4163
4164 if (m_buffer_array_op != NULL)
4165 {
4166 unsigned int ii;
4167
4168 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4169 {
4170 if (m_buffer_array_op[ii].buffer_populated == false)
4171 {
4172 break;
4173 }
4174 }
4175
4176 if (ii == m_port_op.def.nBufferCountActual)
4177 {
4178 retval = OMX_TRUE;
4179 }
4180 }
4181
4182 return retval;
4183 }
4184
4185 /**
4186 * @brief Flush input, output, or both input & output ports.
4187 *
4188 * @param[in] port_index: Index of port to flush.
4189 *
4190 * @retval OMX_ERRORTYPE
4191 */
flush(unsigned int port_index)4192 OMX_ERRORTYPE omx_swvdec::flush(unsigned int port_index)
4193 {
4194 OMX_ERRORTYPE retval = OMX_ErrorNone;
4195
4196 if (((port_index == OMX_CORE_PORT_INDEX_IP) &&
4197 m_port_ip.flush_inprogress) ||
4198 ((port_index == OMX_CORE_PORT_INDEX_OP) &&
4199 m_port_op.flush_inprogress) ||
4200 ((port_index == OMX_ALL) &&
4201 m_port_ip.flush_inprogress &&
4202 m_port_op.flush_inprogress))
4203 {
4204 OMX_SWVDEC_LOG_HIGH("flush port %d already in progress", port_index);
4205 }
4206 else
4207 {
4208 SWVDEC_FLUSH_TYPE swvdec_flush_type;
4209
4210 SWVDEC_STATUS retval_swvdec;
4211
4212 if (port_index == OMX_CORE_PORT_INDEX_IP)
4213 {
4214 m_port_ip.flush_inprogress = OMX_TRUE;
4215
4216 // no separate SwVdec flush type for input
4217 }
4218 else if (port_index == OMX_CORE_PORT_INDEX_OP)
4219 {
4220 m_port_op.flush_inprogress = OMX_TRUE;
4221
4222 swvdec_flush_type = (m_port_ip.flush_inprogress ?
4223 SWVDEC_FLUSH_TYPE_ALL :
4224 SWVDEC_FLUSH_TYPE_OP);
4225
4226 if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4227 swvdec_flush_type)) !=
4228 SWVDEC_STATUS_SUCCESS)
4229 {
4230 retval = retval_swvdec2omx(retval_swvdec);
4231 }
4232 }
4233 else if (port_index == OMX_ALL)
4234 {
4235 m_port_ip.flush_inprogress = OMX_TRUE;
4236 m_port_op.flush_inprogress = OMX_TRUE;
4237
4238 swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL;
4239
4240 if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4241 swvdec_flush_type)) !=
4242 SWVDEC_STATUS_SUCCESS)
4243 {
4244 retval = retval_swvdec2omx(retval_swvdec);
4245 }
4246 }
4247 else
4248 {
4249 assert(0);
4250 }
4251 }
4252
4253 return retval;
4254 }
4255
4256 /**
4257 * @brief Allocate & map ION memory.
4258 */
ion_memory_alloc_map(struct ion_allocation_data * p_alloc_data,struct ion_fd_data * p_fd_data,OMX_U32 size,OMX_U32 alignment)4259 int omx_swvdec::ion_memory_alloc_map(struct ion_allocation_data *p_alloc_data,
4260 struct ion_fd_data *p_fd_data,
4261 OMX_U32 size,
4262 OMX_U32 alignment)
4263 {
4264 int fd = -EINVAL;
4265 int rc = -EINVAL;
4266
4267 if ((p_alloc_data == NULL) || (p_fd_data == NULL) || (size == 0))
4268 {
4269 OMX_SWVDEC_LOG_ERROR("invalid arguments");
4270 goto ion_memory_alloc_map_exit;
4271 }
4272
4273 if ((fd = open("/dev/ion", O_RDONLY)) < 0)
4274 {
4275 OMX_SWVDEC_LOG_ERROR("failed to open ion device; fd = %d", fd);
4276 goto ion_memory_alloc_map_exit;
4277 }
4278
4279 p_alloc_data->len = size;
4280 p_alloc_data->align = (alignment < 4096) ? 4096 : alignment;
4281 p_alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
4282 p_alloc_data->flags = 0;
4283
4284 OMX_SWVDEC_LOG_LOW("heap_id_mask 0x%08x, len %d, align %d",
4285 p_alloc_data->heap_id_mask,
4286 p_alloc_data->len,
4287 p_alloc_data->align);
4288
4289 rc = ioctl(fd, ION_IOC_ALLOC, p_alloc_data);
4290
4291 if (rc || (p_alloc_data->handle == 0))
4292 {
4293 OMX_SWVDEC_LOG_ERROR("ioctl() for allocation failed");
4294 close(fd);
4295 fd = -ENOMEM;
4296 goto ion_memory_alloc_map_exit;
4297 }
4298
4299 p_fd_data->handle = p_alloc_data->handle;
4300
4301 if (ioctl(fd, ION_IOC_MAP, p_fd_data))
4302 {
4303 struct vdec_ion ion_buf_info;
4304
4305 OMX_SWVDEC_LOG_ERROR("ioctl() for mapping failed");
4306
4307 ion_buf_info.ion_alloc_data = *p_alloc_data;
4308 ion_buf_info.ion_fd_device = fd;
4309 ion_buf_info.ion_fd_data = *p_fd_data;
4310
4311 ion_memory_free(&ion_buf_info);
4312
4313 p_fd_data->fd = -1;
4314 close(fd);
4315 fd = -ENOMEM;
4316 goto ion_memory_alloc_map_exit;
4317 }
4318
4319 ion_memory_alloc_map_exit:
4320 return fd;
4321 }
4322
4323 /**
4324 * @brief Free ION memory.
4325 */
ion_memory_free(struct vdec_ion * p_ion_buf_info)4326 void omx_swvdec::ion_memory_free(struct vdec_ion *p_ion_buf_info)
4327 {
4328 if (p_ion_buf_info == NULL)
4329 {
4330 OMX_SWVDEC_LOG_ERROR("p_ion_buf_info = NULL");
4331 goto ion_memory_free_exit;
4332 }
4333
4334 if (ioctl(p_ion_buf_info->ion_fd_device,
4335 ION_IOC_FREE,
4336 &p_ion_buf_info->ion_alloc_data.handle))
4337 {
4338 OMX_SWVDEC_LOG_ERROR("ioctl() for freeing failed");
4339 }
4340
4341 close(p_ion_buf_info->ion_fd_device);
4342
4343 p_ion_buf_info->ion_fd_device = -1;
4344 p_ion_buf_info->ion_alloc_data.handle = 0;
4345 p_ion_buf_info->ion_fd_data.fd = -1;
4346
4347 ion_memory_free_exit:
4348 return;
4349 }
4350
4351 /**
4352 * ----------------------------
4353 * component callback functions
4354 * ----------------------------
4355 */
4356
4357 /**
4358 * @brief Empty buffer done callback.
4359 *
4360 * @param[in] p_buffer_ip: Pointer to input buffer structure.
4361 */
swvdec_empty_buffer_done(SWVDEC_BUFFER * p_buffer_ip)4362 void omx_swvdec::swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip)
4363 {
4364 unsigned long index = (unsigned long) p_buffer_ip->p_client_data;
4365
4366 async_post_event(OMX_SWVDEC_EVENT_EBD,
4367 (unsigned long) &m_buffer_array_ip[index].buffer_header,
4368 index);
4369 }
4370
4371 /**
4372 * @brief Fill buffer done callback.
4373 *
4374 * @param[in] p_buffer_op: Pointer to output buffer structure.
4375 */
swvdec_fill_buffer_done(SWVDEC_BUFFER * p_buffer_op)4376 void omx_swvdec::swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op)
4377 {
4378 unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4379
4380 OMX_BUFFERHEADERTYPE *p_buffer_hdr;
4381
4382 if (index < ((unsigned long) m_port_op.def.nBufferCountActual))
4383 {
4384 p_buffer_hdr = &m_buffer_array_op[index].buffer_header;
4385
4386 p_buffer_hdr->nFlags = p_buffer_op->flags;
4387 p_buffer_hdr->nTimeStamp = p_buffer_op->timestamp;
4388 p_buffer_hdr->nFilledLen = ((m_meta_buffer_mode &&
4389 p_buffer_op->filled_length) ?
4390 p_buffer_hdr->nAllocLen :
4391 p_buffer_op->filled_length);
4392 }
4393
4394 async_post_event(OMX_SWVDEC_EVENT_FBD,
4395 (unsigned long) &m_buffer_array_op[index].buffer_header,
4396 index);
4397 }
4398
4399 /**
4400 * @brief Event handler callback.
4401 *
4402 * @param[in] event: Event.
4403 * @param[in] p_data: Pointer to event-specific data.
4404 */
swvdec_event_handler(SWVDEC_EVENT event,void * p_data)4405 void omx_swvdec::swvdec_event_handler(SWVDEC_EVENT event, void *p_data)
4406 {
4407 switch (event)
4408 {
4409
4410 case SWVDEC_EVENT_FLUSH_ALL_DONE:
4411 {
4412 async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_IP, 0, 0);
4413 async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4414 break;
4415 }
4416
4417 case SWVDEC_EVENT_FLUSH_OP_DONE:
4418 {
4419 async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4420 break;
4421 }
4422
4423 case SWVDEC_EVENT_RELEASE_REFERENCE:
4424 {
4425 SWVDEC_BUFFER *p_buffer_op = (SWVDEC_BUFFER *) p_data;
4426
4427 unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4428
4429 OMX_SWVDEC_LOG_LOW("release reference: %p", p_buffer_op->p_buffer);
4430
4431 assert(index < ((unsigned long) m_port_op.def.nBufferCountActual));
4432
4433 if (m_meta_buffer_mode)
4434 {
4435 meta_buffer_ref_remove(
4436 m_buffer_array_op[index].buffer_payload.pmem_fd,
4437 m_buffer_array_op[index].buffer_payload.offset);
4438 }
4439
4440 break;
4441 }
4442
4443 case SWVDEC_EVENT_RECONFIG_REQUIRED:
4444 {
4445 async_post_event(OMX_SWVDEC_EVENT_PORT_RECONFIG, 0, 0);
4446 break;
4447 }
4448
4449 case SWVDEC_EVENT_FATAL_ERROR:
4450 default:
4451 {
4452 async_post_event(OMX_SWVDEC_EVENT_ERROR, OMX_ErrorHardware, 0);
4453 break;
4454 }
4455
4456 }
4457 }
4458
4459 /**
4460 * @brief Translate SwVdec status return value to OMX error type return value.
4461 *
4462 * @param[in] retval_swvdec: SwVdec status return value.
4463 *
4464 * @retval OMX_ERRORTYPE
4465 */
retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)4466 OMX_ERRORTYPE omx_swvdec::retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)
4467 {
4468 OMX_ERRORTYPE retval_omx;
4469
4470 switch (retval_swvdec)
4471 {
4472
4473 SWVDEC_STATUS_SUCCESS:
4474 retval_omx = OMX_ErrorNone;
4475 break;
4476
4477 SWVDEC_STATUS_FAILURE:
4478 retval_omx = OMX_ErrorUndefined;
4479 break;
4480
4481 SWVDEC_STATUS_NULL_POINTER:
4482 SWVDEC_STATUS_INVALID_PARAMETERS:
4483 retval_omx = OMX_ErrorBadParameter;
4484 break;
4485
4486 SWVDEC_STATUS_INVALID_STATE:
4487 retval_omx = OMX_ErrorInvalidState;
4488 break;
4489
4490 SWVDEC_STATUS_INSUFFICIENT_RESOURCES:
4491 retval_omx = OMX_ErrorInsufficientResources;
4492 break;
4493
4494 SWVDEC_STATUS_UNSUPPORTED:
4495 retval_omx = OMX_ErrorUnsupportedSetting;
4496 break;
4497
4498 SWVDEC_STATUS_NOT_IMPLEMENTED:
4499 retval_omx = OMX_ErrorNotImplemented;
4500 break;
4501
4502 default:
4503 retval_omx = OMX_ErrorUndefined;
4504 break;
4505
4506 }
4507
4508 return retval_omx;
4509 }
4510
4511 /**
4512 * @brief Create asynchronous thread.
4513 *
4514 * @retval OMX_ERRORTYPE
4515 */
async_thread_create()4516 OMX_ERRORTYPE omx_swvdec::async_thread_create()
4517 {
4518 OMX_ERRORTYPE retval = OMX_ErrorNone;
4519
4520 pthread_attr_t thread_attributes;
4521
4522 if (sem_init(&m_async_thread.sem_thread_created, 0, 0))
4523 {
4524 OMX_SWVDEC_LOG_ERROR("failed to create async thread created semaphore");
4525 retval = OMX_ErrorInsufficientResources;
4526 }
4527 else if (sem_init(&m_async_thread.sem_event, 0, 0))
4528 {
4529 OMX_SWVDEC_LOG_ERROR("failed to create async thread event semaphore");
4530 retval = OMX_ErrorInsufficientResources;
4531 }
4532 else if (pthread_attr_init(&thread_attributes))
4533 {
4534 OMX_SWVDEC_LOG_ERROR("failed to create thread attributes object");
4535 retval = OMX_ErrorInsufficientResources;
4536 }
4537 else if (pthread_attr_setdetachstate(&thread_attributes,
4538 PTHREAD_CREATE_JOINABLE))
4539 {
4540 OMX_SWVDEC_LOG_ERROR("failed to set detach state attribute");
4541 retval = OMX_ErrorInsufficientResources;
4542
4543 pthread_attr_destroy(&thread_attributes);
4544 }
4545 else
4546 {
4547 m_async_thread.created = false;
4548 m_async_thread.exit = false;
4549
4550 if (pthread_create(&m_async_thread.handle,
4551 &thread_attributes,
4552 (void *(*)(void *)) async_thread,
4553 this))
4554 {
4555 OMX_SWVDEC_LOG_ERROR("failed to create async thread");
4556 retval = OMX_ErrorInsufficientResources;
4557
4558 pthread_attr_destroy(&thread_attributes);
4559 }
4560 else
4561 {
4562 if (pthread_setname_np(m_async_thread.handle, "swvdec_async"))
4563 {
4564 // don't return error
4565 OMX_SWVDEC_LOG_ERROR("failed to set async thread name");
4566 }
4567
4568 sem_wait(&m_async_thread.sem_thread_created);
4569 m_async_thread.created = true;
4570 }
4571 }
4572
4573 return retval;
4574 }
4575
4576 /**
4577 * @brief Destroy asynchronous thread.
4578 */
async_thread_destroy()4579 void omx_swvdec::async_thread_destroy()
4580 {
4581 if (m_async_thread.created)
4582 {
4583 m_async_thread.exit = true;
4584 sem_post(&m_async_thread.sem_event);
4585
4586 pthread_join(m_async_thread.handle, NULL);
4587 m_async_thread.created = false;
4588 }
4589
4590 m_async_thread.exit = false;
4591
4592 sem_destroy(&m_async_thread.sem_event);
4593 sem_destroy(&m_async_thread.sem_thread_created);
4594 }
4595
4596 /**
4597 * @brief Post event to appropriate queue.
4598 *
4599 * @param[in] event_id: Event ID.
4600 * @param[in] event_param1: Event parameter 1.
4601 * @param[in] event_param2: Event parameter 2.
4602 *
4603 * @retval true if post event successful
4604 * @retval false if post event unsuccessful
4605 */
async_post_event(unsigned long event_id,unsigned long event_param1,unsigned long event_param2)4606 bool omx_swvdec::async_post_event(unsigned long event_id,
4607 unsigned long event_param1,
4608 unsigned long event_param2)
4609 {
4610 OMX_SWVDEC_EVENT_INFO event_info;
4611
4612 bool retval = true;
4613
4614 event_info.event_id = event_id;
4615 event_info.event_param1 = event_param1;
4616 event_info.event_param2 = event_param2;
4617
4618 switch (event_id)
4619 {
4620
4621 case OMX_SWVDEC_EVENT_ETB:
4622 case OMX_SWVDEC_EVENT_EBD:
4623 {
4624 retval = m_queue_port_ip.push(&event_info);
4625 break;
4626 }
4627
4628 case OMX_SWVDEC_EVENT_FTB:
4629 case OMX_SWVDEC_EVENT_FBD:
4630 {
4631 retval = m_queue_port_op.push(&event_info);
4632 break;
4633 }
4634
4635 default:
4636 {
4637 retval = m_queue_command.push(&event_info);
4638 break;
4639 }
4640
4641 }
4642
4643 if (retval == true)
4644 {
4645 sem_post(&m_async_thread.sem_event);
4646 }
4647
4648 return retval;
4649 }
4650
4651 /**
4652 * @brief Asynchronous thread.
4653 *
4654 * @param[in] p_cmp: Pointer to OMX SwVdec component class.
4655 */
async_thread(void * p_cmp)4656 void omx_swvdec::async_thread(void *p_cmp)
4657 {
4658 if (p_cmp == NULL)
4659 {
4660 OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
4661 }
4662 else
4663 {
4664 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_cmp;
4665
4666 ASYNC_THREAD *p_async_thread = &p_omx_swvdec->m_async_thread;
4667
4668 OMX_SWVDEC_LOG_HIGH("created");
4669
4670 sem_post(&p_async_thread->sem_thread_created);
4671
4672 while (p_async_thread->exit == false)
4673 {
4674 sem_wait(&p_async_thread->sem_event);
4675
4676 if (p_async_thread->exit == true)
4677 {
4678 break;
4679 }
4680
4681 p_omx_swvdec->async_process_event(p_cmp);
4682 }
4683 }
4684
4685 OMX_SWVDEC_LOG_HIGH("exiting");
4686 }
4687
4688 /**
4689 * @brief Process event.
4690 *
4691 * @param[in] p_cmp: Pointer to OMX SwVdec component class.
4692 */
async_process_event(void * p_cmp)4693 void omx_swvdec::async_process_event(void *p_cmp)
4694 {
4695 omx_swvdec *p_omx_swvdec;
4696
4697 OMX_SWVDEC_EVENT_INFO event_info;
4698
4699 OMX_ERRORTYPE retval = OMX_ErrorNone;
4700
4701 if (p_cmp == NULL)
4702 {
4703 OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
4704 goto async_process_event_exit;
4705 }
4706
4707 p_omx_swvdec = (omx_swvdec *) p_cmp;
4708
4709 // NOTE: queues popped in order of priority; do not change!
4710
4711 if ((p_omx_swvdec->m_queue_command.pop(&event_info) == false) &&
4712 (p_omx_swvdec->m_queue_port_op.pop(&event_info) == false) &&
4713 (p_omx_swvdec->m_queue_port_ip.pop(&event_info) == false))
4714 {
4715 OMX_SWVDEC_LOG_LOW("no event popped");
4716 goto async_process_event_exit;
4717 }
4718
4719 switch (event_info.event_id)
4720 {
4721
4722 case OMX_SWVDEC_EVENT_CMD:
4723 {
4724 OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1;
4725 OMX_U32 param = (OMX_U32) event_info.event_param2;
4726
4727 retval = p_omx_swvdec->async_process_event_cmd(cmd, param);
4728 break;
4729 }
4730
4731 case OMX_SWVDEC_EVENT_CMD_ACK:
4732 {
4733 OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1;
4734 OMX_U32 param = (OMX_U32) event_info.event_param2;
4735
4736 retval = p_omx_swvdec->async_process_event_cmd_ack(cmd, param);
4737 break;
4738 }
4739
4740 case OMX_SWVDEC_EVENT_ERROR:
4741 {
4742 OMX_ERRORTYPE error_code = (OMX_ERRORTYPE) event_info.event_param1;
4743
4744 retval = p_omx_swvdec->async_process_event_error(error_code);
4745 break;
4746 }
4747
4748 case OMX_SWVDEC_EVENT_ETB:
4749 {
4750 OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4751 (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4752
4753 unsigned int index = event_info.event_param2;
4754
4755 retval = p_omx_swvdec->async_process_event_etb(p_buffer_hdr, index);
4756 break;
4757 }
4758
4759 case OMX_SWVDEC_EVENT_FTB:
4760 {
4761 OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4762 (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4763
4764 unsigned int index = event_info.event_param2;
4765
4766 retval = p_omx_swvdec->async_process_event_ftb(p_buffer_hdr, index);
4767 break;
4768 }
4769
4770 case OMX_SWVDEC_EVENT_EBD:
4771 {
4772 OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4773 (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4774
4775 unsigned int index = event_info.event_param2;
4776
4777 retval = p_omx_swvdec->async_process_event_ebd(p_buffer_hdr, index);
4778 break;
4779 }
4780
4781 case OMX_SWVDEC_EVENT_FBD:
4782 {
4783 OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4784 (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4785
4786 unsigned int index = event_info.event_param2;
4787
4788 retval = p_omx_swvdec->async_process_event_fbd(p_buffer_hdr, index);
4789 break;
4790 }
4791
4792 case OMX_SWVDEC_EVENT_EOS:
4793 {
4794 retval = p_omx_swvdec->async_process_event_eos();
4795 break;
4796 }
4797
4798 case OMX_SWVDEC_EVENT_FLUSH_PORT_IP:
4799 {
4800 retval = p_omx_swvdec->async_process_event_flush_port_ip();
4801 break;
4802 }
4803
4804 case OMX_SWVDEC_EVENT_FLUSH_PORT_OP:
4805 {
4806 retval = p_omx_swvdec->async_process_event_flush_port_op();
4807 break;
4808 }
4809
4810 case OMX_SWVDEC_EVENT_PORT_RECONFIG:
4811 {
4812 retval = p_omx_swvdec->async_process_event_port_reconfig();
4813 break;
4814 }
4815
4816 default:
4817 {
4818 assert(0);
4819 retval = OMX_ErrorUndefined;
4820 break;
4821 }
4822
4823 }
4824
4825 if (retval != OMX_ErrorNone)
4826 {
4827 p_omx_swvdec->async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
4828 }
4829
4830 async_process_event_exit:
4831 return;
4832 }
4833
4834 /**
4835 * @brief Process command event.
4836 *
4837 * @param[in] cmd: Command.
4838 * @param[in] param: Command parameter.
4839 *
4840 * @retval OMX_ERRORTYPE
4841 */
async_process_event_cmd(OMX_COMMANDTYPE cmd,OMX_U32 param)4842 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd(OMX_COMMANDTYPE cmd,
4843 OMX_U32 param)
4844 {
4845 OMX_ERRORTYPE retval = OMX_ErrorNone;
4846
4847 bool cmd_ack = false; // set to 'true' if command is to be acknowledged
4848
4849 SWVDEC_STATUS retval_swvdec;
4850
4851 switch (cmd)
4852 {
4853
4854 case OMX_CommandStateSet:
4855 {
4856 retval = async_process_event_cmd_state_set(&cmd_ack,
4857 (OMX_STATETYPE) param);
4858 break;
4859 }
4860
4861 case OMX_CommandFlush:
4862 {
4863 retval = async_process_event_cmd_flush((unsigned int) param);
4864 break;
4865 }
4866
4867 case OMX_CommandPortDisable:
4868 {
4869 retval = async_process_event_cmd_port_disable(&cmd_ack,
4870 (unsigned int) param);
4871 break;
4872 }
4873
4874 case OMX_CommandPortEnable:
4875 {
4876 retval = async_process_event_cmd_port_enable(&cmd_ack,
4877 (unsigned int) param);
4878 break;
4879 }
4880
4881 default:
4882 {
4883 OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
4884
4885 retval = OMX_ErrorBadParameter;
4886 break;
4887 }
4888
4889 } // switch (cmd)
4890
4891 // post appropriate event
4892
4893 if (retval != OMX_ErrorNone)
4894 {
4895 async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
4896 }
4897 else if (cmd_ack)
4898 {
4899 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, cmd, param);
4900 }
4901
4902 // post to command semaphore
4903 sem_post(&m_sem_cmd);
4904
4905 return retval;
4906 }
4907
4908 /**
4909 * @brief Process command acknowledgement event.
4910 *
4911 * @param[in] cmd: Command.
4912 * @param[in] param: Command parameter.
4913 *
4914 * @retval OMX_ERRORTYPE
4915 */
async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,OMX_U32 param)4916 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,
4917 OMX_U32 param)
4918 {
4919 OMX_ERRORTYPE retval = OMX_ErrorNone;
4920
4921 switch (cmd)
4922 {
4923
4924 case OMX_CommandStateSet:
4925 {
4926 m_state = (OMX_STATETYPE) param;
4927
4928 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
4929 "OMX_CommandStateSet, %s",
4930 OMX_STATETYPE_STRING(m_state));
4931
4932 m_callback.EventHandler(&m_cmp,
4933 m_app_data,
4934 OMX_EventCmdComplete,
4935 OMX_CommandStateSet,
4936 (OMX_U32) m_state,
4937 NULL);
4938 break;
4939 }
4940
4941 case OMX_CommandFlush:
4942 case OMX_CommandPortEnable:
4943 case OMX_CommandPortDisable:
4944 {
4945 if ((cmd == OMX_CommandPortEnable) && m_port_reconfig_inprogress)
4946 {
4947 m_port_reconfig_inprogress = false;
4948 }
4949
4950 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
4951 "%s, port index %d",
4952 OMX_COMMANDTYPE_STRING(cmd),
4953 param);
4954
4955 m_callback.EventHandler(&m_cmp,
4956 m_app_data,
4957 OMX_EventCmdComplete,
4958 cmd,
4959 param,
4960 NULL);
4961 break;
4962 }
4963
4964 default:
4965 {
4966 OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
4967 retval = OMX_ErrorBadParameter;
4968 break;
4969 }
4970
4971 } // switch (cmd)
4972
4973 return retval;
4974 }
4975
4976 /**
4977 * @brief Process error event.
4978 *
4979 * @param[in] error_code: Error code.
4980 *
4981 * @retval OMX_ErrorNone
4982 */
async_process_event_error(OMX_ERRORTYPE error_code)4983 OMX_ERRORTYPE omx_swvdec::async_process_event_error(OMX_ERRORTYPE error_code)
4984 {
4985 if (error_code == OMX_ErrorInvalidState)
4986 {
4987 m_state = OMX_StateInvalid;
4988 }
4989
4990 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventError, 0x%08x",
4991 error_code);
4992
4993 m_callback.EventHandler(&m_cmp,
4994 m_app_data,
4995 OMX_EventError,
4996 (OMX_U32) error_code,
4997 0,
4998 NULL);
4999
5000 return OMX_ErrorNone;
5001 }
5002
5003 /**
5004 * @brief Process OMX_CommandStateSet.
5005 *
5006 * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
5007 * @param[in] state_new: New state to which transition is requested.
5008 *
5009 * @retval OMX_ERRORTYPE
5010 */
async_process_event_cmd_state_set(bool * p_cmd_ack,OMX_STATETYPE state_new)5011 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_state_set(
5012 bool *p_cmd_ack,
5013 OMX_STATETYPE state_new)
5014 {
5015 OMX_ERRORTYPE retval = OMX_ErrorNone;
5016
5017 SWVDEC_STATUS retval_swvdec;
5018
5019 OMX_SWVDEC_LOG_HIGH("'%s-to-%s' requested",
5020 OMX_STATETYPE_STRING(m_state),
5021 OMX_STATETYPE_STRING(state_new));
5022
5023 /**
5024 * Only the following state transitions are allowed via CommandStateSet:
5025 *
5026 * LOADED -> IDLE -> EXECUTING
5027 * LOADED <- IDLE <- EXECUTING
5028 */
5029
5030 if (m_state == OMX_StateInvalid)
5031 {
5032 OMX_SWVDEC_LOG_ERROR("in state %s", OMX_STATETYPE_STRING(m_state));
5033 retval = OMX_ErrorInvalidState;
5034 }
5035 else if (state_new == OMX_StateInvalid)
5036 {
5037 OMX_SWVDEC_LOG_ERROR("requested transition to state %s",
5038 OMX_STATETYPE_STRING(state_new));
5039 retval = OMX_ErrorInvalidState;
5040 }
5041 else if ((m_state == OMX_StateLoaded) &&
5042 (state_new == OMX_StateIdle))
5043 {
5044 if ((m_port_ip.populated == OMX_TRUE) &&
5045 (m_port_op.populated == OMX_TRUE))
5046 {
5047 // start SwVdec
5048 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) ==
5049 SWVDEC_STATUS_SUCCESS)
5050 {
5051 *p_cmd_ack = true;
5052 }
5053 else
5054 {
5055 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
5056 retval = retval_swvdec2omx(retval_swvdec);
5057 }
5058 }
5059 else
5060 {
5061 m_status_flags |= (1 << PENDING_STATE_LOADED_TO_IDLE);
5062
5063 OMX_SWVDEC_LOG_LOW("'loaded-to-idle' pending");
5064 }
5065 }
5066 else if ((m_state == OMX_StateIdle) &&
5067 (state_new == OMX_StateExecuting))
5068 {
5069 *p_cmd_ack = true;
5070 }
5071 else if ((m_state == OMX_StateExecuting) &&
5072 (state_new == OMX_StateIdle))
5073 {
5074 m_status_flags |= (1 << PENDING_STATE_EXECUTING_TO_IDLE);
5075
5076 OMX_SWVDEC_LOG_LOW("'executing-to-idle' pending");
5077
5078 retval = flush(OMX_ALL);
5079 }
5080 else if ((m_state == OMX_StateIdle) &&
5081 (state_new == OMX_StateLoaded))
5082 {
5083 if ((m_port_ip.unpopulated == OMX_TRUE) &&
5084 (m_port_op.unpopulated == OMX_TRUE))
5085 {
5086 // stop SwVdec
5087 if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
5088 SWVDEC_STATUS_SUCCESS)
5089 {
5090 *p_cmd_ack = true;
5091 }
5092 else
5093 {
5094 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
5095 retval = retval_swvdec2omx(retval_swvdec);
5096 }
5097 }
5098 else
5099 {
5100 m_status_flags |= (1 << PENDING_STATE_IDLE_TO_LOADED);
5101
5102 OMX_SWVDEC_LOG_LOW("'idle-to-loaded' pending");
5103 }
5104 }
5105 else
5106 {
5107 OMX_SWVDEC_LOG_ERROR("state transition '%s -> %s' illegal",
5108 OMX_STATETYPE_STRING(m_state),
5109 OMX_STATETYPE_STRING(state_new));
5110
5111 retval = ((state_new == m_state) ?
5112 OMX_ErrorSameState :
5113 OMX_ErrorIncorrectStateTransition);
5114 }
5115
5116 return retval;
5117 }
5118
5119 /**
5120 * @brief Process OMX_CommandFlush.
5121 *
5122 * @param[in] port_index: Index of port to flush.
5123 *
5124 * @retval OMX_ERRORTYPE
5125 */
async_process_event_cmd_flush(unsigned int port_index)5126 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_flush(unsigned int port_index)
5127 {
5128 OMX_ERRORTYPE retval = OMX_ErrorNone;
5129
5130 OMX_SWVDEC_LOG_HIGH("flush port %d requested", port_index);
5131
5132 if (port_index == OMX_CORE_PORT_INDEX_IP)
5133 {
5134 m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5135
5136 OMX_SWVDEC_LOG_LOW("ip port flush pending");
5137 }
5138 else if (port_index == OMX_CORE_PORT_INDEX_OP)
5139 {
5140 m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5141
5142 OMX_SWVDEC_LOG_LOW("op port flush pending");
5143 }
5144 else if (port_index == OMX_ALL)
5145 {
5146 m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5147 m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5148
5149 OMX_SWVDEC_LOG_LOW("ip & op ports flush pending");
5150 }
5151
5152 retval = flush(port_index);
5153
5154 return retval;
5155 }
5156
5157 /**
5158 * @brief Process OMX_CommandPortDisable.
5159 *
5160 * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
5161 * @param[in] port_index: Index of port to disable.
5162 *
5163 * @retval OMX_ERRORTYPE
5164 */
async_process_event_cmd_port_disable(bool * p_cmd_ack,unsigned int port_index)5165 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_disable(
5166 bool *p_cmd_ack,
5167 unsigned int port_index)
5168 {
5169 OMX_ERRORTYPE retval = OMX_ErrorNone;
5170
5171 OMX_SWVDEC_LOG_HIGH("disable port %d requested", port_index);
5172
5173 if (port_index == OMX_CORE_PORT_INDEX_IP)
5174 {
5175 if (m_port_ip.enabled == OMX_FALSE)
5176 {
5177 OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5178 retval = OMX_ErrorBadPortIndex;
5179 }
5180 else
5181 {
5182 m_port_ip.enabled = OMX_FALSE;
5183
5184 if (m_port_ip.unpopulated)
5185 {
5186 *p_cmd_ack = true;
5187 }
5188 else
5189 {
5190 m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5191
5192 OMX_SWVDEC_LOG_LOW("ip port disable pending");
5193
5194 if (m_port_ip.num_pending_buffers)
5195 {
5196 retval = flush(port_index);
5197 }
5198 }
5199 }
5200 }
5201 else if (port_index == OMX_CORE_PORT_INDEX_OP)
5202 {
5203 if (m_port_op.enabled == OMX_FALSE)
5204 {
5205 OMX_SWVDEC_LOG_ERROR("op port already disabled");
5206 retval = OMX_ErrorBadPortIndex;
5207 }
5208 else
5209 {
5210 m_port_op.enabled = OMX_FALSE;
5211
5212 if (m_port_op.unpopulated)
5213 {
5214 *p_cmd_ack = true;
5215 }
5216 else
5217 {
5218 m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5219
5220 OMX_SWVDEC_LOG_LOW("op port disable pending");
5221
5222 if (m_port_op.num_pending_buffers)
5223 {
5224 retval = flush(port_index);
5225 }
5226 }
5227 }
5228 }
5229 else if (port_index == OMX_ALL)
5230 {
5231 if (m_port_ip.enabled == OMX_FALSE)
5232 {
5233 OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5234 retval = OMX_ErrorBadPortIndex;
5235 }
5236 else if (m_port_op.enabled == OMX_FALSE)
5237 {
5238 OMX_SWVDEC_LOG_ERROR("op port already disabled");
5239 retval = OMX_ErrorBadPortIndex;
5240 }
5241 else
5242 {
5243 if (m_port_ip.unpopulated && m_port_op.unpopulated)
5244 {
5245 *p_cmd_ack = true;
5246 }
5247 else
5248 {
5249 m_port_ip.enabled = OMX_FALSE;
5250 m_port_op.enabled = OMX_FALSE;
5251
5252 if (m_port_ip.unpopulated == OMX_FALSE)
5253 {
5254 m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5255
5256 OMX_SWVDEC_LOG_LOW("ip port disable pending");
5257
5258 if (m_port_ip.num_pending_buffers)
5259 {
5260 retval = flush(port_index);
5261 }
5262 }
5263
5264 if ((retval == OMX_ErrorNone) &&
5265 (m_port_op.unpopulated == OMX_FALSE))
5266 {
5267 m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5268
5269 OMX_SWVDEC_LOG_LOW("op port disable pending");
5270
5271 if (m_port_op.num_pending_buffers)
5272 {
5273 retval = flush(port_index);
5274 }
5275 }
5276 }
5277 }
5278 }
5279 else
5280 {
5281 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid");
5282 retval = OMX_ErrorBadPortIndex;
5283 }
5284
5285 return retval;
5286 }
5287
5288 /**
5289 * @brief Process OMX_CommandPortEnable.
5290 *
5291 * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
5292 * @param[in] port_index: Index of port to enable.
5293 *
5294 * @retval OMX_ERRORTYPE
5295 */
async_process_event_cmd_port_enable(bool * p_cmd_ack,unsigned int port_index)5296 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_enable(
5297 bool *p_cmd_ack,
5298 unsigned int port_index)
5299 {
5300 OMX_ERRORTYPE retval = OMX_ErrorNone;
5301
5302 OMX_SWVDEC_LOG_HIGH("enable port %d requested", port_index);
5303
5304 if (port_index == OMX_CORE_PORT_INDEX_IP)
5305 {
5306 if (m_port_ip.enabled)
5307 {
5308 OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5309 retval = OMX_ErrorBadPortIndex;
5310 }
5311 else
5312 {
5313 m_port_ip.enabled = OMX_TRUE;
5314
5315 if (m_port_ip.populated)
5316 {
5317 *p_cmd_ack = true;
5318 }
5319 else
5320 {
5321 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5322
5323 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5324 }
5325 }
5326 }
5327 else if (port_index == OMX_CORE_PORT_INDEX_OP)
5328 {
5329 if (m_port_op.enabled)
5330 {
5331 OMX_SWVDEC_LOG_ERROR("op port already enabled");
5332 retval = OMX_ErrorBadPortIndex;
5333 }
5334 else
5335 {
5336 m_port_op.enabled = OMX_TRUE;
5337
5338 if (m_port_op.populated)
5339 {
5340 *p_cmd_ack = true;
5341 }
5342 else
5343 {
5344 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5345
5346 OMX_SWVDEC_LOG_LOW("op port enable pending");
5347 }
5348 }
5349 }
5350 else if (port_index == OMX_ALL)
5351 {
5352 if (m_port_ip.enabled)
5353 {
5354 OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5355 retval = OMX_ErrorBadPortIndex;
5356 }
5357 else if (m_port_op.enabled)
5358 {
5359 OMX_SWVDEC_LOG_ERROR("op port already enabled");
5360 retval = OMX_ErrorBadPortIndex;
5361 }
5362 else
5363 {
5364 m_port_ip.enabled = OMX_TRUE;
5365 m_port_op.enabled = OMX_TRUE;
5366
5367 if (m_port_ip.populated && m_port_op.populated)
5368 {
5369 *p_cmd_ack = true;
5370 }
5371 else if (m_port_ip.populated == false)
5372 {
5373 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5374
5375 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5376 }
5377 else if (m_port_op.populated == false)
5378 {
5379 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5380
5381 OMX_SWVDEC_LOG_LOW("op port enable pending");
5382 }
5383 }
5384 }
5385 else
5386 {
5387 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid");
5388 retval = OMX_ErrorBadPortIndex;
5389 }
5390
5391 return retval;
5392 }
5393
5394 /**
5395 * @brief Process ETB event.
5396 *
5397 * @param[in] p_buffer_hdr: Pointer to buffer header.
5398 * @param[in] index: Index of buffer in input buffer info array.
5399 *
5400 * @retval OMX_ERRORTYPE
5401 */
async_process_event_etb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5402 OMX_ERRORTYPE omx_swvdec::async_process_event_etb(
5403 OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5404 unsigned int index)
5405 {
5406 OMX_ERRORTYPE retval = OMX_ErrorNone;
5407
5408 m_port_ip.num_pending_buffers++;
5409
5410 if ((p_buffer_hdr->nFilledLen == 0) &&
5411 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) == 0))
5412 {
5413 OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5414 "zero length & no EOS flag",
5415 p_buffer_hdr,
5416 p_buffer_hdr->pBuffer);
5417
5418 async_post_event(OMX_SWVDEC_EVENT_EBD,
5419 (unsigned long) p_buffer_hdr,
5420 (unsigned long) index);
5421 }
5422 else if (m_port_ip.flush_inprogress)
5423 {
5424 OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5425 "ip port flush in progress",
5426 p_buffer_hdr,
5427 p_buffer_hdr->pBuffer);
5428
5429 async_post_event(OMX_SWVDEC_EVENT_EBD,
5430 (unsigned long) p_buffer_hdr,
5431 (unsigned long) index);
5432 }
5433 else
5434 {
5435 SWVDEC_STATUS retval_swvdec;
5436
5437 SWVDEC_BUFFER *p_buffer_swvdec =
5438 &(m_buffer_array_ip[index].buffer_swvdec);
5439
5440 if (p_buffer_hdr->nFilledLen &&
5441 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
5442 {
5443 m_ts_list.push(p_buffer_hdr->nTimeStamp);
5444 }
5445
5446 assert(p_buffer_swvdec->p_buffer == p_buffer_hdr->pBuffer);
5447
5448 p_buffer_swvdec->flags = p_buffer_hdr->nFlags;
5449 p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp;
5450 p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen;
5451
5452 m_diag.dump_ip(p_buffer_swvdec->p_buffer,
5453 p_buffer_swvdec->filled_length);
5454
5455 retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
5456 p_buffer_swvdec);
5457
5458 if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
5459 {
5460 retval = retval_swvdec2omx(retval_swvdec);
5461 }
5462 }
5463
5464 return retval;
5465 }
5466
5467 /**
5468 * @brief Process FTB event.
5469 *
5470 * @param[in] p_buffer_hdr: Pointer to buffer header.
5471 * @param[in] index: Index of buffer in output buffer info array.
5472 *
5473 * @retval OMX_ERRORTYPE
5474 */
async_process_event_ftb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5475 OMX_ERRORTYPE omx_swvdec::async_process_event_ftb(
5476 OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5477 unsigned int index)
5478 {
5479 OMX_ERRORTYPE retval = OMX_ErrorNone;
5480
5481 m_port_op.num_pending_buffers++;
5482
5483 if (m_port_op.flush_inprogress)
5484 {
5485 OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5486 "op port flush in progress",
5487 p_buffer_hdr,
5488 m_buffer_array_op[index].buffer_swvdec.p_buffer);
5489
5490 async_post_event(OMX_SWVDEC_EVENT_FBD,
5491 (unsigned long) p_buffer_hdr,
5492 (unsigned long) index);
5493 }
5494 else
5495 {
5496 SWVDEC_STATUS retval_swvdec;
5497
5498 SWVDEC_BUFFER *p_buffer_swvdec =
5499 &(m_buffer_array_op[index].buffer_swvdec);
5500
5501 retval_swvdec = swvdec_fillthisbuffer(m_swvdec_handle, p_buffer_swvdec);
5502
5503 if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
5504 {
5505 retval = retval_swvdec2omx(retval_swvdec);
5506 }
5507 }
5508
5509 return retval;
5510 }
5511
5512 /**
5513 * @brief Process EBD event.
5514 *
5515 * @param[in] p_buffer_hdr: Pointer to buffer header.
5516 * @param[in] index: Index of buffer in output buffer info array.
5517 *
5518 * @retval OMX_ERRORTYPE
5519 */
async_process_event_ebd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5520 OMX_ERRORTYPE omx_swvdec::async_process_event_ebd(
5521 OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5522 unsigned int index)
5523 {
5524 OMX_ERRORTYPE retval = OMX_ErrorNone;
5525
5526 if (index < m_port_ip.def.nBufferCountActual)
5527 {
5528 m_port_ip.num_pending_buffers--;
5529
5530 // should ideally be set in swvdec_empty_buffer_done()
5531 p_buffer_hdr->nFilledLen = 0;
5532
5533 OMX_SWVDEC_LOG_CALLBACK(
5534 "EmptyBufferDone(): %p, buffer %p",
5535 p_buffer_hdr,
5536 m_buffer_array_ip[index].buffer_swvdec.p_buffer);
5537
5538 m_callback.EmptyBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
5539 }
5540 else
5541 {
5542 OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
5543 retval = OMX_ErrorBadParameter;
5544 }
5545
5546 return retval;
5547 }
5548
5549 /**
5550 * @brief Process FBD event.
5551 *
5552 * @param[in] p_buffer_hdr: Pointer to buffer header.
5553 * @param[in] index: Index of buffer in output buffer info array.
5554 *
5555 * @retval OMX_ERRORTYPE
5556 */
async_process_event_fbd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5557 OMX_ERRORTYPE omx_swvdec::async_process_event_fbd(
5558 OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5559 unsigned int index)
5560 {
5561 OMX_ERRORTYPE retval = OMX_ErrorNone;
5562
5563 if (index < m_port_op.def.nBufferCountActual)
5564 {
5565 OMX_U8 *p_buffer;
5566
5567 p_buffer = m_buffer_array_op[index].buffer_swvdec.p_buffer;
5568
5569 m_port_op.num_pending_buffers--;
5570
5571 if (m_port_op.flush_inprogress)
5572 {
5573 p_buffer_hdr->nFilledLen = 0;
5574 p_buffer_hdr->nTimeStamp = 0;
5575 p_buffer_hdr->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
5576 }
5577
5578 if (p_buffer_hdr->nFilledLen)
5579 {
5580 if (m_sync_frame_decoding_mode)
5581 {
5582 p_buffer_hdr->nTimeStamp = 0;
5583 }
5584 else
5585 {
5586 if (m_ts_list.pop(&p_buffer_hdr->nTimeStamp) == false)
5587 {
5588 OMX_SWVDEC_LOG_ERROR("failed to pop timestamp from list");
5589 }
5590 }
5591
5592 m_diag.dump_op(p_buffer,
5593 m_frame_dimensions.width,
5594 m_frame_dimensions.height,
5595 m_frame_attributes.stride,
5596 m_frame_attributes.scanlines);
5597 }
5598
5599 if (p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS)
5600 {
5601 async_post_event(OMX_SWVDEC_EVENT_EOS, 0, 0);
5602
5603 m_ts_list.reset();
5604 }
5605
5606 if (m_meta_buffer_mode &&
5607 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_READONLY)) == 0)
5608 {
5609 meta_buffer_ref_remove(
5610 m_buffer_array_op[index].buffer_payload.pmem_fd,
5611 m_buffer_array_op[index].buffer_payload.offset);
5612 }
5613
5614 OMX_SWVDEC_LOG_CALLBACK(
5615 "FillBufferDone(): %p, buffer %p, "
5616 "flags 0x%08x, timestamp %lld",
5617 p_buffer_hdr,
5618 p_buffer,
5619 p_buffer_hdr->nFlags,
5620 p_buffer_hdr->nTimeStamp);
5621
5622 m_callback.FillBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
5623 }
5624 else
5625 {
5626 OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
5627 retval = OMX_ErrorBadParameter;
5628 }
5629
5630 async_process_event_fbd_exit:
5631 return retval;
5632 }
5633
5634 /**
5635 * @brief Process EOS event.
5636 *
5637 * @retval OMX_ErrorNone
5638 */
async_process_event_eos()5639 OMX_ERRORTYPE omx_swvdec::async_process_event_eos()
5640 {
5641 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
5642 "OMX_EventBufferFlag, port %d, EOS",
5643 OMX_CORE_PORT_INDEX_OP);
5644
5645 m_callback.EventHandler(&m_cmp,
5646 m_app_data,
5647 OMX_EventBufferFlag,
5648 OMX_CORE_PORT_INDEX_OP,
5649 OMX_BUFFERFLAG_EOS,
5650 NULL);
5651
5652 return OMX_ErrorNone;
5653 }
5654
5655 /**
5656 * @brief Process input port flush event.
5657 *
5658 * @retval OMX_ERRORTYPE
5659 */
async_process_event_flush_port_ip()5660 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_ip()
5661 {
5662 OMX_ERRORTYPE retval = OMX_ErrorNone;
5663
5664 OMX_SWVDEC_EVENT_INFO event_info;
5665
5666 OMX_BUFFERHEADERTYPE *p_buffer_hdr;
5667
5668 unsigned int index;
5669
5670 while (m_queue_port_ip.pop(&event_info))
5671 {
5672 switch (event_info.event_id)
5673 {
5674
5675 case OMX_SWVDEC_EVENT_ETB:
5676 {
5677 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5678 index = event_info.event_param2;
5679
5680 // compensate decrement in async_process_event_ebd()
5681 m_port_ip.num_pending_buffers++;
5682
5683 retval = async_process_event_ebd(p_buffer_hdr, index);
5684 break;
5685 }
5686
5687 case OMX_SWVDEC_EVENT_EBD:
5688 {
5689 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5690 index = event_info.event_param2;
5691
5692 retval = async_process_event_ebd(p_buffer_hdr, index);
5693 break;
5694 }
5695
5696 default:
5697 {
5698 assert(0);
5699 break;
5700 }
5701
5702 }
5703 }
5704
5705 assert(m_port_ip.num_pending_buffers == 0);
5706
5707 if ((retval == OMX_ErrorNone) &&
5708 (m_status_flags & (1 << PENDING_PORT_FLUSH_IP)))
5709 {
5710 m_status_flags &= ~(1 << PENDING_PORT_FLUSH_IP);
5711
5712 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
5713 OMX_CommandFlush,
5714 OMX_CORE_PORT_INDEX_IP);
5715 }
5716
5717 m_port_ip.flush_inprogress = OMX_FALSE;
5718
5719 return retval;
5720 }
5721
5722 /**
5723 * @brief Process output port flush event.
5724 *
5725 * @retval OMX_ERRORTYPE
5726 */
async_process_event_flush_port_op()5727 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_op()
5728 {
5729 OMX_ERRORTYPE retval = OMX_ErrorNone;
5730
5731 OMX_SWVDEC_EVENT_INFO event_info;
5732
5733 OMX_BUFFERHEADERTYPE *p_buffer_hdr;
5734
5735 unsigned int index;
5736
5737 while (m_queue_port_op.pop(&event_info))
5738 {
5739 switch (event_info.event_id)
5740 {
5741
5742 case OMX_SWVDEC_EVENT_FTB:
5743 {
5744 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5745 index = event_info.event_param2;
5746
5747 // compensate decrement in async_process_event_fbd()
5748 m_port_op.num_pending_buffers++;
5749
5750 retval = async_process_event_fbd(p_buffer_hdr, index);
5751 break;
5752 }
5753
5754 case OMX_SWVDEC_EVENT_FBD:
5755 {
5756 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5757 index = event_info.event_param2;
5758
5759 retval = async_process_event_fbd(p_buffer_hdr, index);
5760 break;
5761 }
5762
5763 default:
5764 {
5765 assert(0);
5766 break;
5767 }
5768
5769 }
5770 }
5771
5772 assert(m_port_op.num_pending_buffers == 0);
5773
5774 if ((retval == OMX_ErrorNone) &&
5775 (m_status_flags & (1 << PENDING_PORT_FLUSH_OP)))
5776 {
5777 m_status_flags &= ~(1 << PENDING_PORT_FLUSH_OP);
5778
5779 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
5780 OMX_CommandFlush,
5781 OMX_CORE_PORT_INDEX_OP);
5782 }
5783
5784 if ((retval == OMX_ErrorNone) &&
5785 (m_status_flags & (1 << PENDING_STATE_EXECUTING_TO_IDLE)))
5786 {
5787 m_status_flags &= ~(1 << PENDING_STATE_EXECUTING_TO_IDLE);
5788
5789 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
5790 OMX_CommandStateSet,
5791 OMX_StateIdle);
5792 }
5793
5794 if (m_port_reconfig_inprogress == false)
5795 {
5796 m_ts_list.reset();
5797 }
5798
5799 m_port_op.flush_inprogress = OMX_FALSE;
5800
5801 return retval;
5802 }
5803
5804 /**
5805 * @brief Process port reconfiguration event.
5806 *
5807 * @retval OMX_ERRORTYPE
5808 */
async_process_event_port_reconfig()5809 OMX_ERRORTYPE omx_swvdec::async_process_event_port_reconfig()
5810 {
5811 OMX_ERRORTYPE retval = OMX_ErrorNone;
5812
5813 if (m_port_reconfig_inprogress)
5814 {
5815 OMX_SWVDEC_LOG_ERROR("port reconfiguration in progress");
5816 retval = OMX_ErrorIncorrectStateOperation;
5817 }
5818 else
5819 {
5820 m_port_reconfig_inprogress = true;
5821
5822 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
5823 "OMX_EventPortSettingsChanged, port %d",
5824 OMX_CORE_PORT_INDEX_OP);
5825
5826 m_callback.EventHandler(&m_cmp,
5827 m_app_data,
5828 OMX_EventPortSettingsChanged,
5829 OMX_CORE_PORT_INDEX_OP,
5830 0,
5831 NULL);
5832 }
5833
5834 return retval;
5835 }
5836