aboutsummaryrefslogtreecommitdiff
path: root/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp')
-rw-r--r--videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp367
1 files changed, 367 insertions, 0 deletions
diff --git a/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp b/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..52a5285
--- /dev/null
+++ b/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp
@@ -0,0 +1,367 @@
+/*
+* Copyright (c) 2009-2011 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.
+*/
+
+#include "va_private.h"
+#include "VideoDecoderAVCSecure.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+#define STARTCODE_PREFIX_LEN 3
+#define NALU_TYPE_MASK 0x1F
+#define MAX_NALU_HEADER_BUFFER 8192
+static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
+
+VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
+ : VideoDecoderAVC(mimeType),
+ mNaluHeaderBuffer(NULL),
+ mSliceHeaderBuffer(NULL) {
+ setParserType(VBP_H264SECURE);
+}
+
+VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
+}
+
+Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
+ Decode_Status status = VideoDecoderAVC::start(buffer);
+ if (status != DECODE_SUCCESS) {
+ return status;
+ }
+
+ mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+
+ if (mNaluHeaderBuffer == NULL) {
+ ETRACE("Failed to allocate memory for mNaluHeaderBuffer");
+ return DECODE_MEMORY_FAIL;
+ }
+
+ mSliceHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+ if (mSliceHeaderBuffer == NULL) {
+ ETRACE("Failed to allocate memory for mSliceHeaderBuffer");
+ if (mNaluHeaderBuffer) {
+ delete [] mNaluHeaderBuffer;
+ mNaluHeaderBuffer = NULL;
+ }
+ return DECODE_MEMORY_FAIL;
+ }
+
+ return status;
+}
+
+void VideoDecoderAVCSecure::stop(void) {
+ VideoDecoderAVC::stop();
+
+ if (mNaluHeaderBuffer) {
+ delete [] mNaluHeaderBuffer;
+ mNaluHeaderBuffer = NULL;
+ }
+
+ if (mSliceHeaderBuffer) {
+ delete [] mSliceHeaderBuffer;
+ mSliceHeaderBuffer = NULL;
+ }
+
+}
+
+Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
+ Decode_Status status;
+ int32_t sizeAccumulated = 0;
+ int32_t sliceHeaderSize = 0;
+ int32_t sizeLeft = 0;
+ int32_t sliceIdx = 0;
+ uint8_t naluType;
+ frame_info_t* pFrameInfo;
+
+ mFrameSize = 0;
+ if (buffer->flag & IS_SECURE_DATA) {
+ VTRACE("Decoding protected video ...");
+ mIsEncryptData = 1;
+ } else {
+ VTRACE("Decoding clear video ...");
+ mIsEncryptData = 0;
+ return VideoDecoderAVC::decode(buffer);
+ }
+
+ if (buffer->size != sizeof(frame_info_t)) {
+ ETRACE("Not enough data to read frame_info_t!");
+ return DECODE_INVALID_DATA;
+ }
+ pFrameInfo = (frame_info_t*) buffer->data;
+
+ mFrameSize = pFrameInfo->length;
+ VTRACE("mFrameSize = %d", mFrameSize);
+
+ memcpy(&mEncParam, pFrameInfo->pavp, sizeof(pavp_info_t));
+ for (int32_t i = 0; i < pFrameInfo->num_nalus; i++) {
+ naluType = pFrameInfo->nalus[i].type & NALU_TYPE_MASK;
+ if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
+ memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+ &sliceIdx,
+ sizeof(int32_t));
+ sliceHeaderSize += 4;
+
+ memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+ &pFrameInfo->data,
+ sizeof(uint8_t*));
+ sliceHeaderSize += sizeof(uint8_t*);
+
+ memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+ &pFrameInfo->nalus[i].offset,
+ sizeof(uint32_t));
+ sliceHeaderSize += sizeof(uint32_t);
+
+ memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+ &pFrameInfo->nalus[i].length,
+ sizeof(uint32_t));
+ sliceHeaderSize += sizeof(uint32_t);
+
+ memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+ pFrameInfo->nalus[i].slice_header,
+ sizeof(slice_header_t));
+ sliceHeaderSize += sizeof(slice_header_t);
+ if (pFrameInfo->nalus[i].type & 0x60) {
+ memcpy(mSliceHeaderBuffer+sliceHeaderSize, pFrameInfo->dec_ref_pic_marking, sizeof(dec_ref_pic_marking_t));
+ } else {
+ memset(mSliceHeaderBuffer+sliceHeaderSize, 0, sizeof(dec_ref_pic_marking_t));
+ }
+ sliceHeaderSize += sizeof(dec_ref_pic_marking_t);
+ sliceIdx++;
+ } else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
+ memcpy(mNaluHeaderBuffer + sizeAccumulated,
+ startcodePrefix,
+ STARTCODE_PREFIX_LEN);
+ sizeAccumulated += STARTCODE_PREFIX_LEN;
+ memcpy(mNaluHeaderBuffer + sizeAccumulated,
+ pFrameInfo->nalus[i].data,
+ pFrameInfo->nalus[i].length);
+ sizeAccumulated += pFrameInfo->nalus[i].length;
+ } else {
+ WTRACE("Failure: DECODE_FRAME_DROPPED");
+ return DECODE_FRAME_DROPPED;
+ }
+ }
+
+ vbp_data_h264 *data = NULL;
+ int new_sequence_to_handle = 0;
+
+ if (sizeAccumulated > 0) {
+ status = VideoDecoderBase::parseBuffer(
+ mNaluHeaderBuffer,
+ sizeAccumulated,
+ false,
+ (void**)&data);
+ CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+ // [FIX DRC zoom issue] if one buffer contains more than one nalu
+ // for example SPS+PPS+IDR, new_sps/new_pps flags set in parseBuffer
+ // will be flushed in the following updateBuffer.
+ // So that handleNewSequence will not be handled in decodeFrame()
+ if (data->new_sps || data->new_pps) {
+ new_sequence_to_handle = 1;
+ }
+ }
+
+ if (sliceHeaderSize > 0) {
+ memset(mSliceHeaderBuffer + sliceHeaderSize, 0xFF, 4);
+ sliceHeaderSize += 4;
+ status = VideoDecoderBase::updateBuffer(
+ mSliceHeaderBuffer,
+ sliceHeaderSize,
+ (void**)&data);
+ CHECK_STATUS("VideoDecoderBase::updateBuffer");
+
+ // in case the flags were flushed but indeed new sequence needed to be handled.
+ if ((1 == new_sequence_to_handle) &&
+ ((data->new_sps == 0) || (data->new_pps == 0))) {
+ data->new_sps = 1;
+ data->new_pps = 1;
+ }
+ }
+
+ if (data == NULL) {
+ ETRACE("Invalid data returned by parser!");
+ return DECODE_MEMORY_FAIL;
+ }
+
+ if (!mVAStarted) {
+ if (data->has_sps && data->has_pps) {
+ status = startVA(data);
+ CHECK_STATUS("startVA");
+ } else {
+ WTRACE("Can't start VA as either SPS or PPS is still not available.");
+ return DECODE_SUCCESS;
+ }
+ }
+ status = decodeFrame(buffer, data);
+ return status;
+}
+
+Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+ Decode_Status status;
+ VAStatus vaStatus;
+ uint32_t bufferIDCount = 0;
+ // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
+ VABufferID bufferIDs[5];
+
+ vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+ vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+ VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+ VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+ VAEncryptionParameterBuffer encryptParam;
+
+ if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+ // either condition indicates start of a new frame
+ if (sliceParam->first_mb_in_slice != 0) {
+ WTRACE("The first slice is lost.");
+ // TODO: handle the first slice lost
+ }
+ if (mDecodingFrame) {
+ // interlace content, complete decoding the first field
+ vaStatus = vaEndPicture(mVADisplay, mVAContext);
+ CHECK_VA_STATUS("vaEndPicture");
+
+ // for interlace content, top field may be valid only after the second field is parsed
+ mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
+ }
+
+ // Update the reference frames and surface IDs for DPB and current frame
+ status = updateDPB(picParam);
+ CHECK_STATUS("updateDPB");
+
+ vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+ CHECK_VA_STATUS("vaBeginPicture");
+
+ // start decoding a frame
+ mDecodingFrame = true;
+
+ vaStatus = vaCreateBuffer(
+ mVADisplay,
+ mVAContext,
+ VAPictureParameterBufferType,
+ sizeof(VAPictureParameterBufferH264),
+ 1,
+ picParam,
+ &bufferIDs[bufferIDCount]);
+ CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+ bufferIDCount++;
+
+ vaStatus = vaCreateBuffer(
+ mVADisplay,
+ mVAContext,
+ VAIQMatrixBufferType,
+ sizeof(VAIQMatrixBufferH264),
+ 1,
+ data->IQ_matrix_buf,
+ &bufferIDs[bufferIDCount]);
+ CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+ bufferIDCount++;
+
+ if (mIsEncryptData) {
+ memset(&encryptParam, 0, sizeof(VAEncryptionParameterBuffer));
+ encryptParam.pavpCounterMode = 4;
+ encryptParam.pavpEncryptionType = 2;
+ encryptParam.hostEncryptMode = 2;
+ encryptParam.pavpHasBeenEnabled = 1;
+ encryptParam.app_id = 0;
+ memcpy(encryptParam.pavpAesCounter, mEncParam.iv, 16);
+
+ vaStatus = vaCreateBuffer(
+ mVADisplay,
+ mVAContext,
+ (VABufferType)VAEncryptionParameterBufferType,
+ sizeof(VAEncryptionParameterBuffer),
+ 1,
+ &encryptParam,
+ &bufferIDs[bufferIDCount]);
+ CHECK_VA_STATUS("vaCreateEncryptionParameterBuffer");
+ bufferIDCount++;
+ }
+
+ vaStatus = vaCreateBuffer(
+ mVADisplay,
+ mVAContext,
+ VASliceDataBufferType,
+ mFrameSize, //size
+ 1, //num_elements
+ sliceData->buffer_addr + sliceData->slice_offset,
+ &bufferIDs[bufferIDCount]);
+ CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+ bufferIDCount++;
+
+ }
+
+ vaStatus = vaCreateBuffer(
+ mVADisplay,
+ mVAContext,
+ VASliceParameterBufferType,
+ sizeof(VASliceParameterBufferH264Base),
+ 1,
+ sliceParam,
+ &bufferIDs[bufferIDCount]);
+
+ CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+ bufferIDCount++;
+
+ vaStatus = vaRenderPicture(
+ mVADisplay,
+ mVAContext,
+ bufferIDs,
+ bufferIDCount);
+ CHECK_VA_STATUS("vaRenderPicture");
+
+ return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
+ VAProfile profile, VAConfigID *config)
+{
+ VAStatus vaStatus;
+ VAConfigAttrib attrib[2];
+
+ if (config == NULL) {
+ ETRACE("Invalid parameter!");
+ return DECODE_FAIL;
+ }
+
+ attrib[0].type = VAConfigAttribRTFormat;
+ attrib[0].value = VA_RT_FORMAT_YUV420;
+ attrib[1].type = VAConfigAttribDecSliceMode;
+ attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+
+ vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
+
+ if (attrib[1].value & VA_DEC_SLICE_MODE_BASE)
+ {
+ ITRACE("AVC short format used");
+ attrib[1].value = VA_DEC_SLICE_MODE_BASE;
+ } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
+ ITRACE("AVC long format ssed");
+ attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+ } else {
+ ETRACE("Unsupported Decode Slice Mode!");
+ return DECODE_FAIL;
+ }
+
+ vaStatus = vaCreateConfig(
+ mVADisplay,
+ profile,
+ VAEntrypointVLD,
+ &attrib[0],
+ 2,
+ config);
+ CHECK_VA_STATUS("vaCreateConfig");
+
+ return DECODE_SUCCESS;
+}