You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1837 lines
61 KiB

  1. /*
  2. Copyright (c) 2012, Broadcom Europe Ltd
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in the
  10. documentation and/or other materials provided with the distribution.
  11. * Neither the name of the copyright holder nor the
  12. names of its contributors may be used to endorse or promote products
  13. derived from this software without specific prior written permission.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
  18. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. /*
  26. * \file
  27. *
  28. * \brief This API defines helper functions for writing IL clients.
  29. *
  30. * This file defines an IL client side library. This is useful when
  31. * writing IL clients, since there tends to be much repeated and
  32. * common code across both single and multiple clients. This library
  33. * seeks to remove that common code and abstract some of the
  34. * interactions with components. There is a wrapper around a
  35. * component and tunnel, and some operations can be done on lists of
  36. * these. The callbacks from components are handled, and specific
  37. * events can be checked or waited for.
  38. */
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <stdarg.h>
  42. #include <string.h>
  43. #include <ctype.h>
  44. #include <assert.h>
  45. #include "interface/vcos/vcos.h"
  46. #include "interface/vcos/vcos_logging.h"
  47. #include "interface/vmcs_host/vchost.h"
  48. #include "IL/OMX_Broadcom.h"
  49. #include "ilclient.h"
  50. #define VCOS_LOG_CATEGORY (&ilclient_log_category)
  51. #ifndef ILCLIENT_THREAD_DEFAULT_STACK_SIZE
  52. #define ILCLIENT_THREAD_DEFAULT_STACK_SIZE (6<<10)
  53. #endif
  54. static VCOS_LOG_CAT_T ilclient_log_category;
  55. /******************************************************************************
  56. Static data and types used only in this file.
  57. ******************************************************************************/
  58. struct _ILEVENT_T {
  59. OMX_EVENTTYPE eEvent;
  60. OMX_U32 nData1;
  61. OMX_U32 nData2;
  62. OMX_PTR pEventData;
  63. struct _ILEVENT_T *next;
  64. };
  65. #define NUM_EVENTS 100
  66. struct _ILCLIENT_T {
  67. ILEVENT_T *event_list;
  68. VCOS_SEMAPHORE_T event_sema;
  69. ILEVENT_T event_rep[NUM_EVENTS];
  70. ILCLIENT_CALLBACK_T port_settings_callback;
  71. void *port_settings_callback_data;
  72. ILCLIENT_CALLBACK_T eos_callback;
  73. void *eos_callback_data;
  74. ILCLIENT_CALLBACK_T error_callback;
  75. void *error_callback_data;
  76. ILCLIENT_BUFFER_CALLBACK_T fill_buffer_done_callback;
  77. void *fill_buffer_done_callback_data;
  78. ILCLIENT_BUFFER_CALLBACK_T empty_buffer_done_callback;
  79. void *empty_buffer_done_callback_data;
  80. ILCLIENT_CALLBACK_T configchanged_callback;
  81. void *configchanged_callback_data;
  82. };
  83. struct _COMPONENT_T {
  84. OMX_HANDLETYPE comp;
  85. ILCLIENT_CREATE_FLAGS_T flags;
  86. VCOS_SEMAPHORE_T sema;
  87. VCOS_EVENT_FLAGS_T event;
  88. struct _COMPONENT_T *related;
  89. OMX_BUFFERHEADERTYPE *out_list;
  90. OMX_BUFFERHEADERTYPE *in_list;
  91. char name[32];
  92. char bufname[32];
  93. unsigned int error_mask;
  94. unsigned int private;
  95. ILEVENT_T *list;
  96. ILCLIENT_T *client;
  97. };
  98. #define random_wait()
  99. static char *states[] = {"Invalid", "Loaded", "Idle", "Executing", "Pause", "WaitingForResources"};
  100. typedef enum {
  101. ILCLIENT_ERROR_UNPOPULATED = 0x1,
  102. ILCLIENT_ERROR_SAMESTATE = 0x2,
  103. ILCLIENT_ERROR_BADPARAMETER = 0x4
  104. } ILERROR_MASK_T;
  105. /******************************************************************************
  106. Static functions.
  107. ******************************************************************************/
  108. static OMX_ERRORTYPE ilclient_empty_buffer_done(OMX_IN OMX_HANDLETYPE hComponent,
  109. OMX_IN OMX_PTR pAppData,
  110. OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
  111. static OMX_ERRORTYPE ilclient_empty_buffer_done_error(OMX_IN OMX_HANDLETYPE hComponent,
  112. OMX_IN OMX_PTR pAppData,
  113. OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
  114. static OMX_ERRORTYPE ilclient_fill_buffer_done(OMX_OUT OMX_HANDLETYPE hComponent,
  115. OMX_OUT OMX_PTR pAppData,
  116. OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
  117. static OMX_ERRORTYPE ilclient_fill_buffer_done_error(OMX_OUT OMX_HANDLETYPE hComponent,
  118. OMX_OUT OMX_PTR pAppData,
  119. OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
  120. static OMX_ERRORTYPE ilclient_event_handler(OMX_IN OMX_HANDLETYPE hComponent,
  121. OMX_IN OMX_PTR pAppData,
  122. OMX_IN OMX_EVENTTYPE eEvent,
  123. OMX_IN OMX_U32 nData1,
  124. OMX_IN OMX_U32 nData2,
  125. OMX_IN OMX_PTR pEventData);
  126. static void ilclient_lock_events(ILCLIENT_T *st);
  127. static void ilclient_unlock_events(ILCLIENT_T *st);
  128. /******************************************************************************
  129. Global functions
  130. ******************************************************************************/
  131. /***********************************************************
  132. * Name: ilclient_init
  133. *
  134. * Description: Creates ilclient pointer
  135. *
  136. * Returns: pointer to client structure
  137. ***********************************************************/
  138. ILCLIENT_T *ilclient_init()
  139. {
  140. ILCLIENT_T *st = vcos_malloc(sizeof(ILCLIENT_T), "ilclient");
  141. int i;
  142. if (!st)
  143. return NULL;
  144. vcos_log_set_level(VCOS_LOG_CATEGORY, VCOS_LOG_WARN);
  145. vcos_log_register("ilclient", VCOS_LOG_CATEGORY);
  146. memset(st, 0, sizeof(ILCLIENT_T));
  147. i = vcos_semaphore_create(&st->event_sema, "il:event", 1);
  148. vc_assert(i == VCOS_SUCCESS);
  149. ilclient_lock_events(st);
  150. st->event_list = NULL;
  151. for (i=0; i<NUM_EVENTS; i++)
  152. {
  153. st->event_rep[i].eEvent = -1; // mark as unused
  154. st->event_rep[i].next = st->event_list;
  155. st->event_list = st->event_rep+i;
  156. }
  157. ilclient_unlock_events(st);
  158. return st;
  159. }
  160. /***********************************************************
  161. * Name: ilclient_destroy
  162. *
  163. * Description: frees client state
  164. *
  165. * Returns: void
  166. ***********************************************************/
  167. void ilclient_destroy(ILCLIENT_T *st)
  168. {
  169. vcos_semaphore_delete(&st->event_sema);
  170. vcos_free(st);
  171. vcos_log_unregister(VCOS_LOG_CATEGORY);
  172. }
  173. /***********************************************************
  174. * Name: ilclient_set_port_settings_callback
  175. *
  176. * Description: sets the callback used when receiving port settings
  177. * changed messages. The data field in the callback function will be
  178. * the port index reporting the message.
  179. *
  180. * Returns: void
  181. ***********************************************************/
  182. void ilclient_set_port_settings_callback(ILCLIENT_T *st, ILCLIENT_CALLBACK_T func, void *userdata)
  183. {
  184. st->port_settings_callback = func;
  185. st->port_settings_callback_data = userdata;
  186. }
  187. /***********************************************************
  188. * Name: ilclient_set_eos_callback
  189. *
  190. * Description: sets the callback used when receiving eos flags. The
  191. * data parameter in the callback function will be the port index
  192. * reporting an eos flag.
  193. *
  194. * Returns: void
  195. ***********************************************************/
  196. void ilclient_set_eos_callback(ILCLIENT_T *st, ILCLIENT_CALLBACK_T func, void *userdata)
  197. {
  198. st->eos_callback = func;
  199. st->eos_callback_data = userdata;
  200. }
  201. /***********************************************************
  202. * Name: ilclient_set_error_callback
  203. *
  204. * Description: sets the callback used when receiving error events.
  205. * The data parameter in the callback function will be the error code
  206. * being reported.
  207. *
  208. * Returns: void
  209. ***********************************************************/
  210. void ilclient_set_error_callback(ILCLIENT_T *st, ILCLIENT_CALLBACK_T func, void *userdata)
  211. {
  212. st->error_callback = func;
  213. st->error_callback_data = userdata;
  214. }
  215. /***********************************************************
  216. * Name: ilclient_set_fill_buffer_done_callback
  217. *
  218. * Description: sets the callback used when receiving
  219. * fill_buffer_done event
  220. *
  221. * Returns: void
  222. ***********************************************************/
  223. void ilclient_set_fill_buffer_done_callback(ILCLIENT_T *st, ILCLIENT_BUFFER_CALLBACK_T func, void *userdata)
  224. {
  225. st->fill_buffer_done_callback = func;
  226. st->fill_buffer_done_callback_data = userdata;
  227. }
  228. /***********************************************************
  229. * Name: ilclient_set_empty_buffer_done_callback
  230. *
  231. * Description: sets the callback used when receiving
  232. * empty_buffer_done event
  233. *
  234. * Returns: void
  235. ***********************************************************/
  236. void ilclient_set_empty_buffer_done_callback(ILCLIENT_T *st, ILCLIENT_BUFFER_CALLBACK_T func, void *userdata)
  237. {
  238. st->empty_buffer_done_callback = func;
  239. st->empty_buffer_done_callback_data = userdata;
  240. }
  241. /***********************************************************
  242. * Name: ilclient_set_configchanged_callback
  243. *
  244. * Description: sets the callback used when a config changed
  245. * event is received
  246. *
  247. * Returns: void
  248. ***********************************************************/
  249. void ilclient_set_configchanged_callback(ILCLIENT_T *st, ILCLIENT_CALLBACK_T func, void *userdata)
  250. {
  251. st->configchanged_callback = func;
  252. st->configchanged_callback_data = userdata;
  253. }
  254. /***********************************************************
  255. * Name: ilclient_create_component
  256. *
  257. * Description: initialises a component state structure and creates
  258. * the IL component.
  259. *
  260. * Returns: 0 on success, -1 on failure
  261. ***********************************************************/
  262. int ilclient_create_component(ILCLIENT_T *client, COMPONENT_T **comp, char *name,
  263. ILCLIENT_CREATE_FLAGS_T flags)
  264. {
  265. OMX_CALLBACKTYPE callbacks;
  266. OMX_ERRORTYPE error;
  267. char component_name[128];
  268. int32_t status;
  269. *comp = vcos_malloc(sizeof(COMPONENT_T), "il:comp");
  270. if(!*comp)
  271. return -1;
  272. memset(*comp, 0, sizeof(COMPONENT_T));
  273. #define COMP_PREFIX "OMX.broadcom."
  274. status = vcos_event_flags_create(&(*comp)->event,"il:comp");
  275. vc_assert(status == VCOS_SUCCESS);
  276. status = vcos_semaphore_create(&(*comp)->sema, "il:comp", 1);
  277. vc_assert(status == VCOS_SUCCESS);
  278. (*comp)->client = client;
  279. vcos_snprintf((*comp)->name, sizeof((*comp)->name), "cl:%s", name);
  280. vcos_snprintf((*comp)->bufname, sizeof((*comp)->bufname), "cl:%s buffer", name);
  281. vcos_snprintf(component_name, sizeof(component_name), "%s%s", COMP_PREFIX, name);
  282. (*comp)->flags = flags;
  283. callbacks.EventHandler = ilclient_event_handler;
  284. callbacks.EmptyBufferDone = flags & ILCLIENT_ENABLE_INPUT_BUFFERS ? ilclient_empty_buffer_done : ilclient_empty_buffer_done_error;
  285. callbacks.FillBufferDone = flags & ILCLIENT_ENABLE_OUTPUT_BUFFERS ? ilclient_fill_buffer_done : ilclient_fill_buffer_done_error;
  286. error = OMX_GetHandle(&(*comp)->comp, component_name, *comp, &callbacks);
  287. if (error == OMX_ErrorNone)
  288. {
  289. OMX_UUIDTYPE uid;
  290. char name[128];
  291. OMX_VERSIONTYPE compVersion, specVersion;
  292. if(OMX_GetComponentVersion((*comp)->comp, name, &compVersion, &specVersion, &uid) == OMX_ErrorNone)
  293. {
  294. char *p = (char *) uid + strlen(COMP_PREFIX);
  295. vcos_snprintf((*comp)->name, sizeof((*comp)->name), "cl:%s", p);
  296. (*comp)->name[sizeof((*comp)->name)-1] = 0;
  297. vcos_snprintf((*comp)->bufname, sizeof((*comp)->bufname), "cl:%s buffer", p);
  298. (*comp)->bufname[sizeof((*comp)->bufname)-1] = 0;
  299. }
  300. if(flags & (ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_OUTPUT_ZERO_BUFFERS))
  301. {
  302. OMX_PORT_PARAM_TYPE ports;
  303. OMX_INDEXTYPE types[] = {OMX_IndexParamAudioInit, OMX_IndexParamVideoInit, OMX_IndexParamImageInit, OMX_IndexParamOtherInit};
  304. int i;
  305. ports.nSize = sizeof(OMX_PORT_PARAM_TYPE);
  306. ports.nVersion.nVersion = OMX_VERSION;
  307. for(i=0; i<4; i++)
  308. {
  309. OMX_ERRORTYPE error = OMX_GetParameter((*comp)->comp, types[i], &ports);
  310. if(error == OMX_ErrorNone)
  311. {
  312. uint32_t j;
  313. for(j=0; j<ports.nPorts; j++)
  314. {
  315. if(flags & ILCLIENT_DISABLE_ALL_PORTS)
  316. ilclient_disable_port(*comp, ports.nStartPortNumber+j);
  317. if(flags & ILCLIENT_OUTPUT_ZERO_BUFFERS)
  318. {
  319. OMX_PARAM_PORTDEFINITIONTYPE portdef;
  320. portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
  321. portdef.nVersion.nVersion = OMX_VERSION;
  322. portdef.nPortIndex = ports.nStartPortNumber+j;
  323. if(OMX_GetParameter((*comp)->comp, OMX_IndexParamPortDefinition, &portdef) == OMX_ErrorNone)
  324. {
  325. if(portdef.eDir == OMX_DirOutput && portdef.nBufferCountActual > 0)
  326. {
  327. portdef.nBufferCountActual = 0;
  328. OMX_SetParameter((*comp)->comp, OMX_IndexParamPortDefinition, &portdef);
  329. }
  330. }
  331. }
  332. }
  333. }
  334. }
  335. }
  336. return 0;
  337. }
  338. else
  339. {
  340. vcos_event_flags_delete(&(*comp)->event);
  341. vcos_semaphore_delete(&(*comp)->sema);
  342. vcos_free(*comp);
  343. *comp = NULL;
  344. return -1;
  345. }
  346. }
  347. /***********************************************************
  348. * Name: ilclient_remove_event
  349. *
  350. * Description: Removes an event from a component event list. ignore1
  351. * and ignore2 are flags indicating whether to not match on nData1 and
  352. * nData2 respectively.
  353. *
  354. * Returns: 0 if the event was removed. -1 if no matching event was
  355. * found.
  356. ***********************************************************/
  357. int ilclient_remove_event(COMPONENT_T *st, OMX_EVENTTYPE eEvent,
  358. OMX_U32 nData1, int ignore1, OMX_IN OMX_U32 nData2, int ignore2)
  359. {
  360. ILEVENT_T *cur, *prev;
  361. uint32_t set;
  362. ilclient_lock_events(st->client);
  363. cur = st->list;
  364. prev = NULL;
  365. while (cur && !(cur->eEvent == eEvent && (ignore1 || cur->nData1 == nData1) && (ignore2 || cur->nData2 == nData2)))
  366. {
  367. prev = cur;
  368. cur = cur->next;
  369. }
  370. if (cur == NULL)
  371. {
  372. ilclient_unlock_events(st->client);
  373. return -1;
  374. }
  375. if (prev == NULL)
  376. st->list = cur->next;
  377. else
  378. prev->next = cur->next;
  379. // add back into spare list
  380. cur->next = st->client->event_list;
  381. st->client->event_list = cur;
  382. cur->eEvent = -1; // mark as unused
  383. // if we're removing an OMX_EventError or OMX_EventParamOrConfigChanged event, then clear the error bit from the eventgroup,
  384. // since the user might have been notified through the error callback, and then
  385. // can't clear the event bit - this will then cause problems the next time they
  386. // wait for an error.
  387. if(eEvent == OMX_EventError)
  388. vcos_event_flags_get(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR_CONSUME, 0, &set);
  389. else if(eEvent == OMX_EventParamOrConfigChanged)
  390. vcos_event_flags_get(&st->event, ILCLIENT_CONFIG_CHANGED, VCOS_OR_CONSUME, 0, &set);
  391. ilclient_unlock_events(st->client);
  392. return 0;
  393. }
  394. /***********************************************************
  395. * Name: ilclient_state_transition
  396. *
  397. * Description: Transitions a null terminated list of IL components to
  398. * a given state. All components are told to transition in a random
  399. * order before any are checked for transition completion.
  400. *
  401. * Returns: void
  402. ***********************************************************/
  403. void ilclient_state_transition(COMPONENT_T *list[], OMX_STATETYPE state)
  404. {
  405. OMX_ERRORTYPE error;
  406. int i, num;
  407. uint32_t set;
  408. num=0;
  409. while (list[num])
  410. num++;
  411. // if we transition the supplier port first, it will call freebuffer on the non
  412. // supplier, which will correctly signal a port unpopulated error. We want to
  413. // ignore these errors.
  414. if (state == OMX_StateLoaded)
  415. for (i=0; i<num; i++)
  416. list[i]->error_mask |= ILCLIENT_ERROR_UNPOPULATED;
  417. for (i=0; i<num; i++)
  418. list[i]->private = ((rand() >> 13) & 0xff)+1;
  419. for (i=0; i<num; i++)
  420. {
  421. // transition the components in a random order
  422. int j, min = -1;
  423. for (j=0; j<num; j++)
  424. if (list[j]->private && (min == -1 || list[min]->private > list[j]->private))
  425. min = j;
  426. list[min]->private = 0;
  427. random_wait();
  428. //Clear error event for this component
  429. vcos_event_flags_get(&list[min]->event, ILCLIENT_EVENT_ERROR, VCOS_OR_CONSUME, 0, &set);
  430. error = OMX_SendCommand(list[min]->comp, OMX_CommandStateSet, state, NULL);
  431. vc_assert(error == OMX_ErrorNone);
  432. }
  433. random_wait();
  434. for (i=0; i<num; i++)
  435. if(ilclient_wait_for_command_complete(list[i], OMX_CommandStateSet, state) < 0)
  436. vc_assert(0);
  437. if (state == OMX_StateLoaded)
  438. for (i=0; i<num; i++)
  439. list[i]->error_mask &= ~ILCLIENT_ERROR_UNPOPULATED;
  440. }
  441. /***********************************************************
  442. * Name: ilclient_teardown_tunnels
  443. *
  444. * Description: tears down a null terminated list of tunnels.
  445. *
  446. * Returns: void
  447. ***********************************************************/
  448. void ilclient_teardown_tunnels(TUNNEL_T *tunnel)
  449. {
  450. int i;
  451. OMX_ERRORTYPE error;
  452. i=0;;
  453. while (tunnel[i].source)
  454. {
  455. error = OMX_SetupTunnel(tunnel[i].source->comp, tunnel[i].source_port, NULL, 0);
  456. vc_assert(error == OMX_ErrorNone);
  457. error = OMX_SetupTunnel(tunnel[i].sink->comp, tunnel[i].sink_port, NULL, 0);
  458. vc_assert(error == OMX_ErrorNone);
  459. i++;
  460. }
  461. }
  462. /***********************************************************
  463. * Name: ilclient_disable_tunnel
  464. *
  465. * Description: disables a tunnel by disabling the ports. Allows
  466. * ports to signal same state error if they were already disabled.
  467. *
  468. * Returns: void
  469. ***********************************************************/
  470. void ilclient_disable_tunnel(TUNNEL_T *tunnel)
  471. {
  472. OMX_ERRORTYPE error;
  473. if(tunnel->source == 0 || tunnel->sink == 0)
  474. return;
  475. tunnel->source->error_mask |= ILCLIENT_ERROR_UNPOPULATED;
  476. tunnel->sink->error_mask |= ILCLIENT_ERROR_UNPOPULATED;
  477. error = OMX_SendCommand(tunnel->source->comp, OMX_CommandPortDisable, tunnel->source_port, NULL);
  478. vc_assert(error == OMX_ErrorNone);
  479. error = OMX_SendCommand(tunnel->sink->comp, OMX_CommandPortDisable, tunnel->sink_port, NULL);
  480. vc_assert(error == OMX_ErrorNone);
  481. if(ilclient_wait_for_command_complete(tunnel->source, OMX_CommandPortDisable, tunnel->source_port) < 0)
  482. vc_assert(0);
  483. if(ilclient_wait_for_command_complete(tunnel->sink, OMX_CommandPortDisable, tunnel->sink_port) < 0)
  484. vc_assert(0);
  485. tunnel->source->error_mask &= ~ILCLIENT_ERROR_UNPOPULATED;
  486. tunnel->sink->error_mask &= ~ILCLIENT_ERROR_UNPOPULATED;
  487. }
  488. /***********************************************************
  489. * Name: ilclient_enable_tunnel
  490. *
  491. * Description: enables a tunnel by enabling the ports
  492. *
  493. * Returns: 0 on success, -1 on failure
  494. ***********************************************************/
  495. int ilclient_enable_tunnel(TUNNEL_T *tunnel)
  496. {
  497. OMX_STATETYPE state;
  498. OMX_ERRORTYPE error;
  499. ilclient_debug_output("ilclient: enable tunnel from %x/%d to %x/%d",
  500. tunnel->source, tunnel->source_port,
  501. tunnel->sink, tunnel->sink_port);
  502. error = OMX_SendCommand(tunnel->source->comp, OMX_CommandPortEnable, tunnel->source_port, NULL);
  503. vc_assert(error == OMX_ErrorNone);
  504. error = OMX_SendCommand(tunnel->sink->comp, OMX_CommandPortEnable, tunnel->sink_port, NULL);
  505. vc_assert(error == OMX_ErrorNone);
  506. // to complete, the sink component can't be in loaded state
  507. error = OMX_GetState(tunnel->sink->comp, &state);
  508. vc_assert(error == OMX_ErrorNone);
  509. if (state == OMX_StateLoaded)
  510. {
  511. int ret = 0;
  512. if(ilclient_wait_for_command_complete(tunnel->sink, OMX_CommandPortEnable, tunnel->sink_port) != 0 ||
  513. OMX_SendCommand(tunnel->sink->comp, OMX_CommandStateSet, OMX_StateIdle, NULL) != OMX_ErrorNone ||
  514. (ret = ilclient_wait_for_command_complete_dual(tunnel->sink, OMX_CommandStateSet, OMX_StateIdle, tunnel->source)) < 0)
  515. {
  516. if(ret == -2)
  517. {
  518. // the error was reported fom the source component: clear this error and disable the sink component
  519. ilclient_wait_for_command_complete(tunnel->source, OMX_CommandPortEnable, tunnel->source_port);
  520. ilclient_disable_port(tunnel->sink, tunnel->sink_port);
  521. }
  522. ilclient_debug_output("ilclient: could not change component state to IDLE");
  523. ilclient_disable_port(tunnel->source, tunnel->source_port);
  524. return -1;
  525. }
  526. }
  527. else
  528. {
  529. if (ilclient_wait_for_command_complete(tunnel->sink, OMX_CommandPortEnable, tunnel->sink_port) != 0)
  530. {
  531. ilclient_debug_output("ilclient: could not change sink port %d to enabled", tunnel->sink_port);
  532. //Oops failed to enable the sink port
  533. ilclient_disable_port(tunnel->source, tunnel->source_port);
  534. //Clean up the port enable event from the source port.
  535. ilclient_wait_for_event(tunnel->source, OMX_EventCmdComplete,
  536. OMX_CommandPortEnable, 0, tunnel->source_port, 0,
  537. ILCLIENT_PORT_ENABLED | ILCLIENT_EVENT_ERROR, VCOS_EVENT_FLAGS_SUSPEND);
  538. return -1;
  539. }
  540. }
  541. if(ilclient_wait_for_command_complete(tunnel->source, OMX_CommandPortEnable, tunnel->source_port) != 0)
  542. {
  543. ilclient_debug_output("ilclient: could not change source port %d to enabled", tunnel->source_port);
  544. //Failed to enable the source port
  545. ilclient_disable_port(tunnel->sink, tunnel->sink_port);
  546. return -1;
  547. }
  548. return 0;
  549. }
  550. /***********************************************************
  551. * Name: ilclient_flush_tunnels
  552. *
  553. * Description: flushes all ports used in a null terminated list of
  554. * tunnels. max specifies the maximum number of tunnels to flush from
  555. * the list, where max=0 means all tunnels.
  556. *
  557. * Returns: void
  558. ***********************************************************/
  559. void ilclient_flush_tunnels(TUNNEL_T *tunnel, int max)
  560. {
  561. OMX_ERRORTYPE error;
  562. int i;
  563. i=0;
  564. while (tunnel[i].source && (max == 0 || i < max))
  565. {
  566. error = OMX_SendCommand(tunnel[i].source->comp, OMX_CommandFlush, tunnel[i].source_port, NULL);
  567. vc_assert(error == OMX_ErrorNone);
  568. error = OMX_SendCommand(tunnel[i].sink->comp, OMX_CommandFlush, tunnel[i].sink_port, NULL);
  569. vc_assert(error == OMX_ErrorNone);
  570. ilclient_wait_for_event(tunnel[i].source, OMX_EventCmdComplete,
  571. OMX_CommandFlush, 0, tunnel[i].source_port, 0,
  572. ILCLIENT_PORT_FLUSH, VCOS_EVENT_FLAGS_SUSPEND);
  573. ilclient_wait_for_event(tunnel[i].sink, OMX_EventCmdComplete,
  574. OMX_CommandFlush, 0, tunnel[i].sink_port, 0,
  575. ILCLIENT_PORT_FLUSH, VCOS_EVENT_FLAGS_SUSPEND);
  576. i++;
  577. }
  578. }
  579. /***********************************************************
  580. * Name: ilclient_return_events
  581. *
  582. * Description: Returns all events from a component event list to the
  583. * list of unused event structures.
  584. *
  585. * Returns: void
  586. ***********************************************************/
  587. void ilclient_return_events(COMPONENT_T *comp)
  588. {
  589. ilclient_lock_events(comp->client);
  590. while (comp->list)
  591. {
  592. ILEVENT_T *next = comp->list->next;
  593. comp->list->next = comp->client->event_list;
  594. comp->client->event_list = comp->list;
  595. comp->list = next;
  596. }
  597. ilclient_unlock_events(comp->client);
  598. }
  599. /***********************************************************
  600. * Name: ilclient_cleanup_components
  601. *
  602. * Description: frees all components from a null terminated list and
  603. * deletes resources used in component state structure.
  604. *
  605. * Returns: void
  606. ***********************************************************/
  607. void ilclient_cleanup_components(COMPONENT_T *list[])
  608. {
  609. int i;
  610. OMX_ERRORTYPE error;
  611. i=0;
  612. while (list[i])
  613. {
  614. ilclient_return_events(list[i]);
  615. if (list[i]->comp)
  616. {
  617. error = OMX_FreeHandle(list[i]->comp);
  618. vc_assert(error == OMX_ErrorNone);
  619. }
  620. i++;
  621. }
  622. i=0;
  623. while (list[i])
  624. {
  625. vcos_event_flags_delete(&list[i]->event);
  626. vcos_semaphore_delete(&list[i]->sema);
  627. vcos_free(list[i]);
  628. list[i] = NULL;
  629. i++;
  630. }
  631. }
  632. /***********************************************************
  633. * Name: ilclient_change_component_state
  634. *
  635. * Description: changes the state of a single component. Note: this
  636. * may not be suitable if the component is tunnelled and requires
  637. * connected components to also change state.
  638. *
  639. * Returns: 0 on success, -1 on failure (note - trying to change to
  640. * the same state which causes a OMX_ErrorSameState is treated as
  641. * success)
  642. ***********************************************************/
  643. int ilclient_change_component_state(COMPONENT_T *comp, OMX_STATETYPE state)
  644. {
  645. OMX_ERRORTYPE error;
  646. error = OMX_SendCommand(comp->comp, OMX_CommandStateSet, state, NULL);
  647. vc_assert(error == OMX_ErrorNone);
  648. if(ilclient_wait_for_command_complete(comp, OMX_CommandStateSet, state) < 0)
  649. {
  650. ilclient_debug_output("ilclient: could not change component state to %d", state);
  651. ilclient_remove_event(comp, OMX_EventError, 0, 1, 0, 1);
  652. return -1;
  653. }
  654. return 0;
  655. }
  656. /***********************************************************
  657. * Name: ilclient_disable_port
  658. *
  659. * Description: disables a port on a given component.
  660. *
  661. * Returns: void
  662. ***********************************************************/
  663. void ilclient_disable_port(COMPONENT_T *comp, int portIndex)
  664. {
  665. OMX_ERRORTYPE error;
  666. error = OMX_SendCommand(comp->comp, OMX_CommandPortDisable, portIndex, NULL);
  667. vc_assert(error == OMX_ErrorNone);
  668. if(ilclient_wait_for_command_complete(comp, OMX_CommandPortDisable, portIndex) < 0)
  669. vc_assert(0);
  670. }
  671. /***********************************************************
  672. * Name: ilclient_enabled_port
  673. *
  674. * Description: enables a port on a given component.
  675. *
  676. * Returns: void
  677. ***********************************************************/
  678. void ilclient_enable_port(COMPONENT_T *comp, int portIndex)
  679. {
  680. OMX_ERRORTYPE error;
  681. error = OMX_SendCommand(comp->comp, OMX_CommandPortEnable, portIndex, NULL);
  682. vc_assert(error == OMX_ErrorNone);
  683. if(ilclient_wait_for_command_complete(comp, OMX_CommandPortEnable, portIndex) < 0)
  684. vc_assert(0);
  685. }
  686. /***********************************************************
  687. * Name: ilclient_enable_port_buffers
  688. *
  689. * Description: enables a port on a given component which requires
  690. * buffers to be supplied by the client.
  691. *
  692. * Returns: void
  693. ***********************************************************/
  694. int ilclient_enable_port_buffers(COMPONENT_T *comp, int portIndex,
  695. ILCLIENT_MALLOC_T ilclient_malloc,
  696. ILCLIENT_FREE_T ilclient_free,
  697. void *private)
  698. {
  699. OMX_ERRORTYPE error;
  700. OMX_PARAM_PORTDEFINITIONTYPE portdef;
  701. OMX_BUFFERHEADERTYPE *list = NULL, **end = &list;
  702. OMX_STATETYPE state;
  703. int i;
  704. memset(&portdef, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
  705. portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
  706. portdef.nVersion.nVersion = OMX_VERSION;
  707. portdef.nPortIndex = portIndex;
  708. // work out buffer requirements, check port is in the right state
  709. error = OMX_GetParameter(comp->comp, OMX_IndexParamPortDefinition, &portdef);
  710. if(error != OMX_ErrorNone || portdef.bEnabled != OMX_FALSE || portdef.nBufferCountActual == 0 || portdef.nBufferSize == 0)
  711. return -1;
  712. // check component is in the right state to accept buffers
  713. error = OMX_GetState(comp->comp, &state);
  714. if (error != OMX_ErrorNone || !(state == OMX_StateIdle || state == OMX_StateExecuting || state == OMX_StatePause))
  715. return -1;
  716. // send the command
  717. error = OMX_SendCommand(comp->comp, OMX_CommandPortEnable, portIndex, NULL);
  718. vc_assert(error == OMX_ErrorNone);
  719. for (i=0; i != portdef.nBufferCountActual; i++)
  720. {
  721. unsigned char *buf;
  722. if(ilclient_malloc)
  723. buf = ilclient_malloc(private, portdef.nBufferSize, portdef.nBufferAlignment, comp->bufname);
  724. else
  725. buf = vcos_malloc_aligned(portdef.nBufferSize, portdef.nBufferAlignment, comp->bufname);
  726. if(!buf)
  727. break;
  728. error = OMX_UseBuffer(comp->comp, end, portIndex, NULL, portdef.nBufferSize, buf);
  729. if(error != OMX_ErrorNone)
  730. {
  731. if(ilclient_free)
  732. ilclient_free(private, buf);
  733. else
  734. vcos_free(buf);
  735. break;
  736. }
  737. end = (OMX_BUFFERHEADERTYPE **) &((*end)->pAppPrivate);
  738. }
  739. // queue these buffers
  740. vcos_semaphore_wait(&comp->sema);
  741. if(portdef.eDir == OMX_DirInput)
  742. {
  743. *end = comp->in_list;
  744. comp->in_list = list;
  745. }
  746. else
  747. {
  748. *end = comp->out_list;
  749. comp->out_list = list;
  750. }
  751. vcos_semaphore_post(&comp->sema);
  752. if(i != portdef.nBufferCountActual ||
  753. ilclient_wait_for_command_complete(comp, OMX_CommandPortEnable, portIndex) < 0)
  754. {
  755. ilclient_disable_port_buffers(comp, portIndex, NULL, ilclient_free, private);
  756. // at this point the first command might have terminated with an error, which means that
  757. // the port is disabled before the disable_port_buffers function is called, so we're left
  758. // with the error bit set and an error event in the queue. Clear these now if they exist.
  759. ilclient_remove_event(comp, OMX_EventError, 0, 1, 1, 0);
  760. return -1;
  761. }
  762. // success
  763. return 0;
  764. }
  765. /***********************************************************
  766. * Name: ilclient_disable_port_buffers
  767. *
  768. * Description: disables a port on a given component which has
  769. * buffers supplied by the client.
  770. *
  771. * Returns: void
  772. ***********************************************************/
  773. void ilclient_disable_port_buffers(COMPONENT_T *comp, int portIndex,
  774. OMX_BUFFERHEADERTYPE *bufferList,
  775. ILCLIENT_FREE_T ilclient_free,
  776. void *private)
  777. {
  778. OMX_ERRORTYPE error;
  779. OMX_BUFFERHEADERTYPE *list = bufferList;
  780. OMX_BUFFERHEADERTYPE **head, *clist, *prev;
  781. OMX_PARAM_PORTDEFINITIONTYPE portdef;
  782. int num;
  783. // get the buffers off the relevant queue
  784. memset(&portdef, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
  785. portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
  786. portdef.nVersion.nVersion = OMX_VERSION;
  787. portdef.nPortIndex = portIndex;
  788. // work out buffer requirements, check port is in the right state
  789. error = OMX_GetParameter(comp->comp, OMX_IndexParamPortDefinition, &portdef);
  790. if(error != OMX_ErrorNone || portdef.bEnabled != OMX_TRUE || portdef.nBufferCountActual == 0 || portdef.nBufferSize == 0)
  791. return;
  792. num = portdef.nBufferCountActual;
  793. error = OMX_SendCommand(comp->comp, OMX_CommandPortDisable, portIndex, NULL);
  794. vc_assert(error == OMX_ErrorNone);
  795. while(num > 0)
  796. {
  797. VCOS_UNSIGNED set;
  798. if(list == NULL)
  799. {
  800. vcos_semaphore_wait(&comp->sema);
  801. // take buffers for this port off the relevant queue
  802. head = portdef.eDir == OMX_DirInput ? &comp->in_list : &comp->out_list;
  803. clist = *head;
  804. prev = NULL;
  805. while(clist)
  806. {
  807. if((portdef.eDir == OMX_DirInput ? clist->nInputPortIndex : clist->nOutputPortIndex) == portIndex)
  808. {
  809. OMX_BUFFERHEADERTYPE *pBuffer = clist;
  810. if(!prev)
  811. clist = *head = (OMX_BUFFERHEADERTYPE *) pBuffer->pAppPrivate;
  812. else
  813. clist = prev->pAppPrivate = (OMX_BUFFERHEADERTYPE *) pBuffer->pAppPrivate;
  814. pBuffer->pAppPrivate = list;
  815. list = pBuffer;
  816. }
  817. else
  818. {
  819. prev = clist;
  820. clist = (OMX_BUFFERHEADERTYPE *) &(clist->pAppPrivate);
  821. }
  822. }
  823. vcos_semaphore_post(&comp->sema);
  824. }
  825. while(list)
  826. {
  827. void *buf = list->pBuffer;
  828. OMX_BUFFERHEADERTYPE *next = list->pAppPrivate;
  829. error = OMX_FreeBuffer(comp->comp, portIndex, list);
  830. vc_assert(error == OMX_ErrorNone);
  831. if(ilclient_free)
  832. ilclient_free(private, buf);
  833. else
  834. vcos_free(buf);
  835. num--;
  836. list = next;
  837. }
  838. if(num)
  839. {
  840. OMX_U32 mask = ILCLIENT_PORT_DISABLED | ILCLIENT_EVENT_ERROR;
  841. mask |= (portdef.eDir == OMX_DirInput ? ILCLIENT_EMPTY_BUFFER_DONE : ILCLIENT_FILL_BUFFER_DONE);
  842. // also wait for command complete/error in case we didn't have all the buffers allocated
  843. vcos_event_flags_get(&comp->event, mask, VCOS_OR_CONSUME, -1, &set);
  844. if((set & ILCLIENT_EVENT_ERROR) && ilclient_remove_event(comp, OMX_EventError, 0, 1, 1, 0) >= 0)
  845. return;
  846. if((set & ILCLIENT_PORT_DISABLED) && ilclient_remove_event(comp, OMX_EventCmdComplete, OMX_CommandPortDisable, 0, portIndex, 0) >= 0)
  847. return;
  848. }
  849. }
  850. if(ilclient_wait_for_command_complete(comp, OMX_CommandPortDisable, portIndex) < 0)
  851. vc_assert(0);
  852. }
  853. /***********************************************************
  854. * Name: ilclient_setup_tunnel
  855. *
  856. * Description: creates a tunnel between components that require that
  857. * ports be inititially disabled, then enabled after tunnel setup. If
  858. * timeout is non-zero, it will initially wait until a port settings
  859. * changes message has been received by the output port. If port
  860. * streams are supported by the output port, the requested port stream
  861. * will be selected.
  862. *
  863. * Returns: 0 indicates success, negative indicates failure.
  864. * -1: a timeout waiting for the parameter changed
  865. * -2: an error was returned instead of parameter changed
  866. * -3: no streams are available from this port
  867. * -4: requested stream is not available from this port
  868. * -5: the data format was not acceptable to the sink
  869. ***********************************************************/
  870. int ilclient_setup_tunnel(TUNNEL_T *tunnel, unsigned int portStream, int timeout)
  871. {
  872. OMX_ERRORTYPE error;
  873. OMX_PARAM_U32TYPE param;
  874. OMX_STATETYPE state;
  875. int32_t status;
  876. int enable_error;
  877. // source component must at least be idle, not loaded
  878. error = OMX_GetState(tunnel->source->comp, &state);
  879. vc_assert(error == OMX_ErrorNone);
  880. if (state == OMX_StateLoaded && ilclient_change_component_state(tunnel->source, OMX_StateIdle) < 0)
  881. return -2;
  882. // wait for the port parameter changed from the source port
  883. if(timeout)
  884. {
  885. status = ilclient_wait_for_event(tunnel->source, OMX_EventPortSettingsChanged,
  886. tunnel->source_port, 0, -1, 1,
  887. ILCLIENT_PARAMETER_CHANGED | ILCLIENT_EVENT_ERROR, timeout);
  888. if (status < 0)
  889. {
  890. ilclient_debug_output(
  891. "ilclient: timed out waiting for port settings changed on port %d", tunnel->source_port);
  892. return status;
  893. }
  894. }
  895. // disable ports
  896. ilclient_disable_tunnel(tunnel);
  897. // if this source port uses port streams, we need to select one of them before proceeding
  898. // if getparameter causes an error that's fine, nothing needs selecting
  899. param.nSize = sizeof(OMX_PARAM_U32TYPE);
  900. param.nVersion.nVersion = OMX_VERSION;
  901. param.nPortIndex = tunnel->source_port;
  902. if (OMX_GetParameter(tunnel->source->comp, OMX_IndexParamNumAvailableStreams, &param) == OMX_ErrorNone)
  903. {
  904. if (param.nU32 == 0)
  905. {
  906. // no streams available
  907. // leave the source port disabled, and return a failure
  908. return -3;
  909. }
  910. if (param.nU32 <= portStream)
  911. {
  912. // requested stream not available
  913. // no streams available
  914. // leave the source port disabled, and return a failure
  915. return -4;
  916. }
  917. param.nU32 = portStream;
  918. error = OMX_SetParameter(tunnel->source->comp, OMX_IndexParamActiveStream, &param);
  919. vc_assert(error == OMX_ErrorNone);
  920. }
  921. // now create the tunnel
  922. error = OMX_SetupTunnel(tunnel->source->comp, tunnel->source_port, tunnel->sink->comp, tunnel->sink_port);
  923. enable_error = 0;
  924. if (error != OMX_ErrorNone || (enable_error=ilclient_enable_tunnel(tunnel)) < 0)
  925. {
  926. // probably format not compatible
  927. error = OMX_SetupTunnel(tunnel->source->comp, tunnel->source_port, NULL, 0);
  928. vc_assert(error == OMX_ErrorNone);
  929. error = OMX_SetupTunnel(tunnel->sink->comp, tunnel->sink_port, NULL, 0);
  930. vc_assert(error == OMX_ErrorNone);
  931. if(enable_error)
  932. {
  933. //Clean up the errors. This does risk removing an error that was nothing to do with this tunnel :-/
  934. ilclient_remove_event(tunnel->sink, OMX_EventError, 0, 1, 0, 1);
  935. ilclient_remove_event(tunnel->source, OMX_EventError, 0, 1, 0, 1);
  936. }
  937. ilclient_debug_output("ilclient: could not setup/enable tunnel (setup=0x%x,enable=%d)",
  938. error, enable_error);
  939. return -5;
  940. }
  941. return 0;
  942. }
  943. /***********************************************************
  944. * Name: ilclient_wait_for_event
  945. *
  946. * Description: waits for a given event to appear on a component event
  947. * list. If not immediately present, will wait on that components
  948. * event group for the given event flag.
  949. *
  950. * Returns: 0 indicates success, negative indicates failure.
  951. * -1: a timeout was received.
  952. * -2: an error event was received.
  953. * -3: a config change event was received.
  954. ***********************************************************/
  955. int ilclient_wait_for_event(COMPONENT_T *comp, OMX_EVENTTYPE event,
  956. OMX_U32 nData1, int ignore1, OMX_IN OMX_U32 nData2, int ignore2,
  957. int event_flag, int suspend)
  958. {
  959. int32_t status;
  960. uint32_t set;
  961. while (ilclient_remove_event(comp, event, nData1, ignore1, nData2, ignore2) < 0)
  962. {
  963. // if we want to be notified of errors, check the list for an error now
  964. // before blocking, the event flag may have been cleared already.
  965. if(event_flag & ILCLIENT_EVENT_ERROR)
  966. {
  967. ILEVENT_T *cur;
  968. ilclient_lock_events(comp->client);
  969. cur = comp->list;
  970. while(cur && cur->eEvent != OMX_EventError)
  971. cur = cur->next;
  972. if(cur)
  973. {
  974. // clear error flag
  975. vcos_event_flags_get(&comp->event, ILCLIENT_EVENT_ERROR, VCOS_OR_CONSUME, 0, &set);
  976. ilclient_unlock_events(comp->client);
  977. return -2;
  978. }
  979. ilclient_unlock_events(comp->client);
  980. }
  981. // check for config change event if we are asked to be notified of that
  982. if(event_flag & ILCLIENT_CONFIG_CHANGED)
  983. {
  984. ILEVENT_T *cur;
  985. ilclient_lock_events(comp->client);
  986. cur = comp->list;
  987. while(cur && cur->eEvent != OMX_EventParamOrConfigChanged)
  988. cur = cur->next;
  989. ilclient_unlock_events(comp->client);
  990. if(cur)
  991. return ilclient_remove_event(comp, event, nData1, ignore1, nData2, ignore2) == 0 ? 0 : -3;
  992. }
  993. status = vcos_event_flags_get(&comp->event, event_flag, VCOS_OR_CONSUME,
  994. suspend, &set);
  995. if (status != 0)
  996. return -1;
  997. if (set & ILCLIENT_EVENT_ERROR)
  998. return -2;
  999. if (set & ILCLIENT_CONFIG_CHANGED)
  1000. return ilclient_remove_event(comp, event, nData1, ignore1, nData2, ignore2) == 0 ? 0 : -3;
  1001. }
  1002. return 0;
  1003. }
  1004. /***********************************************************
  1005. * Name: ilclient_wait_for_command_complete_dual
  1006. *
  1007. * Description: Waits for an event signalling command completion. In
  1008. * this version we may also return failure if there is an error event
  1009. * that has terminated a command on a second component.
  1010. *
  1011. * Returns: 0 on success, -1 on failure of comp, -2 on failure of other
  1012. ***********************************************************/
  1013. int ilclient_wait_for_command_complete_dual(COMPONENT_T *comp, OMX_COMMANDTYPE command, OMX_U32 nData2, COMPONENT_T *other)
  1014. {
  1015. OMX_U32 mask = ILCLIENT_EVENT_ERROR;
  1016. int ret = 0;
  1017. switch(command) {
  1018. case OMX_CommandStateSet: mask |= ILCLIENT_STATE_CHANGED; break;
  1019. case OMX_CommandPortDisable: mask |= ILCLIENT_PORT_DISABLED; break;
  1020. case OMX_CommandPortEnable: mask |= ILCLIENT_PORT_ENABLED; break;
  1021. default: return -1;
  1022. }
  1023. if(other)
  1024. other->related = comp;
  1025. while(1)
  1026. {
  1027. ILEVENT_T *cur, *prev = NULL;
  1028. VCOS_UNSIGNED set;
  1029. ilclient_lock_events(comp->client);
  1030. cur = comp->list;
  1031. while(cur &&
  1032. !(cur->eEvent == OMX_EventCmdComplete && cur->nData1 == command && cur->nData2 == nData2) &&
  1033. !(cur->eEvent == OMX_EventError && cur->nData2 == 1))
  1034. {
  1035. prev = cur;
  1036. cur = cur->next;
  1037. }
  1038. if(cur)
  1039. {
  1040. if(prev == NULL)
  1041. comp->list = cur->next;
  1042. else
  1043. prev->next = cur->next;
  1044. // work out whether this was a success or a fail event
  1045. ret = cur->eEvent == OMX_EventCmdComplete || cur->nData1 == OMX_ErrorSameState ? 0 : -1;
  1046. if(cur->eEvent == OMX_EventError)
  1047. vcos_event_flags_get(&comp->event, ILCLIENT_EVENT_ERROR, VCOS_OR_CONSUME, 0, &set);
  1048. // add back into spare list
  1049. cur->next = comp->client->event_list;
  1050. comp->client->event_list = cur;
  1051. cur->eEvent = -1; // mark as unused
  1052. ilclient_unlock_events(comp->client);
  1053. break;
  1054. }
  1055. else if(other != NULL)
  1056. {
  1057. // check the other component for an error event that terminates a command
  1058. cur = other->list;
  1059. while(cur && !(cur->eEvent == OMX_EventError && cur->nData2 == 1))
  1060. cur = cur->next;
  1061. if(cur)
  1062. {
  1063. // we don't remove the event in this case, since the user
  1064. // can confirm that this event errored by calling wait_for_command on the
  1065. // other component
  1066. ret = -2;
  1067. ilclient_unlock_events(comp->client);
  1068. break;
  1069. }
  1070. }
  1071. ilclient_unlock_events(comp->client);
  1072. vcos_event_flags_get(&comp->event, mask, VCOS_OR_CONSUME, VCOS_SUSPEND, &set);
  1073. }
  1074. if(other)
  1075. other->related = NULL;
  1076. return ret;
  1077. }
  1078. /***********************************************************
  1079. * Name: ilclient_wait_for_command_complete
  1080. *
  1081. * Description: Waits for an event signalling command completion.
  1082. *
  1083. * Returns: 0 on success, -1 on failure.
  1084. ***********************************************************/
  1085. int ilclient_wait_for_command_complete(COMPONENT_T *comp, OMX_COMMANDTYPE command, OMX_U32 nData2)
  1086. {
  1087. return ilclient_wait_for_command_complete_dual(comp, command, nData2, NULL);
  1088. }
  1089. /***********************************************************
  1090. * Name: ilclient_get_output_buffer
  1091. *
  1092. * Description: Returns an output buffer returned from a component
  1093. * using the OMX_FillBufferDone callback from the output list for the
  1094. * given component and port index.
  1095. *
  1096. * Returns: pointer to buffer if available, otherwise NULL
  1097. ***********************************************************/
  1098. OMX_BUFFERHEADERTYPE *ilclient_get_output_buffer(COMPONENT_T *comp, int portIndex, int block)
  1099. {
  1100. OMX_BUFFERHEADERTYPE *ret = NULL, *prev = NULL;
  1101. VCOS_UNSIGNED set;
  1102. do {
  1103. vcos_semaphore_wait(&comp->sema);
  1104. ret = comp->out_list;
  1105. while(ret != NULL && ret->nOutputPortIndex != portIndex)
  1106. {
  1107. prev = ret;
  1108. ret = ret->pAppPrivate;
  1109. }
  1110. if(ret)
  1111. {
  1112. if(prev == NULL)
  1113. comp->out_list = ret->pAppPrivate;
  1114. else
  1115. prev->pAppPrivate = ret->pAppPrivate;
  1116. ret->pAppPrivate = NULL;
  1117. }
  1118. vcos_semaphore_post(&comp->sema);
  1119. if(block && !ret)
  1120. vcos_event_flags_get(&comp->event, ILCLIENT_FILL_BUFFER_DONE, VCOS_OR_CONSUME, -1, &set);
  1121. } while(block && !ret);
  1122. return ret;
  1123. }
  1124. /***********************************************************
  1125. * Name: ilclient_get_input_buffer
  1126. *
  1127. * Description: Returns an input buffer return from a component using
  1128. * the OMX_EmptyBufferDone callback from the output list for the given
  1129. * component and port index.
  1130. *
  1131. * Returns: pointer to buffer if available, otherwise NULL
  1132. ***********************************************************/
  1133. OMX_BUFFERHEADERTYPE *ilclient_get_input_buffer(COMPONENT_T *comp, int portIndex, int block)
  1134. {
  1135. OMX_BUFFERHEADERTYPE *ret = NULL, *prev = NULL;
  1136. do {
  1137. VCOS_UNSIGNED set;
  1138. vcos_semaphore_wait(&comp->sema);
  1139. ret = comp->in_list;
  1140. while(ret != NULL && ret->nInputPortIndex != portIndex)
  1141. {
  1142. prev = ret;
  1143. ret = ret->pAppPrivate;
  1144. }
  1145. if(ret)
  1146. {
  1147. if(prev == NULL)
  1148. comp->in_list = ret->pAppPrivate;
  1149. else
  1150. prev->pAppPrivate = ret->pAppPrivate;
  1151. ret->pAppPrivate = NULL;
  1152. }
  1153. vcos_semaphore_post(&comp->sema);
  1154. if(block && !ret)
  1155. vcos_event_flags_get(&comp->event, ILCLIENT_EMPTY_BUFFER_DONE, VCOS_OR_CONSUME, -1, &set);
  1156. } while(block && !ret);
  1157. return ret;
  1158. }
  1159. /***********************************************************
  1160. * Name: ilclient_debug_output
  1161. *
  1162. * Description: prints a varg message to the log or the debug screen
  1163. * under win32
  1164. *
  1165. * Returns: void
  1166. ***********************************************************/
  1167. void ilclient_debug_output(char *format, ...)
  1168. {
  1169. va_list args;
  1170. va_start(args, format);
  1171. vcos_vlog_info(format, args);
  1172. va_end(args);
  1173. }
  1174. /******************************************************************************
  1175. Static functions
  1176. ******************************************************************************/
  1177. /***********************************************************
  1178. * Name: ilclient_lock_events
  1179. *
  1180. * Description: locks the client event structure
  1181. *
  1182. * Returns: void
  1183. ***********************************************************/
  1184. static void ilclient_lock_events(ILCLIENT_T *st)
  1185. {
  1186. vcos_semaphore_wait(&st->event_sema);
  1187. }
  1188. /***********************************************************
  1189. * Name: ilclient_unlock_events
  1190. *
  1191. * Description: unlocks the client event structure
  1192. *
  1193. * Returns: void
  1194. ***********************************************************/
  1195. static void ilclient_unlock_events(ILCLIENT_T *st)
  1196. {
  1197. vcos_semaphore_post(&st->event_sema);
  1198. }
  1199. /***********************************************************
  1200. * Name: ilclient_event_handler
  1201. *
  1202. * Description: event handler passed to core to use as component
  1203. * callback
  1204. *
  1205. * Returns: success
  1206. ***********************************************************/
  1207. static OMX_ERRORTYPE ilclient_event_handler(OMX_IN OMX_HANDLETYPE hComponent,
  1208. OMX_IN OMX_PTR pAppData,
  1209. OMX_IN OMX_EVENTTYPE eEvent,
  1210. OMX_IN OMX_U32 nData1,
  1211. OMX_IN OMX_U32 nData2,
  1212. OMX_IN OMX_PTR pEventData)
  1213. {
  1214. COMPONENT_T *st = (COMPONENT_T *) pAppData;
  1215. ILEVENT_T *event;
  1216. OMX_ERRORTYPE error = OMX_ErrorNone;
  1217. ilclient_lock_events(st->client);
  1218. // go through the events on this component and remove any duplicates in the
  1219. // existing list, since the client probably doesn't need them. it's better
  1220. // than asserting when we run out.
  1221. event = st->list;
  1222. while(event != NULL)
  1223. {
  1224. ILEVENT_T **list = &(event->next);
  1225. while(*list != NULL)
  1226. {
  1227. if((*list)->eEvent == event->eEvent &&
  1228. (*list)->nData1 == event->nData1 &&
  1229. (*list)->nData2 == event->nData2)
  1230. {
  1231. // remove this duplicate
  1232. ILEVENT_T *rem = *list;
  1233. ilclient_debug_output("%s: removing %d/%d/%d", st->name, event->eEvent, event->nData1, event->nData2);
  1234. *list = rem->next;
  1235. rem->eEvent = -1;
  1236. rem->next = st->client->event_list;
  1237. st->client->event_list = rem;
  1238. }
  1239. else
  1240. list = &((*list)->next);
  1241. }
  1242. event = event->next;
  1243. }
  1244. vc_assert(st->client->event_list);
  1245. event = st->client->event_list;
  1246. switch (eEvent) {
  1247. case OMX_EventCmdComplete:
  1248. switch (nData1) {
  1249. case OMX_CommandStateSet:
  1250. ilclient_debug_output("%s: callback state changed (%s)", st->name, states[nData2]);
  1251. vcos_event_flags_set(&st->event, ILCLIENT_STATE_CHANGED, VCOS_OR);
  1252. break;
  1253. case OMX_CommandPortDisable:
  1254. ilclient_debug_output("%s: callback port disable %d", st->name, nData2);
  1255. vcos_event_flags_set(&st->event, ILCLIENT_PORT_DISABLED, VCOS_OR);
  1256. break;
  1257. case OMX_CommandPortEnable:
  1258. ilclient_debug_output("%s: callback port enable %d", st->name, nData2);
  1259. vcos_event_flags_set(&st->event, ILCLIENT_PORT_ENABLED, VCOS_OR);
  1260. break;
  1261. case OMX_CommandFlush:
  1262. ilclient_debug_output("%s: callback port flush %d", st->name, nData2);
  1263. vcos_event_flags_set(&st->event, ILCLIENT_PORT_FLUSH, VCOS_OR);
  1264. break;
  1265. case OMX_CommandMarkBuffer:
  1266. ilclient_debug_output("%s: callback mark buffer %d", st->name, nData2);
  1267. vcos_event_flags_set(&st->event, ILCLIENT_MARKED_BUFFER, VCOS_OR);
  1268. break;
  1269. default:
  1270. vc_assert(0);
  1271. }
  1272. break;
  1273. case OMX_EventError:
  1274. {
  1275. // check if this component failed a command, and we have to notify another command
  1276. // of this failure
  1277. if(nData2 == 1 && st->related != NULL)
  1278. vcos_event_flags_set(&st->related->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1279. error = nData1;
  1280. switch (error) {
  1281. case OMX_ErrorPortUnpopulated:
  1282. if (st->error_mask & ILCLIENT_ERROR_UNPOPULATED)
  1283. {
  1284. ilclient_debug_output("%s: ignore error: port unpopulated (%d)", st->name, nData2);
  1285. event = NULL;
  1286. break;
  1287. }
  1288. ilclient_debug_output("%s: port unpopulated %x (%d)", st->name, error, nData2);
  1289. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1290. break;
  1291. case OMX_ErrorSameState:
  1292. if (st->error_mask & ILCLIENT_ERROR_SAMESTATE)
  1293. {
  1294. ilclient_debug_output("%s: ignore error: same state (%d)", st->name, nData2);
  1295. event = NULL;
  1296. break;
  1297. }
  1298. ilclient_debug_output("%s: same state %x (%d)", st->name, error, nData2);
  1299. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1300. break;
  1301. case OMX_ErrorBadParameter:
  1302. if (st->error_mask & ILCLIENT_ERROR_BADPARAMETER)
  1303. {
  1304. ilclient_debug_output("%s: ignore error: bad parameter (%d)", st->name, nData2);
  1305. event = NULL;
  1306. break;
  1307. }
  1308. ilclient_debug_output("%s: bad parameter %x (%d)", st->name, error, nData2);
  1309. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1310. break;
  1311. case OMX_ErrorIncorrectStateTransition:
  1312. ilclient_debug_output("%s: incorrect state transition %x (%d)", st->name, error, nData2);
  1313. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1314. break;
  1315. case OMX_ErrorBadPortIndex:
  1316. ilclient_debug_output("%s: bad port index %x (%d)", st->name, error, nData2);
  1317. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1318. break;
  1319. case OMX_ErrorStreamCorrupt:
  1320. ilclient_debug_output("%s: stream corrupt %x (%d)", st->name, error, nData2);
  1321. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1322. break;
  1323. case OMX_ErrorInsufficientResources:
  1324. ilclient_debug_output("%s: insufficient resources %x (%d)", st->name, error, nData2);
  1325. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1326. break;
  1327. case OMX_ErrorUnsupportedSetting:
  1328. ilclient_debug_output("%s: unsupported setting %x (%d)", st->name, error, nData2);
  1329. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1330. break;
  1331. case OMX_ErrorOverflow:
  1332. ilclient_debug_output("%s: overflow %x (%d)", st->name, error, nData2);
  1333. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1334. break;
  1335. case OMX_ErrorDiskFull:
  1336. ilclient_debug_output("%s: disk full %x (%d)", st->name, error, nData2);
  1337. //we do not set the error
  1338. break;
  1339. case OMX_ErrorMaxFileSize:
  1340. ilclient_debug_output("%s: max file size %x (%d)", st->name, error, nData2);
  1341. //we do not set the error
  1342. break;
  1343. case OMX_ErrorDrmUnauthorised:
  1344. ilclient_debug_output("%s: drm file is unauthorised %x (%d)", st->name, error, nData2);
  1345. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1346. break;
  1347. case OMX_ErrorDrmExpired:
  1348. ilclient_debug_output("%s: drm file has expired %x (%d)", st->name, error, nData2);
  1349. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1350. break;
  1351. case OMX_ErrorDrmGeneral:
  1352. ilclient_debug_output("%s: drm library error %x (%d)", st->name, error, nData2);
  1353. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1354. break;
  1355. default:
  1356. vc_assert(0);
  1357. ilclient_debug_output("%s: unexpected error %x (%d)", st->name, error, nData2);
  1358. vcos_event_flags_set(&st->event, ILCLIENT_EVENT_ERROR, VCOS_OR);
  1359. break;
  1360. }
  1361. }
  1362. break;
  1363. case OMX_EventBufferFlag:
  1364. ilclient_debug_output("%s: buffer flag %d/%x", st->name, nData1, nData2);
  1365. if (nData2 & OMX_BUFFERFLAG_EOS)
  1366. {
  1367. vcos_event_flags_set(&st->event, ILCLIENT_BUFFER_FLAG_EOS, VCOS_OR);
  1368. nData2 = OMX_BUFFERFLAG_EOS;
  1369. }
  1370. else
  1371. vc_assert(0);
  1372. break;
  1373. case OMX_EventPortSettingsChanged:
  1374. ilclient_debug_output("%s: port settings changed %d", st->name, nData1);
  1375. vcos_event_flags_set(&st->event, ILCLIENT_PARAMETER_CHANGED, VCOS_OR);
  1376. break;
  1377. case OMX_EventMark:
  1378. ilclient_debug_output("%s: buffer mark %p", st->name, pEventData);
  1379. vcos_event_flags_set(&st->event, ILCLIENT_BUFFER_MARK, VCOS_OR);
  1380. break;
  1381. case OMX_EventParamOrConfigChanged:
  1382. ilclient_debug_output("%s: param/config 0x%X on port %d changed", st->name, nData2, nData1);
  1383. vcos_event_flags_set(&st->event, ILCLIENT_CONFIG_CHANGED, VCOS_OR);
  1384. break;
  1385. default:
  1386. vc_assert(0);
  1387. break;
  1388. }
  1389. if (event)
  1390. {
  1391. // fill in details
  1392. event->eEvent = eEvent;
  1393. event->nData1 = nData1;
  1394. event->nData2 = nData2;
  1395. event->pEventData = pEventData;
  1396. // remove from top of spare list
  1397. st->client->event_list = st->client->event_list->next;
  1398. // put at head of component event queue
  1399. event->next = st->list;
  1400. st->list = event;
  1401. }
  1402. ilclient_unlock_events(st->client);
  1403. // now call any callbacks without the event lock so the client can
  1404. // remove the event in context
  1405. switch(eEvent) {
  1406. case OMX_EventError:
  1407. if(event && st->client->error_callback)
  1408. st->client->error_callback(st->client->error_callback_data, st, error);
  1409. break;
  1410. case OMX_EventBufferFlag:
  1411. if ((nData2 & OMX_BUFFERFLAG_EOS) && st->client->eos_callback)
  1412. st->client->eos_callback(st->client->eos_callback_data, st, nData1);
  1413. break;
  1414. case OMX_EventPortSettingsChanged:
  1415. if (st->client->port_settings_callback)
  1416. st->client->port_settings_callback(st->client->port_settings_callback_data, st, nData1);
  1417. break;
  1418. case OMX_EventParamOrConfigChanged:
  1419. if (st->client->configchanged_callback)
  1420. st->client->configchanged_callback(st->client->configchanged_callback_data, st, nData2);
  1421. break;
  1422. default:
  1423. // ignore
  1424. break;
  1425. }
  1426. return OMX_ErrorNone;
  1427. }
  1428. /***********************************************************
  1429. * Name: ilclient_empty_buffer_done
  1430. *
  1431. * Description: passed to core to use as component callback, puts
  1432. * buffer on list
  1433. *
  1434. * Returns:
  1435. ***********************************************************/
  1436. static OMX_ERRORTYPE ilclient_empty_buffer_done(OMX_IN OMX_HANDLETYPE hComponent,
  1437. OMX_IN OMX_PTR pAppData,
  1438. OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
  1439. {
  1440. COMPONENT_T *st = (COMPONENT_T *) pAppData;
  1441. OMX_BUFFERHEADERTYPE *list;
  1442. ilclient_debug_output("%s: empty buffer done %p", st->name, pBuffer);
  1443. vcos_semaphore_wait(&st->sema);
  1444. // insert at end of the list, so we process buffers in
  1445. // the same order
  1446. list = st->in_list;
  1447. while(list && list->pAppPrivate)
  1448. list = list->pAppPrivate;
  1449. if(!list)
  1450. st->in_list = pBuffer;
  1451. else
  1452. list->pAppPrivate = pBuffer;
  1453. pBuffer->pAppPrivate = NULL;
  1454. vcos_semaphore_post(&st->sema);
  1455. vcos_event_flags_set(&st->event, ILCLIENT_EMPTY_BUFFER_DONE, VCOS_OR);
  1456. if (st->client->empty_buffer_done_callback)
  1457. st->client->empty_buffer_done_callback(st->client->empty_buffer_done_callback_data, st);
  1458. return OMX_ErrorNone;
  1459. }
  1460. /***********************************************************
  1461. * Name: ilclient_empty_buffer_done_error
  1462. *
  1463. * Description: passed to core to use as component callback, asserts
  1464. * on use as client not expecting component to use this callback.
  1465. *
  1466. * Returns:
  1467. ***********************************************************/
  1468. static OMX_ERRORTYPE ilclient_empty_buffer_done_error(OMX_IN OMX_HANDLETYPE hComponent,
  1469. OMX_IN OMX_PTR pAppData,
  1470. OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
  1471. {
  1472. vc_assert(0);
  1473. return OMX_ErrorNone;
  1474. }
  1475. /***********************************************************
  1476. * Name: ilclient_fill_buffer_done
  1477. *
  1478. * Description: passed to core to use as component callback, puts
  1479. * buffer on list
  1480. *
  1481. * Returns:
  1482. ***********************************************************/
  1483. static OMX_ERRORTYPE ilclient_fill_buffer_done(OMX_OUT OMX_HANDLETYPE hComponent,
  1484. OMX_OUT OMX_PTR pAppData,
  1485. OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
  1486. {
  1487. COMPONENT_T *st = (COMPONENT_T *) pAppData;
  1488. OMX_BUFFERHEADERTYPE *list;
  1489. ilclient_debug_output("%s: fill buffer done %p", st->name, pBuffer);
  1490. vcos_semaphore_wait(&st->sema);
  1491. // insert at end of the list, so we process buffers in
  1492. // the correct order
  1493. list = st->out_list;
  1494. while(list && list->pAppPrivate)
  1495. list = list->pAppPrivate;
  1496. if(!list)
  1497. st->out_list = pBuffer;
  1498. else
  1499. list->pAppPrivate = pBuffer;
  1500. pBuffer->pAppPrivate = NULL;
  1501. vcos_semaphore_post(&st->sema);
  1502. vcos_event_flags_set(&st->event, ILCLIENT_FILL_BUFFER_DONE, VCOS_OR);
  1503. if (st->client->fill_buffer_done_callback)
  1504. st->client->fill_buffer_done_callback(st->client->fill_buffer_done_callback_data, st);
  1505. return OMX_ErrorNone;
  1506. }
  1507. /***********************************************************
  1508. * Name: ilclient_fill_buffer_done_error
  1509. *
  1510. * Description: passed to core to use as component callback, asserts
  1511. * on use as client not expecting component to use this callback.
  1512. *
  1513. * Returns:
  1514. ***********************************************************/
  1515. static OMX_ERRORTYPE ilclient_fill_buffer_done_error(OMX_OUT OMX_HANDLETYPE hComponent,
  1516. OMX_OUT OMX_PTR pAppData,
  1517. OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
  1518. {
  1519. vc_assert(0);
  1520. return OMX_ErrorNone;
  1521. }
  1522. OMX_HANDLETYPE ilclient_get_handle(COMPONENT_T *comp)
  1523. {
  1524. vcos_assert(comp);
  1525. return comp->comp;
  1526. }
  1527. static struct {
  1528. OMX_PORTDOMAINTYPE dom;
  1529. int param;
  1530. } port_types[] = {
  1531. { OMX_PortDomainVideo, OMX_IndexParamVideoInit },
  1532. { OMX_PortDomainAudio, OMX_IndexParamAudioInit },
  1533. { OMX_PortDomainImage, OMX_IndexParamImageInit },
  1534. { OMX_PortDomainOther, OMX_IndexParamOtherInit },
  1535. };
  1536. int ilclient_get_port_index(COMPONENT_T *comp, OMX_DIRTYPE dir, OMX_PORTDOMAINTYPE type, int index)
  1537. {
  1538. uint32_t i;
  1539. // for each possible port type...
  1540. for (i=0; i<sizeof(port_types)/sizeof(port_types[0]); i++)
  1541. {
  1542. if ((port_types[i].dom == type) || (type == (OMX_PORTDOMAINTYPE) -1))
  1543. {
  1544. OMX_PORT_PARAM_TYPE param;
  1545. OMX_ERRORTYPE error;
  1546. uint32_t j;
  1547. param.nSize = sizeof(param);
  1548. param.nVersion.nVersion = OMX_VERSION;
  1549. error = OMX_GetParameter(ILC_GET_HANDLE(comp), port_types[i].param, &param);
  1550. assert(error == OMX_ErrorNone);
  1551. // for each port of this type...
  1552. for (j=0; j<param.nPorts; j++)
  1553. {
  1554. int port = param.nStartPortNumber+j;
  1555. OMX_PARAM_PORTDEFINITIONTYPE portdef;
  1556. portdef.nSize = sizeof(portdef);
  1557. portdef.nVersion.nVersion = OMX_VERSION;
  1558. portdef.nPortIndex = port;
  1559. error = OMX_GetParameter(ILC_GET_HANDLE(comp), OMX_IndexParamPortDefinition, &portdef);
  1560. assert(error == OMX_ErrorNone);
  1561. if (portdef.eDir == dir)
  1562. {
  1563. if (index-- == 0)
  1564. return port;
  1565. }
  1566. }
  1567. }
  1568. }
  1569. return -1;
  1570. }
  1571. int ilclient_suggest_bufsize(COMPONENT_T *comp, OMX_U32 nBufSizeHint)
  1572. {
  1573. OMX_PARAM_BRCMOUTPUTBUFFERSIZETYPE param;
  1574. OMX_ERRORTYPE error;
  1575. param.nSize = sizeof(param);
  1576. param.nVersion.nVersion = OMX_VERSION;
  1577. param.nBufferSize = nBufSizeHint;
  1578. error = OMX_SetParameter(ILC_GET_HANDLE(comp), OMX_IndexParamBrcmOutputBufferSize,
  1579. &param);
  1580. assert(error == OMX_ErrorNone);
  1581. return (error == OMX_ErrorNone) ? 0 : -1;
  1582. }
  1583. unsigned int ilclient_stack_size(void)
  1584. {
  1585. return ILCLIENT_THREAD_DEFAULT_STACK_SIZE;
  1586. }