aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Poornachandran <rajesh.poornachandran@intel.com>2015-04-13 11:25:58 -0700
committerPatrick Tjin <pattjin@google.com>2015-04-30 10:47:53 -0700
commitce5d181857065512540466b8d6b8944979291ef9 (patch)
treeef2d46a2271addace25811aa83f7183718714dcb
parent3417872a45d599ef169a36ce556e2e0fbdf18303 (diff)
downloadandroid_hardware_intel_common_omx-components-ce5d181857065512540466b8d6b8944979291ef9.tar.gz
android_hardware_intel_common_omx-components-ce5d181857065512540466b8d6b8944979291ef9.tar.bz2
android_hardware_intel_common_omx-components-ce5d181857065512540466b8d6b8944979291ef9.zip
Porting ProtectedDataBuffer changes in OMXVideoDecoderAVCSecure.
Bug: 19964594 Change-Id: Iebbdda9bda3cf7a541a286c4bed7cee5f80fe748 Signed-off-by: Rajesh Poornachandran <rajesh.poornachandran@intel.com>
-rw-r--r--videocodec/securevideo/moorefield/LogDumpHelper.h302
-rwxr-xr-xvideocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.cpp148
-rwxr-xr-xvideocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.h2
-rw-r--r--videocodec/securevideo/moorefield/ProtectedDataBuffer.h171
4 files changed, 564 insertions, 59 deletions
diff --git a/videocodec/securevideo/moorefield/LogDumpHelper.h b/videocodec/securevideo/moorefield/LogDumpHelper.h
new file mode 100644
index 0000000..3a12977
--- /dev/null
+++ b/videocodec/securevideo/moorefield/LogDumpHelper.h
@@ -0,0 +1,302 @@
+/*
+* Copyright (c) 2014 Intel Corporation. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef LOG_DUMP_HELPER_INCLUDED
+#define LOG_DUMP_HELPER_INCLUDED
+
+#ifndef LOG_TAG
+#error "Before including this file, must #define LOG_TAG and #include <utils/Log.h>"
+#endif
+
+#if LOG_NDEBUG == 0
+
+// We have dump routines for the structures defined in the following files:
+#include "VideoFrameInfo.h"
+#include "ProtectedDataBuffer.h"
+
+// The following helps to use these dump routines from command line unit tests:
+#ifdef ANDROID
+#define DUMP_EOL ""
+#else
+#define LOGV printf
+#define LOGE printf
+#define DUMP_EOL "\n"
+#endif // ANDROID
+
+#ifndef log_helper_min
+#define log_helper_min(a,b) ((a) < (b) ? (a) : (b))
+#endif // log_helper_min
+
+static inline void Copy4Bytes(void* dst, const void* src)
+{
+ // Don't check input pointers for NULL: this is internal function,
+ // and if you pass NULL to it, your code deserves to crash.
+
+ uint8_t* bdst = (uint8_t*) dst ;
+ const uint8_t* bsrc = (const uint8_t*) src ;
+
+ *bdst++ = *bsrc++ ;
+ *bdst++ = *bsrc++ ;
+ *bdst++ = *bsrc++ ;
+ *bdst = *bsrc ;
+}
+// End of Copy4Bytes()
+
+static void DumpBufferToString(char* str, uint32_t strSize, const uint8_t* start, uint32_t size)
+{
+ if (str == NULL || strSize == 0 || start == NULL || size == 0)
+ {
+ LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
+ return ;
+ }
+
+ char* s = str ;
+ char* send = str + strSize ;
+
+ const uint8_t* byte = start ;
+ const uint8_t* end = start + size ;
+
+ while (byte < end && s < send)
+ {
+ s += snprintf(s, strSize - (s - str), "%02x ", *byte) ;
+ ++byte ;
+ }
+}
+// End of DumpBufferToString()
+
+static void DumpNaluDataBuffer(uint32_t nalu, const uint8_t* start, uint32_t size)
+{
+ if (start == NULL || size == 0)
+ {
+ LOGV("NALU-dump: error: invalid parameters to %s", __FUNCTION__) ;
+ return ;
+ }
+
+ const uint32_t STR_SIZE = 1024 ;
+ char str[STR_SIZE] = {0} ;
+
+ DumpBufferToString(str, STR_SIZE, start, size) ;
+
+ LOGV("NALU-dump(nalu %u): data: %s" DUMP_EOL, nalu, str) ;
+}
+// End of DumpNaluDataBuffer()
+
+static void DumpBuffer(const char* prefix, const uint8_t* start, uint32_t size)
+{
+ if (start == NULL || size == 0)
+ {
+ LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
+ return ;
+ }
+
+ if (prefix == NULL)
+ {
+ prefix = "" ;
+ }
+
+ const uint32_t STR_SIZE = 1024 ;
+ char str[STR_SIZE] = {0} ;
+
+ DumpBufferToString(str, STR_SIZE, start, size) ;
+
+ LOGV("%s: ptr=%p, size=%u, data=%s" DUMP_EOL, prefix, start, size, str) ;
+}
+// End of DumpBuffer()
+
+static void DumpNaluHeaderBuffer(const uint8_t* const start, uint32_t size)
+{
+ if (start == NULL || size == 0)
+ {
+ LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
+ return ;
+ }
+
+ const uint8_t* current = start ;
+
+ uint32_t numNALUs = 0 ;
+ Copy4Bytes(&numNALUs, current) ;
+ current += sizeof(numNALUs) ;
+
+ LOGV("NALU-dump: num NALUs = %u\n", numNALUs) ;
+
+ if (numNALUs > MAX_NALUS_IN_FRAME)
+ {
+ LOGE("NALU-dump: ERROR, num NALUs is too big (%u)" DUMP_EOL, numNALUs) ;
+ }
+
+ for (uint32_t nalu = 0; nalu < numNALUs; ++nalu)
+ {
+ uint32_t imr_offset = 0 ;
+ Copy4Bytes(&imr_offset, current) ;
+ current += sizeof(imr_offset) ;
+
+ uint32_t nalu_size = 0 ;
+ Copy4Bytes(&nalu_size, current) ;
+ current += sizeof(nalu_size) ;
+
+ uint32_t data_size = 0 ;
+ Copy4Bytes(&data_size, current) ;
+ current += sizeof(data_size) ;
+
+ LOGV("NALU-dump(nalu %u): imr_offset = %u, nalu_size = %u, data_size = %u" DUMP_EOL,
+ nalu, imr_offset, nalu_size, data_size) ;
+
+ DumpNaluDataBuffer(nalu, current, data_size) ;
+
+ // Skip past the data
+ current += data_size ;
+ }
+ // End of for
+}
+// End of DumpNaluHeaderBuffer()
+
+static const char* DrmSchemeToString(uint32_t drmScheme)
+{
+ switch(drmScheme)
+ {
+ case DRM_SCHEME_NONE:
+ return "None" ;
+
+ case DRM_SCHEME_WV_CLASSIC:
+ return "WV Classic" ;
+
+ case DRM_SCHEME_WV_MODULAR:
+ return "WV Modular" ;
+
+#ifdef DRM_SCHEME_MCAST_SINK
+ case DRM_SCHEME_MCAST_SINK:
+ return "MCast Sink" ;
+#endif
+
+#ifdef DRM_SCHEME_PLAYREADY_ASF
+ case DRM_SCHEME_PLAYREADY_ASF:
+ return "PlayReady/ASF" ;
+#endif
+
+ default:
+ return "unknown" ;
+ }
+}
+// End of DrmSchemeToString()
+
+static void DumpBuffer2(const char* prefix, const uint8_t* start, uint32_t size)
+{
+ if (start == NULL || size == 0)
+ {
+ LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
+ return ;
+ }
+
+ if (prefix == NULL)
+ {
+ prefix = "" ;
+ }
+
+ const uint32_t STR_SIZE = 1024 ;
+ char str[STR_SIZE] = {0} ;
+
+ DumpBufferToString(str, STR_SIZE, start, size) ;
+
+ LOGV("%s%s" DUMP_EOL, prefix, str) ;
+}
+// End of DumpBuffer2()
+
+static void DumpProtectedDataBuffer(const char* prefix, ProtectedDataBuffer* buf)
+{
+ if (buf == NULL)
+ {
+ LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
+ return ;
+ }
+
+ if (prefix == NULL) { prefix = "" ; }
+
+ const uint32_t MAX_BUFFER_DUMP_LENGTH = 32 ;
+
+ if (buf->magic != PROTECTED_DATA_BUFFER_MAGIC)
+ {
+ const uint8_t* p = (uint8_t*) &buf->magic ;
+ LOGV("%sWrong magic: %02x %02x %02x %02x" DUMP_EOL, prefix, p[0], p[1], p[2], p[3]) ;
+ return ;
+ }
+
+ LOGV("%smagic: ok, drmScheme: %u (%s), clear: %u, size: %u, num PES: %u" DUMP_EOL, prefix,
+ buf->drmScheme, DrmSchemeToString(buf->drmScheme), buf->clear, buf->size, buf->numPesBuffers) ;
+
+ if (buf->numPesBuffers == 0)
+ {
+ uint32_t dumpLength = log_helper_min(buf->size, MAX_BUFFER_DUMP_LENGTH) ;
+ DumpBuffer2("data: ", buf->data, dumpLength) ;
+ }
+ else
+ {
+ for (uint32_t i = 0; i < buf->numPesBuffers; ++i)
+ {
+ const uint32_t STR_SIZE = 1024 ;
+ char str[STR_SIZE] = {0} ;
+
+ uint32_t dumpLength = log_helper_min(buf->pesBuffers[i].pesSize, MAX_BUFFER_DUMP_LENGTH) ;
+
+ DumpBufferToString(str, STR_SIZE,
+ buf->data + buf->pesBuffers[i].pesDataOffset, dumpLength) ;
+
+ LOGV("PES %u: streamCounter: %u, inputCounter: %llu, offset: %u, size: %u, PES data: %s" DUMP_EOL,
+ i, buf->pesBuffers[i].streamCounter, buf->pesBuffers[i].inputCounter,
+ buf->pesBuffers[i].pesDataOffset, buf->pesBuffers[i].pesSize, str) ;
+ }
+ }
+}
+// End of DumpProtectedDataBuffer
+
+static void DumpVideoFrameInfo(frame_info_t* fInfo)
+{
+ if (fInfo == NULL)
+ {
+ LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
+ return ;
+ }
+
+ LOGV("frame_info_t: data = %p, size = %u, num_nalus = %u", fInfo->data, fInfo->size, fInfo->num_nalus) ;
+
+ for (uint32_t i = 0; i < fInfo->num_nalus; ++i)
+ {
+ LOGV("nalu_info_t: type = %#x, offset = %u (%#x), data = %p, length = %u",
+ fInfo->nalus[i].type, fInfo->nalus[i].offset, fInfo->nalus[i].offset,
+ fInfo->nalus[i].data, fInfo->nalus[i].length) ;
+
+ if (fInfo->nalus[i].data != NULL && fInfo->nalus[i].length > 0)
+ {
+ DumpBuffer2("nalu_info_t::data: ", fInfo->nalus[i].data, fInfo->nalus[i].length) ;
+ }
+ }
+}
+// End of DumpVideoFrameInfo()
+
+#else
+
+// Avoid #ifdef around the dump code
+
+#define DumpBuffer(...)
+#define DumpBuffer2(...)
+#define DumpNaluHeaderBuffer(...)
+#define DumpProtectedDataBuffer(...)
+#define DumpVideoFrameInfo(...)
+
+#define DUMP_EOL
+
+#endif // LOG_NDEBUG == 0
+
+#endif // LOG_DUMP_HELPER_INCLUDED
diff --git a/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.cpp b/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.cpp
index 1e81645..bf346f5 100755
--- a/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.cpp
+++ b/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.cpp
@@ -23,18 +23,21 @@
#include <signal.h>
#include <pthread.h>
+#include "LogDumpHelper.h"
#include "VideoFrameInfo.h"
+#include "ProtectedDataBuffer.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 INPORT_BUFFER_SIZE sizeof(ProtectedDataBuffer)
#define DATA_BUFFER_INITIAL_OFFSET 0 //1024
#define DATA_BUFFER_SIZE (8 * 1024 * 1024)
#define KEEP_ALIVE_INTERVAL 5 // seconds
#define DRM_KEEP_ALIVE_TIMER 1000000
#define WV_SESSION_ID 0x00000011
-#define NALU_BUFFER_SIZE 8192
#define NALU_HEADER_LENGTH 1024 // THis should be changed to 4K
#define FLUSH_WAIT_INTERVAL (30 * 1000) //30 ms
@@ -43,17 +46,6 @@ static const char* AVC_SECURE_MIME_TYPE = "video/avc-secure";
#define DRM_SCHEME_CENC 2
#define DRM_SCHEME_PRASF 3
-//#pragma pack(push, 1)
-struct DataBuffer {
- uint32_t size;
- uint8_t *data;
- uint8_t clear;
- uint32_t drmScheme;
- uint32_t session_id; //used by PR only
- uint32_t flags; //used by PR only
-};
-//#pragma pack(pop)
-
bool OMXVideoDecoderAVCSecure::EnableIEDSession(bool enable)
{
if (mDrmDevFd <= 0) {
@@ -67,6 +59,7 @@ bool OMXVideoDecoderAVCSecure::EnableIEDSession(bool enable)
OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure()
: mKeepAliveTimer(0),
+ mNumInportBuffers(0),
mSessionPaused(false){
ALOGV("OMXVideoDecoderAVCSecure is constructed.");
if (drm_vendor_api_init(&drm_vendor_api)) {
@@ -116,11 +109,6 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitInputPortFormatSpecific(OMX_PARAM_PO
this->ports[INPORT_INDEX]->SetMemAllocator(MemAllocDataBuffer, MemFreeDataBuffer, this);
- for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
- mDataBufferSlot[i].offset = DATA_BUFFER_INITIAL_OFFSET + i * INPORT_BUFFER_SIZE;
- mDataBufferSlot[i].owner = NULL;
- }
-
return OMX_ErrorNone;
}
@@ -180,7 +168,24 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorProcess(
int ret_value;
OMX_BUFFERHEADERTYPE *pInput = *pBuffers[INPORT_INDEX];
- DataBuffer *dataBuffer = (DataBuffer *)pInput->pBuffer;
+ ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *)pInput->pBuffer;
+ // Check that we are dealing with the right buffer
+ if (dataBuffer->magic != PROTECTED_DATA_BUFFER_MAGIC)
+ {
+ if (pInput->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
+ {
+ // Processing codec data, which is not in ProtectedDataBuffer format
+ ALOGV("%s: received AVC codec data (%lu bytes).", __FUNCTION__, pInput->nFilledLen);
+ DumpBuffer2("OMX: AVC codec data: ", pInput->pBuffer, pInput->nFilledLen);
+ return OMX_ErrorNone;
+ }
+ else
+ {
+ // Processing non-codec data, but this buffer is not in ProtectedDataBuffer format
+ ALOGE("%s: protected data buffer pointer %p doesn't have the right magic", __FUNCTION__, dataBuffer);
+ return OMX_ErrorBadParameter;
+ }
+ }
if((dataBuffer->drmScheme == DRM_SCHEME_WVC) && (!mKeepAliveTimer)){
struct sigevent sev;
@@ -266,7 +271,7 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareWVCDecodeBuffer(OMX_BUFFERHEADERT
ALOGW("buffer offset %u is not zero!!!", buffer->nOffset);
}
- DataBuffer *dataBuffer = (DataBuffer *)buffer->pBuffer;
+ ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *)buffer->pBuffer;
if (dataBuffer->clear) {
p->data = dataBuffer->data + buffer->nOffset;
p->size = buffer->nFilledLen;
@@ -341,7 +346,7 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareCENCDecodeBuffer(OMX_BUFFERHEADER
ALOGW("buffer offset %u is not zero!!!", buffer->nOffset);
}
- DataBuffer *dataBuffer = (DataBuffer *)buffer->pBuffer;
+ ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *)buffer->pBuffer;
p->data = dataBuffer->data;
p->size = sizeof(frame_info_t);
p->flag |= IS_SECURE_DATA;
@@ -366,7 +371,7 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PreparePRASFDecodeBuffer(OMX_BUFFERHEADE
ALOGW("PR:buffer offset %u is not zero!!!", buffer->nOffset);
}
- DataBuffer *dataBuffer = (DataBuffer *)buffer->pBuffer;
+ ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *)buffer->pBuffer;
if (dataBuffer->clear) {
p->data = dataBuffer->data + buffer->nOffset;
p->size = buffer->nFilledLen;
@@ -435,7 +440,26 @@ OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE
return OMX_ErrorNone;
}
- DataBuffer *dataBuffer = (DataBuffer *)buffer->pBuffer;
+ ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *)buffer->pBuffer;
+ // Check that we are dealing with the right buffer
+ if (dataBuffer->magic != PROTECTED_DATA_BUFFER_MAGIC)
+ {
+ if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
+ {
+ // Processing codec data, which is not in ProtectedDataBuffer format
+ ALOGI("%s: received AVC codec data (%lu bytes).", __FUNCTION__, buffer->nFilledLen);
+ DumpBuffer2("OMX: AVC codec data: ", buffer->pBuffer, buffer->nFilledLen) ;
+ return OMX_ErrorNone;
+ }
+ else
+ {
+ // Processing non-codec data, but this buffer is not in ProtectedDataBuffer format
+ ALOGE("%s: protected data buffer pointer %p doesn't have the right magic", __FUNCTION__, dataBuffer);
+ return OMX_ErrorBadParameter;
+ }
+ }
+ // End of magic check
+
if(dataBuffer->drmScheme == DRM_SCHEME_WVC){
// OMX_BUFFERFLAG_CODECCONFIG is an optional flag
@@ -539,54 +563,60 @@ void OMXVideoDecoderAVCSecure::MemFreeDataBuffer(OMX_U8 *pBuffer, OMX_PTR pUserD
}
OMX_U8* OMXVideoDecoderAVCSecure::MemAllocDataBuffer(OMX_U32 nSizeBytes) {
- if (nSizeBytes > INPORT_BUFFER_SIZE) {
- ALOGE("Invalid size (%u) of memory to allocate.", nSizeBytes);
+
+ ALOGW_IF(nSizeBytes != INPORT_BUFFER_SIZE,
+ "%s: size of memory to allocate is %lu, but will allocate %u",
+ __FUNCTION__, nSizeBytes, sizeof(ProtectedDataBuffer));
+
+ if (mNumInportBuffers >= INPORT_ACTUAL_BUFFER_COUNT)
+ {
+ ALOGE("%s: cannot allocate buffer: number of inport buffers is %u, which is already at maximum",
+ __FUNCTION__, mNumInportBuffers);
+ return NULL;
+ }
+
+ ProtectedDataBuffer *pBuffer = new ProtectedDataBuffer;
+ if (pBuffer == NULL)
+ {
+ ALOGE("%s: failed to allocate memory.", __FUNCTION__);
return NULL;
}
- ALOGW_IF(nSizeBytes != INPORT_BUFFER_SIZE, "Size of memory to allocate is %u", nSizeBytes);
- for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
- if (mDataBufferSlot[i].owner == NULL) {
- DataBuffer *pBuffer = new DataBuffer;
- if (pBuffer == NULL) {
- ALOGE("Failed to allocate memory.");
- return NULL;
- }
- pBuffer->data = new uint8_t [INPORT_BUFFER_SIZE];
- if (pBuffer->data == NULL) {
- delete pBuffer;
- ALOGE("Failed to allocate memory, size to allocate %d.", INPORT_BUFFER_SIZE);
- return NULL;
- }
+ ++mNumInportBuffers;
- // Is this required for classic or not?
- // pBuffer->offset = mDataBufferSlot[i].offset;
- pBuffer->size = INPORT_BUFFER_SIZE;
- mDataBufferSlot[i].owner = (OMX_U8 *)pBuffer;
+ Init_ProtectedDataBuffer(pBuffer);
+
+ pBuffer->size = INPORT_BUFFER_SIZE;
- ALOGV("Allocating buffer = %#x, Data offset = %#x, data = %#x", (uint32_t)pBuffer, mDataBufferSlot[i].offset, (uint32_t)pBuffer->data);
- return (OMX_U8 *) pBuffer;
- }
- }
- ALOGE("Data buffer slot is not available.");
- return NULL;
+ ALOGV("Allocating buffer = %#x, data = %#x", (uint32_t)pBuffer, (uint32_t)pBuffer->data);
+ return (OMX_U8 *) pBuffer;
}
void OMXVideoDecoderAVCSecure::MemFreeDataBuffer(OMX_U8 *pBuffer) {
- DataBuffer *p = (DataBuffer*) pBuffer;
- if (p == NULL) {
+
+ if (pBuffer == NULL)
+ {
+ ALOGE("%s: trying to free NULL pointer", __FUNCTION__);
return;
}
- for (int i = 0; i < INPORT_ACTUAL_BUFFER_COUNT; i++) {
- if (pBuffer == mDataBufferSlot[i].owner) {
- ALOGV("Freeing Data buffer offset = %d, data = %#x", mDataBufferSlot[i].offset, (uint32_t)p->data);
- delete [] p->data;
- delete p;
- mDataBufferSlot[i].owner = NULL;
- return;
- }
+
+ if (mNumInportBuffers == 0)
+ {
+ ALOGE("%s: allocated inport buffer count is already 0, cannot delete buffer %p",
+ __FUNCTION__, pBuffer);
+ return;
}
- ALOGE("Invalid buffer %#x to de-allocate", (uint32_t)pBuffer);
+
+ ProtectedDataBuffer *p = (ProtectedDataBuffer*) pBuffer;
+ if (p->magic != PROTECTED_DATA_BUFFER_MAGIC)
+ {
+ ALOGE("%s: attempting to free buffer with a wrong magic 0x%08x", __FUNCTION__, p->magic);
+ return;
+ }
+
+ ALOGV("Freeing Data buffer %p with data = %p", p, p->data);
+ delete p;
+ --mNumInportBuffers;
}
void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) {
diff --git a/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.h b/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.h
index b46a923..2a99ef5 100755
--- a/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.h
+++ b/videocodec/securevideo/moorefield/OMXVideoDecoderAVCSecure.h
@@ -87,6 +87,8 @@ private:
timer_t mKeepAliveTimer;
+ // Keep track of number of allocated inport buffers
+ uint32_t mNumInportBuffers;
bool mSessionPaused;
struct drm_vendor_api drm_vendor_api;
int mDrmDevFd;
diff --git a/videocodec/securevideo/moorefield/ProtectedDataBuffer.h b/videocodec/securevideo/moorefield/ProtectedDataBuffer.h
new file mode 100644
index 0000000..8260648
--- /dev/null
+++ b/videocodec/securevideo/moorefield/ProtectedDataBuffer.h
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2014 Intel Corporation. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef PROTECTED_DATA_BUFFER_H
+#define PROTECTED_DATA_BUFFER_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// NOTE: this size takes into account the space used by DRM
+// schemes with full sample encryption (e.g., WV Classic) or
+// subsample encryption (e.g., WV Modular, which uses 2KB for
+// frame info data).
+#define NALU_BUFFER_SIZE (4 * 1024)
+
+// Either start code + type (00 00 00 01 <type byte>) or 4 byte length + type.
+#define NALU_HEADER_SIZE 5
+
+// This should be able to fit compressed 1080p video I-frame, use half
+// of NV12 1080p frame, which on average uses 12 bits per pixel.
+#define MAX_COMPRESSED_FRAME_SIZE (1920 * 1080 * 3 / 4)
+
+#define MAX_PROT_BUFFER_DATA_SIZE (MAX_COMPRESSED_FRAME_SIZE + NALU_BUFFER_SIZE)
+
+#define MAX_PES_BUFFER_SIZE (64*1024)
+
+// TODO: it's not clear, how to calculate this value, since PES packet may contain
+// less than 64KB worth of data.
+#define MAX_PES_PACKETS_PER_FRAME 64
+
+// Video decoder defines maximum number of NALUs per frame as 16.
+// (At least, as of June of 2014.) Use the same value here.
+#define MAX_NALUS_IN_FRAME 16
+
+// Integer, which "PDBF", but no 0 terminator
+#define PROTECTED_DATA_BUFFER_MAGIC (0UL | ('F' << 24) | ('B' << 16) | ('D' << 8) | 'P')
+
+#define DRM_SCHEME_NONE 0
+#define DRM_SCHEME_WV_CLASSIC 1
+#define DRM_SCHEME_WV_MODULAR 2
+#define DRM_SCHEME_MCAST_SINK 3
+#define DRM_SCHEME_PLAYREADY_ASF 4
+
+// Flag to indicate if Last Subsample flag is received for MDRM
+#define PDB_FLAG_COMPLETE_FRAME 0x1000
+
+#pragma pack(push, 4)
+
+typedef struct ProtectedPESBuffer_tag {
+
+ // AES CTR stream counter, needed for HDCP decryption.
+ // If ProtectedDataBuffer::clear is 1, streamCounter is ignored.
+ uint32_t streamCounter ;
+
+ // AES CTR input counter, needed for HDCP decryption
+ // If ProtectedDataBuffer::clear is 1, inputCounter is ignored.
+ uint64_t inputCounter ;
+
+ // Offset within ProtectedDataBuffer::data buffer, to the start
+ // of this PES packet's data.
+ //
+ // IMPORTANT: for protected content (ProtectedDataBuffer::clear is 0),
+ // this offset must be divisible by 16 (AES block size). This is to allow
+ // for in-place transcryption from AES CTR to IED (AES ECB). OMX will
+ // check that the offset is divisible by 16, and will abort
+ // playback, if the offset is NOT divisible by 16. For this reason,
+ // the offset is used and not a byte pointer.
+ uint32_t pesDataOffset ;
+
+ // Size of the PES data, pointed to by pesData
+ uint32_t pesSize ;
+}
+ProtectedPESBuffer ;
+
+typedef struct ProtectedDataBuffer_tag {
+
+ // Must be set to PROTECTED_DATA_BUFFER_MAGIC. Must be the first
+ // member of ProtectedDataBuffer structure.
+ uint32_t magic;
+
+ // See DRM_SCHEME_* defines above
+ uint32_t drmScheme;
+
+ // 1 if clear, 0 if encrypted
+ uint32_t clear;
+
+ // Session ID, used by some DRM schemes (e.g. PlayReady)
+ uint32_t session_id ;
+
+ // Flags, used by some DRM schemes
+ // MDRM uses it to indicate Complete Frame received
+ // Miracast Sink uses it to indicate if Transcription is required
+ uint32_t flags ;
+
+ // Information about the PES data buffers. Used for DRM_SCHEME_MCAST_SINK.
+ // Reserve space for one more PES data buffer for sentinel value, for
+ // ease of implementation.
+ //
+ ProtectedPESBuffer pesBuffers[MAX_PES_PACKETS_PER_FRAME + 1] ;
+
+ // Number of filled-out entries in pesBuffers array.
+ // Used for DRM_SCHEME_MCAST_SINK. If data buffer is not partitioned
+ // into PES packet buffers, set numPesBuffers must be 0.
+ //
+ uint32_t numPesBuffers ;
+
+ // Size of the data buffer.
+ uint32_t size ;
+
+ // For clear content, this is the space for clear data.
+ // For encrypted content, this space is occupied by IED encrypted
+ // data or HDCP encrypted data (payloads only, no PES headers),
+ // depending on the DRM scheme.
+ //
+ // A space is made at the end of encrypted data for
+ // decrypted SPS/PPS headers.
+ //
+ // NOTE: data must be last, to allow for flexibility not
+ // to copy the whole ProtectedDataBuffer, if not whole data
+ // buffer is filled.
+ //
+ uint8_t data[MAX_PROT_BUFFER_DATA_SIZE];
+}
+ProtectedDataBuffer;
+
+#pragma pack(pop)
+
+#define PDBUFFER_DATA_OFFSET offsetof(ProtectedDataBuffer, data)
+
+static inline void Init_ProtectedDataBuffer(ProtectedDataBuffer* buf)
+{
+ // This is internal helper function. If you pass invalid (e.g. NULL)
+ // pointer to it, you deserve to crash.
+
+ // Perform initialization of certain members, ignore the data
+ // areas, which will be overwritten in the course of the
+ // normal usage.
+
+ buf->magic = PROTECTED_DATA_BUFFER_MAGIC ;
+ buf->drmScheme = DRM_SCHEME_NONE ;
+ buf->clear = 0 ;
+ buf->size = 0 ;
+ buf->numPesBuffers = 0 ;
+ buf->session_id = 0 ;
+ buf->flags = 0 ;
+}
+// End of Init_ProtectedDataBuffer()
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // PROTECTED_DATA_BUFFER_H