/omx/gstomx_util.c

https://github.com/niwamatsu/gst-openmax · C · 1136 lines · 842 code · 227 blank · 67 comment · 88 complexity · ee51d35b4225b46bd626c68b9f94122e MD5 · raw file

  1. /*
  2. * Copyright (C) 2006-2007 Texas Instruments, Incorporated
  3. * Copyright (C) 2007-2009 Nokia Corporation.
  4. *
  5. * Author: Felipe Contreras <felipe.contreras@nokia.com>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation
  10. * version 2.1 of the License.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #include "gstomx_util.h"
  23. #include <dlfcn.h>
  24. #include "gstomx.h"
  25. #include "OMXR_Extension.h"
  26. GST_DEBUG_CATEGORY (gstomx_util_debug);
  27. /*
  28. * Forward declarations
  29. */
  30. static inline void change_state (GOmxCore * core, OMX_STATETYPE state);
  31. static inline void wait_for_state (GOmxCore * core, OMX_STATETYPE state);
  32. static inline void
  33. in_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer);
  34. static inline void
  35. out_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer);
  36. static inline void
  37. got_buffer (GOmxCore * core,
  38. GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer);
  39. static OMX_ERRORTYPE
  40. EventHandler (OMX_HANDLETYPE omx_handle,
  41. OMX_PTR app_data,
  42. OMX_EVENTTYPE event, OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data);
  43. static OMX_ERRORTYPE
  44. EmptyBufferDone (OMX_HANDLETYPE omx_handle,
  45. OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer);
  46. static OMX_ERRORTYPE
  47. FillBufferDone (OMX_HANDLETYPE omx_handle,
  48. OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer);
  49. static inline const char *omx_state_to_str (OMX_STATETYPE omx_state);
  50. static inline const char *omx_error_to_str (OMX_ERRORTYPE omx_error);
  51. static inline GOmxPort *get_port (GOmxCore * core, guint index);
  52. static void core_deinit (GOmxCore * core);
  53. static inline void port_free_buffers (GOmxPort * port);
  54. static inline void port_allocate_buffers (GOmxPort * port);
  55. static inline void port_start_buffers (GOmxPort * port);
  56. static OMX_CALLBACKTYPE callbacks =
  57. { EventHandler, EmptyBufferDone, FillBufferDone };
  58. /* protect implementations hash_table */
  59. static GMutex imp_mutex;
  60. static GHashTable *implementations;
  61. static gboolean initialized;
  62. /*
  63. * Util
  64. */
  65. static void
  66. g_ptr_array_clear (GPtrArray * array)
  67. {
  68. guint index;
  69. for (index = 0; index < array->len; index++)
  70. array->pdata[index] = NULL;
  71. }
  72. static void
  73. g_ptr_array_insert (GPtrArray * array, guint index, gpointer data)
  74. {
  75. if (index + 1 > array->len) {
  76. g_ptr_array_set_size (array, index + 1);
  77. }
  78. array->pdata[index] = data;
  79. }
  80. typedef void (*GOmxPortFunc) (GOmxPort * port);
  81. static inline void
  82. core_for_each_port (GOmxCore * core, GOmxPortFunc func)
  83. {
  84. guint index;
  85. for (index = 0; index < core->ports->len; index++) {
  86. GOmxPort *port;
  87. port = get_port (core, index);
  88. if (port)
  89. func (port);
  90. }
  91. }
  92. /*
  93. * Main
  94. */
  95. static GOmxImp *imp_new (const gchar * name);
  96. static void imp_free (GOmxImp * imp);
  97. static GOmxImp *
  98. imp_new (const gchar * name)
  99. {
  100. GOmxImp *imp;
  101. imp = g_new0 (GOmxImp, 1);
  102. /* Load the OpenMAX IL symbols */
  103. {
  104. void *handle;
  105. GST_DEBUG ("loading: %s", name);
  106. imp->dl_handle = handle = dlopen (name, RTLD_LAZY);
  107. GST_DEBUG ("dlopen(%s) -> %p", name, handle);
  108. if (!handle) {
  109. g_warning ("%s\n", dlerror ());
  110. g_free (imp);
  111. return NULL;
  112. }
  113. g_mutex_init(&imp->mutex);
  114. imp->sym_table.init = dlsym (handle, "OMX_Init");
  115. imp->sym_table.deinit = dlsym (handle, "OMX_Deinit");
  116. imp->sym_table.get_handle = dlsym (handle, "OMX_GetHandle");
  117. imp->sym_table.free_handle = dlsym (handle, "OMX_FreeHandle");
  118. }
  119. return imp;
  120. }
  121. static void
  122. imp_free (GOmxImp * imp)
  123. {
  124. if (imp->dl_handle) {
  125. dlclose (imp->dl_handle);
  126. }
  127. g_mutex_clear(&imp->mutex);
  128. g_free (imp);
  129. }
  130. static inline GOmxImp *
  131. request_imp (const gchar * name, gboolean disable_postproc)
  132. {
  133. GOmxImp *imp = NULL;
  134. int retry = 1;
  135. g_mutex_lock (&imp_mutex);
  136. imp = g_hash_table_lookup (implementations, name);
  137. if (!imp) {
  138. imp = imp_new (name);
  139. if (imp)
  140. g_hash_table_insert (implementations, g_strdup (name), imp);
  141. }
  142. g_mutex_unlock (&imp_mutex);
  143. if (!imp)
  144. return NULL;
  145. g_mutex_lock (&imp->mutex);
  146. reinit:
  147. if (imp->client_count == 0) {
  148. OMX_ERRORTYPE (*r_config) (OMX_STRING path);
  149. OMX_ERRORTYPE omx_error;
  150. #define FILE_OMXR_CFG_NO_IPC "/usr/lib/omxr/omxr_av_codec_no_ipc.cfg"
  151. if (disable_postproc) {
  152. r_config = dlsym (imp->dl_handle, "OMXR_SetConfiguration");
  153. if (r_config)
  154. omx_error = r_config (FILE_OMXR_CFG_NO_IPC);
  155. if ((r_config == NULL) || (omx_error != OMX_ErrorNone)) {
  156. g_mutex_unlock (&imp->mutex);
  157. return NULL;
  158. }
  159. }
  160. omx_error = imp->sym_table.init ();
  161. if (omx_error) {
  162. if (retry-- > 0) {
  163. imp->sym_table.deinit ();
  164. goto reinit;
  165. }
  166. g_mutex_unlock (&imp->mutex);
  167. return NULL;
  168. }
  169. }
  170. imp->client_count++;
  171. g_mutex_unlock (&imp->mutex);
  172. return imp;
  173. }
  174. static inline void
  175. release_imp (GOmxImp * imp)
  176. {
  177. g_mutex_lock (&imp->mutex);
  178. imp->client_count--;
  179. if (imp->client_count == 0) {
  180. imp->sym_table.deinit ();
  181. }
  182. g_mutex_unlock (&imp->mutex);
  183. }
  184. void
  185. g_omx_init (void)
  186. {
  187. if (!initialized) {
  188. /* safe as plugin_init is safe */
  189. g_mutex_init(&imp_mutex);
  190. implementations = g_hash_table_new_full (g_str_hash,
  191. g_str_equal, g_free, (GDestroyNotify) imp_free);
  192. initialized = TRUE;
  193. }
  194. }
  195. void
  196. g_omx_deinit (void)
  197. {
  198. if (initialized) {
  199. g_hash_table_destroy (implementations);
  200. g_mutex_clear (&imp_mutex);
  201. initialized = FALSE;
  202. }
  203. }
  204. /*
  205. * Core
  206. */
  207. GOmxCore *
  208. g_omx_core_new (void *object)
  209. {
  210. GOmxCore *core;
  211. core = g_new0 (GOmxCore, 1);
  212. core->object = object;
  213. core->ports = g_ptr_array_new ();
  214. g_cond_init(&core->omx_state_condition);
  215. g_mutex_init(&core->omx_state_mutex);
  216. core->done_sem = g_sem_new ();
  217. core->flush_sem = g_sem_new ();
  218. core->port_sem = g_sem_new ();
  219. core->omx_state = OMX_StateInvalid;
  220. return core;
  221. }
  222. void
  223. g_omx_core_free (GOmxCore * core)
  224. {
  225. core_deinit (core);
  226. g_sem_free (core->port_sem);
  227. g_sem_free (core->flush_sem);
  228. g_sem_free (core->done_sem);
  229. g_mutex_clear (&core->omx_state_mutex);
  230. g_cond_clear (&core->omx_state_condition);
  231. g_ptr_array_free (core->ports, TRUE);
  232. g_free (core);
  233. }
  234. void
  235. g_omx_core_init (GOmxCore * core)
  236. {
  237. int retry = 1;
  238. GST_DEBUG_OBJECT (core->object, "loading: %s %s (%s)",
  239. core->component_name,
  240. core->component_role ? core->component_role : "", core->library_name);
  241. reinit:
  242. core->imp = request_imp (core->library_name, !core->postproc);
  243. if (!core->imp)
  244. return;
  245. core->omx_error = core->imp->sym_table.get_handle (&core->omx_handle,
  246. (char *) core->component_name, core, &callbacks);
  247. GST_DEBUG_OBJECT (core->object, "OMX_GetHandle(&%p) -> %d",
  248. core->omx_handle, core->omx_error);
  249. if (!core->omx_error) {
  250. core->omx_state = OMX_StateLoaded;
  251. if (core->component_role) {
  252. OMX_PARAM_COMPONENTROLETYPE param;
  253. GST_DEBUG_OBJECT (core->object, "setting component role: %s",
  254. core->component_role);
  255. G_OMX_INIT_PARAM (param);
  256. strncpy ((char *) param.cRole, core->component_role,
  257. OMX_MAX_STRINGNAME_SIZE);
  258. OMX_SetParameter (core->omx_handle, OMX_IndexParamStandardComponentRole,
  259. &param);
  260. }
  261. } else if (retry-- > 0) {
  262. release_imp (core->imp);
  263. GST_INFO_OBJECT (core->object, "reinitializing the OMXIL instance");
  264. goto reinit;
  265. }
  266. }
  267. static void
  268. core_deinit (GOmxCore * core)
  269. {
  270. if (!core->imp)
  271. return;
  272. if (core->omx_state == OMX_StateLoaded || core->omx_state == OMX_StateInvalid) {
  273. if (core->omx_handle) {
  274. core->omx_error = core->imp->sym_table.free_handle (core->omx_handle);
  275. GST_DEBUG_OBJECT (core->object, "OMX_FreeHandle(%p) -> %d",
  276. core->omx_handle, core->omx_error);
  277. }
  278. } else {
  279. GST_WARNING_OBJECT (core->object, "Incorrect state: %s",
  280. omx_state_to_str (core->omx_state));
  281. }
  282. g_free (core->library_name);
  283. g_free (core->component_name);
  284. g_free (core->component_role);
  285. release_imp (core->imp);
  286. core->imp = NULL;
  287. }
  288. void
  289. g_omx_core_prepare (GOmxCore * core)
  290. {
  291. change_state (core, OMX_StateIdle);
  292. /* Allocate buffers. */
  293. core_for_each_port (core, port_allocate_buffers);
  294. wait_for_state (core, OMX_StateIdle);
  295. }
  296. void
  297. g_omx_core_start (GOmxCore * core)
  298. {
  299. change_state (core, OMX_StateExecuting);
  300. wait_for_state (core, OMX_StateExecuting);
  301. if (core->omx_state == OMX_StateExecuting)
  302. core_for_each_port (core, port_start_buffers);
  303. }
  304. void
  305. g_omx_core_stop (GOmxCore * core)
  306. {
  307. if (core->omx_state == OMX_StateExecuting ||
  308. core->omx_state == OMX_StatePause) {
  309. change_state (core, OMX_StateIdle);
  310. wait_for_state (core, OMX_StateIdle);
  311. }
  312. }
  313. void
  314. g_omx_core_pause (GOmxCore * core)
  315. {
  316. change_state (core, OMX_StatePause);
  317. wait_for_state (core, OMX_StatePause);
  318. }
  319. void
  320. g_omx_core_unload (GOmxCore * core)
  321. {
  322. if (core->omx_state == OMX_StateIdle ||
  323. core->omx_state == OMX_StateWaitForResources ||
  324. core->omx_state == OMX_StateInvalid) {
  325. if (core->omx_state != OMX_StateInvalid)
  326. change_state (core, OMX_StateLoaded);
  327. core_for_each_port (core, port_free_buffers);
  328. if (core->omx_state != OMX_StateInvalid)
  329. wait_for_state (core, OMX_StateLoaded);
  330. }
  331. core_for_each_port (core, g_omx_port_free);
  332. g_ptr_array_clear (core->ports);
  333. }
  334. static inline GOmxPort *
  335. get_port (GOmxCore * core, guint index)
  336. {
  337. if (G_LIKELY (index < core->ports->len)) {
  338. return g_ptr_array_index (core->ports, index);
  339. }
  340. return NULL;
  341. }
  342. GOmxPort *
  343. g_omx_core_new_port (GOmxCore * core, guint index)
  344. {
  345. GOmxPort *port = get_port (core, index);
  346. if (port) {
  347. GST_WARNING_OBJECT (core->object, "port %d already exists", index);
  348. return port;
  349. }
  350. port = g_omx_port_new (core, index);
  351. g_ptr_array_insert (core->ports, index, port);
  352. return port;
  353. }
  354. void
  355. g_omx_core_set_done (GOmxCore * core)
  356. {
  357. g_sem_up (core->done_sem);
  358. }
  359. void
  360. g_omx_core_wait_for_done (GOmxCore * core)
  361. {
  362. g_sem_down (core->done_sem);
  363. }
  364. void
  365. g_omx_core_flush_start (GOmxCore * core)
  366. {
  367. core_for_each_port (core, g_omx_port_pause);
  368. }
  369. void
  370. g_omx_core_flush_stop (GOmxCore * core)
  371. {
  372. g_omx_core_pause (core);
  373. core_for_each_port (core, g_omx_port_flush);
  374. core_for_each_port (core, g_omx_port_resume);
  375. change_state (core, OMX_StateExecuting);
  376. wait_for_state (core, OMX_StateExecuting);
  377. }
  378. /*
  379. * Port
  380. */
  381. /**
  382. * note: this is not intended to be called directly by elements (which should
  383. * instead use g_omx_core_new_port())
  384. */
  385. GOmxPort *
  386. g_omx_port_new (GOmxCore * core, guint index)
  387. {
  388. GOmxPort *port;
  389. port = g_new0 (GOmxPort, 1);
  390. port->core = core;
  391. port->port_index = index;
  392. port->num_buffers = 0;
  393. port->buffer_size = 0;
  394. port->buffers = NULL;
  395. port->enabled = TRUE;
  396. port->queue = async_queue_new ();
  397. g_mutex_init (&port->mutex);
  398. return port;
  399. }
  400. void
  401. g_omx_port_free (GOmxPort * port)
  402. {
  403. g_mutex_clear (&port->mutex);
  404. async_queue_free (port->queue);
  405. g_free (port->buffers);
  406. g_free (port);
  407. }
  408. void
  409. g_omx_port_setup (GOmxPort * port)
  410. {
  411. GOmxPortType type = -1;
  412. OMX_PARAM_PORTDEFINITIONTYPE param;
  413. G_OMX_INIT_PARAM (param);
  414. param.nPortIndex = port->port_index;
  415. OMX_GetParameter (port->core->omx_handle, OMX_IndexParamPortDefinition,
  416. &param);
  417. switch (param.eDir) {
  418. case OMX_DirInput:
  419. type = GOMX_PORT_INPUT;
  420. break;
  421. case OMX_DirOutput:
  422. type = GOMX_PORT_OUTPUT;
  423. break;
  424. default:
  425. break;
  426. }
  427. port->type = type;
  428. /** @todo should it be nBufferCountMin? */
  429. port->num_buffers = param.nBufferCountActual;
  430. port->buffer_size = param.nBufferSize;
  431. GST_DEBUG_OBJECT (port->core->object,
  432. "type=%d, num_buffers=%d, buffer_size=%ld, port_index=%d",
  433. port->type, port->num_buffers, port->buffer_size, port->port_index);
  434. g_free (port->buffers);
  435. port->buffers = g_new0 (OMX_BUFFERHEADERTYPE *, port->num_buffers);
  436. }
  437. static void
  438. port_allocate_buffers (GOmxPort * port)
  439. {
  440. guint i;
  441. gsize size;
  442. size = port->buffer_size;
  443. for (i = 0; i < port->num_buffers; i++) {
  444. if (port->omx_allocate) {
  445. GST_DEBUG_OBJECT (port->core->object,
  446. "%d: OMX_AllocateBuffer(), size=%" G_GSIZE_FORMAT, i, size);
  447. OMX_AllocateBuffer (port->core->omx_handle, &port->buffers[i],
  448. port->port_index, NULL, size);
  449. } else {
  450. gpointer buffer_data;
  451. buffer_data = g_malloc (size);
  452. GST_DEBUG_OBJECT (port->core->object,
  453. "%d: OMX_UseBuffer(), size=%" G_GSIZE_FORMAT, i, size);
  454. OMX_UseBuffer (port->core->omx_handle, &port->buffers[i],
  455. port->port_index, NULL, size, buffer_data);
  456. }
  457. }
  458. }
  459. static void
  460. port_free_buffers (GOmxPort * port)
  461. {
  462. guint i;
  463. for (i = 0; i < port->num_buffers; i++) {
  464. OMX_BUFFERHEADERTYPE *omx_buffer;
  465. omx_buffer = port->buffers[i];
  466. if (omx_buffer) {
  467. #if 0
  468. /** @todo how shall we free that buffer? */
  469. if (!port->omx_allocate) {
  470. g_free (omx_buffer->pBuffer);
  471. omx_buffer->pBuffer = NULL;
  472. }
  473. #endif
  474. OMX_FreeBuffer (port->core->omx_handle, port->port_index, omx_buffer);
  475. port->buffers[i] = NULL;
  476. }
  477. }
  478. }
  479. static void
  480. port_start_buffers (GOmxPort * port)
  481. {
  482. guint i;
  483. for (i = 0; i < port->num_buffers; i++) {
  484. OMX_BUFFERHEADERTYPE *omx_buffer;
  485. omx_buffer = port->buffers[i];
  486. /* If it's an input port we will need to fill the buffer, so put it in
  487. * the queue, otherwise send to omx for processing (fill it up). */
  488. if (port->type == GOMX_PORT_INPUT)
  489. got_buffer (port->core, port, omx_buffer);
  490. else
  491. g_omx_port_release_buffer (port, omx_buffer);
  492. }
  493. }
  494. void
  495. g_omx_port_push_buffer (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
  496. {
  497. async_queue_push (port->queue, omx_buffer);
  498. }
  499. OMX_BUFFERHEADERTYPE *
  500. g_omx_port_request_buffer (GOmxPort * port)
  501. {
  502. return async_queue_pop (port->queue);
  503. }
  504. void
  505. g_omx_port_release_buffer (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
  506. {
  507. switch (port->type) {
  508. case GOMX_PORT_INPUT:
  509. OMX_EmptyThisBuffer (port->core->omx_handle, omx_buffer);
  510. break;
  511. case GOMX_PORT_OUTPUT:
  512. OMX_FillThisBuffer (port->core->omx_handle, omx_buffer);
  513. break;
  514. default:
  515. break;
  516. }
  517. }
  518. void
  519. g_omx_port_resume (GOmxPort * port)
  520. {
  521. async_queue_enable (port->queue);
  522. }
  523. void
  524. g_omx_port_pause (GOmxPort * port)
  525. {
  526. async_queue_disable (port->queue);
  527. }
  528. void
  529. g_omx_port_flush (GOmxPort * port)
  530. {
  531. if (port->type == GOMX_PORT_OUTPUT) {
  532. OMX_BUFFERHEADERTYPE *omx_buffer;
  533. while ((omx_buffer = async_queue_pop_forced (port->queue))) {
  534. omx_buffer->nFilledLen = 0;
  535. g_omx_port_release_buffer (port, omx_buffer);
  536. }
  537. OMX_SendCommand (port->core->omx_handle, OMX_CommandFlush, port->port_index,
  538. NULL);
  539. g_sem_down (port->core->flush_sem);
  540. } else {
  541. OMX_SendCommand (port->core->omx_handle, OMX_CommandFlush, port->port_index,
  542. NULL);
  543. g_sem_down (port->core->flush_sem);
  544. }
  545. }
  546. void
  547. g_omx_port_enable (GOmxPort * port)
  548. {
  549. GOmxCore *core;
  550. core = port->core;
  551. OMX_SendCommand (core->omx_handle, OMX_CommandPortEnable, port->port_index,
  552. NULL);
  553. port_allocate_buffers (port);
  554. if (core->omx_state != OMX_StateLoaded)
  555. port_start_buffers (port);
  556. g_omx_port_resume (port);
  557. g_sem_down (core->port_sem);
  558. }
  559. void
  560. g_omx_port_disable (GOmxPort * port)
  561. {
  562. GOmxCore *core;
  563. core = port->core;
  564. OMX_SendCommand (core->omx_handle, OMX_CommandPortDisable, port->port_index,
  565. NULL);
  566. g_omx_port_pause (port);
  567. g_omx_port_flush (port);
  568. port_free_buffers (port);
  569. g_sem_down (core->port_sem);
  570. }
  571. void
  572. g_omx_port_finish (GOmxPort * port)
  573. {
  574. port->enabled = FALSE;
  575. async_queue_disable (port->queue);
  576. }
  577. /*
  578. * Helper functions.
  579. */
  580. static inline void
  581. change_state (GOmxCore * core, OMX_STATETYPE state)
  582. {
  583. g_mutex_lock (&core->omx_state_mutex);
  584. GST_DEBUG_OBJECT (core->object, "state=%d", state);
  585. OMX_SendCommand (core->omx_handle, OMX_CommandStateSet, state, NULL);
  586. }
  587. static inline void
  588. complete_change_state (GOmxCore * core, OMX_STATETYPE state)
  589. {
  590. g_mutex_lock (&core->omx_state_mutex);
  591. core->omx_state = state;
  592. g_cond_signal (&core->omx_state_condition);
  593. GST_DEBUG_OBJECT (core->object, "state=%d", state);
  594. g_mutex_unlock (&core->omx_state_mutex);
  595. }
  596. static inline void
  597. wait_for_state (GOmxCore * core, OMX_STATETYPE state)
  598. {
  599. GTimeVal tv;
  600. gboolean signaled;
  601. g_get_current_time (&tv);
  602. g_time_val_add (&tv, 15 * G_USEC_PER_SEC);
  603. /* try once */
  604. if (core->omx_state != state) {
  605. gint64 t = g_get_monotonic_time () +
  606. ((gint64)tv.tv_sec * G_USEC_PER_SEC + tv.tv_usec -
  607. g_get_real_time ());
  608. signaled =
  609. g_cond_wait_until (&core->omx_state_condition, &core->omx_state_mutex,
  610. t);
  611. if (!signaled) {
  612. GST_ERROR_OBJECT (core->object, "timed out switching from '%s' to '%s'",
  613. omx_state_to_str (core->omx_state), omx_state_to_str (state));
  614. }
  615. }
  616. if (core->omx_error != OMX_ErrorNone)
  617. goto leave;
  618. if (core->omx_state != state) {
  619. GST_ERROR_OBJECT (core->object,
  620. "wrong state received: state=%d, expected=%d", core->omx_state, state);
  621. }
  622. leave:
  623. g_mutex_unlock (&core->omx_state_mutex);
  624. }
  625. /*
  626. * Callbacks
  627. */
  628. static inline void
  629. in_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
  630. {
  631. /** @todo remove this */
  632. if (!port->enabled)
  633. return;
  634. }
  635. static inline void
  636. out_port_cb (GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
  637. {
  638. /** @todo remove this */
  639. if (!port->enabled)
  640. return;
  641. #if 0
  642. if (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS) {
  643. g_omx_port_set_done (port);
  644. return;
  645. }
  646. #endif
  647. }
  648. static inline void
  649. got_buffer (GOmxCore * core, GOmxPort * port, OMX_BUFFERHEADERTYPE * omx_buffer)
  650. {
  651. if (G_UNLIKELY (!omx_buffer)) {
  652. return;
  653. }
  654. if (G_LIKELY (port)) {
  655. g_omx_port_push_buffer (port, omx_buffer);
  656. switch (port->type) {
  657. case GOMX_PORT_INPUT:
  658. in_port_cb (port, omx_buffer);
  659. break;
  660. case GOMX_PORT_OUTPUT:
  661. out_port_cb (port, omx_buffer);
  662. break;
  663. default:
  664. break;
  665. }
  666. }
  667. }
  668. static gboolean
  669. is_err_type_state_change (OMX_ERRORTYPE err)
  670. {
  671. gboolean ret;
  672. switch (err) {
  673. case OMX_ErrorInsufficientResources:
  674. case OMX_ErrorUndefined:
  675. case OMX_ErrorInvalidComponent:
  676. case OMX_ErrorBadParameter:
  677. case OMX_ErrorInvalidState:
  678. case OMX_ErrorVersionMismatch:
  679. case OMX_ErrorTimeout:
  680. case OMX_ErrorBadPortIndex:
  681. case OMX_ErrorIncorrectStateTransition:
  682. case OMX_ErrorSameState:
  683. case OMXR_MGR_ErrorInvalidHandle:
  684. case OMXR_MGR_ErrorNoSignal:
  685. case OMXR_MGR_ErrorOsWrapper:
  686. case OMXR_MGR_ErrorSectionNotFound:
  687. ret = TRUE;
  688. break;
  689. default:
  690. ret = FALSE;
  691. break;
  692. }
  693. return ret;
  694. }
  695. /*
  696. * OpenMAX IL callbacks.
  697. */
  698. static OMX_ERRORTYPE
  699. EventHandler (OMX_HANDLETYPE omx_handle,
  700. OMX_PTR app_data,
  701. OMX_EVENTTYPE event, OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
  702. {
  703. GOmxCore *core;
  704. core = (GOmxCore *) app_data;
  705. switch (event) {
  706. case OMX_EventCmdComplete:
  707. {
  708. OMX_COMMANDTYPE cmd;
  709. cmd = (OMX_COMMANDTYPE) data_1;
  710. GST_DEBUG_OBJECT (core->object, "OMX_EventCmdComplete: %d", cmd);
  711. switch (cmd) {
  712. case OMX_CommandStateSet:
  713. complete_change_state (core, data_2);
  714. break;
  715. case OMX_CommandFlush:
  716. g_sem_up (core->flush_sem);
  717. break;
  718. case OMX_CommandPortDisable:
  719. case OMX_CommandPortEnable:
  720. g_sem_up (core->port_sem);
  721. default:
  722. break;
  723. }
  724. break;
  725. }
  726. case OMX_EventBufferFlag:
  727. {
  728. GST_DEBUG_OBJECT (core->object, "OMX_EventBufferFlag");
  729. if (data_2 & OMX_BUFFERFLAG_EOS) {
  730. g_omx_core_set_done (core);
  731. }
  732. break;
  733. }
  734. case OMX_EventPortSettingsChanged:
  735. {
  736. GST_DEBUG_OBJECT (core->object, "OMX_EventPortSettingsChanged");
  737. /** @todo only on the relevant port. */
  738. if (core->settings_changed_cb) {
  739. core->settings_changed_cb (core);
  740. }
  741. break;
  742. }
  743. case OMX_EventError:
  744. {
  745. core->omx_error = data_1;
  746. GST_ERROR_OBJECT (core->object, "unrecoverable error: %s (0x%lx)",
  747. omx_error_to_str (data_1), data_1);
  748. /* component might leave us waiting for buffers, unblock */
  749. g_omx_core_flush_start (core);
  750. /*
  751. * This signal should be sent when an error is related to changing state
  752. * by calling OMX_SendCommand().
  753. */
  754. if (is_err_type_state_change (core->omx_error)) {
  755. /* unlock wait_for_state */
  756. g_mutex_lock (&core->omx_state_mutex);
  757. g_cond_signal (&core->omx_state_condition);
  758. g_mutex_unlock (&core->omx_state_mutex);
  759. }
  760. GST_ELEMENT_ERROR (core->object, STREAM, FAILED, (NULL),
  761. ("Error from OpenMAX component"));
  762. break;
  763. }
  764. default:
  765. break;
  766. }
  767. return OMX_ErrorNone;
  768. }
  769. static OMX_ERRORTYPE
  770. EmptyBufferDone (OMX_HANDLETYPE omx_handle,
  771. OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer)
  772. {
  773. GOmxCore *core;
  774. GOmxPort *port;
  775. core = (GOmxCore *) app_data;
  776. port = get_port (core, omx_buffer->nInputPortIndex);
  777. GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer=%p",
  778. omx_buffer);
  779. got_buffer (core, port, omx_buffer);
  780. return OMX_ErrorNone;
  781. }
  782. static OMX_ERRORTYPE
  783. FillBufferDone (OMX_HANDLETYPE omx_handle,
  784. OMX_PTR app_data, OMX_BUFFERHEADERTYPE * omx_buffer)
  785. {
  786. GOmxCore *core;
  787. GOmxPort *port;
  788. core = (GOmxCore *) app_data;
  789. port = get_port (core, omx_buffer->nOutputPortIndex);
  790. GST_CAT_LOG_OBJECT (gstomx_util_debug, core->object, "omx_buffer=%p",
  791. omx_buffer);
  792. got_buffer (core, port, omx_buffer);
  793. return OMX_ErrorNone;
  794. }
  795. static inline const char *
  796. omx_state_to_str (OMX_STATETYPE omx_state)
  797. {
  798. switch (omx_state) {
  799. case OMX_StateInvalid:
  800. return "invalid";
  801. case OMX_StateLoaded:
  802. return "loaded";
  803. case OMX_StateIdle:
  804. return "idle";
  805. case OMX_StateExecuting:
  806. return "executing";
  807. case OMX_StatePause:
  808. return "pause";
  809. case OMX_StateWaitForResources:
  810. return "wait for resources";
  811. default:
  812. return "unknown";
  813. }
  814. }
  815. static inline const char *
  816. omx_error_to_str (OMX_ERRORTYPE omx_error)
  817. {
  818. switch (omx_error) {
  819. case OMX_ErrorNone:
  820. return "None";
  821. case OMX_ErrorInsufficientResources:
  822. return
  823. "There were insufficient resources to perform the requested operation";
  824. case OMX_ErrorUndefined:
  825. return "The cause of the error could not be determined";
  826. case OMX_ErrorInvalidComponentName:
  827. return "The component name string was not valid";
  828. case OMX_ErrorComponentNotFound:
  829. return "No component with the specified name string was found";
  830. case OMX_ErrorInvalidComponent:
  831. return "The component specified did not have an entry point";
  832. case OMX_ErrorBadParameter:
  833. return "One or more parameters were not valid";
  834. case OMX_ErrorNotImplemented:
  835. return "The requested function is not implemented";
  836. case OMX_ErrorUnderflow:
  837. return "The buffer was emptied before the next buffer was ready";
  838. case OMX_ErrorOverflow:
  839. return "The buffer was not available when it was needed";
  840. case OMX_ErrorHardware:
  841. return "The hardware failed to respond as expected";
  842. case OMX_ErrorInvalidState:
  843. return "The component is in invalid state";
  844. case OMX_ErrorStreamCorrupt:
  845. return "Stream is found to be corrupt";
  846. case OMX_ErrorPortsNotCompatible:
  847. return "Ports being connected are not compatible";
  848. case OMX_ErrorResourcesLost:
  849. return "Resources allocated to an idle component have been lost";
  850. case OMX_ErrorNoMore:
  851. return "No more indices can be enumerated";
  852. case OMX_ErrorVersionMismatch:
  853. return "The component detected a version mismatch";
  854. case OMX_ErrorNotReady:
  855. return "The component is not ready to return data at this time";
  856. case OMX_ErrorTimeout:
  857. return "There was a timeout that occurred";
  858. case OMX_ErrorSameState:
  859. return
  860. "This error occurs when trying to transition into the state you are already in";
  861. case OMX_ErrorResourcesPreempted:
  862. return
  863. "Resources allocated to an executing or paused component have been preempted";
  864. case OMX_ErrorPortUnresponsiveDuringAllocation:
  865. return
  866. "Waited an unusually long time for the supplier to allocate buffers";
  867. case OMX_ErrorPortUnresponsiveDuringDeallocation:
  868. return
  869. "Waited an unusually long time for the supplier to de-allocate buffers";
  870. case OMX_ErrorPortUnresponsiveDuringStop:
  871. return
  872. "Waited an unusually long time for the non-supplier to return a buffer during stop";
  873. case OMX_ErrorIncorrectStateTransition:
  874. return "Attempting a state transition that is not allowed";
  875. case OMX_ErrorIncorrectStateOperation:
  876. return
  877. "Attempting a command that is not allowed during the present state";
  878. case OMX_ErrorUnsupportedSetting:
  879. return
  880. "The values encapsulated in the parameter or config structure are not supported";
  881. case OMX_ErrorUnsupportedIndex:
  882. return
  883. "The parameter or config indicated by the given index is not supported";
  884. case OMX_ErrorBadPortIndex:
  885. return "The port index supplied is incorrect";
  886. case OMX_ErrorPortUnpopulated:
  887. return
  888. "The port has lost one or more of its buffers and it thus unpopulated";
  889. case OMX_ErrorComponentSuspended:
  890. return "Component suspended due to temporary loss of resources";
  891. case OMX_ErrorDynamicResourcesUnavailable:
  892. return
  893. "Component suspended due to an inability to acquire dynamic resources";
  894. case OMX_ErrorMbErrorsInFrame:
  895. return "Frame generated macroblock error";
  896. case OMX_ErrorFormatNotDetected:
  897. return "Cannot parse or determine the format of an input stream";
  898. case OMX_ErrorContentPipeOpenFailed:
  899. return "The content open operation failed";
  900. case OMX_ErrorContentPipeCreationFailed:
  901. return "The content creation operation failed";
  902. case OMX_ErrorSeperateTablesUsed:
  903. return "Separate table information is being used";
  904. case OMX_ErrorTunnelingUnsupported:
  905. return "Tunneling is unsupported by the component";
  906. default:
  907. return "Unknown error";
  908. }
  909. }