aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBuddy Liong2015-11-24 16:32:11 -0600
committerBuddy Liong2016-03-01 17:11:16 -0600
commit4cde6d994029b7a442bc2e32f161ca3aa284f6fa (patch)
treefa0c79a6f6fea7f64dcb512f11395a83eabe94a9 /libdce.c
parente05d0b506a8f5e9218449d3952ee6c1d327fddb5 (diff)
downloadrepo-libdce-4cde6d994029b7a442bc2e32f161ca3aa284f6fa.tar.gz
repo-libdce-4cde6d994029b7a442bc2e32f161ca3aa284f6fa.tar.xz
repo-libdce-4cde6d994029b7a442bc2e32f161ca3aa284f6fa.zip
H.264 low latency with IVIDEO_NUMROWS
H.264 codec user guide describes the functionality of low latency. This functionality allows user to encode/decode a sub-frame level data communications. Without low latency, user can only encode/decode a complete/full frame only. More information about H264 low latency can be found in codec release package: * H.264 Encoder 2.0 on HDVICP2 and Media Controller Based Platform User's Guide (SPRUHG3), Appendix G - Low Latency / Sub Frame Level Synchronization * H.264 Decoder 2.0 on HDVICP2 and Media Controller Based Platform User's Guide (SPRUHF9), Appendix I - Low Latency / Sub Frame Level Synchronization This commit is only implemented low latency with IVIDEO_NUMROWS. H.264 encoder handles inputDataMode = IVIDEO_NUMROWS with getDataFxn as callback to get the numRows being filled into the inputBuffer pointer passed at process call. From H.264 encoder user guide Appendix G, more details can be found in sec. G2 H.264 Encoder Input with sub frame level synchronization H.264 decoder handles outputDataMode = IVIDEO_NUMROWS with putDataFxn as callback to notify client on the numRows/numBlocks being filled by codec into the outputBuffer pointer passed at process call. From H.264 decoder user guide Appendix I, more details can be found in sec. I.2 Details of using Sub Frame Level data sync at output side. The update is only valid on video codec on IVA-HD. This changes depend on the changes done on IPUMM DCE server. No low latency update is performed on video codec on DSP. This commit has dependencies on: IPC 3.42.00.02 or latest IPUMM commit ids: commit e37750cc921a9442c48e7212824b28850ac3aaa7 - H.264 low latency - IVIDEO_NUMROWS commit 266749c0b6a2584d563625f881f998c3d78ca873 - Handling when MPU crashes, eg. CTRL-C on MPU side. commit 030572aaa1964bb50a903852fab0ecc0149b6b7e - H.264 Low Latency - sync put_DataFxn to MPU side Change-Id: I308bc74a879099f38705df6e6dda4a86b6645986 Signed-off-by: Buddy Liong <buddy.liong@ti.com>
Diffstat (limited to 'libdce.c')
-rw-r--r--libdce.c672
1 files changed, 587 insertions, 85 deletions
diff --git a/libdce.c b/libdce.c
index 108d8f3..82eaf46 100644
--- a/libdce.c
+++ b/libdce.c
@@ -35,6 +35,7 @@
35#include <stdio.h> 35#include <stdio.h>
36#include <pthread.h> 36#include <pthread.h>
37#include <errno.h> 37#include <errno.h>
38#include <semaphore.h>
38 39
39/* IPC Headers */ 40/* IPC Headers */
40#include <ti/ipc/mm/MmRpc.h> 41#include <ti/ipc/mm/MmRpc.h>
@@ -45,23 +46,72 @@
45#include "dce_priv.h" 46#include "dce_priv.h"
46#include "memplugin.h" 47#include "memplugin.h"
47 48
48
49/***************** GLOBALS ***************************/ 49/***************** GLOBALS ***************************/
50/* Handle used for Remote Communication */ 50/* Handle used for Remote Communication */
51MmRpc_Handle MmRpcHandle[MAX_REMOTEDEVICES] = { NULL}; 51MmRpc_Handle MmRpcHandle[MAX_REMOTEDEVICES] = { NULL};
52Engine_Handle gEngineHandle[MAX_INSTANCES][MAX_REMOTEDEVICES] = { {NULL, NULL}}; 52Engine_Handle gEngineHandle[MAX_INSTANCES][MAX_REMOTEDEVICES] = { {NULL, NULL}};
53MmRpc_Handle MmRpcCallbackHandle = NULL;
54static int MmRpcCallback_count = 0;
53 55
54#ifdef BUILDOS_LINUX 56#ifdef BUILDOS_LINUX
55pthread_mutex_t ipc_mutex; 57pthread_mutex_t ipc_mutex;
58pthread_mutex_t dce_callback_mutex;
56#else 59#else
57pthread_mutex_t ipc_mutex = PTHREAD_MUTEX_INITIALIZER; 60pthread_mutex_t ipc_mutex = PTHREAD_MUTEX_INITIALIZER;
61static pthread_mutex_t dce_callback_mutex = PTHREAD_MUTEX_INITIALIZER;
58#endif 62#endif
59 63
60static int __ClientCount[MAX_REMOTEDEVICES] = {0}; 64static int __ClientCount[MAX_REMOTEDEVICES] = {0};
61int dce_debug = DCE_DEBUG_LEVEL; 65int dce_debug = DCE_DEBUG_LEVEL;
62const String DCE_DEVICE_NAME[MAX_REMOTEDEVICES]= {"rpmsg-dce","rpmsg-dce-dsp"}; 66const String DCE_DEVICE_NAME[MAX_REMOTEDEVICES]= {"rpmsg-dce","rpmsg-dce-dsp"};
67const String DCE_CALLBACK_NAME = "dce-callback";
68
69typedef struct {
70 XDAS_UInt32 codec_handle;
71 XDM_DataSyncHandle local_dataSyncHandle;
72 XDM_DataSyncDesc *local_dataSyncDesc;
73 XDAS_Int32 getDataFlag;
74 XDM_DataSyncGetFxn (*local_get_DataFxn) (XDM_DataSyncHandle, XDM_DataSyncDesc*);
75 XDAS_Int32 putDataFlag;
76 XDM_DataSyncGetFxn (*local_put_DataFxn) (XDM_DataSyncHandle, XDM_DataSyncDesc*);
77 XDAS_Int32 getBufferFlag;
78 pthread_t getDataFxn_thread;
79 pthread_t putDataFxn_thread;
80 sem_t sem_dec_row_mode;
81 sem_t sem_enc_row_mode;
82 int row_mode;
83 int first_control;
84 int receive_numBlocks;
85 int total_numBlocks;
86} CallbackFlag;
87
88static CallbackFlag callbackmsg[MAX_INSTANCES];
63 89
64/***************** INLINE FUNCTIONS ******************/ 90/***************** INLINE FUNCTIONS ******************/
91static inline int get_callback(Uint32 codec)
92{
93 int i;
94 for (i = 0; i < MAX_INSTANCES; i++) {
95 if( callbackmsg[i].codec_handle == codec ) {
96 return i;
97 }
98 }
99 return -1;
100}
101
102static inline int update_clients_table(Engine_Handle engine, int core)
103{
104 int i;
105 for(i = 0; i < MAX_INSTANCES; i++)
106 {
107 if( gEngineHandle[i][core] == 0 ) {
108 gEngineHandle[i][core] = engine;
109 return i;
110 }
111 }
112 return -1;
113}
114
65static inline void Fill_MmRpc_fxnCtx(MmRpc_FxnCtx *fxnCtx, int fxn_id, int num_params, int num_xlts, MmRpc_Xlt *xltAry) 115static inline void Fill_MmRpc_fxnCtx(MmRpc_FxnCtx *fxnCtx, int fxn_id, int num_params, int num_xlts, MmRpc_Xlt *xltAry)
66{ 116{
67 fxnCtx->fxn_id = fxn_id; 117 fxnCtx->fxn_id = fxn_id;
@@ -106,12 +156,12 @@ static inline void Fill_MmRpc_fxnCtx_Xlt_Array(MmRpc_Xlt *mmrpc_xlt, int index,
106 156
107static int __inline getCoreIndexFromName(String name) 157static int __inline getCoreIndexFromName(String name)
108{ 158{
109 if(name == NULL) 159 if( name == NULL )
110 return INVALID_CORE; 160 return INVALID_CORE;
111 161
112 if(!strcmp(name,"ivahd_vidsvr")) 162 if( !strcmp(name,"ivahd_vidsvr") )
113 return IPU; 163 return IPU;
114 else if(!strcmp(name, "dsp_vidsvr")) 164 else if( !strcmp(name, "dsp_vidsvr") )
115 return DSP; 165 return DSP;
116 else 166 else
117 return INVALID_CORE; 167 return INVALID_CORE;
@@ -119,9 +169,9 @@ static int __inline getCoreIndexFromName(String name)
119 169
120static int __inline getCoreIndexFromCodec(int codec_id) 170static int __inline getCoreIndexFromCodec(int codec_id)
121{ 171{
122 if(codec_id == OMAP_DCE_VIDENC2 || codec_id == OMAP_DCE_VIDDEC3) 172 if( codec_id == OMAP_DCE_VIDENC2 || codec_id == OMAP_DCE_VIDDEC3 )
123 return IPU; 173 return IPU;
124 else if(codec_id == OMAP_DCE_VIDDEC2) 174 else if( codec_id == OMAP_DCE_VIDDEC2 )
125 return DSP; 175 return DSP;
126 else 176 else
127 return INVALID_CORE; 177 return INVALID_CORE;
@@ -132,16 +182,15 @@ static int __inline getCoreIndexFromEngine(Engine_Handle engine, int *tabIdx)
132 int i; 182 int i;
133 int core = INVALID_CORE; 183 int core = INVALID_CORE;
134 184
135
136 *tabIdx = -1; 185 *tabIdx = -1;
137 186
138 for(i = 0; i < MAX_INSTANCES ; i++) { 187 for(i = 0; i < MAX_INSTANCES ; i++) {
139 if(engine == gEngineHandle[i][IPU]) { 188 if( engine == gEngineHandle[i][IPU] ) {
140 core = IPU; 189 core = IPU;
141 *tabIdx = i; 190 *tabIdx = i;
142 break; 191 break;
143 } 192 }
144 else if(engine == gEngineHandle[i][DSP]) { 193 else if( engine == gEngineHandle[i][DSP] ) {
145 *tabIdx = i; 194 *tabIdx = i;
146 core = DSP; 195 core = DSP;
147 break; 196 break;
@@ -167,6 +216,175 @@ void dce_free(void *ptr)
167 memplugin_free(ptr); 216 memplugin_free(ptr);
168} 217}
169 218
219/* dce_callback_putDataFxn is a callback function that runs on different Thread id. */
220/* It is an infinite loop notifying client when partial output data is available when outputDataMode = IVIDEO_ROWMODE. */
221int dce_callback_putDataFxn(void *codec)
222{
223 MmRpc_FxnCtx fxnCtx;
224 int32_t fxnRet;
225 int32_t return_callback;
226 dce_error_status eError = DCE_EOK;
227 XDM_DataSyncHandle *codec_handle = (XDM_DataSyncHandle *) codec;
228 int id;
229
230 DEBUG("======================START======================== codec_handle 0x%x", (unsigned int) *codec_handle);
231
232 id = get_callback((Uint32) *codec_handle);
233 if( id < 0 ) {
234 ERROR("Cannot find the entry in callbackmsg");
235 } else {
236 (callbackmsg[id]).local_dataSyncHandle = *codec_handle;
237 /* This is called from VIDDEC3_process, so we can start telling client to get the output data and provide the numBlocks info. */
238 /* Call the callback function specified in the dynParams->putDataFxn */
239 while (1) {
240 if( (callbackmsg[id]).putDataFlag == 1 ) {
241 DEBUG("lock (callbackmsg[%d]).putDataFxn_thread 0x%x (callbackmsg[%d]).local_dataSyncHandle 0x%x",
242 id, (callbackmsg[id]).putDataFxn_thread, id, (unsigned int) (callbackmsg[id]).local_dataSyncHandle);
243 pthread_mutex_lock(&dce_callback_mutex);
244 if( (callbackmsg[id]).row_mode ) {
245 /* Marshall function arguments into the send callback information to codec for put_DataFxn */
246 Fill_MmRpc_fxnCtx(&fxnCtx, DCE_CALLBACK_RPC_PUT_DATAFXN, 2, 0, NULL);
247 Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[0]), sizeof(int32_t), (int32_t) (callbackmsg[id]).local_dataSyncHandle);
248 Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[1]), GetSz((callbackmsg[id]).local_dataSyncDesc), (void *) P2H((callbackmsg[id]).local_dataSyncDesc),
249 sizeof(MemHeader), memplugin_share((callbackmsg[id]).local_dataSyncDesc));
250
251 DEBUG("Calling MmRpc_call on MmRpcCallbackHandle %p", MmRpcCallbackHandle);
252 eError = MmRpc_call(MmRpcCallbackHandle, &fxnCtx, &fxnRet);
253 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);
254
255 /* When this return it means that Codec has called DCE Server with putDataFxn callback that has the numBlock information. */
256 /* At this point, codec should have filled the outputBuffer pointer that is passed in VIDDEC3_process. */
257 DEBUG("From codec (callbackmsg[%d]).local_dataSyncHandle %p (callbackmsg[%d]).local_dataSyncDesc->numBlocks %d ",
258 id, (callbackmsg[id]).local_dataSyncHandle, id, (int32_t) (callbackmsg[id]).local_dataSyncDesc->numBlocks);
259
260 if( (callbackmsg[id]).local_dataSyncDesc->numBlocks ) {
261 (callbackmsg[id]).receive_numBlocks += (callbackmsg[id]).local_dataSyncDesc->numBlocks;
262 return_callback = (int32_t) ((callbackmsg[id]).local_put_DataFxn)((callbackmsg[id]).local_dataSyncHandle, (callbackmsg[id]).local_dataSyncDesc);
263 if( return_callback < 0 ) {
264 /* dce_callback_putDataFxn getting no output data saved when calling the callback. Ignore and continue. */
265 ERROR("Received return_callback %d when asking client to save the output Data of (callbackmsg[%d]).numBlock %d",
266 return_callback, id, (callbackmsg[id]).local_dataSyncDesc->numBlocks);
267 }
268
269 DEBUG("(callbackmsg[%d]).local_dataSyncHandle %p (callbackmsg[%d]).receive_numBlocks %d >= (callbackmsg[%d]).total_numBlocks %d (callbackmsg[%d]).putDataFlag %d",
270 id, (callbackmsg[id]).local_dataSyncHandle, id, (callbackmsg[id]).receive_numBlocks, id, (callbackmsg[id]).total_numBlocks, id, (callbackmsg[id]).putDataFlag);
271 } else {
272 /* dce_callback_putDataFxn getting 0 numBlocks from DCE server. Need to stop the loop as it indicates VIDDEC3_process will be returned*/
273 DEBUG("dce_callback_putDataFxn is getting (callbackmsg[%d]).numBlock %d when calling putDataFxn callback",
274 id, (callbackmsg[id]).local_dataSyncDesc->numBlocks);
275 (callbackmsg[id]).putDataFlag = 0;
276 }
277
278 DEBUG("unlock (callbackmsg[%d]).putDataFxn_thread 0x%x (callbackmsg[%d]).local_dataSyncHandle %p",
279 id, (callbackmsg[id]).putDataFxn_thread, id, (callbackmsg[id]).local_dataSyncHandle);
280 pthread_mutex_unlock(&dce_callback_mutex);
281 }
282 } else if( (callbackmsg[id]).putDataFlag == 2 ) {
283 /* Receive an indication to clean up and exit the thread. */
284 DEBUG("CLEAN UP indication due to (callbackmsg[%d]).putDataFlag %d is set.", id, (callbackmsg[id]).putDataFlag);
285 pthread_exit(0);
286 } else {
287 DEBUG("Do nothing (callbackmsg[%d]).local_dataSyncHandle 0x%x because (callbackmsg[%d]).putDataFlag %d is not 1.",
288 id, (unsigned int)(callbackmsg[id]).local_dataSyncHandle, id, (callbackmsg[id]).putDataFlag);
289 if ((callbackmsg[id]).receive_numBlocks) {
290 (callbackmsg[id]).receive_numBlocks = 0;
291 DEBUG("Signal sem_dec_row_mode as VIDDEC3_process might wait before returning to client.");
292 sem_post(&((callbackmsg[id]).sem_dec_row_mode));
293 }
294 sem_wait(&((callbackmsg[id]).sem_dec_row_mode));
295 }
296 }
297 }
298
299EXIT:
300
301 DEBUG("======================END======================== codec_handle 0x%x", (unsigned int) *codec_handle);
302 return (0);
303}
304
305
306/* dce_callback_getDataFxn is running on different Thread id. */
307/* It is an infinite loop request to client for more input data when inputDataMode = IVIDEO_ROWMODE. */
308int dce_callback_getDataFxn(void *codec)
309{
310 MmRpc_FxnCtx fxnCtx;
311 int32_t fxnRet;
312 int32_t return_callback;
313 dce_error_status eError = DCE_EOK;
314 XDM_DataSyncHandle *codec_handle = (XDM_DataSyncHandle *) codec;
315 int id;
316
317 DEBUG("======================START========================");
318 DEBUG(" >> dce_callback_getDataFxn codec_handle 0x%x", (unsigned int) *codec_handle);
319
320 id = get_callback((Uint32) *codec_handle);
321 if( id < 0 ) {
322 ERROR("Cannot find the entry in callbackmsg");
323 } else {
324 (callbackmsg[id]).local_dataSyncHandle = *codec_handle;
325 /* This is called from VIDENC2_process, so we can start request client to fill in input and provide the row information written. */
326 /* Call the callback function specified in the dynParams->getDataFxn */
327 while( 1 ) {
328 if( (callbackmsg[id]).getDataFlag == 1 ) {
329 DEBUG("lock (callbackmsg[%d]).getDataFxn_thread 0x%x (callbackmsg[%d]).local_dataSyncHandle %p",
330 id, (callbackmsg[id]).getDataFxn_thread, id, (callbackmsg[id]).local_dataSyncHandle);
331 pthread_mutex_lock(&dce_callback_mutex);
332 if( (callbackmsg[id]).row_mode ) {
333 /* Calling client callback function to pass data received from IVA-HD codec */
334 return_callback = (int32_t) ((callbackmsg[id]).local_get_DataFxn)((callbackmsg[id]).local_dataSyncHandle, (callbackmsg[id]).local_dataSyncDesc);
335 if( return_callback < 0 ) {
336 /* dce_callback_getDataFxn getting error when calling the callback. Ignore and re-try. */
337 ERROR("dce_callback_getDataFxn is getting return_callback %d when calling getDataFxn callback. Retry callback for more data.", return_callback);
338 } else {
339 (callbackmsg[id]).receive_numBlocks += (callbackmsg[id]).local_dataSyncDesc->numBlocks;
340
341 if( (callbackmsg[id]).local_dataSyncDesc->numBlocks ) {
342 /* Marshall function arguments into the send callback information to codec for get_dataFxn */
343 Fill_MmRpc_fxnCtx(&fxnCtx, DCE_CALLBACK_RPC_GET_DATAFXN, 2, 0, NULL);
344 Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[0]), sizeof(int32_t), (int32_t) (callbackmsg[id]).local_dataSyncHandle);
345 Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[1]), GetSz((callbackmsg[id]).local_dataSyncDesc), (void *) P2H((callbackmsg[id]).local_dataSyncDesc),
346 sizeof(MemHeader), memplugin_share((callbackmsg[id]).local_dataSyncDesc));
347
348 eError = MmRpc_call(MmRpcCallbackHandle, &fxnCtx, &fxnRet);
349 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);
350
351 DEBUG("(callbackmsg[%d]).local_dataSyncHandle %p (callbackmsg[%d]).receive_numBlocks %d >= (callbackmsg[%d]).total_numBlocks %d",
352 id, (callbackmsg[id]).local_dataSyncHandle, id, (callbackmsg[id]).receive_numBlocks, id, (callbackmsg[id]).total_numBlocks);
353
354 if( (callbackmsg[id]).receive_numBlocks >= (callbackmsg[id]).total_numBlocks ) {
355 /* one full frame has been sent to codec. Need to stop the callback call to client. */
356 /* it will be resumed once VIDENC2_process for the next one. */
357 (callbackmsg[id]).receive_numBlocks = 0;
358 (callbackmsg[id]).getDataFlag = 0;
359 DEBUG("Setting the (callbackmsg[%d]).getDataFlag to 0 to stop calling client to fill", id);
360 }
361 } else {
362 /* dce_callback_getDataFxn getting 0 numBlocks when calling the callback. Ignore and re-try. */
363 DEBUG("Received dataSyncDesc->numBlocks == 0 meaning the callback thread has no data -ignore.");
364 }
365 }
366 DEBUG("unlock (callbackmsg[%d]).getDataFxn_thread 0x%x (callbackmsg[%d]).local_dataSyncHandle %p",
367 id, (callbackmsg[id]).getDataFxn_thread, id, (callbackmsg[id]).local_dataSyncHandle);
368 pthread_mutex_unlock(&dce_callback_mutex);
369 }
370 } else if( (callbackmsg[id]).getDataFlag == 2 ) {
371 /* Receive an indication to clean up and exit the thread. */
372 DEBUG("CLEAN UP indication due to (callbackmsg[%d]).getDataFlag %d is set.", id, (callbackmsg[id]).getDataFlag);
373 pthread_exit(0);
374 } else {
375 DEBUG("Do nothing (callbackmsg[%d]).local_dataSyncHandle 0x%x because msg-getDataFlag %d is not 1.",
376 id, (unsigned int)(callbackmsg[id]).local_dataSyncHandle, (callbackmsg[id]).getDataFlag);
377 sem_wait(&((callbackmsg[id]).sem_enc_row_mode));
378 }
379 }
380 }
381
382EXIT:
383 DEBUG(" << dce_callback_getDataFxn COMPLETE");
384 DEBUG("======================END========================");
385 return (0);
386}
387
170/*=====================================================================================*/ 388/*=====================================================================================*/
171/** dce_ipc_init : Initialize MmRpc. This function is called within Engine_open(). 389/** dce_ipc_init : Initialize MmRpc. This function is called within Engine_open().
172 * 390 *
@@ -180,7 +398,7 @@ int dce_ipc_init(int core)
180 DEBUG(" >> dce_ipc_init\n"); 398 DEBUG(" >> dce_ipc_init\n");
181 399
182 /*First check if maximum clients are already using ipc*/ 400 /*First check if maximum clients are already using ipc*/
183 if(__ClientCount[core] >= MAX_INSTANCES) { 401 if( __ClientCount[core] >= MAX_INSTANCES ) {
184 eError = DCE_EXDM_UNSUPPORTED; 402 eError = DCE_EXDM_UNSUPPORTED;
185 return (eError); 403 return (eError);
186 } 404 }
@@ -188,7 +406,7 @@ int dce_ipc_init(int core)
188 /* Create remote server insance */ 406 /* Create remote server insance */
189 __ClientCount[core]++; 407 __ClientCount[core]++;
190 408
191 if(__ClientCount[core] > 1) { 409 if( __ClientCount[core] > 1 ) {
192 goto EXIT; 410 goto EXIT;
193 } 411 }
194 412
@@ -208,13 +426,13 @@ EXIT:
208 */ 426 */
209void dce_ipc_deinit(int core, int tableIdx) 427void dce_ipc_deinit(int core, int tableIdx)
210{ 428{
211 if(__ClientCount[core] == 0) { 429 if( __ClientCount[core] == 0 ) {
212 DEBUG("Nothing to be done: a spurious call\n"); 430 DEBUG("Nothing to be done: a spurious call\n");
213 return; 431 return;
214 } 432 }
215 __ClientCount[core]--; 433 __ClientCount[core]--;
216 434
217 if (tableIdx >= 0) 435 if ( tableIdx >= 0 )
218 gEngineHandle[tableIdx][core] = 0; 436 gEngineHandle[tableIdx][core] = 0;
219 437
220 if( __ClientCount[core] > 0 ) { 438 if( __ClientCount[core] > 0 ) {
@@ -230,21 +448,6 @@ EXIT:
230 return; 448 return;
231} 449}
232 450
233static inline int update_clients_table(Engine_Handle engine, int core)
234{
235 int i;
236 for(i = 0; i < MAX_INSTANCES; i++)
237 {
238 if(gEngineHandle[i][core] == 0) {
239 gEngineHandle[i][core] = engine;
240 return i;
241 }
242 }
243 return -1;
244}
245
246
247
248/*===============================================================*/ 451/*===============================================================*/
249/** Engine_open : Open Codec Engine. 452/** Engine_open : Open Codec Engine.
250 * 453 *
@@ -264,7 +467,7 @@ Engine_Handle Engine_open(String name, Engine_Attrs *attrs, Engine_Error *ec)
264 int coreIdx = INVALID_CORE; 467 int coreIdx = INVALID_CORE;
265 int tabIdx = -1; 468 int tabIdx = -1;
266 469
267 470 DEBUG("START Engine_open ipc_mutex 0x%x", (unsigned int) &ipc_mutex);
268 /*Acquire permission to use IPC*/ 471 /*Acquire permission to use IPC*/
269 pthread_mutex_lock(&ipc_mutex); 472 pthread_mutex_lock(&ipc_mutex);
270 473
@@ -317,6 +520,7 @@ EXIT:
317 } 520 }
318 /*Relinquish IPC*/ 521 /*Relinquish IPC*/
319 pthread_mutex_unlock(&ipc_mutex); 522 pthread_mutex_unlock(&ipc_mutex);
523 DEBUG("END Engine_open ipc_mutex 0x%x", (unsigned int) &ipc_mutex);
320 524
321 return ((Engine_Handle)engine_handle); 525 return ((Engine_Handle)engine_handle);
322} 526}
@@ -352,7 +556,7 @@ Void Engine_close(Engine_Handle engine)
352 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); 556 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);
353 557
354EXIT: 558EXIT:
355 if(coreIdx != INVALID_CORE) 559 if( coreIdx != INVALID_CORE )
356 dce_ipc_deinit(coreIdx, tableIdx); 560 dce_ipc_deinit(coreIdx, tableIdx);
357 561
358 /*Relinquish IPC*/ 562 /*Relinquish IPC*/
@@ -383,10 +587,6 @@ static void *create(Engine_Handle engine, String name, void *params, dce_codec_t
383 char *codec_name = NULL; 587 char *codec_name = NULL;
384 int coreIdx = INVALID_CORE; 588 int coreIdx = INVALID_CORE;
385 589
386
387 /*Acquire permission to use IPC*/
388 pthread_mutex_lock(&ipc_mutex);
389
390 _ASSERT(name != '\0', DCE_EINVALID_INPUT); 590 _ASSERT(name != '\0', DCE_EINVALID_INPUT);
391 _ASSERT(engine != NULL, DCE_EINVALID_INPUT); 591 _ASSERT(engine != NULL, DCE_EINVALID_INPUT);
392 _ASSERT(params != NULL, DCE_EINVALID_INPUT); 592 _ASSERT(params != NULL, DCE_EINVALID_INPUT);
@@ -416,8 +616,6 @@ static void *create(Engine_Handle engine, String name, void *params, dce_codec_t
416 616
417EXIT: 617EXIT:
418 memplugin_free(codec_name); 618 memplugin_free(codec_name);
419 /*Relinquish IPC*/
420 pthread_mutex_unlock(&ipc_mutex);
421 return ((void *)codec_handle); 619 return ((void *)codec_handle);
422} 620}
423 621
@@ -443,10 +641,6 @@ static XDAS_Int32 control(void *codec, int id, void *dynParams, void *status, dc
443 dce_error_status eError = DCE_EOK; 641 dce_error_status eError = DCE_EOK;
444 int coreIdx = INVALID_CORE; 642 int coreIdx = INVALID_CORE;
445 643
446
447 /*Acquire permission to use IPC*/
448 pthread_mutex_lock(&ipc_mutex);
449
450 _ASSERT(codec != NULL, DCE_EINVALID_INPUT); 644 _ASSERT(codec != NULL, DCE_EINVALID_INPUT);
451 _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT); 645 _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT);
452 _ASSERT(status != NULL, DCE_EINVALID_INPUT); 646 _ASSERT(status != NULL, DCE_EINVALID_INPUT);
@@ -469,16 +663,14 @@ static XDAS_Int32 control(void *codec, int id, void *dynParams, void *status, dc
469 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); 663 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);
470 664
471EXIT: 665EXIT:
472 /*Relinquish IPC*/
473 pthread_mutex_unlock(&ipc_mutex);
474 return (fxnRet); 666 return (fxnRet);
475 667
476} 668}
477 669
478/*===============================================================*/ 670/*===============================================================*/
479/** get_version : Codec control call to get the codec version. This call has been made 671/** get_version : Codec control call to get the codec version. This call has been made
480 * separate from control call because it involves an additional version 672 * separate from control call because it involves an additional version
481 * buffer translation. 673 * buffer translation.
482 * 674 *
483 * @ param codec [in] : Codec Handle obtained in create() call. 675 * @ param codec [in] : Codec Handle obtained in create() call.
484 * @ param id [in] : Command id for XDM control operation. 676 * @ param id [in] : Command id for XDM control operation.
@@ -501,10 +693,6 @@ static XDAS_Int32 get_version(void *codec, void *dynParams, void *status, dce_co
501 dce_error_status eError = DCE_EOK; 693 dce_error_status eError = DCE_EOK;
502 int coreIdx = INVALID_CORE; 694 int coreIdx = INVALID_CORE;
503 695
504
505 /*Acquire permission to use IPC*/
506 pthread_mutex_lock(&ipc_mutex);
507
508 _ASSERT(codec != NULL, DCE_EINVALID_INPUT); 696 _ASSERT(codec != NULL, DCE_EINVALID_INPUT);
509 _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT); 697 _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT);
510 _ASSERT(status != NULL, DCE_EINVALID_INPUT); 698 _ASSERT(status != NULL, DCE_EINVALID_INPUT);
@@ -540,8 +728,6 @@ static XDAS_Int32 get_version(void *codec, void *dynParams, void *status, dce_co
540 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); 728 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);
541 729
542EXIT: 730EXIT:
543 /*Relinquish IPC*/
544 pthread_mutex_unlock(&ipc_mutex);
545 return (fxnRet); 731 return (fxnRet);
546} 732}
547 733
@@ -590,10 +776,6 @@ static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs,
590 int32_t outbuf_offset[MAX_OUTPUT_BUF]; 776 int32_t outbuf_offset[MAX_OUTPUT_BUF];
591#endif 777#endif
592 778
593
594 /*Acquire permission to use IPC*/
595 pthread_mutex_lock(&ipc_mutex);
596
597 _ASSERT(codec != NULL, DCE_EINVALID_INPUT); 779 _ASSERT(codec != NULL, DCE_EINVALID_INPUT);
598 _ASSERT(inBufs != NULL, DCE_EINVALID_INPUT); 780 _ASSERT(inBufs != NULL, DCE_EINVALID_INPUT);
599 _ASSERT(outBufs != NULL, DCE_EINVALID_INPUT); 781 _ASSERT(outBufs != NULL, DCE_EINVALID_INPUT);
@@ -661,8 +843,8 @@ static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs,
661 (size_t)*data_buf, (size_t)*data_buf); 843 (size_t)*data_buf, (size_t)*data_buf);
662#ifdef BUILDOS_LINUX 844#ifdef BUILDOS_LINUX
663 /*Single planar input buffer for Encoder. No adjustments needed for Multiplanar case*/ 845 /*Single planar input buffer for Encoder. No adjustments needed for Multiplanar case*/
664 if(count == CHROMA_BUF && codec_id == OMAP_DCE_VIDENC2 && ((IVIDEO2_BufDesc *)inBufs)->planeDesc[LUMA_BUF].buf == ((IVIDEO2_BufDesc *)inBufs)->planeDesc[CHROMA_BUF].buf){ 846 if( count == CHROMA_BUF && codec_id == OMAP_DCE_VIDENC2 && ((IVIDEO2_BufDesc *)inBufs)->planeDesc[LUMA_BUF].buf == ((IVIDEO2_BufDesc *)inBufs)->planeDesc[CHROMA_BUF].buf ) {
665 if(((IVIDEO2_BufDesc *)inBufs)->planeDesc[count].memType == XDM_MEMTYPE_RAW || 847 if( ((IVIDEO2_BufDesc *)inBufs)->planeDesc[count].memType == XDM_MEMTYPE_RAW ||
666 ((IVIDEO2_BufDesc *)inBufs)->planeDesc[count].memType == XDM_MEMTYPE_TILEDPAGE ) 848 ((IVIDEO2_BufDesc *)inBufs)->planeDesc[count].memType == XDM_MEMTYPE_TILEDPAGE )
667 *data_buf += ((IVIDEO2_BufDesc *)inBufs)->planeDesc[LUMA_BUF].bufSize.bytes; 849 *data_buf += ((IVIDEO2_BufDesc *)inBufs)->planeDesc[LUMA_BUF].bufSize.bytes;
668 else 850 else
@@ -675,8 +857,8 @@ static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs,
675 857
676 /* Output Buffers */ 858 /* Output Buffers */
677 for( count = 0; count < numOutBufs; count++, total_count++ ) { 859 for( count = 0; count < numOutBufs; count++, total_count++ ) {
678 if(codec_id == OMAP_DCE_VIDENC2 || codec_id == OMAP_DCE_VIDDEC3) { 860 if( codec_id == OMAP_DCE_VIDENC2 || codec_id == OMAP_DCE_VIDDEC3 ) {
679 if(((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].buf != ((XDM2_BufDesc *)outBufs)->descs[CHROMA_BUF].buf ) { 861 if( ((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].buf != ((XDM2_BufDesc *)outBufs)->descs[CHROMA_BUF].buf ) {
680 /* Either Encode usecase or MultiPlanar Buffers for Decode usecase */ 862 /* Either Encode usecase or MultiPlanar Buffers for Decode usecase */
681 data_buf = (void * *)(&(((XDM2_BufDesc *)outBufs)->descs[count].buf)); 863 data_buf = (void * *)(&(((XDM2_BufDesc *)outBufs)->descs[count].buf));
682#ifdef BUILDOS_ANDROID 864#ifdef BUILDOS_ANDROID
@@ -701,7 +883,7 @@ static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs,
701 (size_t)*data_buf, (size_t)*data_buf); 883 (size_t)*data_buf, (size_t)*data_buf);
702 884
703 if( count == CHROMA_BUF ) { 885 if( count == CHROMA_BUF ) {
704 if(((XDM2_BufDesc *)outBufs)->descs[count].memType == XDM_MEMTYPE_RAW || 886 if( ((XDM2_BufDesc *)outBufs)->descs[count].memType == XDM_MEMTYPE_RAW ||
705 ((XDM2_BufDesc *)outBufs)->descs[count].memType == XDM_MEMTYPE_TILEDPAGE ) { 887 ((XDM2_BufDesc *)outBufs)->descs[count].memType == XDM_MEMTYPE_TILEDPAGE ) {
706 *data_buf += ((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].bufSize.bytes; 888 *data_buf += ((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].bufSize.bytes;
707 } else { 889 } else {
@@ -711,8 +893,8 @@ static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs,
711 } 893 }
712 } 894 }
713#endif 895#endif
714 } else if(codec_id == OMAP_DCE_VIDDEC2) { 896 } else if( codec_id == OMAP_DCE_VIDDEC2 ) {
715 if(count == LUMA_BUF) { 897 if( count == LUMA_BUF ) {
716 buf_arry = (void * *)(&(((XDM_BufDesc *)outBufs)->bufs)); 898 buf_arry = (void * *)(&(((XDM_BufDesc *)outBufs)->bufs));
717 899
718 Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), OUTBUFS_INDEX, 900 Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), OUTBUFS_INDEX,
@@ -764,8 +946,6 @@ static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs,
764 eError = (dce_error_status)(fxnRet); 946 eError = (dce_error_status)(fxnRet);
765 947
766EXIT: 948EXIT:
767 /*Relinquish IPC*/
768 pthread_mutex_unlock(&ipc_mutex);
769 return (eError); 949 return (eError);
770} 950}
771 951
@@ -783,10 +963,6 @@ static void delete(void *codec, dce_codec_type codec_id)
783 dce_error_status eError = DCE_EOK; 963 dce_error_status eError = DCE_EOK;
784 int coreIdx = INVALID_CORE; 964 int coreIdx = INVALID_CORE;
785 965
786
787 /*Acquire permission to use IPC*/
788 pthread_mutex_lock(&ipc_mutex);
789
790 _ASSERT(codec != NULL, DCE_EINVALID_INPUT); 966 _ASSERT(codec != NULL, DCE_EINVALID_INPUT);
791 coreIdx = getCoreIndexFromCodec(codec_id); 967 coreIdx = getCoreIndexFromCodec(codec_id);
792 _ASSERT(coreIdx != INVALID_CORE, DCE_EINVALID_INPUT); 968 _ASSERT(coreIdx != INVALID_CORE, DCE_EINVALID_INPUT);
@@ -801,8 +977,6 @@ static void delete(void *codec, dce_codec_type codec_id)
801 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL); 977 _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);
802 978
803EXIT: 979EXIT:
804 /*Relinquish IPC*/
805 pthread_mutex_unlock(&ipc_mutex);
806 return; 980 return;
807} 981}
808 982
@@ -810,27 +984,110 @@ EXIT:
810VIDDEC3_Handle VIDDEC3_create(Engine_Handle engine, String name, 984VIDDEC3_Handle VIDDEC3_create(Engine_Handle engine, String name,
811 VIDDEC3_Params *params) 985 VIDDEC3_Params *params)
812{ 986{
813 VIDDEC3_Handle codec; 987 VIDDEC3_Handle codec = NULL;
988 MmRpc_Params args;
989 dce_error_status eError = DCE_EOK;
990 int id;
991
992 /*Acquire permission to use IPC*/
993 pthread_mutex_lock(&ipc_mutex);
994
995 id = get_callback(0);
996 if (id < 0) {
997 /* This is depended on the MAX_INSTANCE, by default it handles only 4 instances of codec instance (full frame or low latency) */
998 ERROR("Failed because too many codec clients, Max is %d. MAX_INSTANCES default needs to be changed if required.", MAX_INSTANCES);
999 goto EXIT;
1000 } else { /* Found empty array to be populated */
1001 if( params->outputDataMode == IVIDEO_NUMROWS ) {
1002 (callbackmsg[id]).row_mode = 1;
1003 (callbackmsg[id]).first_control = TRUE;
1004 (callbackmsg[id]).total_numBlocks = params->maxHeight / 16;
1005 DEBUG("callbackmsg[%d]->total_numBlocks %d", id, (callbackmsg[id]).total_numBlocks);
1006
1007 (callbackmsg[id]).local_dataSyncDesc = memplugin_alloc(sizeof(XDM_DataSyncDesc), 1, DEFAULT_REGION, 0, IPU);
1008 DEBUG("Checking local_dataSyncDesc %p local_put_DataFxn %p local_dataSyncHandle %p",
1009 (callbackmsg[id]).local_dataSyncDesc, (callbackmsg[id]).local_put_DataFxn, (callbackmsg[id]).local_dataSyncHandle);
1010 if( (callbackmsg[id]).local_dataSyncDesc == NULL ) {
1011 goto EXIT;
1012 }
1013
1014 /* Create sem_dec_row_mode */
1015 sem_init(&((callbackmsg[id]).sem_dec_row_mode), 0, 0);
1016
1017 DEBUG("MmRpcCallbackHandle 0x%x MmRpcCallback_count %d", (int)MmRpcCallbackHandle, MmRpcCallback_count);
1018 if( !MmRpcCallbackHandle ) {
1019 /* Need to create another MmRpcHandle for codec callback */
1020 MmRpc_Params_init(&args);
1021 eError = MmRpc_create(DCE_CALLBACK_NAME, &args, &MmRpcCallbackHandle);
1022 _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CREATE_FAIL, MmRpcCallbackHandle = NULL);
1023 DEBUG("open(/dev/%s]) -> 0x%x\n", DCE_CALLBACK_NAME, (int)MmRpcCallbackHandle);
1024 }
1025 MmRpcCallback_count++;
1026 } else if( params->outputDataMode == IVIDEO_ENTIREFRAME ) {
1027 (callbackmsg[id]).row_mode = 0; /* full frame; the other parameters are not used in full frame mode */
1028 } else {
1029 ERROR("outputDataMode %d is not supported.", params->outputDataMode);
1030 goto EXIT;
1031 }
1032 DEBUG("Checking row_mode %d first_control %d",
1033 (callbackmsg[id]).row_mode, (callbackmsg[id]).first_control);
1034 }
814 1035
815 DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params); 1036 DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params);
816 codec = create(engine, name, params, OMAP_DCE_VIDDEC3); 1037 codec = create(engine, name, params, OMAP_DCE_VIDDEC3);
817 DEBUG("<< codec=%p", codec); 1038 DEBUG("<< codec=%p", codec);
1039
1040 if( params->outputDataMode == IVIDEO_NUMROWS ) {
1041 (callbackmsg[id]).codec_handle = (XDAS_UInt32) codec;
1042 DEBUG("Saving the codec %p to (callbackmsg[%d]).codec_handle = 0x%x", codec, id, (unsigned int) (callbackmsg[id]).codec_handle);
1043 }
1044
1045EXIT:
1046 /*Relinquish IPC*/
1047 pthread_mutex_unlock(&ipc_mutex);
818 return (codec); 1048 return (codec);
819} 1049}
820 1050
821XDAS_Int32 VIDDEC3_control(VIDDEC3_Handle codec, VIDDEC3_Cmd id, 1051XDAS_Int32 VIDDEC3_control(VIDDEC3_Handle codec, VIDDEC3_Cmd cmd_id,
822 VIDDEC3_DynamicParams *dynParams, VIDDEC3_Status *status) 1052 VIDDEC3_DynamicParams *dynParams, VIDDEC3_Status *status)
823{ 1053{
824 XDAS_Int32 ret; 1054 XDAS_Int32 ret;
1055 int id;
825 1056
826 DEBUG(">> codec=%p, id=%d, dynParams=%p, status=%p", 1057 /*Acquire permission to use IPC*/
827 codec, id, dynParams, status); 1058 pthread_mutex_lock(&ipc_mutex);
828 if( id == XDM_GETVERSION ) { 1059
1060 id = get_callback((Uint32) codec);
1061 if( id < 0 ) {
1062 DEBUG("Could not find the entry; control on full frame mode");
1063 } else {
1064 DEBUG("Checking codec_handle 0x%x row_mode %d first_control %d",
1065 (unsigned int) (callbackmsg[id]).codec_handle, (callbackmsg[id]).row_mode, (callbackmsg[id]).first_control);
1066 if( (callbackmsg[id]).row_mode && (callbackmsg[id]).first_control ) {
1067 /* dynParams has the function callback; store the information as it will get overwritten by the M4 codec for their own callback Fxn. */
1068 (callbackmsg[id]).local_put_DataFxn = (void*) dynParams->putDataFxn;
1069 (callbackmsg[id]).local_dataSyncHandle = dynParams->putDataHandle;
1070 (callbackmsg[id]).first_control = FALSE;
1071 DEBUG("Set callback pointer local_get_dataFxn %p local_dataSyncHandle %p",
1072 (callbackmsg[id]).local_put_DataFxn, (callbackmsg[id]).local_dataSyncHandle);
1073 }
1074
1075 if( cmd_id == XDM_FLUSH ) {
1076 DEBUG("FLUSH HAS BEEN ORDERED");
1077 }
1078 }
1079
1080 DEBUG(">> codec=%p, cmd_id=%d, dynParams=%p, status=%p",
1081 codec, cmd_id, dynParams, status);
1082 if( cmd_id == XDM_GETVERSION ) {
829 ret = get_version(codec, dynParams, status, OMAP_DCE_VIDDEC3); 1083 ret = get_version(codec, dynParams, status, OMAP_DCE_VIDDEC3);
830 } else { 1084 } else {
831 ret = control(codec, id, dynParams, status, OMAP_DCE_VIDDEC3); 1085 ret = control(codec, cmd_id, dynParams, status, OMAP_DCE_VIDDEC3);
832 } 1086 }
1087 DEBUG("dynParams->putDataFxn %p", dynParams->putDataFxn);
833 DEBUG("<< ret=%d", ret); 1088 DEBUG("<< ret=%d", ret);
1089 /*Relinquish IPC*/
1090 pthread_mutex_unlock(&ipc_mutex);
834 return (ret); 1091 return (ret);
835} 1092}
836 1093
@@ -838,19 +1095,110 @@ XDAS_Int32 VIDDEC3_process(VIDDEC3_Handle codec,
838 XDM2_BufDesc *inBufs, XDM2_BufDesc *outBufs, 1095 XDM2_BufDesc *inBufs, XDM2_BufDesc *outBufs,
839 VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs) 1096 VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs)
840{ 1097{
841 XDAS_Int32 ret; 1098 XDAS_Int32 ret;
1099 pthread_attr_t attr;
1100 int id;
842 1101
843 DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p", 1102 DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p",
844 codec, inBufs, outBufs, inArgs, outArgs); 1103 codec, inBufs, outBufs, inArgs, outArgs);
1104
1105 /*Acquire permission to use IPC*/
1106 pthread_mutex_lock(&ipc_mutex);
1107 id = get_callback((Uint32) codec);
1108 if( id < 0 ) {
1109 DEBUG("Received VIDDEC3_process for ENTIRE/FULL FRAME decoding.");
1110 } else {
1111 pthread_mutex_lock(&dce_callback_mutex);
1112 DEBUG("Checking row_mode %d SETTING (callbackmsg[id]).putDataFlag = 0", (callbackmsg[id]).row_mode);
1113 if( (callbackmsg[id]).row_mode ) {
1114 (callbackmsg[id]).putDataFlag = 0;
1115 DEBUG("Checking callbackmsg[%d]->putDataFxn_thread %p", id, (void*) (callbackmsg[id]).putDataFxn_thread);
1116 if( !(callbackmsg[id]).putDataFxn_thread ) {
1117 /* Need to start a new thread for the callback handling to request for data - process call will be synchronous. */
1118 pthread_attr_init(&attr);
1119 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1120 if( pthread_create(&((callbackmsg[id]).putDataFxn_thread), &attr, (void*)dce_callback_putDataFxn, (void*) &codec) ) {
1121 pthread_mutex_unlock(&ipc_mutex);
1122 return DCE_EXDM_FAIL;
1123 }
1124 }
1125 DEBUG("Checking thread callbackmsg[%d]->putDataFxn_thread %p", id, (void*) (callbackmsg[id]).putDataFxn_thread);
1126
1127 /* Start the callback to get putDataFxn from codec to client. */
1128 (callbackmsg[id]).putDataFlag = 1;
1129 sem_post(&((callbackmsg[id]).sem_dec_row_mode));
1130
1131 DEBUG("Start the callback to client callbackmsg[%d]->putDataFlag %d on callbackmsg[%d]->local_dataSyncHandle 0x%x",
1132 id, (callbackmsg[id]).putDataFlag, id, (unsigned int) (callbackmsg[id]).local_dataSyncHandle);
1133 }
1134 pthread_mutex_unlock(&dce_callback_mutex);
1135 }
1136
845 ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDDEC3); 1137 ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDDEC3);
846 DEBUG("<< ret=%d", ret); 1138 DEBUG("<< ret=%d", ret);
1139
1140 if( (callbackmsg[id]).row_mode ) {
1141 DEBUG("(callbackmsg[%d]).receive_numBlocks %d >= (callbackmsg[%d]).total_numBlocks %d",
1142 id, (callbackmsg[id]).receive_numBlocks, id, (callbackmsg[id]).total_numBlocks);
1143
1144 if( (callbackmsg[id]).receive_numBlocks >= (callbackmsg[id]).total_numBlocks ) {
1145 DEBUG("Stop the callback to client callbackmsg[%d]->putDataFlag %d reach full frame (callbackmsg[%d]).receive_numBlocks %d",
1146 id, (callbackmsg[id]).putDataFlag, id, (callbackmsg[id]).receive_numBlocks);
1147 (callbackmsg[id]).putDataFlag = 0;
1148 if ((callbackmsg[id]).receive_numBlocks) {
1149 DEBUG("Waiting for dce_callback_putDataFxn to be in waiting case.");
1150 sem_wait(&((callbackmsg[id]).sem_dec_row_mode));
1151 }
1152 }
1153 }
1154
1155 /*Relinquish IPC*/
1156 pthread_mutex_unlock(&ipc_mutex);
847 return (ret); 1157 return (ret);
848} 1158}
849 1159
850Void VIDDEC3_delete(VIDDEC3_Handle codec) 1160Void VIDDEC3_delete(VIDDEC3_Handle codec)
851{ 1161{
1162 void *res;
1163 int id;
1164
852 DEBUG(">> codec=%p", codec); 1165 DEBUG(">> codec=%p", codec);
1166
1167 /*Acquire permission to use IPC*/
1168 pthread_mutex_lock(&ipc_mutex);
1169
1170 id = get_callback((Uint32) codec);
1171 if( id < 0 ) {
1172 DEBUG("Delete decode instance in full frame mode");
1173 } else {
1174 if( (callbackmsg[id]).row_mode ) {
1175 MmRpcCallback_count--;
1176 /* Exit the callback thread to request to client */
1177 (callbackmsg[id]).putDataFlag = 2;
1178 DEBUG("Exit the callback to client callbackmsg[%d]->getDataFlag %d callbackmsg[%d]->getDataFxn_thread %p",
1179 id, (callbackmsg[id]).putDataFlag, id, (void*) ((callbackmsg[id]).putDataFxn_thread));
1180 sem_post(&((callbackmsg[id]).sem_dec_row_mode));
1181
1182 pthread_join((callbackmsg[id]).putDataFxn_thread, (void*) &res);
1183 DEBUG("PTHREAD_JOIN res %d", (int) res);
1184
1185 /* Clean up the allocation earlier. */
1186 memplugin_free((callbackmsg[id]).local_dataSyncDesc);
1187
1188 /* Destroy sem_dec_row_mode */
1189 sem_destroy(&((callbackmsg[id]).sem_dec_row_mode));
1190
1191 DEBUG("Checking on MmRpcCallback_count %d MmRpcCallbackHandle 0x%x", MmRpcCallback_count, (unsigned int) MmRpcCallbackHandle);
1192 if( MmRpcCallback_count == 0 && MmRpcCallbackHandle != NULL ) {
1193 MmRpc_delete(&MmRpcCallbackHandle);
1194 MmRpcCallbackHandle = NULL;
1195 }
1196 }
1197 }
1198
853 delete(codec, OMAP_DCE_VIDDEC3); 1199 delete(codec, OMAP_DCE_VIDDEC3);
1200 /*Relinquish IPC*/
1201 pthread_mutex_unlock(&ipc_mutex);
854 DEBUG("<<"); 1202 DEBUG("<<");
855} 1203}
856 1204
@@ -858,27 +1206,101 @@ Void VIDDEC3_delete(VIDDEC3_Handle codec)
858VIDENC2_Handle VIDENC2_create(Engine_Handle engine, String name, 1206VIDENC2_Handle VIDENC2_create(Engine_Handle engine, String name,
859 VIDENC2_Params *params) 1207 VIDENC2_Params *params)
860{ 1208{
861 VIDENC2_Handle codec; 1209 VIDENC2_Handle codec = NULL;
1210 MmRpc_Params args;
1211 dce_error_status eError = DCE_EOK;
1212 int id;
1213
1214 /*Acquire permission to use IPC*/
1215 pthread_mutex_lock(&ipc_mutex);
1216
1217 id = get_callback(0);
1218 if( id < 0 ) {
1219 /* This is depended on the MAX_INSTANCE, by default it handles only 4 instances of codec instance (full frame or low latency) */
1220 ERROR("Failed because too many codec clients, Max is %d. MAX_INSTANCES default needs to be changed if required.", MAX_INSTANCES);
1221 goto EXIT;
1222 } else { /* Found empty array to be populated */
1223 if( params->inputDataMode == IVIDEO_NUMROWS ) {
1224 (callbackmsg[id]).row_mode = 1;
1225 (callbackmsg[id]).first_control = TRUE;
1226 (callbackmsg[id]).total_numBlocks = params->maxHeight / 16;
1227 DEBUG("callbackmsg[%d]->total_numBlocks %d", id, (callbackmsg[id]).total_numBlocks);
1228
1229 /* Create sem_dec_row_mode */
1230 sem_init(&((callbackmsg[id]).sem_enc_row_mode), 0, 0);
1231
1232 (callbackmsg[id]).local_dataSyncDesc = memplugin_alloc(sizeof(XDM_DataSyncDesc), 1, DEFAULT_REGION, 0, IPU);
1233 DEBUG("Checking local_dataSyncDesc %p local_get_DataFxn %p local_dataSyncHandle %p",
1234 (callbackmsg[id]).local_dataSyncDesc, (callbackmsg[id]).local_get_DataFxn, (callbackmsg[id]).local_dataSyncHandle);
1235 if( (callbackmsg[id]).local_dataSyncDesc == NULL ) {
1236 goto EXIT;
1237 }
1238
1239 if( !MmRpcCallbackHandle ) {
1240 /* Need to create another MmRpcHandle for codec callback */
1241 MmRpc_Params_init(&args);
1242 eError = MmRpc_create(DCE_CALLBACK_NAME, &args, &MmRpcCallbackHandle);
1243 _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CREATE_FAIL, MmRpcCallbackHandle = NULL);
1244 DEBUG("open(/dev/%s]) -> 0x%x\n", DCE_CALLBACK_NAME, (int)MmRpcCallbackHandle);
1245 }
1246 MmRpcCallback_count++;
1247 } else if( params->inputDataMode == IVIDEO_ENTIREFRAME ) {
1248 (callbackmsg[id]).row_mode = 0; /* full frame; the other parameters are not used in full frame mode */
1249 } else {
1250 ERROR("inputDataMode %d is not supported.", params->inputDataMode);
1251 goto EXIT;
1252 }
1253 DEBUG("Checking row_mode %d first_control %d", (callbackmsg[id]).row_mode, (callbackmsg[id]).first_control);
1254 }
862 1255
863 DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params); 1256 DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params);
864 codec = create(engine, name, params, OMAP_DCE_VIDENC2); 1257 codec = create(engine, name, params, OMAP_DCE_VIDENC2);
865 DEBUG("<< codec=%p", codec); 1258 DEBUG("<< codec=%p", codec);
1259
1260 if( params->inputDataMode == IVIDEO_NUMROWS ) {
1261 (callbackmsg[id]).codec_handle = (XDAS_UInt32) codec;
1262 }
1263
1264EXIT:
1265 /*Relinquish IPC*/
1266 pthread_mutex_unlock(&ipc_mutex);
866 return (codec); 1267 return (codec);
867} 1268}
868 1269
869XDAS_Int32 VIDENC2_control(VIDENC2_Handle codec, VIDENC2_Cmd id, 1270XDAS_Int32 VIDENC2_control(VIDENC2_Handle codec, VIDENC2_Cmd cmd_id,
870 VIDENC2_DynamicParams *dynParams, VIDENC2_Status *status) 1271 VIDENC2_DynamicParams *dynParams, VIDENC2_Status *status)
871{ 1272{
872 XDAS_Int32 ret; 1273 XDAS_Int32 ret;
1274 int id;
873 1275
874 DEBUG(">> codec=%p, id=%d, dynParams=%p, status=%p", 1276 /*Acquire permission to use IPC*/
875 codec, id, dynParams, status); 1277 pthread_mutex_lock(&ipc_mutex);
876 if( id == XDM_GETVERSION ) { 1278
1279 id = get_callback((Uint32) codec);
1280 if( id < 0 ) {
1281 DEBUG("Could not find the entry in callbackmsg array; might not be rowmode; should be full frame mode");
1282 } else {
1283 DEBUG("Checking row_mode %d first_control %d", (callbackmsg[id]).row_mode, (callbackmsg[id]).first_control);
1284 if( (callbackmsg[id]).row_mode && (callbackmsg[id]).first_control ) {
1285 /* dynParams has the function callback; store the information as it will get overwritten by the M4 codec for their own callback Fxn. */
1286 (callbackmsg[id]).local_get_DataFxn = (void*) dynParams->getDataFxn;
1287 (callbackmsg[id]).local_dataSyncHandle = dynParams->getDataHandle;
1288 (callbackmsg[id]).first_control = FALSE;
1289 DEBUG("Set callback pointer local_get_dataFxn %p local_dataSyncHandle %p", (callbackmsg[id]).local_get_DataFxn, (callbackmsg[id]).local_dataSyncHandle);
1290 }
1291 }
1292
1293 DEBUG(">> codec=%p, cmd_id=%d, dynParams=%p, status=%p",
1294 codec, cmd_id, dynParams, status);
1295 if( cmd_id == XDM_GETVERSION ) {
877 ret = get_version(codec, dynParams, status, OMAP_DCE_VIDENC2); 1296 ret = get_version(codec, dynParams, status, OMAP_DCE_VIDENC2);
878 } else { 1297 } else {
879 ret = control(codec, id, dynParams, status, OMAP_DCE_VIDENC2); 1298 ret = control(codec, cmd_id, dynParams, status, OMAP_DCE_VIDENC2);
880 } 1299 }
1300
881 DEBUG("<< ret=%d", ret); 1301 DEBUG("<< ret=%d", ret);
1302 /*Relinquish IPC*/
1303 pthread_mutex_unlock(&ipc_mutex);
882 return (ret); 1304 return (ret);
883} 1305}
884 1306
@@ -886,19 +1308,99 @@ XDAS_Int32 VIDENC2_process(VIDENC2_Handle codec,
886 IVIDEO2_BufDesc *inBufs, XDM2_BufDesc *outBufs, 1308 IVIDEO2_BufDesc *inBufs, XDM2_BufDesc *outBufs,
887 VIDENC2_InArgs *inArgs, VIDENC2_OutArgs *outArgs) 1309 VIDENC2_InArgs *inArgs, VIDENC2_OutArgs *outArgs)
888{ 1310{
889 XDAS_Int32 ret; 1311 XDAS_Int32 ret = 0;
1312 pthread_attr_t attr;
1313 int id;
890 1314
891 DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p", 1315 DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p",
892 codec, inBufs, outBufs, inArgs, outArgs); 1316 codec, inBufs, outBufs, inArgs, outArgs);
1317
1318 /*Acquire permission to use IPC*/
1319 pthread_mutex_lock(&ipc_mutex);
1320
1321 id = get_callback((Uint32) codec);
1322 if( id < 0 ) {
1323 DEBUG("Received VIDENC2_process for ENTIRE FRAME encoding because no entry found in callbackmsg");
1324 } else {
1325 DEBUG("Checking row_mode %d", (callbackmsg[id]).row_mode);
1326 if( (callbackmsg[id]).row_mode ) {
1327 (callbackmsg[id]).getDataFlag = 0;
1328 DEBUG("Checking callbackmsg[%d]->getDataFxn_thread 0x%x", id, (callbackmsg[id]).getDataFxn_thread);
1329 if( !(callbackmsg[id]).getDataFxn_thread ) {
1330 /* Need to start a new thread for the callback handling to request for data - process call will be synchronous. */
1331 pthread_attr_init(&attr);
1332 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1333 if( pthread_create(&((callbackmsg[id]).getDataFxn_thread), &attr, (void*)dce_callback_getDataFxn, (void*) &codec) ) {
1334 pthread_mutex_unlock(&ipc_mutex);
1335 return DCE_EXDM_FAIL;
1336 }
1337 }
1338 DEBUG("Create thread callbackmsg[%d]->getDataFxn_thread 0x%x", id, (unsigned int) (callbackmsg[id]).getDataFxn_thread);
1339
1340 /* Start the callback to request to client */
1341 (callbackmsg[id]).getDataFlag = 1;
1342 sem_post(&((callbackmsg[id]).sem_enc_row_mode));
1343 DEBUG("Start the callback to client (callbackmsg[%d]).getDataFlag %d on (callbackmsg[%d]).local_dataSyncHandle 0x%x",
1344 id, (callbackmsg[id]).getDataFlag, id, (unsigned int) (callbackmsg[id]).local_dataSyncHandle);
1345 }
1346 }
1347
893 ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDENC2); 1348 ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDENC2);
894 DEBUG("<< ret=%d", ret); 1349 DEBUG("<< ret=%d", ret);
1350
1351 if( (callbackmsg[id]).row_mode ) {
1352 /* Stop the callback to request to client */
1353 DEBUG("Stop the callback to client callbackmsg[%d]->getDataFlag %d", id, (callbackmsg[id]).getDataFlag);
1354 (callbackmsg[id]).getDataFlag = 0;
1355 }
1356
1357 /*Relinquish IPC*/
1358 pthread_mutex_unlock(&ipc_mutex);
895 return (ret); 1359 return (ret);
896} 1360}
897 1361
898Void VIDENC2_delete(VIDENC2_Handle codec) 1362Void VIDENC2_delete(VIDENC2_Handle codec)
899{ 1363{
1364 void *res;
1365 int id;
1366
900 DEBUG(">> codec=%p", codec); 1367 DEBUG(">> codec=%p", codec);
1368
1369 /*Acquire permission to use IPC*/
1370 pthread_mutex_lock(&ipc_mutex);
1371
1372 id = get_callback((Uint32) codec);
1373 if( id < 0 ) {
1374 DEBUG("Delete encode instance in full frame mode");
1375 } else {
1376 if( (callbackmsg[id]).row_mode ) {
1377 MmRpcCallback_count--;
1378 /* Exit the callback thread to request to client */
1379 (callbackmsg[id]).getDataFlag = 2;
1380 DEBUG("Exit the callback to client (callbackmsg[%d]).getDataFlag %d (callbackmsg[%d]).getDataFxn_thread 0x%x",
1381 id, (callbackmsg[id]).getDataFlag, id, (unsigned int) (callbackmsg[id]).getDataFxn_thread);
1382 sem_post(&((callbackmsg[id]).sem_enc_row_mode));
1383
1384 pthread_join((callbackmsg[id]).getDataFxn_thread, (void*) &res);
1385 DEBUG("PTHREAD_JOIN res %d", (int) res);
1386
1387 /* Clean up the allocation earlier. */
1388 memplugin_free((callbackmsg[id]).local_dataSyncDesc);
1389
1390 /* Destroy sem_dec_row_mode */
1391 sem_destroy(&((callbackmsg[id]).sem_enc_row_mode));
1392
1393 DEBUG("Check on MmRpcCallback_count %d", MmRpcCallback_count);
1394 if( MmRpcCallback_count == 0 && MmRpcCallbackHandle != NULL ) {
1395 MmRpc_delete(&MmRpcCallbackHandle);
1396 MmRpcCallbackHandle = NULL;
1397 }
1398 }
1399 }
1400
901 delete(codec, OMAP_DCE_VIDENC2); 1401 delete(codec, OMAP_DCE_VIDENC2);
1402 /*Relinquish IPC*/
1403 pthread_mutex_unlock(&ipc_mutex);
902 DEBUG("<<"); 1404 DEBUG("<<");
903} 1405}
904 1406