aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Poornachandran <rajesh.poornachandran@intel.com>2013-06-03 12:20:30 -0700
committerPatrick Tjin <pattjin@google.com>2014-07-21 22:02:52 -0700
commit9bf33af84b0d334e97dbdacf74bde071402c31c5 (patch)
treefbfb07fa14ce825baa0b1e5720f5cb8e8c8c7e62
parent27b6ed6d5d3a9b3f19ab1b10aa308a7dedb7cb83 (diff)
downloadandroid_hardware_intel_common_omx-components-9bf33af84b0d334e97dbdacf74bde071402c31c5.tar.gz
android_hardware_intel_common_omx-components-9bf33af84b0d334e97dbdacf74bde071402c31c5.tar.bz2
android_hardware_intel_common_omx-components-9bf33af84b0d334e97dbdacf74bde071402c31c5.zip
BYT-OMXVideoDecoderAVCSecure: Enable BYT-DRM-WV
BZ: 108017 Details: - SEC decrypt and parsing - 4MB shared allocation from MEI driver - OMX to allocate only 16 bytes for xscript_key - OUTPORT_NATIVE_BUFFER_COUNT = 20 - OMX with NativeBuffer handler - cleanup phase # 1 - fix video marco artifact - fix to handle 0 NALU due to format change Change-Id: Iaa4a0dda3c058670045b4d68a1365b099a06e141 Signed-off-by: Rajesh Poornachandran <rajesh.poornachandran@intel.com> Reviewed-on: http://android.intel.com:8080/100539 Reviewed-by: Akula, VarshaX A <varshax.a.akula@intel.com> Reviewed-by: Zurcher, Paul <paul.zurcher@intel.com> Tested-by: Sun, Hang L <hang.l.sun@intel.com> Reviewed-by: buildbot <buildbot@intel.com> Tested-by: buildbot <buildbot@intel.com>
-rwxr-xr-xvideocodec/Android.mk33
-rw-r--r--videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp532
-rw-r--r--videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h59
-rw-r--r--videocodec/securevideo/baytrail/secvideoparser/Android.mk11
-rwxr-xr-xvideocodec/securevideo/baytrail/secvideoparser/libsecvideoparser.sobin0 -> 25428 bytes
-rw-r--r--videocodec/securevideo/baytrail/secvideoparser/secvideoparser.h157
-rw-r--r--videocodec/securevideo/baytrail/widevine.h491
7 files changed, 1098 insertions, 185 deletions
diff --git a/videocodec/Android.mk b/videocodec/Android.mk
index 30d0b21..89606c9 100755
--- a/videocodec/Android.mk
+++ b/videocodec/Android.mk
@@ -238,11 +238,29 @@ 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_SHARED_LIBRARIES += libstlport \
+ libutils \
+ libz \
+ libdl \
+ libcrypto \
+ libssl \
+ libicuuc \
+ libcutils \
+ libc \
+ libmeimm \
+ libpavp \
+ libsecvideoparser
+
+LOCAL_C_INCLUDES += bionic \
+ external/stlport/stlport \
+ external/openssl/include \
+ external/libxml2/include \
+ $(TARGET_OUT_HEADERS)/secvideoparser \
+ $(LOCAL_PATH)/securevideo/baytrail/ \
+ $(TOP)/vendor/intel/hardware/txei/meimm/ \
+ $(TOP)/vendor/intel/hardware/PRIVATE/ufo/include
+
+LOCAL_SRC_FILES += securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp
LOCAL_CFLAGS += -DVED_TILING
endif
@@ -473,4 +491,9 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libOMXVideoEncoderVP8
include $(BUILD_SHARED_LIBRARY)
+# prnz - prebuilt SEC video parser
+SAVE_LOCAL_PATH := $(LOCAL_PATH)
+include $(LOCAL_PATH)/securevideo/baytrail/secvideoparser/Android.mk
+LOCAL_PATH = $(SAVE_LOCAL_PATH)
+
endif
diff --git a/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp
index 37ac5f4..f116d85 100644
--- a/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp
+++ b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp
@@ -24,39 +24,63 @@
#include <pthread.h>
extern "C" {
-#include <sepdrm.h>
-#include <fcntl.h>
-#include "psb_drm.h"
-#include "xf86drm.h"
-#include "xf86drmMode.h"
+#include "widevine.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 PASS_FRAME_INFO 1
+#define WV_CEILING(a,b) ((a)%(b)==0?(a):((a)/(b)+1)*(b))
+#define DMA_BUFFER_SIZE (4 * 1024 * 1024)
+#define SEC_INITIAL_OFFSET 0 //1024
+#define SEC_BUFFER_SIZE (4 * 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
+// SEC addressable region
+#define SEC_REGION_SIZE (0x01000000) // 16 MB
+#define SEC_REGION_FRAME_BUFFERS_OFFSET (0)
+#define SEC_REGION_FRAME_BUFFERS_SIZE (0x00F00000) // 15 MB
+#define SEC_REGION_NALU_BUFFERS_OFFSET (SEC_REGION_FRAME_BUFFERS_OFFSET+SEC_REGION_FRAME_BUFFERS_SIZE)
+#define SEC_REGION_NALU_BUFFERS_SIZE (NALU_BUFFER_SIZE*INPORT_ACTUAL_BUFFER_COUNT)
+#define SEC_REGION_PAVP_INFO_OFFSET (SEC_REGION_NALU_BUFFERS_OFFSET+SEC_REGION_NALU_BUFFERS_SIZE)
+#define SEC_REGION_PAVP_INFO_SIZE (sizeof(pavp_info_t)*INPORT_ACTUAL_BUFFER_COUNT)
+
+// TEST ONLY
+static uint8_t* g_SECRegionTest_REMOVE_ME;
#pragma pack(push, 1)
-struct IMRDataBuffer {
- uint32_t offset;
+#define WV_AES_IV_SIZE 16
+#define WV_MAX_PACKETS_IN_FRAME 20 /* 20*64K=1.3M, max frame size */
+typedef struct {
+ uint16_t packet_byte_size; // number of bytes in this PES packet, same for input and output
+ uint16_t packet_is_not_encrypted; // 1 if this PES packet is not encrypted. 0 otherwise
+ uint8_t packet_iv[WV_AES_IV_SIZE]; // IV used for CBC-CTS decryption, if the PES packet is encrypted
+} wv_packet_metadata;
+// TODO: synchronize SECFrameBuffer with SECDataBuffer in WVCrypto.cpp
+// - offset replaced by index.
+
+struct SECFrameBuffer {
+ uint32_t index;
uint32_t size;
uint8_t *data;
- uint8_t clear; // 0 when IMR offset is valid, 1 when data is valid
+ uint8_t clear; // 0 when SEC offset is valid, 1 when data is valid
+ uint8_t num_entries;
+ wv_packet_metadata packet_metadata[WV_MAX_PACKETS_IN_FRAME];
+ uint8_t key[16];
+ pavp_lib_session *pLibInstance;
};
#pragma pack(pop)
+uint8_t outiv[WV_AES_IV_SIZE];
OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure()
- : mKeepAliveTimer(0),
- mSessionPaused(false),
- mDrmDevFd(-1) {
+ : mSessionPaused(false),
+ mpLibInstance(NULL) {
LOGV("OMXVideoDecoderAVCSecure is constructed.");
mVideoDecoder = createVideoDecoder(AVC_SECURE_MIME_TYPE);
if (!mVideoDecoder) {
@@ -66,20 +90,18 @@ OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure()
mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
BuildHandlerList();
-
- mDrmDevFd = open("/dev/card0", O_RDWR, 0);
- if (mDrmDevFd < 0) {
- LOGE("Failed to open drm device.");
- }
+ mSECRegion.initialized = 0;
}
OMXVideoDecoderAVCSecure::~OMXVideoDecoderAVCSecure() {
LOGV("OMXVideoDecoderAVCSecure is destructed.");
- if (mDrmDevFd) {
- close(mDrmDevFd);
- mDrmDevFd = 0;
+ if(g_SECRegionTest_REMOVE_ME)
+ {
+ delete[] g_SECRegionTest_REMOVE_ME;
+ g_SECRegionTest_REMOVE_ME = NULL;
}
+ LOGV("OMXVideoDecoderAVCSecure is destructed.");
}
OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) {
@@ -98,21 +120,35 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitInputPortFormatSpecific(OMX_PARAM_PO
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;
+ // PREPRODUCTION: allocate 16MB region off the heap
+ g_SECRegionTest_REMOVE_ME = new uint8_t[SEC_REGION_SIZE];
+ if(!g_SECRegionTest_REMOVE_ME) {
+ return OMX_ErrorInsufficientResources;
}
+ // Set up SEC-addressable memory region
+ InitSECRegion(g_SECRegionTest_REMOVE_ME, SEC_REGION_SIZE);
+
+ // Set memory allocator
+ this->ports[INPORT_INDEX]->SetMemAllocator(MemAllocSEC, MemFreeSEC, this);
+
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);
- }
+
+ int status = meimm_init(&mMeiMm, true);
+
+ if (status)
+ LOGE("meimm_init FAILED ret: %#x", status);
+
+ status = meimm_alloc_map_memory(&mMeiMm, DMA_BUFFER_SIZE);
+ if (status)
+ LOGE("meimm_alloc_map_memory FAILED ret: %#x", status);
+
+ mVADmaBase = (uint32_t)meimm_get_addr(&mMeiMm);
+ LOGI("mVADMAOffset: %#x", mVADmaBase);
+
mSessionPaused = false;
return OMXVideoDecoderBase::ProcessorInit();
}
@@ -120,71 +156,30 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorInit(void) {
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 secOffset = 0;
+ uint32_t secBufferSize = SEC_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;
+ // destroy PAVP session
+ if(mpLibInstance) {
+ pavp_lib_session::pavp_lib_code rc = pavp_lib_session::status_ok;
+ LOGI("Destroying the PAVP session...\n");
+ rc = mpLibInstance->pavp_destroy_session();
+ if (rc != pavp_lib_session::status_ok)
+ LOGE("pavp_destroy_session failed with error 0x%x\n", rc);
}
-
+ meimm_free_memory(&mMeiMm);
+ meimm_deinit(&mMeiMm);
return OMXVideoDecoderBase::ProcessorStop();
}
@@ -199,16 +194,16 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorProcess(
OMX_U32 numberBuffers) {
OMX_BUFFERHEADERTYPE *pInput = *pBuffers[INPORT_INDEX];
- IMRDataBuffer *imrBuffer = (IMRDataBuffer *)pInput->pBuffer;
- if (imrBuffer->size == 0) {
+ SECFrameBuffer *secBuffer = (SECFrameBuffer *)pInput->pBuffer;
+ if (secBuffer->size == 0) {
// error occurs during decryption.
- LOGW("size of returned IMR buffer is 0, decryption fails.");
+ LOGW("size of returned SEC 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;
+ // reset SEC buffer size
+ secBuffer->size = INPORT_BUFFER_SIZE;
this->ports[INPORT_INDEX]->FlushPort();
this->ports[OUTPORT_INDEX]->FlushPort();
return OMX_ErrorNone;
@@ -233,18 +228,10 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorProcess(
}
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();
}
@@ -276,31 +263,132 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE
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;
+ SECFrameBuffer *secBuffer = (SECFrameBuffer *)buffer->pBuffer;
+ pavp_lib_session::pavp_lib_code rc = pavp_lib_session::status_ok;
+ uint32_t parse_size = 0;
+
+ if(!mpLibInstance && secBuffer->pLibInstance)
+ {
+ pavp_lib_session::pavp_lib_code rc = pavp_lib_session::status_ok;
+ LOGE("PAVP Heavy session creation...\n");
+ rc = secBuffer->pLibInstance->pavp_create_session(true);
+ if (rc != pavp_lib_session::status_ok) {
+ LOGE("PAVP Heavy: pavp_create_session failed with error 0x%x\n", rc);
+ } else {
+ mpLibInstance = secBuffer->pLibInstance;
+ }
+ {
+ pavp_lib_session::pavp_lib_code rc = pavp_lib_session::status_ok;
+ wv_set_xcript_key_in input;
+ wv_set_xcript_key_out output;
+
+ input.Header.ApiVersion = WV_API_VERSION;
+ input.Header.CommandId = wv_set_xcript_key;
+ input.Header.Status = 0;
+ input.Header.BufferLength = sizeof(input)-sizeof(PAVP_CMD_HEADER);
+
+ if (secBuffer->pLibInstance) {
+ rc = secBuffer->pLibInstance->sec_pass_through(
+ reinterpret_cast<BYTE*>(&input),
+ sizeof(input),
+ reinterpret_cast<BYTE*>(&output),
+ sizeof(output));
+ }
+
+ if (rc != pavp_lib_session::status_ok)
+ LOGE("sec_pass_through:wv_set_xcript_key() failed with error 0x%x\n", rc);
+
+ if (output.Header.Status)
+ LOGE("SEC failed: wv_set_xcript_key() returned 0x%x\n", output.Header.Status);
+ }
+ }
+ {
+ wv_heci_process_video_frame_in input;
+ wv_heci_process_video_frame_out output;
+ sec_wv_packet_metadata metadata;
+
+ input.Header.ApiVersion = WV_API_VERSION;
+ input.Header.CommandId = wv_process_video_frame;
+ input.Header.Status = 0;
+ input.Header.BufferLength = sizeof(input) - sizeof(PAVP_CMD_HEADER);
+
+ input.num_of_packets = secBuffer->num_entries;
+ input.is_frame_not_encrypted = secBuffer->clear;
+ input.src_offset = 0x0; //Src Frame offset is 0
+ input.dest_offset = 1024 * 512; //Dest Frame offset is 512KB
+ input.metadata_offset = 1024 * 1024; //Metadata offset is 1MB
+ input.header_offset = (1024*1024)+512; //Header offset is 1M + 512
+
+ for(int pes_count=0, pesoffset =0, dmaoffset=0; pes_count < secBuffer->num_entries; pes_count++) {
+
+ dmaoffset = WV_CEILING(dmaoffset,32);
+
+ metadata.packet_byte_size = secBuffer->packet_metadata[pes_count].packet_byte_size;
+ memset(&metadata.packet_iv[0], 0x0, sizeof(metadata.packet_iv));
+ memcpy(&secBuffer->data[(1024*1024)] + (pes_count * sizeof(metadata)), &metadata, sizeof(metadata));
+
+ //copy frame data
+ meimm_memcpy(&mMeiMm, dmaoffset, (secBuffer->data+pesoffset), metadata.packet_byte_size);
+ //copy meta data
+ meimm_memcpy(&mMeiMm, ((1024 * 1024)+(pes_count * sizeof(metadata))), &metadata, sizeof(metadata));
+ //update offset
+ dmaoffset += metadata.packet_byte_size;
+ pesoffset += metadata.packet_byte_size;
+ }
+
+ if (secBuffer->pLibInstance) {
+ rc = secBuffer->pLibInstance->sec_pass_through(
+ reinterpret_cast<BYTE*>(&input),
+ sizeof(input),
+ reinterpret_cast<BYTE*>(&output),
+ sizeof(output));
+ }
+
+ if (rc != pavp_lib_session::status_ok)
+ LOGE(" sec_pass_through failed with error 0x%x\n", rc);
+
+ if (output.Header.Status != 0x0){
+ LOGE(" SEC failed for wv_process_video_frame() returned 0x%x\n", output.Header.Status);
} else {
- mSessionPaused = false;
- p->data = imrBuffer->data;
- p->size = imrBuffer->size;
- p->flag |= IS_SECURE_DATA;
+ memcpy((unsigned char *)(secBuffer->data), (const unsigned int*) (mVADmaBase + (1024*512)), buffer->nFilledLen);
+ parse_size = output.parsed_data_size;
+ memcpy((unsigned char *)(secBuffer->data + buffer->nFilledLen + 4), (const unsigned int*) (mVADmaBase + ((1024*1024)+512)), output.parsed_data_size);
+ memcpy(&outiv, output.iv, WV_AES_IV_SIZE);
}
}
- //reset IMR size
- imrBuffer->size = NALU_BUFFER_SIZE;
+ p->data = secBuffer->data + buffer->nOffset;
+ p->size = buffer->nFilledLen;
+
+ // Call "SEC" to parse frame
+ SECParsedFrame* parsedFrame = &(mParsedFrames[secBuffer->index]);
+ memcpy(parsedFrame->nalu_data, (unsigned char *)(secBuffer->data + buffer->nFilledLen + 4), parse_size);
+ parsedFrame->nalu_data_size = parse_size;
+ memcpy(parsedFrame->pavp_info->iv, outiv, WV_AES_IV_SIZE);
+
+ // construct frame_info
+ ret = ConstructFrameInfo(p->data, p->size, parsedFrame->pavp_info,
+ parsedFrame->nalu_data, parsedFrame->nalu_data_size, &(parsedFrame->frame_info));
+
+ if(ret == OMX_ErrorNone) {
+ if (parsedFrame->frame_info.num_nalus == 0 ) {
+ LOGE("NALU parsing failed - num_nalus = 0!");
+ secBuffer->size = 0;
+ ret = OMX_ErrorNotReady;
+ }
+ }
+ if(ret == OMX_ErrorNone) {
+#ifdef PASS_FRAME_INFO
+ // Pass frame info to VideoDecoderAVCSecure in VideoDecodeBuffer
+ p->data = (uint8_t *)&(parsedFrame->frame_info);
+ p->size = sizeof(frame_info_t);
+ p->flag = p->flag | IS_SECURE_DATA;
+#else
+ // Pass decrypted frame
+ p->data = secBuffer->data + buffer->nOffset;
+ p->size = buffer->nFilledLen;
+#endif
+ }
return ret;
}
@@ -308,6 +396,7 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::BuildHandlerList(void) {
OMXVideoDecoderBase::BuildHandlerList();
AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc);
AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoAVCProfileLevel, SetParamVideoAVCProfileLevel);
+ AddHandler(static_cast<OMX_INDEXTYPE> (OMX_IndexExtEnableNativeBuffer), GetNativeBufferMode, SetNativeBufferMode);
return OMX_ErrorNone;
}
@@ -353,98 +442,195 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAVCProfileLevel(OMX_PTR pSt
return OMX_ErrorUnsupportedSetting;
}
-OMX_U8* OMXVideoDecoderAVCSecure::MemAllocIMR(OMX_U32 nSizeBytes, OMX_PTR pUserData) {
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetNativeBufferMode(OMX_PTR pStructure) {
+ LOGE("GetNativeBufferMode is not implemented");
+ return OMX_ErrorNotImplemented;
+}
+
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetNativeBufferMode(OMX_PTR pStructure) {
+ OMXVideoDecoderBase::SetNativeBufferMode(pStructure);
+ PortVideo *port = NULL;
+ port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
+
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
+ port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
+ port->SetPortDefinition(&port_def,true);
+
+ return OMX_ErrorNone;
+}
+
+OMX_U8* OMXVideoDecoderAVCSecure::MemAllocSEC(OMX_U32 nSizeBytes, OMX_PTR pUserData) {
OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData;
if (p) {
- return p->MemAllocIMR(nSizeBytes);
+ return p->MemAllocSEC(nSizeBytes);
}
LOGE("NULL pUserData.");
return NULL;
}
-void OMXVideoDecoderAVCSecure::MemFreeIMR(OMX_U8 *pBuffer, OMX_PTR pUserData) {
+void OMXVideoDecoderAVCSecure::MemFreeSEC(OMX_U8 *pBuffer, OMX_PTR pUserData) {
OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData;
if (p) {
- p->MemFreeIMR(pBuffer);
+ p->MemFreeSEC(pBuffer);
return;
}
LOGE("NULL pUserData.");
}
-OMX_U8* OMXVideoDecoderAVCSecure::MemAllocIMR(OMX_U32 nSizeBytes) {
+OMX_U8* OMXVideoDecoderAVCSecure::MemAllocSEC(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;
- }
+ LOGW_IF(nSizeBytes != INPORT_BUFFER_SIZE, "WARNING:MemAllocSEC asked to allocate buffer of size %lu (expected %lu)", nSizeBytes, INPORT_BUFFER_SIZE);
- 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;
+ int index = 0;
+ for (; index < INPORT_ACTUAL_BUFFER_COUNT; index++) {
+ if(!mSECRegion.frameBuffers.buffers[index].allocated) {
+ break;
+ }
+ }
+ if(index >= INPORT_ACTUAL_BUFFER_COUNT) {
+ LOGE("No free buffers");
+ return NULL;
+ }
- LOGV("Allocating buffer = %#x, IMR offset = %#x, data = %#x", (uint32_t)pBuffer, mIMRSlot[i].offset, (uint32_t)pBuffer->data);
- return (OMX_U8 *) pBuffer;
- }
+ SECFrameBuffer *pBuffer = new SECFrameBuffer;
+ if (pBuffer == NULL) {
+ LOGE("Failed to allocate SECFrameBuffer.");
+ return NULL;
}
- LOGE("IMR slot is not available.");
- return NULL;
+
+ pBuffer->index = index;
+ pBuffer->data = mSECRegion.frameBuffers.buffers[index].base;
+ pBuffer->size = mSECRegion.frameBuffers.buffers[index].size;
+ mParsedFrames[index].nalu_data = mSECRegion.naluBuffers.buffers[index].base;
+ mParsedFrames[index].nalu_data_size = mSECRegion.naluBuffers.buffers[index].size;
+ mParsedFrames[index].pavp_info = (pavp_info_t*)mSECRegion.pavpInfo.buffers[index].base;
+
+ mSECRegion.frameBuffers.buffers[index].allocated = 1;
+ mSECRegion.naluBuffers.buffers[index].allocated = 1;
+ mSECRegion.pavpInfo.buffers[index].allocated = 1;
+
+ return (OMX_U8 *) pBuffer;
}
-void OMXVideoDecoderAVCSecure::MemFreeIMR(OMX_U8 *pBuffer) {
- IMRDataBuffer *p = (IMRDataBuffer*) pBuffer;
+void OMXVideoDecoderAVCSecure::MemFreeSEC(OMX_U8 *pBuffer) {
+ SECFrameBuffer *p = (SECFrameBuffer*) 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);
+
+ mSECRegion.frameBuffers.buffers[p->index].allocated = 0;
+ mSECRegion.naluBuffers.buffers[p->index].allocated = 0;
+ mSECRegion.pavpInfo.buffers[p->index].allocated = 0;
+
+ delete(p);
}
-void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) {
- OMXVideoDecoderAVCSecure *p = (OMXVideoDecoderAVCSecure *)v.sival_ptr;
- if (p) {
- p->KeepAliveTimerCallback();
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitSECRegion(uint8_t* region, uint32_t size)
+{
+ if(mSECRegion.initialized) {
+ return OMX_ErrorNone;
}
-}
-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);
+ mSECRegion.base = region;
+ mSECRegion.size = size;
+
+ // Partition the SEC region
+ mSECRegion.frameBuffers.base = mSECRegion.base + SEC_REGION_FRAME_BUFFERS_OFFSET;
+ mSECRegion.frameBuffers.size = SEC_REGION_FRAME_BUFFERS_SIZE;
+
+ mSECRegion.naluBuffers.base = mSECRegion.base + SEC_REGION_NALU_BUFFERS_OFFSET;
+ mSECRegion.naluBuffers.size = SEC_REGION_NALU_BUFFERS_SIZE;
+
+ mSECRegion.pavpInfo.base = mSECRegion.base + SEC_REGION_PAVP_INFO_OFFSET;
+ mSECRegion.pavpInfo.size = SEC_REGION_PAVP_INFO_SIZE;
+
+ for(int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
+ mSECRegion.frameBuffers.buffers[i].allocated = 0;
+ mSECRegion.frameBuffers.buffers[i].base = mSECRegion.frameBuffers.base + (i*INPORT_BUFFER_SIZE);
+ mSECRegion.frameBuffers.buffers[i].size = INPORT_BUFFER_SIZE;
+ mSECRegion.naluBuffers.buffers[i].allocated = 0;
+ mSECRegion.naluBuffers.buffers[i].base = mSECRegion.naluBuffers.base + (i*NALU_BUFFER_SIZE);
+ mSECRegion.naluBuffers.buffers[i].size = NALU_BUFFER_SIZE;
+ mSECRegion.pavpInfo.buffers[i].allocated = 0;
+ mSECRegion.pavpInfo.buffers[i].base = mSECRegion.pavpInfo.base + (i*sizeof(pavp_info_t));
+ mSECRegion.pavpInfo.buffers[i].size = sizeof(pavp_info_t);
}
+
+ mSECRegion.initialized = 1;
+
+ return OMX_ErrorNone;
}
+OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ConstructFrameInfo(
+ uint8_t* frame_data,
+ uint32_t frame_size,
+ pavp_info_t* pavp_info,
+ uint8_t* nalu_data,
+ uint32_t nalu_data_size,
+ frame_info_t* frame_info) {
+
+ uint32_t* dword_ptr = (uint32_t*)nalu_data;
+ uint8_t* byte_ptr = NULL;
+ uint32_t data_size = 0;
+
+ frame_info->data = frame_data;
+ frame_info->length = frame_size;
+ frame_info->pavp = pavp_info;
+
+ frame_info->num_nalus = byteswap_32(*dword_ptr);
+ dword_ptr++;
+ for(uint32_t n = 0; n < frame_info->num_nalus; n++) {
+ // Byteswap offset
+ frame_info->nalus[n].offset = byteswap_32(*dword_ptr);
+ dword_ptr++;
+
+ // Byteswap nalu_size
+ frame_info->nalus[n].length = byteswap_32(*dword_ptr);
+ dword_ptr++;
+
+ // Byteswap data_size
+ data_size = byteswap_32(*dword_ptr);
+ dword_ptr++;
+
+ byte_ptr = (uint8_t*)dword_ptr;
+ frame_info->nalus[n].type = *byte_ptr;
+ switch(frame_info->nalus[n].type & 0x1F) {
+ case h264_NAL_UNIT_TYPE_SPS:
+ case h264_NAL_UNIT_TYPE_PPS:
+ case h264_NAL_UNIT_TYPE_SEI:
+ // Point to cleartext in nalu data buffer
+ frame_info->nalus[n].data = byte_ptr;
+ frame_info->nalus[n].slice_header = NULL;
+ break;
+ case h264_NAL_UNIT_TYPE_SLICE:
+ case h264_NAL_UNIT_TYPE_IDR:
+ // Point to ciphertext in frame buffer
+ frame_info->nalus[n].data = frame_info->data + frame_info->nalus[n].offset;
+ byteswap_slice_header((slice_header_t*)byte_ptr);
+ frame_info->nalus[n].slice_header = (slice_header_t*)byte_ptr;
+
+ frame_info->dec_ref_pic_marking = NULL;
+ if(data_size > sizeof(slice_header_t)) {
+ byte_ptr += sizeof(slice_header_t);
+ frame_info->dec_ref_pic_marking = (dec_ref_pic_marking_t*)byte_ptr;
+ }
+ break;
+ default:
+ LOGE("ERROR: SEC returned an unsupported NALU type: %x", frame_info->nalus[n].type);
+ frame_info->nalus[n].data = NULL;
+ frame_info->nalus[n].slice_header = NULL;
+ break;
+ }
-bool OMXVideoDecoderAVCSecure::EnableIEDSession(bool enable)
-{
- if (mDrmDevFd < 0) {
- return false;
+ // Advance to next NALU (including padding)
+ dword_ptr += (data_size + 3) >> 2;
}
- int request = enable ? DRM_PSB_ENABLE_IED_SESSION : DRM_PSB_DISABLE_IED_SESSION;
- int ret = drmCommandNone(mDrmDevFd, request);
- return ret == 0;
+
+ return OMX_ErrorNone;
}
DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC.secure", "video_decoder.avc", OMXVideoDecoderAVCSecure);
diff --git a/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h
index 310e9ba..040dee4 100644
--- a/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h
+++ b/videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h
@@ -19,6 +19,11 @@
#include "OMXVideoDecoderBase.h"
+extern "C" {
+#include "secvideoparser.h"
+#include "libpavp.h"
+#include "meimm.h"
+}
class OMXVideoDecoderAVCSecure : public OMXVideoDecoderBase {
public:
@@ -45,15 +50,22 @@ protected:
virtual OMX_ERRORTYPE BuildHandlerList(void);
DECLARE_HANDLER(OMXVideoDecoderAVCSecure, ParamVideoAvc);
DECLARE_HANDLER(OMXVideoDecoderAVCSecure, ParamVideoAVCProfileLevel);
+ DECLARE_HANDLER(OMXVideoDecoderAVCSecure, NativeBufferMode);
+ static OMX_U8* MemAllocSEC(OMX_U32 nSizeBytes, OMX_PTR pUserData);
+ static void MemFreeSEC(OMX_U8 *pBuffer, OMX_PTR pUserData);
+ OMX_U8* MemAllocSEC(OMX_U32 nSizeBytes);
+ void MemFreeSEC(OMX_U8 *pBuffer);
+
+ OMX_ERRORTYPE InitSECRegion(uint8_t* region, uint32_t size);
+ OMX_ERRORTYPE ConstructFrameInfo(uint8_t* frame_data, uint32_t frame_size,
+ pavp_info_t* pavp_info, uint8_t* nalu_data, uint32_t nalu_data_size,
+ frame_info_t* frame_info);
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 {
@@ -66,7 +78,7 @@ private:
// default number of reference frame
NUM_REFERENCE_FRAME = 4,
- OUTPORT_NATIVE_BUFFER_COUNT = 15,
+ OUTPORT_NATIVE_BUFFER_COUNT = 20,
};
OMX_VIDEO_PARAM_AVCTYPE mParamAvc;
@@ -76,10 +88,43 @@ private:
uint8_t *owner; // pointer to OMX buffer that owns this slot
} mIMRSlot[INPORT_ACTUAL_BUFFER_COUNT];
- timer_t mKeepAliveTimer;
-
bool mSessionPaused;
- int mDrmDevFd;
+
+ struct SECBuffer {
+ uint8_t allocated;
+ uint8_t* base;
+ uint32_t size;
+ };
+
+ struct SECSubRegion {
+ uint8_t* base;
+ uint32_t size;
+ SECBuffer buffers[INPORT_ACTUAL_BUFFER_COUNT];
+ };
+
+ struct SECRegion {
+ uint8_t initialized;
+ uint8_t* base;
+ uint32_t size;
+ SECSubRegion frameBuffers;
+ SECSubRegion naluBuffers;
+ SECSubRegion pavpInfo;
+ };
+
+ SECRegion mSECRegion;
+
+ struct SECParsedFrame {
+ uint8_t* nalu_data;
+ uint32_t nalu_data_size;
+ pavp_info_t* pavp_info;
+ frame_info_t frame_info;
+ };
+
+ SECParsedFrame mParsedFrames[INPORT_ACTUAL_BUFFER_COUNT];
+
+ struct meimm mMeiMm;
+ uint32_t mVADmaBase;
+ pavp_lib_session *mpLibInstance;
};
#endif /* OMX_VIDEO_DECODER_AVC_SECURE_H_ */
diff --git a/videocodec/securevideo/baytrail/secvideoparser/Android.mk b/videocodec/securevideo/baytrail/secvideoparser/Android.mk
new file mode 100644
index 0000000..4eea0be
--- /dev/null
+++ b/videocodec/securevideo/baytrail/secvideoparser/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO := secvideoparser
+LOCAL_COPY_HEADERS := secvideoparser.h
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+LOCAL_PREBUILT_LIBS := libsecvideoparser.so
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_MULTI_PREBUILT)
diff --git a/videocodec/securevideo/baytrail/secvideoparser/libsecvideoparser.so b/videocodec/securevideo/baytrail/secvideoparser/libsecvideoparser.so
new file mode 100755
index 0000000..7f30bf0
--- /dev/null
+++ b/videocodec/securevideo/baytrail/secvideoparser/libsecvideoparser.so
Binary files differ
diff --git a/videocodec/securevideo/baytrail/secvideoparser/secvideoparser.h b/videocodec/securevideo/baytrail/secvideoparser/secvideoparser.h
new file mode 100644
index 0000000..03f480d
--- /dev/null
+++ b/videocodec/securevideo/baytrail/secvideoparser/secvideoparser.h
@@ -0,0 +1,157 @@
+/* INTEL CONFIDENTIAL
+* Copyright (c) 2013 Intel Corporation. All rights reserved.
+*
+* The source code contained or described herein and all documents
+* related to the source code ("Material") are owned by Intel
+* Corporation or its suppliers or licensors. Title to the
+* Material remains with Intel Corporation or its suppliers and
+* licensors. The Material contains trade secrets and proprietary
+* and confidential information of Intel or its suppliers and
+* licensors. The Material is protected by worldwide copyright and
+* trade secret laws and treaty provisions. No part of the Material
+* may be used, copied, reproduced, modified, published, uploaded,
+* posted, transmitted, distributed, or disclosed in any way without
+* Intel's prior express written permission.
+*
+* No license under any patent, copyright, trade secret or other
+* intellectual property right is granted to or conferred upon you
+* by disclosure or delivery of the Materials, either expressly, by
+* implication, inducement, estoppel or otherwise. Any license
+* under such intellectual property rights must be express and
+* approved by Intel in writing.
+*/
+
+#ifndef SEC_VIDEO_PARSER_H_
+#define SEC_VIDEO_PARSER_H_
+
+#include <stdint.h>
+
+/* H264 start code values */
+typedef enum _h264_nal_unit_type
+{
+ h264_NAL_UNIT_TYPE_unspecified = 0,
+ h264_NAL_UNIT_TYPE_SLICE,
+ h264_NAL_UNIT_TYPE_DPA,
+ h264_NAL_UNIT_TYPE_DPB,
+ h264_NAL_UNIT_TYPE_DPC,
+ h264_NAL_UNIT_TYPE_IDR,
+ h264_NAL_UNIT_TYPE_SEI,
+ h264_NAL_UNIT_TYPE_SPS,
+ h264_NAL_UNIT_TYPE_PPS,
+ h264_NAL_UNIT_TYPE_Acc_unit_delimiter,
+ h264_NAL_UNIT_TYPE_EOSeq,
+ h264_NAL_UNIT_TYPE_EOstream,
+ h264_NAL_UNIT_TYPE_filler_data,
+ h264_NAL_UNIT_TYPE_SPS_extension,
+ h264_NAL_UNIT_TYPE_ACP = 19,
+ h264_NAL_UNIT_TYPE_Slice_extension = 20
+} h264_nal_unit_type_t;
+
+#define MAX_OP 16
+
+enum dec_ref_pic_marking_flags {
+ IDR_PIC_FLAG = 0,
+ NO_OUTPUT_OF_PRIOR_PICS_FLAG,
+ LONG_TERM_REFERENCE_FLAG,
+ ADAPTIVE_REF_PIC_MARKING_MODE_FLAG
+};
+
+typedef struct _dec_ref_pic_marking_t {
+ union {
+ uint8_t flags;
+ struct {
+ uint8_t idr_pic_flag:1;
+ uint8_t no_output_of_prior_pics_flag:1;
+ uint8_t long_term_reference_flag:1;
+ uint8_t adaptive_ref_pic_marking_mode_flag:1;
+ };
+ };
+ struct {
+ uint8_t memory_management_control_operation;
+ union {
+ struct {
+ uint8_t difference_of_pic_nums_minus1;
+ } op1;
+ struct {
+ uint8_t long_term_pic_num;
+ } op2;
+ struct {
+ uint8_t difference_of_pic_nums_minus1;
+ uint8_t long_term_frame_idx;
+ } op3;
+ struct {
+ uint8_t max_long_term_frame_idx_plus1;
+ } op4;
+ struct {
+ uint8_t long_term_frame_idx;
+ } op6;
+ };
+ } op[MAX_OP];
+} dec_ref_pic_marking_t;
+
+enum slice_header_flags {
+ FIELD_PIC_FLAG = 0,
+ BOTTOM_FIELD_FLAG
+};
+
+typedef struct _slice_header_t {
+ uint8_t nal_unit_type;
+ union {
+ uint8_t flags;
+ struct {
+ uint8_t field_pic_flag:1;
+ uint8_t bottom_field_flag:1;
+ };
+ };
+ uint8_t pps_id;
+ uint8_t padding; // Align the next field to a 32-bit address
+ uint32_t first_mb_in_slice;
+ uint32_t frame_num;
+ uint16_t idr_pic_id;
+ uint16_t pic_order_cnt_lsb;
+ int32_t delta_pic_order_cnt_bottom;
+ int32_t delta_pic_order_cnt[2];
+} slice_header_t;
+
+typedef struct {
+ uint8_t type;
+ uint32_t offset;
+ uint8_t* data;
+ uint32_t length;
+ slice_header_t* slice_header;
+} nalu_info_t;
+
+typedef struct {
+ uint32_t iv[4];
+ uint32_t mode;
+ uint32_t app_id;
+} pavp_info_t;
+
+#define MAX_NUM_NALUS 20
+
+typedef struct {
+ uint8_t* data;
+ uint32_t length;
+ pavp_info_t* pavp;
+ dec_ref_pic_marking_t* dec_ref_pic_marking;
+ uint32_t num_nalus;
+ nalu_info_t nalus[MAX_NUM_NALUS];
+} frame_info_t;
+
+int parser_init(void);
+int parse_frame(uint8_t* frame, uint32_t frame_size, uint8_t* nalu_data, uint32_t* nalu_data_size);
+
+// DEBUG PRINTING
+void print_slice_header(slice_header_t* slice_header);
+void print_dec_ref_pic_marking(dec_ref_pic_marking_t* dec_ref_pic_marking);
+void print_data_bytes(uint8_t* data, uint32_t count);
+void print_nalu_data(uint8_t* nalu_data, uint32_t nalu_data_size);
+
+// BYTESWAPPING
+uint16_t byteswap_16(uint16_t word);
+uint32_t byteswap_32(uint32_t dword);
+void byteswap_slice_header(slice_header_t* slice_header);
+void byteswap_dec_ref_pic_marking(dec_ref_pic_marking_t* dec_ref_pic_marking);
+void byteswap_nalu_data(uint8_t* nalu_data, uint32_t nalu_data_size);
+
+#endif /* SEC_VIDEO_PARSER_H_ */
diff --git a/videocodec/securevideo/baytrail/widevine.h b/videocodec/securevideo/baytrail/widevine.h
new file mode 100644
index 0000000..a53a822
--- /dev/null
+++ b/videocodec/securevideo/baytrail/widevine.h
@@ -0,0 +1,491 @@
+/*++
+
+ INTEL CONFIDENTIAL
+ Copyright (c) 2013- Intel Corporation All Rights Reserved.
+
+ The source code contained or described herein and all documents related to
+ the source code ("Material") are owned by Intel Corporation or its
+ suppliers or licensors. Title to the Material remains with Intel
+ Corporation or its suppliers and licensors. The Material contains trade
+ secrets and proprietary and confidential information of Intel or its
+ suppliers and licensors. The Material is protected by worldwide copyright
+ and trade secret laws and treaty provisions. No part of the Material may be
+ used, copied, reproduced, modified, published, uploaded, posted, transmitted,
+ distributed, or disclosed in any way without Intel's prior express written
+ permission.
+
+ No license under any patent, copyright, trade secret or other intellectual
+ property right is granted to or conferred upon you by disclosure or delivery
+ of the Materials, either expressly, by implication, inducement, estoppel or
+ otherwise. Any license under such intellectual property rights must be
+ express and approved by Intel in writing.
+
+File Name:
+
+ widevine.h
+
+Abstract:
+
+
+
+Author:
+
+ Ruan, Xiaoyu
+ Patel, Arpit A
+
+Revision history:
+
+ 3/17/2013: WV SEC FW API v0.19
+ 3/21/2013: v0.30
+ 3/29/2013: v0.40
+ 4/4/2013: v0.43
+ 4/8/2013: v0.45
+ 4/11/2013: v0.50
+ 4/24/2013: v0.51
+
+--*/
+
+#ifndef __WIDEVINE_H
+#define __WIDEVINE_H
+
+#if 0
+#include "CompMgmt.h"
+#include "Heci.h"
+#include "Crypto.h"
+#include "Storage.h"
+#include "Memory.h"
+#include "MemDefs.h"
+#include <string.h>
+
+#include "PavpHeciApiCommonDefs.h"
+#include "PavpHeciApi.h"
+#include "PavpVideoKeyMgr.h"
+#include "PavpBaseKeyMgr.h"
+#include "GfxKeyMgrDefs.h"
+
+#include "dbg.h"
+#include "romapi.h"
+
+#include "bitstream.h"
+#include "decoder.h"
+#include "nalu.h"
+#include "sei.h"
+#include "sps.h"
+#include "pps.h"
+#include "slice_header.h"
+#include "flag.h"
+#endif
+
+#define WV_USE_SATT 1
+
+#define WV_1KB 1024
+#define WV_DEVICE_ID_SIZE 32
+#define WV_DEVICE_KEY_SIZE 16
+#define WV_KEY_DATA_SIZE 72
+#define MV_KEYBOX_MAGIC_SIZE 4
+#define WV_CRC_SIZE 4
+#define WV_MAGIC_SIZE 4
+#define WV_AES_IV_SIZE 16
+#define WV_AES_KEY_SIZE 16
+#define WV_AES_BLOCK_SIZE 16
+#define WV_MAX_PACKETS_IN_FRAME 20 /* 20*64K=1.3M, max frame size */
+#define WV_MAX_PACKET_SIZE (64*WV_1KB-1)
+#define WV_PARSED_BUFFER_SIZE (4*WV_1KB)
+#define WV_PER_DMA_SIZE (8*WV_1KB + 16 + 16) /* 16 is AES block size, for CTS last block. add 16 more for DMA alignment */
+#define WV_PARSER_BUF_EDGE 64
+#define WV_WORK_BUFFER_SIZE (WV_PER_DMA_SIZE+WV_PARSER_BUF_EDGE)
+#define WV_ECM_SIZE 32
+#define WV_FLAGS_SIZE 4
+#define WV_RAND_SIZE 32
+#define WV_API_VERSION 0x00010000
+#define WV_FRAME_METADATA_SIZE (WV_MAX_PACKETS_IN_FRAME*sizeof(wv_frame_metadata))
+#define WV_MALLOC_ALIGNMENT 32
+#define WV_MALLOC_TIMEOUT 0
+#define WV_DMA_ALIGNMENT 32
+#define WV_XCRIPT_DMA_OUT_SWAP (CIPHER_DST_SWAP)
+#define WV_OUT_MSG_FLAG 0x80000000
+#define WV_SATT_BASE SATT_2
+
+#define WV_CEILING(a,b) ((a)%(b)==0?(a):((a)/(b)+1)*(b))
+#define PREPRODUCTION (RomData.gBringupDataPtr->FuseMap.DevModeEnabled || RomData.gBringupDataPtr->FuseMap.JtagEnabled)
+#define WV_SWAP_DWORD(dword) (((dword) & 0x000000ff) << 24 | ((dword) & 0x0000ff00) << 8 | ((dword) & 0x00ff0000) >> 8 | ((dword) & 0xff000000) >> 24)
+#define WV_SWAP_SHORT(sho) (((sho) & (0x00ff)) << 8 | ((sho) & (0xff00)) >> 8)
+
+/**
+ * @brief PAVP HECI message header.
+ */
+typedef struct _PAVP_CMD_HEADER
+{
+ UINT32 ApiVersion;
+ UINT32 CommandId;
+ UINT32 Status;
+ UINT32 BufferLength;
+} PAVP_CMD_HEADER;
+
+typedef struct _PAVP_CMD_NODATA
+{
+ PAVP_CMD_HEADER Header;
+ // no data follows header
+} PAVP_CMD_NODATA;
+
+typedef int BOOL;
+
+typedef struct {
+ uint8_t device_id[WV_DEVICE_ID_SIZE];
+ uint8_t device_key[WV_DEVICE_KEY_SIZE];
+ uint8_t key_data[WV_KEY_DATA_SIZE];
+ uint8_t magic[WV_MAGIC_SIZE];
+ uint8_t key_data_crc[WV_CRC_SIZE];
+} wv_keybox;
+
+typedef struct {
+ uint32_t packet_byte_size; // number of bytes in this PES packet, same for input and output
+ uint8_t packet_iv[WV_AES_IV_SIZE]; // IV used for CBC-CTS decryption, if the PES packet is encrypted
+} sec_wv_packet_metadata;
+
+typedef struct {
+ sec_wv_packet_metadata *metadata_buffer;//WV_MAX_PACKETS_IN_FRAME * sizeof(wv_packet_metadata)
+ uint32_t title_video_size;
+} wv_frame_metadata;
+
+/* wv_nalu and wv_nalu_headers are for host only. FW does not use */
+typedef struct {
+ uint32_t imr_offset;
+ uint32_t nalu_size;
+ uint32_t data_size;
+ uint8_t data[1]; //place holder. actual size is data_size
+} wv_nalu;
+
+/* wv_nalu and wv_nalu_headers are for host only. FW does not use */
+typedef struct {
+ uint32_t num_nalu;
+ wv_nalu drm_nalu[1];// place holder. actual size is num_nalu
+} wv_nalu_headers;
+
+#if 0
+typedef struct {
+ wv_frame_metadata frame_metadata;
+ uint32_t *frame_header; //WV_PARSED_BUFFER_SIZE, dynamic allocation from locked memory
+ uint8_t *frame_proc_buffer;// size = WV_PER_DMA_SIZE, dynamic allocation from locked memory
+ uint8_t *work_buffer;// size = WV_WORK_BUFFER_SIZE, dynamic allocation from locked memory
+ uint8_t *parser_work_buffer;// size = WV_WORK_BUFFER_SIZE, dynamic allocation from locked memory
+ uint8_t asset_key[WV_AES_KEY_SIZE];
+ BOOL asset_key_valid;
+ uint8_t title_key[WV_AES_KEY_SIZE];
+ uint8_t title_decrypt_key[WV_AES_KEY_SIZE];
+ BOOL title_key_valid;
+ uint8_t pavp_key[WV_AES_KEY_SIZE];
+ BOOL pavp_key_valid;
+ uint8_t pavp_counter[WV_AES_IV_SIZE];
+ decoder_ctx_t decoder;
+ uint32_t video_frame_count;
+ BOOL bypass_transcryption;
+ uint32_t audio_frame_count;
+ uint32_t time_start; /*timer starts at first frame of a video frame*/
+ uint32_t time_end; /*timer ends at title_complete*/
+ uint32_t time_start_heci;
+ uint32_t time_heci;
+ uint32_t time_dma_in;
+ uint32_t time_decrypt;
+ uint32_t time_parse;
+ uint32_t time_encrypt_dma_out;
+} wv_title_context;
+
+typedef struct {
+#if !WV_USE_SATT
+ uint32_t host_phy_mem_lo;
+ uint32_t host_phy_mem_hi;
+ uint32_t host_phy_mem_size;
+ BOOL host_phy_mem_valid;
+#endif
+ wv_keybox keybox;
+ BOOL keybox_valid;
+ wv_title_context title;
+ PAVP_STREAM_ID wvVideoStreamSlot;
+} wv_context;
+#endif
+
+/*******************
+ * HECI APIs
+ *******************/
+
+typedef enum {
+ WV_SUCCESS = 0,
+ WV_SUCCESS_PRIV_DATA = 0x80000000,
+ WV_FAIL_INVALID_PARAMS = 0x000F0001,
+ WV_FAIL_INVALID_INPUT_HEADER,
+ WV_FAIL_NOT_PROVISIONED,
+ WV_FAIL_BAD_KEYBOX_CRC,
+ WV_FAIL_UNKNOWN_ERROR,
+ WV_FAIL_HDCP_OFF,
+ WV_FAIL_NO_HOST_MEM,
+ WV_FAIL_NOT_EXPECTED,
+ WV_FAIL_INVALID_AUDIO_FRAME,
+ WV_FAIL_KEYBOX_INVALID_BAD_PROVISIONING,
+ WV_FAIL_KEYBOX_INVALID_BAD_MAGIC,
+ WV_FAIL_WV_NO_ASSET_KEY,
+ WV_FAIL_WV_NO_CEK,
+ WV_FAIL_REACHED_HOST_MEM_LIMIT,
+ WV_FAIL_WV_SESSION_NALU_PARSE_FAILURE,
+ WV_FAIL_WV_SESSION_NALU_PARSE_TOO_MANY_HEADERS,
+ WV_FAIL_GENERATE_RANDOM_NUMBER_FAILURE,
+ WV_FAIL_AES_CBC_FAILURE,
+ WV_FAIL_AES_XCRIPT_FAILURE,
+ WV_FAIL_AES_ECB_FAILURE,
+ WV_FAIL_BLOB_ERROR,
+ WV_FAIL_BAD_AUDIO_CLEAR_PKT,
+ WV_FAIL_NO_TITLE_KEY,
+ WV_FAIL_OUT_OF_MEMORY,
+ WV_FAIL_PAVP_INJECT_KEY_ERROR,
+ WV_FAIL_MSG_NOT_FROM_RING_0,
+ WV_FAIL_DMA_READ,
+ WV_FAIL_DMA_WRITE,
+ WV_FAIL_DMA_WRITE_HEADER,
+ WV_FAIL_INVALID_TITLE_KEY,
+ WV_FAIL_INVALID_PAVP_KEY,
+ WV_FAIL_INVALID_NUM_OF_PACKETS,
+ WV_FAIL_PAVP_INIT_NOT_COMPLETE,
+ WV_FAIL_STATUS_CHAIN_NOT_INITIALIZED,
+ WV_FAIL_OUTPUT_HOST_MEM_OVERLAP,
+ WV_FAIL_NOT_SUPPORTED
+} wv_heci_status;
+
+typedef enum {
+ wv_init_dma = 0x000A0002,
+ wv_heci_begin = wv_init_dma,
+ wv_get_random,
+ wv_get_keybox_data,
+ wv_set_xcript_key,
+ wv_set_entitlement_key,
+ wv_derive_control_word,
+ wv_process_video_frame,
+ wv_process_audio_frame,
+ wv_title_completed,
+ wv_uninit_dma,
+ wv_heci_end = wv_uninit_dma,
+ wv_dbg_get_title_key = 0x000A00F0,
+ wv_heci_dbg_begin = wv_dbg_get_title_key,
+ wv_dbg_get_xcript_key,
+ wv_dbg_dis_xcript_enc,
+ wv_dbg_en_xcript_enc,
+ wv_dbg_get_diag,
+ wv_dbg_set_keybox,
+ wv_dbg_reset_keybox,
+ wv_dbg_set_xcript_key_wo_pavp,
+ wv_dbg_reset_xcript_key_wo_pavp,
+ wv_heci_dbg_end = wv_dbg_reset_xcript_key_wo_pavp,
+
+ wv_init_dma_rsp = (WV_OUT_MSG_FLAG | wv_init_dma),
+ wv_get_random_rsp,
+ wv_get_keybox_data_rsp,
+ wv_set_xcript_key_rsp,
+ wv_set_entitlement_key_rsp,
+ wv_derive_control_word_rsp,
+ wv_process_video_frame_rsp,
+ wv_process_audio_frame_rsp,
+ wv_title_completed_rsp,
+ wv_uninit_dma_rsp,
+ wv_dbg_get_title_key_rsp = (WV_OUT_MSG_FLAG | wv_dbg_get_title_key),
+ wv_dbg_get_xcript_key_rsp,
+ wv_dbg_dis_xcript_enc_rsp,
+ wv_dbg_en_xcript_enc_rsp,
+ wv_dbg_get_diag_rsp,
+ wv_dbg_set_keybox_rsp,
+ wv_dbg_reset_keybox_rsp,
+ wv_dbg_set_xcript_key_wo_pavp_rsp,
+ wv_dbg_reset_xcript_key_wo_pavp_rsp,
+} wv_heci_command_id;
+
+
+/*wv_init_dma*/
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint32_t phy_mem_lo;
+ uint32_t phy_mem_hi;
+ uint32_t phy_mem_size;
+} wv_init_dma_in;
+
+typedef PAVP_CMD_NODATA wv_init_dma_out;
+
+/*wv_heci_get_random*/
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint32_t size_in_bytes;
+} wv_heci_get_random_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint8_t random_bytes[WV_RAND_SIZE];
+} wv_heci_get_random_out;
+
+/*wv_heci_get_keybox_data*/
+typedef PAVP_CMD_NODATA wv_heci_get_keybox_data_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint8_t key_data[WV_KEY_DATA_SIZE];
+ uint8_t device_id[WV_DEVICE_ID_SIZE];
+} wv_heci_get_keybox_data_out;
+
+/*wv_set_xcript_key*/
+typedef PAVP_CMD_NODATA wv_set_xcript_key_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ /* private data for driver. Size excluded in Header.Length
+ * app caller: do not include this field*/
+ //uint8_t wrapped_xcript_key[WV_AES_KEY_SIZE];// libpcp will take care of this. Remove this from OMX.
+} wv_set_xcript_key_out;
+
+/*wv_heci_set_entitlement_key*/
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint8_t entitlement_key[WV_AES_KEY_SIZE];
+} wv_heci_set_entitlement_key_in;
+
+typedef PAVP_CMD_NODATA wv_heci_set_entitlement_key_out;
+
+/*wv_heci_derive_control_word*/
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint8_t ecm[WV_ECM_SIZE];
+} wv_heci_derive_control_word_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint8_t flags[WV_FLAGS_SIZE];
+} wv_heci_derive_control_word_out;
+
+/*wv_heci_process_video_frame*/
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint32_t num_of_packets;//<=20
+ BOOL is_frame_not_encrypted;
+ uint32_t src_offset;
+ uint32_t dest_offset;
+ uint32_t metadata_offset;
+ uint32_t header_offset;
+} wv_heci_process_video_frame_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint32_t parsed_data_size;
+ /* private data for driver. Size excluded in Header.Length
+ * app caller: do not include this field*/ //Remove comment
+ uint8_t iv[WV_AES_IV_SIZE];
+} wv_heci_process_video_frame_out;
+
+/*wv_heci_process_audio_frame*/
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint32_t num_of_packets;//<=20
+ BOOL is_frame_not_encrypted;
+ uint32_t src_offset;
+ uint32_t dest_offset;
+ uint32_t metadata_offset;
+} wv_heci_process_audio_frame_in;
+
+typedef PAVP_CMD_NODATA wv_heci_process_audio_frame_out;
+
+/*wv_title_completed*/
+typedef PAVP_CMD_NODATA wv_title_completed_in;
+typedef PAVP_CMD_NODATA wv_title_completed_out;
+
+/*wv_dbg_get_title_key*/
+typedef PAVP_CMD_NODATA wv_dbg_get_title_key_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ BOOL title_key_valid;
+ uint8_t title_key[WV_AES_KEY_SIZE];
+} wv_dbg_get_title_key_out;
+
+/*wv_uninit_dma*/
+typedef PAVP_CMD_NODATA wv_uninit_dma_in;
+typedef PAVP_CMD_NODATA wv_uninit_dma_out;
+
+/*wv_dbg_get_xcript_key*/
+typedef PAVP_CMD_NODATA wv_dbg_get_xcript_key_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ BOOL xcript_key_valid;
+ uint8_t xcript_key[WV_AES_KEY_SIZE];
+ uint8_t xcript_counter[WV_AES_IV_SIZE];
+} wv_dbg_get_xcript_key_out;
+
+/*wv_dbg_dis_xcript_enc*/
+typedef PAVP_CMD_NODATA wv_dbg_dis_xcript_enc_in;
+typedef PAVP_CMD_NODATA wv_dbg_dis_xcript_enc_out;
+
+/*wv_dbg_en_xcript_enc*/
+typedef PAVP_CMD_NODATA wv_dbg_en_xcript_enc_in;
+typedef PAVP_CMD_NODATA wv_dbg_en_xcript_enc_out;
+
+/*wv_dbg_get_diag*/
+typedef PAVP_CMD_NODATA wv_dbg_get_diag_in;
+
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ uint16_t fw_major_ver;
+ uint16_t fw_minor_ver;
+ uint16_t fw_hotfix;
+ uint16_t fw_build;
+ BOOL production_part;
+#if !WV_USE_SATT
+ uint32_t host_phy_mem_lo;
+ uint32_t host_phy_mem_hi;
+ uint32_t host_phy_mem_size;
+ BOOL host_phy_mem_valid;
+#endif
+ uint32_t video_frame_count;
+ uint32_t audio_frame_count;
+ uint32_t slice_count_for_this_frame;
+ uint32_t total_slice_count_for_this_title;
+ uint32_t bypass_transcryption : 1;
+ uint32_t frame_header_valid : 1;
+ uint32_t frame_proc_buffer_valid : 1;
+ uint32_t work_buffer_valid : 1;
+ uint32_t parser_work_buffer_valid : 1;
+ uint32_t asset_key_valid_valid : 1;
+ uint32_t title_key_valid_valid : 1;
+ uint32_t pavp_key_valid : 1;
+ uint32_t keybox_valid : 1;
+ uint32_t reserved1 : 7;
+ uint32_t wvVideoStreamSlot : 8;
+ uint32_t reserved2 : 8;
+ uint32_t time_start; /*timer starts at first frame of a video frame*/
+ uint32_t time_end; /*timer ends at title_complete*/
+ uint32_t time_elapsed; /*time_end - time_start, unit is microsecond*/
+ uint32_t video_size;
+ uint32_t throughput; /*bits/microsecond*/
+ uint32_t time_heci;
+ uint32_t time_dma_in;
+ uint32_t time_decrypt;
+ uint32_t time_parse;
+ uint32_t time_encrypt_dma_out;
+} wv_dbg_get_diag_out;
+//C_ASSERT(sizeof(wv_dbg_get_diag_out) == WV_USE_SATT ? 64 : 48);
+
+/*wv_dbg_set_keybox*/
+typedef struct {
+ PAVP_CMD_HEADER Header;
+ wv_keybox keybox;
+} wv_dbg_set_keybox_in;
+
+typedef PAVP_CMD_NODATA wv_dbg_set_keybox_out;
+
+/*wv_dbg_reset_keybox*/
+typedef PAVP_CMD_NODATA wv_dbg_reset_keybox_in;
+typedef PAVP_CMD_NODATA wv_dbg_reset_keybox_out;
+
+/*wv_dbg_set_xcript_key_wo_pavp*/
+typedef PAVP_CMD_NODATA wv_dbg_set_xcript_key_wo_pavp_in;
+typedef PAVP_CMD_NODATA wv_dbg_set_xcript_key_wo_pavp_out;
+
+/*wv_dbg_reset_xcript_key_wo_pavp*/
+typedef PAVP_CMD_NODATA wv_dbg_reset_xcript_key_wo_pavp_in;
+typedef PAVP_CMD_NODATA wv_dbg_reset_xcript_key_wo_pavp_out;
+
+#endif
+