Handling when MPU crashes, eg. CTRL-C on MPU side.
authorBuddy Liong <a0270631@ti.com>
Thu, 7 Jan 2016 21:28:41 +0000 (15:28 -0600)
committerBuddy Liong <a0270631@ti.com>
Mon, 2 Oct 2017 15:20:14 +0000 (10:20 -0500)
During low latency encode and decode, when MPU is crashing
DCE server is not handling the clean up properly which can cause
the system to hang afterward.

Based on the information from the codec support, since process call
is in blocked state, the client needs to send proper numBlocks for
codec to return the process call properly.

In H.264 low latency encoder, codec will call function callback
H264E_GetDataFxn to get the numBlocks, when MPU has crashed, DCE
server needs to propagate the numBlocks to codec so that codec can
proceed and return the process call.
There are 2 alternatives, one is to return proper numBlocks based
on resolution, the other is to return bogus numBlocks which is big
enough for codec to detect an error and return the process call.
This task implements the returning bogus '100' numBlocks to codec
because the implementation for proper numBlocks requires some
calculation to be implemented and the input buffer will not have
proper data anyway.

In H.264 low latency decoder, codec will call function callback
H264D_PutDataFxn to post the numBlocks to client, when MPU has
crashed, DCE server should ignore this information and return
immediately. There could be multiple callback from codec until codec
reach the proper numBlocks and DCE server should ignore and return
immediately.

Change-Id: I56c0f3b5792504e18d2fb2a57a3c34d26f0b55e5
Signed-off-by: Buddy Liong <a0270631@ti.com>
src/ti/framework/dce/dce.c

index 497215c8063960c84ede7a6eff358b08a5fe9021..68a9cbc23e900517a8664ba9f661ff6662817df9 100644 (file)
@@ -127,6 +127,7 @@ typedef struct {
     Uint32 getdata_ready;
     Uint32 codec_request;
     Uint32 putdata_ready;
+    Uint32 mpu_crash_indication;
 } Callback_data;
 
 typedef struct {
@@ -279,6 +280,7 @@ static XDAS_Int32 videnc2_control(VIDENC2_Handle codec, VIDENC2_Cmd id,
             if (c->encode_codec[i] == codec) {
                 if (c->encode_callback[i].row_mode) {
                     c->encode_callback[i].dataSyncHandle = codec;
+                    c->encode_callback[i].mpu_crash_indication = FALSE;
                     dynParams->getDataFxn = (XDM_DataSyncGetFxn) H264E_GetDataFxn;
                     dynParams->getDataHandle = codec;
                 }
@@ -347,6 +349,7 @@ static XDAS_Int32 viddec3_control(VIDDEC3_Handle codec,VIDDEC3_Cmd id,VIDDEC3_Dy
                 if (c->decode_callback[i].row_mode) {
                     DEBUG("Check codec 0x%x", codec);
                     c->decode_callback[i].dataSyncHandle = codec;
+                    c->decode_callback[i].mpu_crash_indication = FALSE;
                     dynParams->putDataFxn = (XDM_DataSyncPutFxn) H264D_PutDataFxn;
                     dynParams->putDataHandle = codec;
                 }
@@ -1314,6 +1317,25 @@ Void dce_SrvDelNotification(Void)
     if( c ) {
         DEBUG("cleanup: mm_serv_id=0x%x c=%p c->refs=%d", mm_serv_id, c, c->refs);
 
+        /* For low latency instance, need to trigger the flag to callback function so that it will return full numblock*/
+        for( i = 0; i < DIM(c->decode_codec); i++ ) {
+            //DEBUG("c->decode_callback[%d].row_mode %d", i, c->decode_callback[i].row_mode);
+            if (c->decode_callback[i].row_mode) {
+                DEBUG("Setting c->decode_callback[%d].mpu_crash_indication = TRUE c->decode_codec[%d].callback_mutex 0x%x", i, i, c->decode_callback[i].callback_mutex);
+                c->decode_callback[i].mpu_crash_indication = TRUE;
+                pthread_cond_signal(&(c->decode_callback[i].synch_callback));
+            }
+        }
+
+        for( i = 0; i < DIM(c->encode_codec); i++ ) {
+            //DEBUG("c->encode_callback[%d].row_mode %d", i, c->encode_callback[i].row_mode);
+            if (c->encode_callback[i].row_mode) {
+                DEBUG("Setting c->encode_callback[%d].mpu_crash_indication = TRUE c->encode_codec[%d].callback_mutex 0x%x", i, i, c->encode_callback[i].callback_mutex);
+                c->encode_callback[i].mpu_crash_indication = TRUE;
+                pthread_cond_signal(&(c->encode_callback[i].synch_callback));
+            }
+        }
+
         /* Make sure IVAHD and SL2 are idle before proceeding */
         ivahd_idle_check();
 
@@ -1327,6 +1349,7 @@ Void dce_SrvDelNotification(Void)
                     pthread_mutex_destroy(&(c->decode_callback[i].callback_mutex));
                     pthread_cond_destroy(&(c->decode_callback[i].synch_callback));
                     c->decode_callback[i].row_mode = 0;
+                    c->decode_callback[i].mpu_crash_indication = FALSE;
                 }
                 codec_fxns[OMAP_DCE_VIDDEC3].delete((void *)c->decode_codec[i]);
                 c->decode_codec[i] = NULL;
@@ -1342,6 +1365,7 @@ Void dce_SrvDelNotification(Void)
                     pthread_mutex_destroy(&(c->encode_callback[i].callback_mutex));
                     pthread_cond_destroy(&(c->encode_callback[i].synch_callback));
                     c->encode_callback[i].row_mode = 0;
+                    c->encode_callback[i].mpu_crash_indication = FALSE;
                 }
                 codec_fxns[OMAP_DCE_VIDENC2].delete((void *)c->encode_codec[i]);
                 c->encode_codec[i] = NULL;
@@ -1517,39 +1541,53 @@ XDM_DataSyncGetFxn H264E_GetDataFxn(XDM_DataSyncHandle dataSyncHandle,
                 pthread_mutex_lock(&(c->encode_callback[i].callback_mutex));
                 DEBUG("H264E_GetDataFxn dataSyncHandle 0x%x c->encode_callback[%d].callback_mutex 0x%x", dataSyncHandle, i, c->encode_callback[i].callback_mutex);
                 // Check if H264E_GetDataFxn from codec and get_DataFxn from MPU side. Which comes first.
-                if (c->encode_callback[i].getdata_ready) {
-                    // Already have data to be passed to codec
-                    DEBUG("H264E_GetDataFxn Case#2 c->encode_callback[%d].dataSyncHandle 0x%x c->encode_callback[%d].dataSyncDesc 0x%x",
-                    i, c->encode_callback[i].dataSyncHandle, i, c->encode_callback[i].dataSyncDesc);
-                    if (dataSyncHandle == c->encode_callback[i].dataSyncHandle) {
-                        dataSyncDesc->size = (c->encode_callback[i].dataSyncDesc)->size;
-                        dataSyncDesc->scatteredBlocksFlag = (c->encode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
-                        dataSyncDesc->baseAddr = (c->encode_callback[i].dataSyncDesc)->baseAddr;
-                        dataSyncDesc->numBlocks = (c->encode_callback[i].dataSyncDesc)->numBlocks;
-                        dataSyncDesc->varBlockSizesFlag = (c->encode_callback[i].dataSyncDesc)->varBlockSizesFlag;
-                        dataSyncDesc->blockSizes = (c->encode_callback[i].dataSyncDesc)->blockSizes;
-                    }
-
-                    // Order get_DataFxn to continue request to MPU client side for more data as it is currently pending.
-                    pthread_cond_signal(&(c->encode_callback[i].synch_callback));
+                // Check if MPU has crashed c->encode_callback[i].mpu_crash_indication, if it is then send the highest numBlock to codec so that VIDENC2_process will be returned and IVA back to IDLE.
+                if (c->encode_callback[i].mpu_crash_indication) {
+                    // Since MPU has crashed, need to send the numBlocks to codec so that VIDENC2_process can be returned and IVA back to IDLE.
+                    // Send the numBlocks as expected max value or add functionality to count up to proper numBlocks to be returned to codec.
+                    // Current implementation will send arbitrary value 100 numBlocks (height resolution 1600) which will let codec return the process call and move IVA into IDLE state.
+                    DEBUG("MPU has crashed, send arbitrary numBlocks 100 so that VIDENC2_process will be returned");
+                    dataSyncDesc->size = sizeof(XDM_DataSyncDesc);
+                    dataSyncDesc->scatteredBlocksFlag = 0;
+                    dataSyncDesc->baseAddr = 0;
+                    dataSyncDesc->numBlocks = 100;
+                    dataSyncDesc->varBlockSizesFlag = 0;
+                    dataSyncDesc->blockSizes = 0;
                 } else {
-                    c->encode_callback[i].codec_request = 1;
-
-                    // Wait until get_DataFxn is received from MPU client side. Need the information to be passed to codec as currently not available.
-                    pthread_cond_wait(&(c->encode_callback[i].synch_callback), &(c->encode_callback[i].callback_mutex));
-
-                    // Once get_DataFxn is received from MPU side continue by providing it to IVA-HD codec.
-                    DEBUG("H264E_GetDataFxn Case#1 c->encode_callback[%d].dataSyncHandle 0x%x c->encode_callback[%d].dataSyncDesc 0x%x",
-                        i, c->encode_callback[i].dataSyncHandle, i, c->encode_callback[i].dataSyncDesc);
-                    if (dataSyncHandle == c->encode_callback[i].dataSyncHandle) {
-                        dataSyncDesc->size = (c->encode_callback[i].dataSyncDesc)->size;
-                        dataSyncDesc->scatteredBlocksFlag = (c->encode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
-                        dataSyncDesc->baseAddr = (c->encode_callback[i].dataSyncDesc)->baseAddr;
-                        dataSyncDesc->numBlocks = (c->encode_callback[i].dataSyncDesc)->numBlocks;
-                        dataSyncDesc->varBlockSizesFlag = (c->encode_callback[i].dataSyncDesc)->varBlockSizesFlag;
-                        dataSyncDesc->blockSizes = (c->encode_callback[i].dataSyncDesc)->blockSizes;
+                    if (c->encode_callback[i].getdata_ready) {
+                        // Already have data to be passed to codec
+                        DEBUG("H264E_GetDataFxn Case#2 c->encode_callback[%d].dataSyncHandle 0x%x c->encode_callback[%d].dataSyncDesc 0x%x",
+                            i, c->encode_callback[i].dataSyncHandle, i, c->encode_callback[i].dataSyncDesc);
+                        if (dataSyncHandle == c->encode_callback[i].dataSyncHandle) {
+                            dataSyncDesc->size = (c->encode_callback[i].dataSyncDesc)->size;
+                            dataSyncDesc->scatteredBlocksFlag = (c->encode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
+                            dataSyncDesc->baseAddr = (c->encode_callback[i].dataSyncDesc)->baseAddr;
+                            dataSyncDesc->numBlocks = (c->encode_callback[i].dataSyncDesc)->numBlocks;
+                            dataSyncDesc->varBlockSizesFlag = (c->encode_callback[i].dataSyncDesc)->varBlockSizesFlag;
+                            dataSyncDesc->blockSizes = (c->encode_callback[i].dataSyncDesc)->blockSizes;
+                        }
+
+                        // Order get_DataFxn to continue request to MPU client side for more data as it is currently pending.
+                        pthread_cond_signal(&(c->encode_callback[i].synch_callback));
+                    } else {
+                        c->encode_callback[i].codec_request = 1;
+
+                        // Wait until get_DataFxn is received from MPU client side. Need the information to be passed to codec as currently not available.
+                        pthread_cond_wait(&(c->encode_callback[i].synch_callback), &(c->encode_callback[i].callback_mutex));
+
+                        // Once get_DataFxn is received from MPU side continue by providing it to IVA-HD codec.
+                        DEBUG("H264E_GetDataFxn Case#1 c->encode_callback[%d].dataSyncHandle 0x%x c->encode_callback[%d].dataSyncDesc 0x%x",
+                            i, c->encode_callback[i].dataSyncHandle, i, c->encode_callback[i].dataSyncDesc);
+                        if (dataSyncHandle == c->encode_callback[i].dataSyncHandle) {
+                            dataSyncDesc->size = (c->encode_callback[i].dataSyncDesc)->size;
+                            dataSyncDesc->scatteredBlocksFlag = (c->encode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
+                            dataSyncDesc->baseAddr = (c->encode_callback[i].dataSyncDesc)->baseAddr;
+                            dataSyncDesc->numBlocks = (c->encode_callback[i].dataSyncDesc)->numBlocks;
+                            dataSyncDesc->varBlockSizesFlag = (c->encode_callback[i].dataSyncDesc)->varBlockSizesFlag;
+                            dataSyncDesc->blockSizes = (c->encode_callback[i].dataSyncDesc)->blockSizes;
+                        }
+                        c->encode_callback[i].codec_request = 0;
                     }
-                    c->encode_callback[i].codec_request = 0;
                 }
                 pthread_mutex_unlock(&(c->encode_callback[i].callback_mutex));
             }
@@ -1602,21 +1640,24 @@ XDM_DataSyncPutFxn H264D_PutDataFxn(XDM_DataSyncHandle dataSyncHandle,
                     DEBUG("From Codec (c->decode_callback[%d].dataSyncDesc)->blockSizes %d ", i, (c->decode_callback[i].dataSyncDesc)->blockSizes);
                 }
 
-                // Check if put_DataFxn from MPU side has come before H264D_PutDataFxn.
-                if (c->decode_callback[i].putdata_ready) {
-                    // Already receive request from client for partial decoded output information from codec.
-                    // Order put_DataFxn to continue sending codec partial decoded data in the local structure to MPU side.
-                    DEBUG("H264D_PutDataFxn Case#2 c->decode_callback[%d].dataSyncHandle 0x%x c->decode_callback[%d].dataSyncDesc 0x%x",
-                    i, c->decode_callback[i].dataSyncHandle, i, c->decode_callback[i].dataSyncDesc);
-
-                    // After storing the data from codec, send thread signal conditional for put_DataFxn to continue passing the codec data to MPU.
-                    pthread_cond_signal(&(c->decode_callback[i].synch_callback));
-                } else {
-                    // Wait until the put_DataFxn is received from MPU side. Codec has callback with partial decoded data but put_DataFxn is not received yet.
-                    c->decode_callback[i].codec_request = 1;
-                    DEBUG("H264D_PutDataFxn Case#1 wait on pthread_cond_wait c->decode_codec[%d].callback_mutex 0x%x", i, c->decode_callback[i].callback_mutex);
-                    pthread_cond_wait(&(c->decode_callback[i].synch_callback), &(c->decode_callback[i].callback_mutex));
-                    c->decode_callback[i].codec_request = 0;
+                // If MPU has crashed, there is no way MPU will respond after this. Let codec thinking that MPU has received the numblock. Don't wait, just returned.
+                if (!(c->decode_callback[i].mpu_crash_indication)) {
+                    // MPU is alive. Wait until the put_DataFxn is received from MPU side. Codec has callback with partial decoded data but put_DataFxn is not received yet.
+                    // Check if put_DataFxn from MPU side has come before H264D_PutDataFxn.
+                    if (c->decode_callback[i].putdata_ready) {
+                        // Already receive request from client for partial decoded output information from codec.
+                        // Order put_DataFxn to continue sending codec partial decoded data in the local structure to MPU side.
+                        DEBUG("H264D_PutDataFxn Case#2 c->decode_callback[%d].dataSyncHandle 0x%x c->decode_callback[%d].dataSyncDesc 0x%x",
+                            i, c->decode_callback[i].dataSyncHandle, i, c->decode_callback[i].dataSyncDesc);
+
+                        // After storing the data from codec, send thread signal conditional for put_DataFxn to continue passing the codec data to MPU.
+                        pthread_cond_signal(&(c->decode_callback[i].synch_callback));
+                    } else {
+                        c->decode_callback[i].codec_request = 1;
+                        DEBUG("H264D_PutDataFxn Case#1 wait on pthread_cond_wait c->decode_codec[%d].callback_mutex 0x%x", i, c->decode_callback[i].callback_mutex);
+                        pthread_cond_wait(&(c->decode_callback[i].synch_callback), &(c->decode_callback[i].callback_mutex));
+                        c->decode_callback[i].codec_request = 0;
+                    }
                 }
                 pthread_mutex_unlock(&(c->decode_callback[i].callback_mutex));
             }