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