diff options
| author | Rajesh Poornachandran <rajesh.poornachandran@intel.com> | 2013-06-03 12:20:30 -0700 |
|---|---|---|
| committer | Patrick Tjin <pattjin@google.com> | 2014-07-21 22:02:52 -0700 |
| commit | 9bf33af84b0d334e97dbdacf74bde071402c31c5 (patch) | |
| tree | fbfb07fa14ce825baa0b1e5720f5cb8e8c8c7e62 /videocodec/securevideo | |
| parent | 27b6ed6d5d3a9b3f19ab1b10aa308a7dedb7cb83 (diff) | |
| download | android_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>
Diffstat (limited to 'videocodec/securevideo')
| -rw-r--r-- | videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.cpp | 532 | ||||
| -rw-r--r-- | videocodec/securevideo/baytrail/OMXVideoDecoderAVCSecure.h | 59 | ||||
| -rw-r--r-- | videocodec/securevideo/baytrail/secvideoparser/Android.mk | 11 | ||||
| -rwxr-xr-x | videocodec/securevideo/baytrail/secvideoparser/libsecvideoparser.so | bin | 0 -> 25428 bytes | |||
| -rw-r--r-- | videocodec/securevideo/baytrail/secvideoparser/secvideoparser.h | 157 | ||||
| -rw-r--r-- | videocodec/securevideo/baytrail/widevine.h | 491 |
6 files changed, 1070 insertions, 180 deletions
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 Binary files differnew file mode 100755 index 0000000..7f30bf0 --- /dev/null +++ b/videocodec/securevideo/baytrail/secvideoparser/libsecvideoparser.so 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
+
|
