Home | History | Annotate | Download | only in merrplus
      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         // NALU headers are appended to encrypted video bitstream
    129         // |...encrypted video bitstream (16 bytes aligned)...| 4 bytes of header size |...NALU headers..|
    130         pByteStream = buffer->data + buffer->size + 4;
    131         sizeLeft = *(int32_t *)(buffer->data + buffer->size);
    132         VTRACE("%s sizeLeft: %d buffer->size: %#x", __func__, sizeLeft, buffer->size);
    133         mInputBuffer = buffer->data;
    134     } else {
    135         status = parseAnnexBStream(buffer->data, buffer->size, &mByteStream);
    136         CHECK_STATUS("parseAnnexBStream");
    137         pByteStream = mByteStream.byteStream;
    138         sizeLeft = mByteStream.streamPos;
    139         mInputBuffer = buffer->data;
    140     }
    141     if (sizeLeft < 4) {
    142         ETRACE("Not enough data to read number of NALU.");
    143         return DECODE_INVALID_DATA;
    144     }
    145 
    146     // read number of NALU
    147     memcpy(&(mMetadata.naluNumber), pByteStream, sizeof(int32_t));
    148     pByteStream += 4;
    149     sizeLeft -= 4;
    150 
    151     if (mMetadata.naluNumber == 0) {
    152         WTRACE("Number of NALU is ZERO!");
    153         return DECODE_SUCCESS;
    154     }
    155 
    156     for (int32_t i = 0; i < mMetadata.naluNumber; i++) {
    157         if (sizeLeft < 12) {
    158             ETRACE("Not enough data to parse NALU offset, size, header length for NALU %d, left = %d", i, sizeLeft);
    159             return DECODE_INVALID_DATA;
    160         }
    161         sizeLeft -= 12;
    162         // read NALU offset
    163         memcpy(&(pNaluInfo->naluOffset), pByteStream, sizeof(int32_t));
    164         pByteStream += 4;
    165 
    166         // read NALU size
    167         memcpy(&(pNaluInfo->naluLen), pByteStream, sizeof(int32_t));
    168         pByteStream += 4;
    169 
    170         // read NALU header length
    171         memcpy(&(pNaluInfo->naluHeaderLen), pByteStream, sizeof(int32_t));
    172         pByteStream += 4;
    173 
    174 
    175         if (sizeLeft < pNaluInfo->naluHeaderLen) {
    176             ETRACE("Not enough data to copy NALU header for %d, left = %d, header len = %d", i, sizeLeft, pNaluInfo->naluHeaderLen);
    177             return DECODE_INVALID_DATA;
    178         }
    179 
    180         sizeLeft -=  pNaluInfo->naluHeaderLen;
    181 
    182         if (pNaluInfo->naluHeaderLen) {
    183             // copy start code prefix to buffer
    184             memcpy(mNaluHeaderBuffer + sizeAccumulated,
    185                 startcodePrefix,
    186                 STARTCODE_PREFIX_LEN);
    187             sizeAccumulated += STARTCODE_PREFIX_LEN;
    188 
    189             // copy NALU header
    190             memcpy(mNaluHeaderBuffer + sizeAccumulated, pByteStream, pNaluInfo->naluHeaderLen);
    191             pByteStream += pNaluInfo->naluHeaderLen;
    192 
    193             sizeAccumulated += pNaluInfo->naluHeaderLen;
    194         } else {
    195             WTRACE("header len is zero for NALU %d", i);
    196         }
    197 
    198         // for next NALU
    199         pNaluInfo++;
    200     }
    201 
    202     buffer->data = mNaluHeaderBuffer;
    203     buffer->size = sizeAccumulated;
    204 
    205     return VideoDecoderAVC::decode(buffer);
    206 }
    207 
    208 
    209 Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
    210 
    211     Decode_Status status;
    212     VAStatus vaStatus;
    213     uint32_t bufferIDCount = 0;
    214     // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
    215     VABufferID bufferIDs[4];
    216 
    217     vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
    218     vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
    219     VAPictureParameterBufferH264 *picParam = picData->pic_parms;
    220     VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
    221 
    222     if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
    223         // either condition indicates start of a new frame
    224         if (sliceParam->first_mb_in_slice != 0) {
    225             WTRACE("The first slice is lost.");
    226             // TODO: handle the first slice lost
    227         }
    228         if (mDecodingFrame) {
    229             // interlace content, complete decoding the first field
    230             vaStatus = vaEndPicture(mVADisplay, mVAContext);
    231             CHECK_VA_STATUS("vaEndPicture");
    232 
    233             // for interlace content, top field may be valid only after the second field is parsed
    234             mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
    235         }
    236 
    237         // Check there is no reference frame loss before decoding a frame
    238 
    239         // Update  the reference frames and surface IDs for DPB and current frame
    240         status = updateDPB(picParam);
    241         CHECK_STATUS("updateDPB");
    242 
    243         //We have to provide a hacked DPB rather than complete DPB for libva as workaround
    244         status = updateReferenceFrames(picData);
    245         CHECK_STATUS("updateReferenceFrames");
    246 
    247         vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    248         CHECK_VA_STATUS("vaBeginPicture");
    249 
    250         // start decoding a frame
    251         mDecodingFrame = true;
    252 
    253         vaStatus = vaCreateBuffer(
    254             mVADisplay,
    255             mVAContext,
    256             VAPictureParameterBufferType,
    257             sizeof(VAPictureParameterBufferH264),
    258             1,
    259             picParam,
    260             &bufferIDs[bufferIDCount]);
    261         CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    262         bufferIDCount++;
    263 
    264         vaStatus = vaCreateBuffer(
    265             mVADisplay,
    266             mVAContext,
    267             VAIQMatrixBufferType,
    268             sizeof(VAIQMatrixBufferH264),
    269             1,
    270             data->IQ_matrix_buf,
    271             &bufferIDs[bufferIDCount]);
    272         CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
    273         bufferIDCount++;
    274     }
    275 
    276     status = setReference(sliceParam);
    277     CHECK_STATUS("setReference");
    278 
    279     // find which naluinfo is correlated to current slice
    280     int naluIndex = 0;
    281     uint32_t accumulatedHeaderLen = 0;
    282     uint32_t headerLen = 0;
    283     for (; naluIndex < mMetadata.naluNumber; naluIndex++)  {
    284         headerLen = mMetadata.naluInfo[naluIndex].naluHeaderLen;
    285         if (headerLen == 0) {
    286             WTRACE("lenght of current NAL unit is 0.");
    287             continue;
    288         }
    289         accumulatedHeaderLen += STARTCODE_PREFIX_LEN;
    290         if (accumulatedHeaderLen + headerLen > sliceData->slice_offset) {
    291             break;
    292         }
    293         accumulatedHeaderLen += headerLen;
    294     }
    295 
    296     if (sliceData->slice_offset != accumulatedHeaderLen) {
    297         WTRACE("unexpected slice offset %d, accumulatedHeaderLen = %d", sliceData->slice_offset, accumulatedHeaderLen);
    298     }
    299 
    300     sliceParam->slice_data_size = mMetadata.naluInfo[naluIndex].naluLen;
    301     uint32_t sliceOffset = mMetadata.naluInfo[naluIndex].naluOffset;
    302     uint32_t slice_offset_shift =  sliceOffset % 16;
    303     sliceParam->slice_data_offset += slice_offset_shift;
    304     sliceData->slice_size = (sliceParam->slice_data_size + slice_offset_shift + 0xF) & ~0xF;
    305 
    306     vaStatus = vaCreateBuffer(
    307         mVADisplay,
    308         mVAContext,
    309         VASliceParameterBufferType,
    310         sizeof(VASliceParameterBufferH264),
    311         1,
    312         sliceParam,
    313         &bufferIDs[bufferIDCount]);
    314     CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
    315     bufferIDCount++;
    316 
    317     // sliceData->slice_offset - accumulatedHeaderLen is the absolute offset to start codes of current NAL unit
    318     // offset points to first byte of NAL unit
    319 
    320     if (mInputBuffer != NULL) {
    321         vaStatus = vaCreateBuffer(
    322             mVADisplay,
    323             mVAContext,
    324             VASliceDataBufferType,
    325             sliceData->slice_size,  //Slice size
    326             1,                      // num_elements
    327             mInputBuffer + sliceOffset - slice_offset_shift,
    328             &bufferIDs[bufferIDCount]);
    329     } else {
    330         vaStatus = vaCreateBuffer(
    331             mVADisplay,
    332             mVAContext,
    333             VAProtectedSliceDataBufferType,
    334             sliceData->slice_size, //size
    335             1,        //num_elements
    336             (uint8_t*)sliceOffset, // IMR offset
    337             &bufferIDs[bufferIDCount]);
    338     }
    339     CHECK_VA_STATUS("vaCreateSliceDataBuffer");
    340     bufferIDCount++;
    341 
    342     vaStatus = vaRenderPicture(
    343         mVADisplay,
    344         mVAContext,
    345         bufferIDs,
    346         bufferIDCount);
    347     CHECK_VA_STATUS("vaRenderPicture");
    348 
    349     return DECODE_SUCCESS;
    350 }
    351 
    352 
    353 // Parse byte string pattern "0x000001" (3 bytes)  in the current buffer.
    354 // Returns offset of position following  the pattern in the buffer if pattern is found or -1 if not found.
    355 int32_t VideoDecoderAVCSecure::findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length) {
    356     uint8_t *ptr;
    357     uint32_t left = 0, data = 0, phase = 0;
    358     uint8_t mask1 = 0, mask2 = 0;
    359 
    360     /* Meaning of phase:
    361         0: initial status, "0x000001" bytes are not found so far;
    362         1: one "0x00" byte is found;
    363         2: two or more consecutive "0x00" bytes" are found;
    364         3: "0x000001" patten is found ;
    365         4: if there is one more byte after "0x000001";
    366        */
    367 
    368     left = length;
    369     ptr = (uint8_t *) (stream + offset);
    370     phase = 0;
    371 
    372     // parse until there is more data and start code not found
    373     while ((left > 0) && (phase < 3)) {
    374         // 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.
    375         if (((((uint32_t)ptr) & 0x3) == 0) && (phase == 0)) {
    376             while (left > 3) {
    377                 data = *((uint32_t *)ptr);
    378                 mask1 = (STARTCODE_00 != (data & STARTCODE_MASK0));
    379                 mask2 = (STARTCODE_00 != (data & STARTCODE_MASK1));
    380                 // If second byte and fourth byte are not zero's then we cannot have a start code here,
    381                 //  as we need two consecutive zero bytes for a start code pattern.
    382                 if (mask1 && mask2) {
    383                     // skip 4 bytes and start over
    384                     ptr += 4;
    385                     left -=4;
    386                     continue;
    387                 } else {
    388                     break;
    389                 }
    390             }
    391         }
    392 
    393         // At this point either data is not on a 32-bit boundary or phase > 0 so we look at one byte at a time
    394         if (left > 0) {
    395             if (*ptr == STARTCODE_00) {
    396                 phase++;
    397                 if (phase > 2) {
    398                     // more than 2 consecutive '0x00' bytes is found
    399                     phase = 2;
    400                 }
    401             } else if ((*ptr == STARTCODE_01) && (phase == 2)) {
    402                 // start code is found
    403                 phase = 3;
    404             } else {
    405                 // reset lookup
    406                 phase = 0;
    407             }
    408             ptr++;
    409             left--;
    410         }
    411     }
    412 
    413     if ((left > 0) && (phase == 3)) {
    414         phase = 4;
    415         // return offset of position following the pattern in the buffer which matches "0x000001" byte string
    416         return (int32_t)(ptr - stream);
    417     }
    418     return -1;
    419 }
    420 
    421 
    422 Decode_Status VideoDecoderAVCSecure::copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream) {
    423     uint8_t naluType;
    424     int32_t naluHeaderLen;
    425 
    426     naluType = *(uint8_t *)(stream + naluStream->naluOffset);
    427     naluType &= NALU_TYPE_MASK;
    428     // first update nalu header length based on nalu type
    429     if (naluType >= NAL_UNIT_TYPE_SLICE && naluType <= NAL_UNIT_TYPE_IDR) {
    430         // coded slice, return only up to MAX_SLICE_HEADER_SIZE bytes
    431         naluHeaderLen = min(naluStream->naluLen, MAX_SLICE_HEADER_SIZE);
    432     } else if (naluType >= NAL_UNIT_TYPE_SEI && naluType <= NAL_UNIT_TYPE_PPS) {
    433         //sps, pps, sei, etc, return the entire NAL unit in clear
    434         naluHeaderLen = naluStream->naluLen;
    435     } else {
    436         return DECODE_FRAME_DROPPED;
    437     }
    438 
    439     memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluOffset), sizeof(int32_t));
    440     naluStream->streamPos += 4;
    441 
    442     memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluLen), sizeof(int32_t));
    443     naluStream->streamPos += 4;
    444 
    445     memcpy(naluStream->byteStream + naluStream->streamPos, &naluHeaderLen, sizeof(int32_t));
    446     naluStream->streamPos += 4;
    447 
    448     if (naluHeaderLen) {
    449         memcpy(naluStream->byteStream + naluStream->streamPos, (uint8_t*)(stream + naluStream->naluOffset), naluHeaderLen);
    450         naluStream->streamPos += naluHeaderLen;
    451     }
    452     return DECODE_SUCCESS;
    453 }
    454 
    455 
    456 // parse start-code prefixed stream, also knowns as Annex B byte stream, commonly used in AVI, ES, MPEG2 TS container
    457 Decode_Status VideoDecoderAVCSecure::parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream) {
    458     int32_t naluOffset, offset, left;
    459     NaluInfo *info;
    460     uint32_t ret = DECODE_SUCCESS;
    461 
    462     naluOffset = 0;
    463     offset = 0;
    464     left = length;
    465 
    466     // leave 4 bytes to copy nalu count
    467     naluStream->streamPos = 4;
    468     naluStream->naluCount = 0;
    469     memset(naluStream->byteStream, 0, MAX_NALU_HEADER_BUFFER);
    470 
    471     for (; ;) {
    472         naluOffset = findNalUnitOffset(stream, offset, left);
    473         if (naluOffset == -1) {
    474             break;
    475         }
    476 
    477         if (naluStream->naluCount == 0) {
    478             naluStream->naluOffset = naluOffset;
    479         } else {
    480             naluStream->naluLen = naluOffset - naluStream->naluOffset - STARTCODE_PREFIX_LEN;
    481             ret = copyNaluHeader(stream, naluStream);
    482             if (ret != DECODE_SUCCESS && ret != DECODE_FRAME_DROPPED) {
    483                 LOGW("copyNaluHeader returned %d", ret);
    484                 return ret;
    485             }
    486             // starting position for next NALU
    487             naluStream->naluOffset = naluOffset;
    488         }
    489 
    490         if (ret == DECODE_SUCCESS) {
    491             naluStream->naluCount++;
    492         }
    493 
    494         // update next lookup position and length
    495         offset = naluOffset + 1; // skip one byte of NAL unit type
    496         left = length - offset;
    497     }
    498 
    499     if (naluStream->naluCount > 0) {
    500         naluStream->naluLen = length - naluStream->naluOffset;
    501         memcpy(naluStream->byteStream, &(naluStream->naluCount), sizeof(int32_t));
    502         // ignore return value, either DECODE_SUCCESS or DECODE_FRAME_DROPPED
    503         copyNaluHeader(stream, naluStream);
    504         return DECODE_SUCCESS;
    505     }
    506 
    507     LOGW("number of valid NALU is 0!");
    508     return DECODE_SUCCESS;
    509 }
    510 
    511