aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuneel Kandru <suneel.kandru@intel.com>2013-04-26 14:45:07 -0700
committerPatrick Tjin <pattjin@google.com>2014-07-21 22:02:51 -0700
commit1a9d0e266f950857761bd70e1a58f06055d2e855 (patch)
tree388d2d757eca5cf4958a6e8579687b32d656344d
parent828a2823300f3e2c8b95a3d00957145942572288 (diff)
downloadandroid_hardware_intel_common_omx-components-1a9d0e266f950857761bd70e1a58f06055d2e855.tar.gz
android_hardware_intel_common_omx-components-1a9d0e266f950857761bd70e1a58f06055d2e855.tar.bz2
android_hardware_intel_common_omx-components-1a9d0e266f950857761bd70e1a58f06055d2e855.zip
Enable WIDEVINE for Merrifield platform.
BZ: 103732 Created New OMXVideoDecoderAVCSecure source and header file for Merrifield platform. Moved clovertrail files to ctp folder. Change-Id: Ibd34eff55b071171b63fabd3bced0cb531fb70b7 Signed-off-by: Suneel Kandru <suneel.kandru@intel.com> Reviewed-on: http://android.intel.com:8080/105180 Reviewed-by: cactus <cactus@intel.com> Reviewed-by: Poornachandran, Rajesh <rajesh.poornachandran@intel.com> Tested-by: Post, DavidX J <davidx.j.post@intel.com> Reviewed-by: buildbot <buildbot@intel.com> Tested-by: buildbot <buildbot@intel.com>
-rwxr-xr-x[-rw-r--r--]videocodec/Android.mk111
-rw-r--r--videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp (renamed from videocodec/OMXVideoDecoderAVCSecure.cpp)0
-rw-r--r--videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h (renamed from videocodec/OMXVideoDecoderAVCSecure.h)0
-rw-r--r--videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.cpp450
-rw-r--r--videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.h85
-rw-r--r--videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.cpp466
-rw-r--r--videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.h85
7 files changed, 1155 insertions, 42 deletions
diff --git a/videocodec/Android.mk b/videocodec/Android.mk
index 383cd9d..fcc4a1d 100644..100755
--- a/videocodec/Android.mk
+++ b/videocodec/Android.mk
@@ -168,7 +168,6 @@ endif
include $(BUILD_SHARED_LIBRARY)
-
include $(CLEAR_VARS)
LOCAL_CPPFLAGS :=
@@ -213,6 +212,75 @@ LOCAL_CPPFLAGS :=
LOCAL_LDFLAGS :=
LOCAL_SHARED_LIBRARIES := \
+ libwrs_omxil_common \
+ libdrm \
+ libva_videodecoder \
+ liblog \
+ libva \
+ libva-android
+
+LOCAL_C_INCLUDES := \
+ $(TARGET_OUT_HEADERS)/wrs_omxil_core \
+ $(TARGET_OUT_HEADERS)/khronos/openmax \
+ $(PV_INCLUDES) \
+ $(TARGET_OUT_HEADERS)/libmix_videodecoder \
+ $(TARGET_OUT_HEADERS)/libva \
+ $(TARGET_OUT_HEADERS)/drm \
+ $(TARGET_OUT_HEADERS)/libdrm \
+ $(TARGET_OUT_HEADERS)/libttm \
+ $(TOP)/frameworks/native/include/media/hardware \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/$(KERNEL_SRC_DIR)/drivers/staging/intel_media/common
+
+LOCAL_SRC_FILES := \
+ OMXComponentCodecBase.cpp\
+ OMXVideoDecoderBase.cpp
+
+ifeq ($(TARGET_BOARD_PLATFORM),clovertrail)
+LOCAL_SHARED_LIBRARIES += libsepdrm
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/libsepdrm
+
+LOCAL_SRC_FILES += securevideo/ctp/OMXVideoDecoderAVCSecure.cpp
+
+LOCAL_CFLAGS += -DVED_TILING
+endif
+
+ifeq ($(TARGET_BOARD_PLATFORM),merrifield)
+LOCAL_SHARED_LIBRARIES += \
+ libsepdrm_cc54 \
+ libdx_cc7
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/hardware/intel/cc54/libsepdrm/inc \
+ $(TOP)/hardware/intel/cc54/libsepdrm/shared/inc
+
+LOCAL_SRC_FILES += securevideo/merrifield/OMXVideoDecoderAVCSecure.cpp
+endif
+
+ifeq ($(TARGET_BOARD_PLATFORM),baytrail)
+LOCAL_SHARED_LIBRARIES += libsepdrm
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/libsepdrm
+
+LOCAL_SRC_FILES += securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp
+
+LOCAL_CFLAGS += -DVED_TILING
+endif
+
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libOMXVideoDecoderAVCSecure
+
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_CPPFLAGS :=
+LOCAL_LDFLAGS :=
+
+LOCAL_SHARED_LIBRARIES := \
libwrs_omxil_common \
liblog \
libva_videoencoder \
@@ -417,45 +485,4 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libOMXVideoEncoderVP8
include $(BUILD_SHARED_LIBRARY)
-include $(CLEAR_VARS)
-
-LOCAL_CPPFLAGS :=
-LOCAL_LDFLAGS :=
-
-LOCAL_SHARED_LIBRARIES := \
- libwrs_omxil_common \
- libdrm \
- libva_videodecoder \
- liblog \
- libva \
- libva-android \
- libsepdrm
-
-LOCAL_C_INCLUDES := \
- $(TARGET_OUT_HEADERS)/wrs_omxil_core \
- $(TARGET_OUT_HEADERS)/khronos/openmax \
- $(PV_INCLUDES) \
- $(TARGET_OUT_HEADERS)/libmix_videodecoder \
- $(TARGET_OUT_HEADERS)/libva \
- $(TARGET_OUT_HEADERS)/libsepdrm \
- $(TARGET_OUT_HEADERS)/drm \
- $(TARGET_OUT_HEADERS)/libdrm \
- $(TARGET_OUT_HEADERS)/libttm \
- $(TOP)/frameworks/native/include/media/hardware \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/$(KERNEL_SRC_DIR)/drivers/staging/intel_media/common
-
-LOCAL_SRC_FILES := \
- OMXComponentCodecBase.cpp\
- OMXVideoDecoderBase.cpp\
- OMXVideoDecoderAVCSecure.cpp
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libOMXVideoDecoderAVCSecure
-ifeq ($(TARGET_BOARD_PLATFORM),clovertrail)
-LOCAL_CFLAGS += -DVED_TILING
-endif
-
-include $(BUILD_SHARED_LIBRARY)
-
endif
diff --git a/videocodec/OMXVideoDecoderAVCSecure.cpp b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp
index 37ac5f4..37ac5f4 100644
--- a/videocodec/OMXVideoDecoderAVCSecure.cpp
+++ b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp
diff --git a/videocodec/OMXVideoDecoderAVCSecure.h b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h
index 310e9ba..310e9ba 100644
--- a/videocodec/OMXVideoDecoderAVCSecure.h
+++ b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h
diff --git a/videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.cpp b/videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..37ac5f4
--- /dev/null
+++ b/videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.cpp
@@ -0,0 +1,450 @@
+/*
+* Copyright (c) 2009-2012 Intel Corporation. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXVideoDecoder"
+#include <utils/Log.h>
+#include "OMXVideoDecoderAVCSecure.h"
+#include <time.h>
+#include <signal.h>
+#include <pthread.h>
+
+extern "C" {
+#include <sepdrm.h>
+#include <fcntl.h>
+#include "psb_drm.h"
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+}
+
+// Be sure to have an equal string in VideoDecoderHost.cpp (libmix)
+static const char* AVC_MIME_TYPE = "video/avc";
+static const char* AVC_SECURE_MIME_TYPE = "video/avc-secure";
+
+#define IMR_INITIAL_OFFSET 0 //1024
+#define IMR_BUFFER_SIZE (8 * 1024 * 1024)
+#define KEEP_ALIVE_INTERVAL 5 // seconds
+#define DRM_KEEP_ALIVE_TIMER 1000000
+#define WV_SESSION_ID 0x00000011
+#define NALU_BUFFER_SIZE 8192
+#define FLUSH_WAIT_INTERVAL (30 * 1000) //30 ms
+
+
+#pragma pack(push, 1)
+struct IMRDataBuffer {
+ uint32_t offset;
+ uint32_t size;
+ uint8_t *data;
+ uint8_t clear; // 0 when IMR offset is valid, 1 when data is valid
+};
+#pragma pack(pop)
+
+OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure()
+ : mKeepAliveTimer(0),
+ mSessionPaused(false),
+ mDrmDevFd(-1) {
+ LOGV("OMXVideoDecoderAVCSecure is constructed.");
+ mVideoDecoder = createVideoDecoder(AVC_SECURE_MIME_TYPE);
+ if (!mVideoDecoder) {
+ LOGE("createVideoDecoder failed for \"%s\"", AVC_SECURE_MIME_TYPE);
+ }
+ // Override default native buffer count defined in the base class
+ mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
+
+ BuildHandlerList();
+
+ mDrmDevFd = open("/dev/card0", O_RDWR, 0);
+ if (mDrmDevFd < 0) {
+ LOGE("Failed to open drm device.");
+ }
+}
+
+OMXVideoDecoderAVCSecure::~OMXVideoDecoderAVCSecure() {
+ LOGV("OMXVideoDecoderAVCSecure is destructed.");
+
+ if (mDrmDevFd) {
+ close(mDrmDevFd);
+ mDrmDevFd = 0;
+ }
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) {
+ // OMX_PARAM_PORTDEFINITIONTYPE
+ paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
+ paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
+ paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
+ paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE;
+ paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+
+ // OMX_VIDEO_PARAM_AVCTYPE
+ memset(&mParamAvc, 0, sizeof(mParamAvc));
+ SetTypeHeader(&mParamAvc, sizeof(mParamAvc));
+ mParamAvc.nPortIndex = INPORT_INDEX;
+ // TODO: check eProfile/eLevel
+ mParamAvc.eProfile = OMX_VIDEO_AVCProfileHigh; //OMX_VIDEO_AVCProfileBaseline;
+ mParamAvc.eLevel = OMX_VIDEO_AVCLevel41; //OMX_VIDEO_AVCLevel1;
+
+ this->ports[INPORT_INDEX]->SetMemAllocator(MemAllocIMR, MemFreeIMR, this);
+
+ for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
+ mIMRSlot[i].offset = IMR_INITIAL_OFFSET + i * INPORT_BUFFER_SIZE;
+ mIMRSlot[i].owner = NULL;
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorInit(void) {
+ 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) {
+ // Session should be torn down in ProcessorStop, delayed to ProcessorDeinit
+ // to allow remaining frames completely rendered.
+ LOGI("Calling Drm_DestroySession.");
+ sec_result_t sepres = Drm_DestroySession(WV_SESSION_ID);
+ if (sepres != 0) {
+ LOGW("Drm_DestroySession returns %#x", sepres);
+ }
+ EnableIEDSession(false);
+
+ return OMXVideoDecoderBase::ProcessorDeinit();
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorStart(void) {
+ uint32_t imrOffset = 0;
+ uint32_t imrBufferSize = IMR_BUFFER_SIZE;
+ uint32_t sessionID;
+
+ EnableIEDSession(true);
+ sec_result_t sepres = Drm_WV_CreateSession(&imrOffset, &imrBufferSize, &sessionID);
+ if (sepres != 0) {
+ 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);
+ if (imrBufferSize != IMR_BUFFER_SIZE) {
+ LOGE("Mismatch in IMR size: Requested: %#x Obtained: %#x", IMR_BUFFER_SIZE, imrBufferSize);
+ }
+ drmCommandNone(mDrmDevFd, DRM_PSB_HDCP_DISPLAY_IED_OFF);
+
+
+ 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.");
+ } else {
+ 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();
+}
+
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorFlush(OMX_U32 portIndex) {
+ return OMXVideoDecoderBase::ProcessorFlush(portIndex);
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorProcess(
+ OMX_BUFFERHEADERTYPE ***pBuffers,
+ buffer_retain_t *retains,
+ OMX_U32 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 = INPORT_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) {
+ LOGE("OMXVideoDecoderBase::ProcessorProcess failed. Result: %#x", ret);
+ 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) {
+ sec_result_t sepres = Drm_Playback_Pause(WV_SESSION_ID);
+ if (sepres != 0) {
+ LOGE("Drm_Playback_Pause failed. Result = %#x", sepres);
+ }
+ return OMXVideoDecoderBase::ProcessorPause();
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorResume(void) {
+ sec_result_t sepres = Drm_Playback_Resume(WV_SESSION_ID);
+ if (sepres != 0) {
+ LOGE("Drm_Playback_Resume failed. Result = %#x", sepres);
+ }
+ return OMXVideoDecoderBase::ProcessorResume();
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareConfigBuffer(VideoConfigBuffer *p) {
+ OMX_ERRORTYPE ret;
+ ret = OMXVideoDecoderBase::PrepareConfigBuffer(p);
+ CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareConfigBuffer");
+ p->flag |= WANT_SURFACE_PROTECTION;
+ return ret;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
+ OMX_ERRORTYPE ret;
+ ret = OMXVideoDecoderBase::PrepareDecodeBuffer(buffer, retain, p);
+ CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareDecodeBuffer");
+
+ if (buffer->nFilledLen == 0) {
+ return OMX_ErrorNone;
+ }
+ // OMX_BUFFERFLAG_CODECCONFIG is an optional flag
+ // if flag is set, buffer will only contain codec data.
+ if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ LOGV("Received AVC codec data.");
+ return ret;
+ }
+ p->flag |= HAS_COMPLETE_FRAME;
+
+ if (buffer->nOffset != 0) {
+ LOGW("buffer offset %d is not zero!!!", buffer->nOffset);
+ }
+
+ IMRDataBuffer *imrBuffer = (IMRDataBuffer *)buffer->pBuffer;
+ if (imrBuffer->clear) {
+ p->data = imrBuffer->data + buffer->nOffset;
+ p->size = buffer->nFilledLen;
+ } 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 == 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);
+ ret = OMX_ErrorHardware;
+ } else {
+ mSessionPaused = false;
+ p->data = imrBuffer->data;
+ p->size = imrBuffer->size;
+ p->flag |= IS_SECURE_DATA;
+ }
+ }
+
+ //reset IMR size
+ imrBuffer->size = NALU_BUFFER_SIZE;
+ return ret;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::BuildHandlerList(void) {
+ OMXVideoDecoderBase::BuildHandlerList();
+ AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc);
+ AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoAVCProfileLevel, SetParamVideoAVCProfileLevel);
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetParamVideoAvc(OMX_PTR pStructure) {
+ OMX_ERRORTYPE ret;
+ OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
+ CHECK_TYPE_HEADER(p);
+ CHECK_PORT_INDEX(p, INPORT_INDEX);
+
+ memcpy(p, &mParamAvc, sizeof(*p));
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAvc(OMX_PTR pStructure) {
+ OMX_ERRORTYPE ret;
+ OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
+ CHECK_TYPE_HEADER(p);
+ CHECK_PORT_INDEX(p, INPORT_INDEX);
+ CHECK_SET_PARAM_STATE();
+
+ // TODO: do we need to check if port is enabled?
+ // TODO: see SetPortAvcParam implementation - Can we make simple copy????
+ memcpy(&mParamAvc, p, sizeof(mParamAvc));
+ return OMX_ErrorNone;
+}
+
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetParamVideoAVCProfileLevel(OMX_PTR pStructure) {
+ OMX_ERRORTYPE ret;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure;
+ CHECK_TYPE_HEADER(p);
+ CHECK_PORT_INDEX(p, INPORT_INDEX);
+ CHECK_ENUMERATION_RANGE(p->nProfileIndex,1);
+
+ p->eProfile = mParamAvc.eProfile;
+ p->eLevel = mParamAvc.eLevel;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAVCProfileLevel(OMX_PTR pStructure) {
+ LOGW("SetParamVideoAVCProfileLevel is not supported.");
+ return OMX_ErrorUnsupportedSetting;
+}
+
+OMX_U8* OMXVideoDecoderAVCSecure::MemAllocIMR(OMX_U32 nSizeBytes, OMX_PTR pUserData) {
+ OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData;
+ if (p) {
+ return p->MemAllocIMR(nSizeBytes);
+ }
+ LOGE("NULL pUserData.");
+ return NULL;
+}
+
+void OMXVideoDecoderAVCSecure::MemFreeIMR(OMX_U8 *pBuffer, OMX_PTR pUserData) {
+ OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData;
+ if (p) {
+ p->MemFreeIMR(pBuffer);
+ return;
+ }
+ LOGE("NULL pUserData.");
+}
+
+OMX_U8* OMXVideoDecoderAVCSecure::MemAllocIMR(OMX_U32 nSizeBytes) {
+ if (nSizeBytes > INPORT_BUFFER_SIZE) {
+ LOGE("Invalid size (%lu) of memory to allocate.", nSizeBytes);
+ return NULL;
+ }
+ LOGW_IF(nSizeBytes != INPORT_BUFFER_SIZE, "Size of memory to allocate is %lu", nSizeBytes);
+ for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
+ if (mIMRSlot[i].owner == NULL) {
+ IMRDataBuffer *pBuffer = new IMRDataBuffer;
+ if (pBuffer == NULL) {
+ LOGE("Failed to allocate memory.");
+ return NULL;
+ }
+
+ pBuffer->data = new uint8_t [INPORT_BUFFER_SIZE];
+ if (pBuffer->data == NULL) {
+ delete pBuffer;
+ LOGE("Failed to allocate memory, size to allocate %d.", INPORT_BUFFER_SIZE);
+ return NULL;
+ }
+
+ pBuffer->offset = mIMRSlot[i].offset;
+ pBuffer->size = INPORT_BUFFER_SIZE;
+ mIMRSlot[i].owner = (OMX_U8 *)pBuffer;
+
+ LOGV("Allocating buffer = %#x, IMR offset = %#x, data = %#x", (uint32_t)pBuffer, mIMRSlot[i].offset, (uint32_t)pBuffer->data);
+ return (OMX_U8 *) pBuffer;
+ }
+ }
+ LOGE("IMR slot is not available.");
+ return NULL;
+}
+
+void OMXVideoDecoderAVCSecure::MemFreeIMR(OMX_U8 *pBuffer) {
+ IMRDataBuffer *p = (IMRDataBuffer*) pBuffer;
+ if (p == NULL) {
+ return;
+ }
+ for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
+ if (pBuffer == mIMRSlot[i].owner) {
+ LOGV("Freeing IMR offset = %d, data = %#x", mIMRSlot[i].offset, (uint32_t)p->data);
+ delete [] p->data;
+ delete p;
+ mIMRSlot[i].owner = NULL;
+ return;
+ }
+ }
+ LOGE("Invalid buffer %#x to de-allocate", (uint32_t)pBuffer);
+}
+
+void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) {
+ OMXVideoDecoderAVCSecure *p = (OMXVideoDecoderAVCSecure *)v.sival_ptr;
+ if (p) {
+ p->KeepAliveTimerCallback();
+ }
+}
+
+void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback() {
+ uint32_t timeout = DRM_KEEP_ALIVE_TIMER;
+ sec_result_t sepres = Drm_KeepAlive(WV_SESSION_ID, &timeout);
+ if (sepres != 0) {
+ LOGE("Drm_KeepAlive failed. Result = %#x", sepres);
+ }
+}
+
+
+bool OMXVideoDecoderAVCSecure::EnableIEDSession(bool enable)
+{
+ if (mDrmDevFd < 0) {
+ return false;
+ }
+ int request = enable ? DRM_PSB_ENABLE_IED_SESSION : DRM_PSB_DISABLE_IED_SESSION;
+ int ret = drmCommandNone(mDrmDevFd, request);
+ return ret == 0;
+}
+
+DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC.secure", "video_decoder.avc", OMXVideoDecoderAVCSecure);
diff --git a/videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.h b/videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.h
new file mode 100644
index 0000000..310e9ba
--- /dev/null
+++ b/videocodec/securevideo/ctp/OMXVideoDecoderAVCSecure.h
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2009-2012 Intel Corporation. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef OMX_VIDEO_DECODER_AVC_SECURE_H_
+#define OMX_VIDEO_DECODER_AVC_SECURE_H_
+
+
+#include "OMXVideoDecoderBase.h"
+
+class OMXVideoDecoderAVCSecure : public OMXVideoDecoderBase {
+public:
+ OMXVideoDecoderAVCSecure();
+ virtual ~OMXVideoDecoderAVCSecure();
+
+protected:
+ virtual OMX_ERRORTYPE InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput);
+ virtual OMX_ERRORTYPE ProcessorInit(void);
+ virtual OMX_ERRORTYPE ProcessorDeinit(void);
+ virtual OMX_ERRORTYPE ProcessorStart(void);
+ virtual OMX_ERRORTYPE ProcessorStop(void);
+ virtual OMX_ERRORTYPE ProcessorPause(void);
+ virtual OMX_ERRORTYPE ProcessorResume(void);
+ virtual OMX_ERRORTYPE ProcessorFlush(OMX_U32 portIndex);
+ virtual OMX_ERRORTYPE ProcessorProcess(
+ OMX_BUFFERHEADERTYPE ***pBuffers,
+ buffer_retain_t *retains,
+ OMX_U32 numberBuffers);
+
+ virtual OMX_ERRORTYPE PrepareConfigBuffer(VideoConfigBuffer *p);
+ virtual OMX_ERRORTYPE PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p);
+
+ virtual OMX_ERRORTYPE BuildHandlerList(void);
+ DECLARE_HANDLER(OMXVideoDecoderAVCSecure, ParamVideoAvc);
+ DECLARE_HANDLER(OMXVideoDecoderAVCSecure, ParamVideoAVCProfileLevel);
+
+private:
+ static OMX_U8* MemAllocIMR(OMX_U32 nSizeBytes, OMX_PTR pUserData);
+ static void MemFreeIMR(OMX_U8 *pBuffer, OMX_PTR pUserData);
+ OMX_U8* MemAllocIMR(OMX_U32 nSizeBytes);
+ void MemFreeIMR(OMX_U8 *pBuffer);
+ static void KeepAliveTimerCallback(sigval v);
+ void KeepAliveTimerCallback();
+ bool EnableIEDSession(bool enable);
+
+private:
+ enum {
+ // OMX_PARAM_PORTDEFINITIONTYPE
+ INPORT_MIN_BUFFER_COUNT = 1,
+ INPORT_ACTUAL_BUFFER_COUNT = 5,
+ INPORT_BUFFER_SIZE = 1382400,
+
+ // for OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS
+ // default number of reference frame
+ NUM_REFERENCE_FRAME = 4,
+
+ OUTPORT_NATIVE_BUFFER_COUNT = 15,
+ };
+
+ OMX_VIDEO_PARAM_AVCTYPE mParamAvc;
+
+ struct IMRSlot {
+ uint32_t offset;
+ uint8_t *owner; // pointer to OMX buffer that owns this slot
+ } mIMRSlot[INPORT_ACTUAL_BUFFER_COUNT];
+
+ timer_t mKeepAliveTimer;
+
+ bool mSessionPaused;
+ int mDrmDevFd;
+};
+
+#endif /* OMX_VIDEO_DECODER_AVC_SECURE_H_ */
diff --git a/videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.cpp b/videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..82ae149
--- /dev/null
+++ b/videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.cpp
@@ -0,0 +1,466 @@
+/*
+* Copyright (c) 2009-2012 Intel Corporation. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXVideoDecoder"
+#include <utils/Log.h>
+#include "OMXVideoDecoderAVCSecure.h"
+#include <time.h>
+#include <signal.h>
+#include <pthread.h>
+
+extern "C" {
+#include <sepdrm.h>
+#include <fcntl.h>
+#include "psb_drm.h"
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+}
+
+// Be sure to have an equal string in VideoDecoderHost.cpp (libmix)
+static const char* AVC_MIME_TYPE = "video/avc";
+static const char* AVC_SECURE_MIME_TYPE = "video/avc-secure";
+
+#define IMR_INITIAL_OFFSET 0 //1024
+#define IMR_BUFFER_SIZE (8 * 1024 * 1024)
+#define KEEP_ALIVE_INTERVAL 5 // seconds
+#define DRM_KEEP_ALIVE_TIMER 1000000
+#define WV_SESSION_ID 0x00000011
+#define NALU_BUFFER_SIZE 8192
+#define FLUSH_WAIT_INTERVAL (30 * 1000) //30 ms
+
+
+#pragma pack(push, 1)
+struct IMRDataBuffer {
+ uint32_t offset;
+ uint32_t size;
+ uint8_t *data;
+ uint8_t clear; // 0 when IMR offset is valid, 1 when data is valid
+};
+#pragma pack(pop)
+
+OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure()
+ : mKeepAliveTimer(0),
+ mSessionPaused(false),
+ mDrmDevFd(-1) {
+ LOGV("OMXVideoDecoderAVCSecure is constructed.");
+ mVideoDecoder = createVideoDecoder(AVC_SECURE_MIME_TYPE);
+ if (!mVideoDecoder) {
+ LOGE("createVideoDecoder failed for \"%s\"", AVC_SECURE_MIME_TYPE);
+ }
+ // Override default native buffer count defined in the base class
+ mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
+
+ BuildHandlerList();
+
+ mDrmDevFd = open("/dev/card0", O_RDWR, 0);
+ if (mDrmDevFd < 0) {
+ LOGE("Failed to open drm device.");
+ }
+}
+
+OMXVideoDecoderAVCSecure::~OMXVideoDecoderAVCSecure() {
+ LOGV("OMXVideoDecoderAVCSecure is destructed.");
+
+ if (mDrmDevFd) {
+ close(mDrmDevFd);
+ mDrmDevFd = 0;
+ }
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) {
+ // OMX_PARAM_PORTDEFINITIONTYPE
+ paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
+ paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
+ paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
+ paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE;
+ paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+
+ // OMX_VIDEO_PARAM_AVCTYPE
+ memset(&mParamAvc, 0, sizeof(mParamAvc));
+ SetTypeHeader(&mParamAvc, sizeof(mParamAvc));
+ mParamAvc.nPortIndex = INPORT_INDEX;
+ // TODO: check eProfile/eLevel
+ mParamAvc.eProfile = OMX_VIDEO_AVCProfileHigh; //OMX_VIDEO_AVCProfileBaseline;
+ mParamAvc.eLevel = OMX_VIDEO_AVCLevel41; //OMX_VIDEO_AVCLevel1;
+
+ this->ports[INPORT_INDEX]->SetMemAllocator(MemAllocIMR, MemFreeIMR, this);
+
+ for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
+ mIMRSlot[i].offset = IMR_INITIAL_OFFSET + i * INPORT_BUFFER_SIZE;
+ mIMRSlot[i].owner = NULL;
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorInit(void) {
+ mSessionPaused = false;
+ return OMXVideoDecoderBase::ProcessorInit();
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorDeinit(void) {
+ // Session should be torn down in ProcessorStop, delayed to ProcessorDeinit
+ // to allow remaining frames completely rendered.
+ LOGI("Calling Drm_DestroySession.");
+ uint32_t sepres = drm_destroy_session(WV_SESSION_ID);
+ if (sepres != 0) {
+ LOGW("Drm_DestroySession returns %#x", sepres);
+ }
+ EnableIEDSession(false);
+
+ return OMXVideoDecoderBase::ProcessorDeinit();
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorStart(void) {
+ uint32_t imrOffset = 0;
+ uint32_t imrBufferSize = IMR_BUFFER_SIZE;
+ uint32_t sessionID;
+
+ EnableIEDSession(true);
+ uint32_t sepres = drm_wv_create_session( &sessionID);
+ if (sepres != 0) {
+ 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_create_session: sessionID = %#x", sessionID);
+
+ drmCommandNone(mDrmDevFd, DRM_PSB_HDCP_DISPLAY_IED_OFF);
+
+ 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.");
+ } else {
+ 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();
+}
+
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorFlush(OMX_U32 portIndex) {
+ return OMXVideoDecoderBase::ProcessorFlush(portIndex);
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorProcess(
+ OMX_BUFFERHEADERTYPE ***pBuffers,
+ buffer_retain_t *retains,
+ OMX_U32 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 = INPORT_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) {
+ LOGE("OMXVideoDecoderBase::ProcessorProcess failed. Result: %#x", ret);
+ 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) {
+#if 0
+ uint32_t sepres = Drm_Playback_Pause(WV_SESSION_ID);
+ if (sepres != 0) {
+ LOGE("Drm_Playback_Pause failed. Result = %#x", sepres);
+ }
+#endif
+ return OMXVideoDecoderBase::ProcessorPause();
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorResume(void) {
+#if 0
+ uint32_t sepres = Drm_Playback_Resume(WV_SESSION_ID);
+ if (sepres != 0) {
+ LOGE("Drm_Playback_Resume failed. Result = %#x", sepres);
+ }
+#endif
+ return OMXVideoDecoderBase::ProcessorResume();
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareConfigBuffer(VideoConfigBuffer *p) {
+ OMX_ERRORTYPE ret;
+ ret = OMXVideoDecoderBase::PrepareConfigBuffer(p);
+ CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareConfigBuffer");
+ p->flag |= WANT_SURFACE_PROTECTION;
+ return ret;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
+ OMX_ERRORTYPE ret;
+ ret = OMXVideoDecoderBase::PrepareDecodeBuffer(buffer, retain, p);
+ CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareDecodeBuffer");
+
+ if (buffer->nFilledLen == 0) {
+ return OMX_ErrorNone;
+ }
+ // OMX_BUFFERFLAG_CODECCONFIG is an optional flag
+ // if flag is set, buffer will only contain codec data.
+ if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ LOGV("Received AVC codec data.");
+ return ret;
+ }
+ p->flag |= HAS_COMPLETE_FRAME;
+
+ if (buffer->nOffset != 0) {
+ LOGW("buffer offset %d is not zero!!!", buffer->nOffset);
+ }
+
+ IMRDataBuffer *imrBuffer = (IMRDataBuffer *)buffer->pBuffer;
+ if (imrBuffer->clear) {
+ p->data = imrBuffer->data + buffer->nOffset;
+ p->size = buffer->nFilledLen;
+ } else {
+ imrBuffer->size = NALU_BUFFER_SIZE;
+ struct drm_wv_nalu_headers nalu_headers;
+ nalu_headers.p_enc_ciphertext = imrBuffer->data;
+
+ // TODO: NALU Buffer is supposed to be 4k but using 1k, fix it once chaabi fix is there
+
+ nalu_headers.hdrs_buf_len = 1024;
+ nalu_headers.frame_size = buffer->nFilledLen;
+ // Make sure that NALU header frame size is 16 bytes aligned
+ nalu_headers.frame_size = (nalu_headers.frame_size + 0xF) & (~0xF);
+ // Use same video buffer to fill NALU headers returned by chaabi,
+ // Adding 4 because the first 4 bytes after databuffer will be used to store length of NALU headers
+ nalu_headers.p_hdrs_buf = (uint8_t *)(imrBuffer->data + nalu_headers.frame_size + 4);
+ nalu_headers.parse_size = buffer->nFilledLen;
+
+ uint32_t res = drm_wv_return_naluheaders(WV_SESSION_ID, &nalu_headers);
+ if (res == DRM_FAIL_FW_SESSION || !nalu_headers.hdrs_buf_len) {
+ 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, frame_size: %d, len = %d", res, nalu_headers.frame_size, buffer->nFilledLen);
+ ret = OMX_ErrorHardware;
+ } else {
+ mSessionPaused = false;
+ LOGE("Drm_WV_ReturnNALUHeaders Succeeded. ret = %#x, NALU HDR Len: %d, Input frame_size: %#x ", res, nalu_headers.hdrs_buf_len, nalu_headers.frame_size);
+ // NALU headers are appended to encrypted video bitstream
+ // |...encrypted video bitstream (16 bytes aligned)...| 4 bytes of header size |...NALU headers..|
+ uint32_t *ptr = (uint32_t*)(imrBuffer->data + nalu_headers.frame_size);
+ *ptr = nalu_headers.hdrs_buf_len;
+ p->data = imrBuffer->data;
+ p->size = nalu_headers.frame_size;
+ p->flag |= IS_SECURE_DATA;
+ }
+ }
+
+ // reset IMR size
+ imrBuffer->size = NALU_BUFFER_SIZE;
+ return ret;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::BuildHandlerList(void) {
+ OMXVideoDecoderBase::BuildHandlerList();
+ AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc);
+ AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoAVCProfileLevel, SetParamVideoAVCProfileLevel);
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetParamVideoAvc(OMX_PTR pStructure) {
+ OMX_ERRORTYPE ret;
+ OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
+ CHECK_TYPE_HEADER(p);
+ CHECK_PORT_INDEX(p, INPORT_INDEX);
+
+ memcpy(p, &mParamAvc, sizeof(*p));
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAvc(OMX_PTR pStructure) {
+ OMX_ERRORTYPE ret;
+ OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
+ CHECK_TYPE_HEADER(p);
+ CHECK_PORT_INDEX(p, INPORT_INDEX);
+ CHECK_SET_PARAM_STATE();
+
+ // TODO: do we need to check if port is enabled?
+ // TODO: see SetPortAvcParam implementation - Can we make simple copy????
+ memcpy(&mParamAvc, p, sizeof(mParamAvc));
+ return OMX_ErrorNone;
+}
+
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetParamVideoAVCProfileLevel(OMX_PTR pStructure) {
+ OMX_ERRORTYPE ret;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure;
+ CHECK_TYPE_HEADER(p);
+ CHECK_PORT_INDEX(p, INPORT_INDEX);
+ CHECK_ENUMERATION_RANGE(p->nProfileIndex,1);
+
+ p->eProfile = mParamAvc.eProfile;
+ p->eLevel = mParamAvc.eLevel;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAVCProfileLevel(OMX_PTR pStructure) {
+ LOGW("SetParamVideoAVCProfileLevel is not supported.");
+ return OMX_ErrorUnsupportedSetting;
+}
+
+OMX_U8* OMXVideoDecoderAVCSecure::MemAllocIMR(OMX_U32 nSizeBytes, OMX_PTR pUserData) {
+ OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData;
+ if (p) {
+ return p->MemAllocIMR(nSizeBytes);
+ }
+ LOGE("NULL pUserData.");
+ return NULL;
+}
+
+void OMXVideoDecoderAVCSecure::MemFreeIMR(OMX_U8 *pBuffer, OMX_PTR pUserData) {
+ OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData;
+ if (p) {
+ p->MemFreeIMR(pBuffer);
+ return;
+ }
+ LOGE("NULL pUserData.");
+}
+
+OMX_U8* OMXVideoDecoderAVCSecure::MemAllocIMR(OMX_U32 nSizeBytes) {
+ if (nSizeBytes > INPORT_BUFFER_SIZE) {
+ LOGE("Invalid size (%lu) of memory to allocate.", nSizeBytes);
+ return NULL;
+ }
+ LOGW_IF(nSizeBytes != INPORT_BUFFER_SIZE, "Size of memory to allocate is %lu", nSizeBytes);
+ for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
+ if (mIMRSlot[i].owner == NULL) {
+ IMRDataBuffer *pBuffer = new IMRDataBuffer;
+ if (pBuffer == NULL) {
+ LOGE("Failed to allocate memory.");
+ return NULL;
+ }
+
+ pBuffer->data = new uint8_t [INPORT_BUFFER_SIZE];
+ if (pBuffer->data == NULL) {
+ delete pBuffer;
+ LOGE("Failed to allocate memory, size to allocate %d.", INPORT_BUFFER_SIZE);
+ return NULL;
+ }
+
+ pBuffer->offset = mIMRSlot[i].offset;
+ pBuffer->size = INPORT_BUFFER_SIZE;
+ mIMRSlot[i].owner = (OMX_U8 *)pBuffer;
+
+ LOGV("Allocating buffer = %#x, IMR offset = %#x, data = %#x", (uint32_t)pBuffer, mIMRSlot[i].offset, (uint32_t)pBuffer->data);
+ return (OMX_U8 *) pBuffer;
+ }
+ }
+ LOGE("IMR slot is not available.");
+ return NULL;
+}
+
+void OMXVideoDecoderAVCSecure::MemFreeIMR(OMX_U8 *pBuffer) {
+ IMRDataBuffer *p = (IMRDataBuffer*) pBuffer;
+ if (p == NULL) {
+ return;
+ }
+ for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
+ if (pBuffer == mIMRSlot[i].owner) {
+ LOGV("Freeing IMR offset = %d, data = %#x", mIMRSlot[i].offset, (uint32_t)p->data);
+ delete [] p->data;
+ delete p;
+ mIMRSlot[i].owner = NULL;
+ return;
+ }
+ }
+ LOGE("Invalid buffer %#x to de-allocate", (uint32_t)pBuffer);
+}
+
+void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) {
+ OMXVideoDecoderAVCSecure *p = (OMXVideoDecoderAVCSecure *)v.sival_ptr;
+ if (p) {
+ p->KeepAliveTimerCallback();
+ }
+}
+
+void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback() {
+ uint32_t timeout = DRM_KEEP_ALIVE_TIMER;
+ uint32_t sepres = drm_keep_alive(WV_SESSION_ID, &timeout);
+ if (sepres != 0) {
+ LOGE("Drm_KeepAlive failed. Result = %#x", sepres);
+ }
+}
+
+
+bool OMXVideoDecoderAVCSecure::EnableIEDSession(bool enable)
+{
+ if (mDrmDevFd < 0) {
+ return false;
+ }
+ int request = enable ? DRM_PSB_ENABLE_IED_SESSION : DRM_PSB_DISABLE_IED_SESSION;
+ int ret = drmCommandNone(mDrmDevFd, request);
+ return ret == 0;
+}
+
+DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC.secure", "video_decoder.avc", OMXVideoDecoderAVCSecure);
diff --git a/videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.h b/videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.h
new file mode 100644
index 0000000..310e9ba
--- /dev/null
+++ b/videocodec/securevideo/merrifield/OMXVideoDecoderAVCSecure.h
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2009-2012 Intel Corporation. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef OMX_VIDEO_DECODER_AVC_SECURE_H_
+#define OMX_VIDEO_DECODER_AVC_SECURE_H_
+
+
+#include "OMXVideoDecoderBase.h"
+
+class OMXVideoDecoderAVCSecure : public OMXVideoDecoderBase {
+public:
+ OMXVideoDecoderAVCSecure();
+ virtual ~OMXVideoDecoderAVCSecure();
+
+protected:
+ virtual OMX_ERRORTYPE InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput);
+ virtual OMX_ERRORTYPE ProcessorInit(void);
+ virtual OMX_ERRORTYPE ProcessorDeinit(void);
+ virtual OMX_ERRORTYPE ProcessorStart(void);
+ virtual OMX_ERRORTYPE ProcessorStop(void);
+ virtual OMX_ERRORTYPE ProcessorPause(void);
+ virtual OMX_ERRORTYPE ProcessorResume(void);
+ virtual OMX_ERRORTYPE ProcessorFlush(OMX_U32 portIndex);
+ virtual OMX_ERRORTYPE ProcessorProcess(
+ OMX_BUFFERHEADERTYPE ***pBuffers,
+ buffer_retain_t *retains,
+ OMX_U32 numberBuffers);
+
+ virtual OMX_ERRORTYPE PrepareConfigBuffer(VideoConfigBuffer *p);
+ virtual OMX_ERRORTYPE PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p);
+
+ virtual OMX_ERRORTYPE BuildHandlerList(void);
+ DECLARE_HANDLER(OMXVideoDecoderAVCSecure, ParamVideoAvc);
+ DECLARE_HANDLER(OMXVideoDecoderAVCSecure, ParamVideoAVCProfileLevel);
+
+private:
+ static OMX_U8* MemAllocIMR(OMX_U32 nSizeBytes, OMX_PTR pUserData);
+ static void MemFreeIMR(OMX_U8 *pBuffer, OMX_PTR pUserData);
+ OMX_U8* MemAllocIMR(OMX_U32 nSizeBytes);
+ void MemFreeIMR(OMX_U8 *pBuffer);
+ static void KeepAliveTimerCallback(sigval v);
+ void KeepAliveTimerCallback();
+ bool EnableIEDSession(bool enable);
+
+private:
+ enum {
+ // OMX_PARAM_PORTDEFINITIONTYPE
+ INPORT_MIN_BUFFER_COUNT = 1,
+ INPORT_ACTUAL_BUFFER_COUNT = 5,
+ INPORT_BUFFER_SIZE = 1382400,
+
+ // for OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS
+ // default number of reference frame
+ NUM_REFERENCE_FRAME = 4,
+
+ OUTPORT_NATIVE_BUFFER_COUNT = 15,
+ };
+
+ OMX_VIDEO_PARAM_AVCTYPE mParamAvc;
+
+ struct IMRSlot {
+ uint32_t offset;
+ uint8_t *owner; // pointer to OMX buffer that owns this slot
+ } mIMRSlot[INPORT_ACTUAL_BUFFER_COUNT];
+
+ timer_t mKeepAliveTimer;
+
+ bool mSessionPaused;
+ int mDrmDevFd;
+};
+
+#endif /* OMX_VIDEO_DECODER_AVC_SECURE_H_ */