diff options
| -rw-r--r-- | videocodec/OMXVideoDecoderAVCSecure.cpp | 122 | ||||
| -rw-r--r-- | videocodec/OMXVideoDecoderAVCSecure.h | 2 |
2 files changed, 85 insertions, 39 deletions
diff --git a/videocodec/OMXVideoDecoderAVCSecure.cpp b/videocodec/OMXVideoDecoderAVCSecure.cpp index e3e0c3e..4f23287 100644 --- a/videocodec/OMXVideoDecoderAVCSecure.cpp +++ b/videocodec/OMXVideoDecoderAVCSecure.cpp @@ -22,6 +22,7 @@ #include <time.h> #include <signal.h> #include <pthread.h> + extern "C" { #include <sepdrm.h> } @@ -35,6 +36,7 @@ static const char* AVC_SECURE_MIME_TYPE = "video/avc-secure"; #define IMR_BUFFER_SIZE (8 * 1024 * 1024) #define WV_SESSION_ID 0x00000011 #define NALU_BUFFER_SIZE 8192 +#define FLUSH_WAIT_INTERVAL (30 * 1000) //30 ms #pragma pack(push, 1) @@ -48,7 +50,8 @@ struct IMRDataBuffer { OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure() - : mKeepAliveTimer(0) { + : mKeepAliveTimer(0), + mSessionPaused(false) { LOGV("OMXVideoDecoderAVCSecure is constructed."); mVideoDecoder = createVideoDecoder(AVC_SECURE_MIME_TYPE); if (!mVideoDecoder) { @@ -56,6 +59,7 @@ OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure() } // Override default native buffer count defined in the base class mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT; + BuildHandlerList(); } @@ -90,43 +94,15 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitInputPortFormatSpecific(OMX_PARAM_PO } OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorInit(void) { - int ret; - struct sigevent sev; - memset(&sev, 0, sizeof(sev)); - sev.sigev_notify = SIGEV_THREAD; - sev.sigev_value.sival_ptr = this; - sev.sigev_notify_function = KeepAliveTimerCallback; - - ret = timer_create(CLOCK_REALTIME, &sev, &mKeepAliveTimer); - if (ret != 0) { - LOGE("Failed to create timer."); - } - - struct itimerspec its; - its.it_value.tv_sec = -1; // never expire - its.it_value.tv_nsec = 0; - its.it_interval.tv_sec = KEEP_ALIVE_INTERVAL; - its.it_interval.tv_nsec = 0; - - ret = timer_settime(mKeepAliveTimer, TIMER_ABSTIME, &its, NULL); - if (ret != 0) { - LOGE("Failed to set timer."); - } - sec_result_t sepres = Drm_Library_Init(); if (sepres != 0) { LOGE("Drm_Library_Init returned %08X", (unsigned int)sepres); } - + mSessionPaused = false; return OMXVideoDecoderBase::ProcessorInit(); } OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorDeinit(void) { - if (mKeepAliveTimer != 0) { - timer_delete(mKeepAliveTimer); - mKeepAliveTimer = 0; - } - // Session should be torn down in ProcessorStop, delayed to ProcessorDeinit // to allow remaining frames completely rendered. sec_result_t sepres = Drm_DestroySession(WV_SESSION_ID); @@ -143,20 +119,49 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorStart(void) { uint32_t sessionID; sec_result_t sepres = Drm_WV_CreateSession(&imrOffset, &imrBufferSize, &sessionID); if (sepres != 0) { - LOGE("Drm_WV_CreateSession failed. Result = %#x", sepres); - // TODO: return OMX_ErrorHardware - // Ignored temporarily, as this component can be used to play protected video using SW implementation. + LOGW("Drm_WV_CreateSession failed. Result = %#x", sepres); + // Returning error will cause OMX client to crash. //return OMX_ErrorHardware; } if (sessionID != WV_SESSION_ID) { LOGE("Invalid session ID %#x created", sessionID); + //return OMX_ErrorHardware; } LOGI("Drm_WV_CreateSession: IMR Offset = %d, IMR size = %#x", imrOffset, imrBufferSize); + int ret; + struct sigevent sev; + memset(&sev, 0, sizeof(sev)); + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_value.sival_ptr = this; + sev.sigev_notify_function = KeepAliveTimerCallback; + + ret = timer_create(CLOCK_REALTIME, &sev, &mKeepAliveTimer); + if (ret != 0) { + LOGE("Failed to create timer."); + } + + struct itimerspec its; + its.it_value.tv_sec = -1; // never expire + its.it_value.tv_nsec = 0; + its.it_interval.tv_sec = KEEP_ALIVE_INTERVAL; + its.it_interval.tv_nsec = 0; + + ret = timer_settime(mKeepAliveTimer, TIMER_ABSTIME, &its, NULL); + if (ret != 0) { + LOGE("Failed to set timer."); + } + + mSessionPaused = false; return OMXVideoDecoderBase::ProcessorStart(); } OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorStop(void) { + if (mKeepAliveTimer != 0) { + timer_delete(mKeepAliveTimer); + mKeepAliveTimer = 0; + } + return OMXVideoDecoderBase::ProcessorStop(); } @@ -169,7 +174,38 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorProcess( OMX_BUFFERHEADERTYPE ***pBuffers, buffer_retain_t *retains, OMX_U32 numberBuffers) { - return OMXVideoDecoderBase::ProcessorProcess(pBuffers, retains, numberBuffers); + + OMX_BUFFERHEADERTYPE *pInput = *pBuffers[INPORT_INDEX]; + IMRDataBuffer *imrBuffer = (IMRDataBuffer *)pInput->pBuffer; + if (imrBuffer->size == 0) { + // error occurs during decryption. + LOGW("size of returned IMR buffer is 0, decryption fails."); + mVideoDecoder->flush(); + usleep(FLUSH_WAIT_INTERVAL); + OMX_BUFFERHEADERTYPE *pOutput = *pBuffers[OUTPORT_INDEX]; + pOutput->nFilledLen = 0; + // reset IMR buffer size + imrBuffer->size = IMR_BUFFER_SIZE; + this->ports[INPORT_INDEX]->FlushPort(); + this->ports[OUTPORT_INDEX]->FlushPort(); + return OMX_ErrorNone; + } + + OMX_ERRORTYPE ret; + ret = OMXVideoDecoderBase::ProcessorProcess(pBuffers, retains, numberBuffers); + if (ret != OMX_ErrorNone) { + return ret; + } + + if (mSessionPaused && (retains[OUTPORT_INDEX] == BUFFER_RETAIN_GETAGAIN)) { + retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; + OMX_BUFFERHEADERTYPE *pOutput = *pBuffers[OUTPORT_INDEX]; + pOutput->nFilledLen = 0; + this->ports[INPORT_INDEX]->FlushPort(); + this->ports[OUTPORT_INDEX]->FlushPort(); + } + + return ret; } OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorPause(void) { @@ -223,13 +259,20 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE } else { imrBuffer->size = NALU_BUFFER_SIZE; sec_result_t res = Drm_WV_ReturnNALUHeaders(WV_SESSION_ID, imrBuffer->offset, buffer->nFilledLen, imrBuffer->data, (uint32_t *)&(imrBuffer->size)); - if (res != 0) { + if (res == DRM_FAIL_FW_SESSION) { + LOGW("Drm_WV_ReturnNALUHeaders failed. Session is disabled."); + mSessionPaused = true; + ret = OMX_ErrorNotReady; + } else if (res != 0) { + mSessionPaused = false; LOGE("Drm_WV_ReturnNALUHeaders failed. Error = %#x, IMR offset = %d, len = %d", res, imrBuffer->offset, buffer->nFilledLen); - return OMX_ErrorHardware; + ret = OMX_ErrorHardware; + } else { + mSessionPaused = false; + p->data = imrBuffer->data; + p->size = imrBuffer->size; + p->flag |= IS_SECURE_DATA; } - p->data = imrBuffer->data; - p->size = imrBuffer->size; - p->flag |= IS_SECURE_DATA; } //reset IMR size @@ -366,4 +409,5 @@ void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback() { Drm_KeepAlive(WV_SESSION_ID, &timeout); } + DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC.secure", "video_decoder.avc", OMXVideoDecoderAVCSecure); diff --git a/videocodec/OMXVideoDecoderAVCSecure.h b/videocodec/OMXVideoDecoderAVCSecure.h index 4fdfc10..7f9fc10 100644 --- a/videocodec/OMXVideoDecoderAVCSecure.h +++ b/videocodec/OMXVideoDecoderAVCSecure.h @@ -76,6 +76,8 @@ private: } mIMRSlot[INPORT_ACTUAL_BUFFER_COUNT]; timer_t mKeepAliveTimer; + + bool mSessionPaused; }; #endif /* OMX_VIDEO_DECODER_AVC_SECURE_H_ */ |
