Home | History | Annotate | Download | only in clovertrail
      1 /*
      2 * Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #include "VideoDecoderAVCSecure.h"
     18 #include "VideoDecoderTrace.h"
     19 #include <string.h>
     20 
     21 
     22 #define STARTCODE_00                0x00
     23 #define STARTCODE_01                0x01
     24 #define STARTCODE_PREFIX_LEN        3
     25 #define NALU_TYPE_MASK              0x1F
     26 
     27 
     28 // mask for little endian, to mast the second and fourth bytes in the byte stream
     29 #define STARTCODE_MASK0             0xFF000000 //0x00FF0000
     30 #define STARTCODE_MASK1             0x0000FF00  //0x000000FF
     31 
     32 
     33 typedef enum {
     34     NAL_UNIT_TYPE_unspecified0 = 0,
     35     NAL_UNIT_TYPE_SLICE,
     36     NAL_UNIT_TYPE_DPA,
     37     NAL_UNIT_TYPE_DPB,
     38     NAL_UNIT_TYPE_DPC,
     39     NAL_UNIT_TYPE_IDR,
     40     NAL_UNIT_TYPE_SEI,
     41     NAL_UNIT_TYPE_SPS,
     42     NAL_UNIT_TYPE_PPS,
     43     NAL_UNIT_TYPE_Acc_unit_delimiter,
     44     NAL_UNIT_TYPE_EOSeq,
     45     NAL_UNIT_TYPE_EOstream,
     46     NAL_UNIT_TYPE_filler_data,
     47     NAL_UNIT_TYPE_SPS_extension,
     48     NAL_UNIT_TYPE_Reserved14,
     49     NAL_UNIT_TYPE_Reserved15,
     50     NAL_UNIT_TYPE_Reserved16,
     51     NAL_UNIT_TYPE_Reserved17,
     52     NAL_UNIT_TYPE_Reserved18,
     53     NAL_UNIT_TYPE_ACP,
     54     NAL_UNIT_TYPE_Reserved20,
     55     NAL_UNIT_TYPE_Reserved21,
     56     NAL_UNIT_TYPE_Reserved22,
     57     NAL_UNIT_TYPE_Reserved23,
     58     NAL_UNIT_TYPE_unspecified24,
     59 } NAL_UNIT_TYPE;
     60 
     61 #ifndef min
     62 #define min(X, Y)  ((X) <(Y) ? (X) : (Y))
     63 #endif
     64 
     65 
     66 static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
     67 
     68 
     69 VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
     70     : VideoDecoderAVC(mimeType),
     71       mNaluHeaderBuffer(NULL),
     72       mInputBuffer(NULL) {
     73 
     74     memset(&mMetadata, 0, sizeof(NaluMetadata));
     75     memset(&mByteStream, 0, sizeof(NaluByteStream));
     76 }
     77 
     78 VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
     79 }
     80 
     81 Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
     82     Decode_Status status = VideoDecoderAVC::start(buffer);
     83     if (status != DECODE_SUCCESS) {
     84         return status;
     85     }
     86 
     87     mMetadata.naluInfo = new NaluInfo [MAX_NALU_NUMBER];
     88     mByteStream.byteStream = new uint8_t [MAX_NALU_HEADER_BUFFER];
     89     mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
     90 
     91     if (mMetadata.naluInfo == NULL ||
     92         mByteStream.byteStream == NULL ||
     93         mNaluHeaderBuffer == NULL) {
     94         ETRACE("Failed to allocate memory.");
     95         // TODO: release all allocated memory
     96         return DECODE_MEMORY_FAIL;
     97     }
     98     return status;
     99 }
    100 
    101 void VideoDecoderAVCSecure::stop(void) {
    102     VideoDecoderAVC::stop();
    103 
    104     if (mMetadata.naluInfo) {
    105         delete [] mMetadata.naluInfo;
    106         mMetadata.naluInfo = NULL;
    107     }
    108 
    109     if (mByteStream.byteStream) {
    110         delete [] mByteStream.byteStream;
    111         mByteStream.byteStream = NULL;
    112     }
    113 
    114     if (mNaluHeaderBuffer) {
    115         delete [] mNaluHeaderBuffer;
    116         mNaluHeaderBuffer = NULL;
    117     }
    118 }
    119 
    120 Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
    121     Decode_Status status;
    122     int32_t sizeAccumulated = 0;
    123     int32_t sizeLeft = 0;
    124     uint8_t *pByteStream = NULL;
    125     NaluInfo *pNaluInfo = mMetadata.naluInfo;
    126 
    127     if (buffer->flag & IS_SECURE_DATA) {
    128         pByteStream = buffer->data;
    129         sizeLeft = buffer->size;
    130         mInputBuffer = NULL;
    131     } else {
    132         status = parseAnnexBStream(buffer->data, buffer->size, &mByteStream);
    133         CHECK_STATUS("parseAnnexBStream");
    134         pByteStream = mByteStream.byteStream;
    135         sizeLeft = mByteStream.streamPos;
    136         mInputBuffer = buffer->data;
    137     }
    138     if (sizeLeft < 4) {
    139         ETRACE("Not enough data to read number of NALU.");
    140         return DECODE_INVALID_DATA;
    141     }
    142 
    143     // read number of NALU
    144     memcpy(&(mMetadata.naluNumber), pByteStream, sizeof(int32_t));
    145     pByteStream += 4;
    146     sizeLeft -= 4;
    147 
    148     if (mMetadata.naluNumber == 0) {
    149         WTRACE("Number of NALU is ZERO!");
    150         return DECODE_SUCCESS;
    151     }
    152 
    153     for (int32_t i = 0; i < mMetadata.naluNumber; i++) {
    154         if (sizeLeft < 12) {
    155             ETRACE("Not enough data to parse NALU offset, size, header length for NALU %d, left = %d", i, sizeLeft);
    156             return DECODE_INVALID_DATA;
    157         }
    158         sizeLeft -= 12;
    159         // read NALU offset
    160         memcpy(&(pNaluInfo->naluOffset), pByteStream, sizeof(int32_t));
    161         pByteStream += 4;
    162 
    163         // read NALU size
    164         memcpy(&(pNaluInfo->naluLen), pByteStream, sizeof(int32_t));
    165         pByteStream += 4;
    166 
    167         // read NALU header length
    168         memcpy(&(pNaluInfo->naluHeaderLen), pByteStream, sizeof(int32_t));
    169         pByteStream += 4;
    170 
    171         if (sizeLeft < pNaluInfo->naluHeaderLen) {
    172             ETRACE("Not enough data to copy NALU header for %d, left = %d, header len = %d", i, sizeLeft, pNaluInfo->naluHeaderLen);
    173             return DECODE_INVALID_DATA;
    174         }
    175 
    176         sizeLeft -=  pNaluInfo->naluHeaderLen;
    177 
    178         if (pNaluInfo->naluHeaderLen) {
    179             // copy start code prefix to buffer
    180             memcpy(mNaluHeaderBuffer + sizeAccumulated,
    181                 startcodePrefix,
    182                 STARTCODE_PREFIX_LEN);
    183             sizeAccumulated += STARTCODE_PREFIX_LEN;
    184 
    185             // copy NALU header
    186             memcpy(mNaluHeaderBuffer + sizeAccumulated, pByteStream, pNaluInfo->naluHeaderLen);
    187             pByteStream += pNaluInfo->naluHeaderLen;
    188 
    189             sizeAccumulated += pNaluInfo->naluHeaderLen;
    190         } else {
    191             WTRACE("header len is zero for NALU %d", i);
    192         }
    193 
    194         // for next NALU
    195         pNaluInfo++;
    196     }
    197 
    198     buffer->data = mNaluHeaderBuffer;
    199     buffer->size = sizeAccumulated;
    200 
    201     return VideoDecoderAVC::decode(buffer);
    202 }
    203 
    204 
    205 Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
    206 
    207     Decode_Status status;
    208     VAStatus vaStatus;
    209     uint32_t bufferIDCount = 0;
    210     // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
    211     VABufferID bufferIDs[4];
    212 
    213     vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
    214     vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
    215     VAPictureParameterBufferH264 *picParam = picData->pic_parms;
    216     VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
    217 
    218     if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
    219         // either condition indicates start of a new frame
    220         if (sliceParam->first_mb_in_slice != 0) {
    221             WTRACE("The first slice is lost.");
    222             // TODO: handle the first slice lost
    223         }
    224         if (mDecodingFrame) {
    225             // interlace content, complete decoding the first field
    226             vaStatus = vaEndPicture(mVADisplay, mVAContext);
    227             CHECK_VA_STATUS("vaEndPicture");
    228 
    229             // for interlace content, top field may be valid only after the second field is parsed
    230             mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
    231         }
    232 
    233         // Check there is no reference frame loss before decoding a frame
    234 
    235         // Update  the reference frames and surface IDs for DPB and current frame
    236         status = updateDPB(picParam);
    237         CHECK_STATUS("updateDPB");
    238 
    239         //We have to provide a hacked DPB rather than complete DPB for libva as workaround
    240         status = updateReferenceFrames(picData);
    241         CHECK_STATUS("updateReferenceFrames");
    242 
    243         vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    244         CHECK_VA_STATUS("vaBeginPicture");
    245 
    246         // start decoding a frame
    247         mDecodingFrame = true;
    248 
    249         vaStatus = vaCreateBuffer(
    250             mVADisplay,
    251             mVAContext,
    252             VAPictureParameterBufferType,
    253             sizeof(VAPictureParameterBufferH264),
    254             1,
    255             picParam,
    256             &bufferIDs[bufferIDCount]);
    257         CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    258         bufferIDCount++;
    259 
    260         vaStatus = vaCreateBuffer(
    261             mVADisplay,
    262             mVAContext,
    263             VAIQMatrixBufferType,
    264             sizeof(VAIQMatrixBufferH264),
    265             1,
    266             data->IQ_matrix_buf,
    267             &bufferIDs[bufferIDCount]);
    268         CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
    269         bufferIDCount++;
    270     }
    271 
    272     status = setReference(sliceParam);
    273     CHECK_STATUS("setReference");
    274 
    275     // find which naluinfo is correlated to current slice
    276     int naluIndex = 0;
    277     uint32_t accumulatedHeaderLen = 0;
    278     uint32_t headerLen = 0;
    279     for (; naluIndex < mMetadata.naluNumber; naluIndex++)  {
    280         headerLen = mMetadata.naluInfo[naluIndex].naluHeaderLen;
    281         if (headerLen == 0) {
    282             WTRACE("lenght of current NAL unit is 0.");
    283             continue;
    284         }
    285         accumulatedHeaderLen += STARTCODE_PREFIX_LEN;
    286         if (accumulatedHeaderLen + headerLen > sliceData->slice_offset) {
    287             break;
    288         }
    289         accumulatedHeaderLen += headerLen;
    290     }
    291 
    292     if (sliceData->slice_offset != accumulatedHeaderLen) {
    293         WTRACE("unexpected slice offset %d, accumulatedHeaderLen = %d", sliceData->slice_offset, accumulatedHeaderLen);
    294     }
    295 
    296     sliceParam->slice_data_size = mMetadata.naluInfo[naluIndex].naluLen;
    297     sliceData->slice_size = sliceParam->slice_data_size;
    298 
    299     // no need to update:
    300     // sliceParam->slice_data_offset - 0 always
    301     // sliceParam->slice_data_bit_offset - relative to  sliceData->slice_offset
    302 
    303     vaStatus = vaCreateBuffer(
    304         mVADisplay,
    305         mVAContext,
    306         VASliceParameterBufferType,
    307         sizeof(VASliceParameterBufferH264),
    308         1,
    309         sliceParam,
    310         &bufferIDs[bufferIDCount]);
    311     CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
    312     bufferIDCount++;
    313 
    314     // sliceData->slice_offset - accumulatedHeaderLen is the absolute offset to start codes of current NAL unit
    315     // offset points to first byte of NAL unit
    316     uint32_t sliceOffset = mMetadata.naluInfo[naluIndex].naluOffset;
    317     if (mInputBuffer != NULL) {
    318         vaStatus = vaCreateBuffer(
    319             mVADisplay,
    320             mVAContext,
    321             VASliceDataBufferType,
    322             sliceData->slice_size, //size
    323             1,        //num_elements
    324             mInputBuffer  + sliceOffset,
    325             &bufferIDs[bufferIDCount]);
    326     } else {
    327         vaStatus = vaCreateBuffer(
    328             mVADisplay,
    329             mVAContext,
    330             VAProtectedSliceDataBufferType,
    331             sliceData->slice_size, //size
    332             1,        //num_elements
    333             (uint8_t*)sliceOffset, // IMR offset
    334             &bufferIDs[bufferIDCount]);
    335     }
    336     CHECK_VA_STATUS("vaCreateSliceDataBuffer");
    337     bufferIDCount++;
    338 
    339     vaStatus = vaRenderPicture(
    340         mVADisplay,
    341         mVAContext,
    342         bufferIDs,
    343         bufferIDCount);
    344     CHECK_VA_STATUS("vaRenderPicture");
    345 
    346     return DECODE_SUCCESS;
    347 }
    348 
    349 
    350 // Parse byte string pattern "0x000001" (3 bytes)  in the current buffer.
    351 // Returns offset of position following  the pattern in the buffer if pattern is found or -1 if not found.
    352 int32_t VideoDecoderAVCSecure::findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length) {
    353     uint8_t *ptr;
    354     uint32_t left = 0, data = 0, phase = 0;
    355     uint8_t mask1 = 0, mask2 = 0;
    356 
    357     /* Meaning of phase:
    358         0: initial status, "0x000001" bytes are not found so far;
    359         1: one "0x00" byte is found;
    360         2: two or more consecutive "0x00" bytes" are found;
    361         3: "0x000001" patten is found ;
    362         4: if there is one more byte after "0x000001";
    363        */
    364 
    365     left = length;
    366     ptr = (uint8_t *) (stream + offset);
    367     phase = 0;
    368 
    369     // parse until there is more data and start code not found
    370     while ((left > 0) && (phase < 3)) {
    371         // Check if the address is 32-bit aligned & phase=0, if thats the case we can check 4 bytes instead of one byte at a time.
    372         if (((((uint32_t)ptr) & 0x3) == 0) && (phase == 0)) {
    373             while (left > 3) {
    374                 data = *((uint32_t *)ptr);
    375                 mask1 = (STARTCODE_00 != (data & STARTCODE_MASK0));
    376                 mask2 = (STARTCODE_00 != (data & STARTCODE_MASK1));
    377                 // If second byte and fourth byte are not zero's then we cannot have a start code here,
    378                 //  as we need two consecutive zero bytes for a start code pattern.
    379                 if (mask1 && mask2) {
    380                     // skip 4 bytes and start over
    381                     ptr += 4;
    382                     left -=4;
    383                     continue;
    384                 } else {
    385                     break;
    386                 }
    387             }
    388         }
    389 
    390         // At this point either data is not on a 32-bit boundary or phase > 0 so we look at one byte at a time
    391         if (left > 0) {
    392             if (*ptr == STARTCODE_00) {
    393                 phase++;
    394                 if (phase > 2) {
    395                     // more than 2 consecutive '0x00' bytes is found
    396                     phase = 2;
    397                 }
    398             } else if ((*ptr == STARTCODE_01) && (phase == 2)) {
    399                 // start code is found
    400                 phase = 3;
    401             } else {
    402                 // reset lookup
    403                 phase = 0;
    404             }
    405             ptr++;
    406             left--;
    407         }
    408     }
    409 
    410     if ((left > 0) && (phase == 3)) {
    411         phase = 4;
    412         // return offset of position following the pattern in the buffer which matches "0x000001" byte string
    413         return (int32_t)(ptr - stream);
    414     }
    415     return -1;
    416 }
    417 
    418 
    419 Decode_Status VideoDecoderAVCSecure::copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream) {
    420     uint8_t naluType;
    421     int32_t naluHeaderLen;
    422 
    423     naluType = *(uint8_t *)(stream + naluStream->naluOffset);
    424     naluType &= NALU_TYPE_MASK;
    425     // first update nalu header length based on nalu type
    426     if (naluType >= NAL_UNIT_TYPE_SLICE && naluType <= NAL_UNIT_TYPE_IDR) {
    427         // coded slice, return only up to MAX_SLICE_HEADER_SIZE bytes
    428         naluHeaderLen = min(naluStream->naluLen, MAX_SLICE_HEADER_SIZE);
    429     } else if (naluType >= NAL_UNIT_TYPE_SEI && naluType <= NAL_UNIT_TYPE_PPS) {
    430         //sps, pps, sei, etc, return the entire NAL unit in clear
    431         naluHeaderLen = naluStream->naluLen;
    432     } else {
    433         return DECODE_FRAME_DROPPED;
    434     }
    435 
    436     memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluOffset), sizeof(int32_t));
    437     naluStream->streamPos += 4;
    438 
    439     memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluLen), sizeof(int32_t));
    440     naluStream->streamPos += 4;
    441 
    442     memcpy(naluStream->byteStream + naluStream->streamPos, &naluHeaderLen, sizeof(int32_t));
    443     naluStream->streamPos += 4;
    444 
    445     if (naluHeaderLen) {
    446         memcpy(naluStream->byteStream + naluStream->streamPos, (uint8_t*)(stream + naluStream->naluOffset), naluHeaderLen);
    447         naluStream->streamPos += naluHeaderLen;
    448     }
    449     return DECODE_SUCCESS;
    450 }
    451 
    452 
    453 // parse start-code prefixed stream, also knowns as Annex B byte stream, commonly used in AVI, ES, MPEG2 TS container
    454 Decode_Status VideoDecoderAVCSecure::parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream) {
    455     int32_t naluOffset, offset, left;
    456     NaluInfo *info;
    457     uint32_t ret = DECODE_SUCCESS;
    458 
    459     naluOffset = 0;
    460     offset = 0;
    461     left = length;
    462 
    463     // leave 4 bytes to copy nalu count
    464     naluStream->streamPos = 4;
    465     naluStream->naluCount = 0;
    466     memset(naluStream->byteStream, 0, MAX_NALU_HEADER_BUFFER);
    467 
    468     for (; ;) {
    469         naluOffset = findNalUnitOffset(stream, offset, left);
    470         if (naluOffset == -1) {
    471             break;
    472         }
    473 
    474         if (naluStream->naluCount == 0) {
    475             naluStream->naluOffset = naluOffset;
    476         } else {
    477             naluStream->naluLen = naluOffset - naluStream->naluOffset - STARTCODE_PREFIX_LEN;
    478             ret = copyNaluHeader(stream, naluStream);
    479             if (ret != DECODE_SUCCESS && ret != DECODE_FRAME_DROPPED) {
    480                 LOGW("copyNaluHeader returned %d", ret);
    481                 return ret;
    482             }
    483             // starting position for next NALU
    484             naluStream->naluOffset = naluOffset;
    485         }
    486 
    487         if (ret == DECODE_SUCCESS) {
    488             naluStream->naluCount++;
    489         }
    490 
    491         // update next lookup position and length
    492         offset = naluOffset + 1; // skip one byte of NAL unit type
    493         left = length - offset;
    494     }
    495 
    496     if (naluStream->naluCount > 0) {
    497         naluStream->naluLen = length - naluStream->naluOffset;
    498         memcpy(naluStream->byteStream, &(naluStream->naluCount), sizeof(int32_t));
    499         // ignore return value, either DECODE_SUCCESS or DECODE_FRAME_DROPPED
    500         copyNaluHeader(stream, naluStream);
    501         return DECODE_SUCCESS;
    502     }
    503 
    504     LOGW("number of valid NALU is 0!");
    505     return DECODE_SUCCESS;
    506 }
    507 
    508