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