Esempio n. 1
0
u32 h264bsdDecode(storage_t *pStorage, u8 *byteStrm, u32 len, u32 picId,
    u32 *readBytes)
{

/* Variables */

    u32 tmp, ppsId, spsId;
    i32 picOrderCnt;
    nalUnit_t nalUnit;
    seqParamSet_t seqParamSet;
    picParamSet_t picParamSet;
    strmData_t strm;
    u32 accessUnitBoundaryFlag = HANTRO_FALSE;
    u32 picReady = HANTRO_FALSE;

/* Code */

    /*ASSERT(pStorage);
    ASSERT(byteStrm);
    ASSERT(len);
    ASSERT(readBytes);*/

    /* if previous buffer was not finished and same pointer given -> skip NAL
     * unit extraction */
    if (pStorage->prevBufNotFinished && byteStrm == pStorage->prevBufPointer)
    {
        strm = pStorage->strm[0];
        strm.pStrmCurrPos = strm.pStrmBuffStart;
        strm.strmBuffReadBits = strm.bitPosInWord = 0;
        *readBytes = pStorage->prevBytesConsumed;
    }
    else
    {
        tmp = h264bsdExtractNalUnit(byteStrm, len, &strm, readBytes);
        if (tmp != HANTRO_OK)
        {
            EPRINT("BYTE_STREAM");
            return(H264BSD_ERROR);
        }
        /* store stream */
        pStorage->strm[0] = strm;
        pStorage->prevBytesConsumed = *readBytes;
        pStorage->prevBufPointer = byteStrm;
    }
    pStorage->prevBufNotFinished = HANTRO_FALSE;

    tmp = h264bsdDecodeNalUnit(&strm, &nalUnit);
    if (tmp != HANTRO_OK)
    {
        EPRINT("NAL_UNIT");
        return(H264BSD_ERROR);
    }

#ifndef SINGLE_SLICE
    /* Discard unspecified, reserved, SPS extension and auxiliary picture slices */
    if(nalUnit.nalUnitType == 0 || nalUnit.nalUnitType >= 13)
    {
        DEBUG(("DISCARDED NAL (UNSPECIFIED, REGISTERED, SPS ext or AUX slice)\n"));
        return(H264BSD_RDY);
    }
    tmp = h264bsdCheckAccessUnitBoundary(
      &strm,
      &nalUnit,
      pStorage,
      &accessUnitBoundaryFlag);
    if (tmp != HANTRO_OK)
    {
        EPRINT("ACCESS UNIT BOUNDARY CHECK");
        if (tmp == PARAM_SET_ERROR)
            return(H264BSD_PARAM_SET_ERROR);
        else
            return(H264BSD_ERROR);
    }
  
    if ( accessUnitBoundaryFlag )
    {
        DEBUG(("Access unit boundary\n"));
        /* conceal if picture started and param sets activated */
        if (pStorage->picStarted && pStorage->activeSps != NULL)
        {
            DEBUG(("CONCEALING..."));

            /* return error if second phase of
             * initialization is not completed */
            if (pStorage->pendingActivation)
            {
                EPRINT("Pending activation not completed");
                return (H264BSD_ERROR);
            }

            if (!pStorage->validSliceInAccessUnit)
            {
                pStorage->currImage->data =
                    h264bsdAllocateDpbImage(pStorage->dpb);
                h264bsdInitRefPicList(pStorage->dpb);
                tmp = h264bsdConceal(pStorage, pStorage->currImage, P_SLICE);
            }
            else
                tmp = h264bsdConceal(pStorage, pStorage->currImage,
                    pStorage->sliceHeader->sliceType);

            picReady = HANTRO_TRUE;

            /* current NAL unit should be decoded on next activation -> set
             * readBytes to 0 */
            *readBytes = 0;
            pStorage->prevBufNotFinished = HANTRO_TRUE;
            DEBUG(("...DONE\n"));
        }
        else
        {
            pStorage->validSliceInAccessUnit = HANTRO_FALSE;
        }
        pStorage->skipRedundantSlices = HANTRO_FALSE;
    }
#endif

    if (!picReady)
    {
        switch (nalUnit.nalUnitType)
        {
            case NAL_SEQ_PARAM_SET:
                DEBUG(("SEQ PARAM SET\n"));
                tmp = h264bsdDecodeSeqParamSet(&strm, &seqParamSet);
                if (tmp != HANTRO_OK)
                {
                    EPRINT("SEQ_PARAM_SET");
                    FREE(seqParamSet.offsetForRefFrame);
                    FREE(seqParamSet.vuiParameters);
                    return(H264BSD_ERROR);
                }
                tmp = h264bsdStoreSeqParamSet(pStorage, &seqParamSet);
                break;

            case NAL_PIC_PARAM_SET:
                DEBUG(("PIC PARAM SET\n"));
                tmp = h264bsdDecodePicParamSet(&strm, &picParamSet);
                if (tmp != HANTRO_OK)
                {
                    EPRINT("PIC_PARAM_SET");
                    FREE(picParamSet.runLength);
                    FREE(picParamSet.topLeft);
                    FREE(picParamSet.bottomRight);
                    FREE(picParamSet.sliceGroupId);
                    return(H264BSD_ERROR);
                }
                tmp = h264bsdStorePicParamSet(pStorage, &picParamSet);
                break;

            case NAL_CODED_SLICE_IDR:
                DEBUG(("IDR "));
                /* fall through */
            case NAL_CODED_SLICE:
                DEBUG(("SLICE HEADER\n"));

                /* picture successfully finished and still decoding same old
                 * access unit -> no need to decode redundant slices */
                if (pStorage->skipRedundantSlices)
                    return(H264BSD_RDY);

                pStorage->picStarted = HANTRO_TRUE;

                if (h264bsdIsStartOfPicture(pStorage))
                {
                    pStorage->numConcealedMbs = 0;
                    pStorage->currentPicId    = picId;

                    tmp = h264bsdCheckPpsId(&strm, &ppsId);
                    ASSERT(tmp == HANTRO_OK);
                    /* store old activeSpsId and return headers ready
                     * indication if activeSps changes */
                    spsId = pStorage->activeSpsId;
                    tmp = h264bsdActivateParamSets(pStorage, ppsId,
                            IS_IDR_NAL_UNIT(&nalUnit) ?
                            HANTRO_TRUE : HANTRO_FALSE);
                    if (tmp != HANTRO_OK)
                    {
                        EPRINT("Param set activation");
                        pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS;
                        pStorage->activePps = NULL;
                        pStorage->activeSpsId = MAX_NUM_SEQ_PARAM_SETS;
                        pStorage->activeSps = NULL;
                        pStorage->pendingActivation = HANTRO_FALSE;

                        if(tmp == MEMORY_ALLOCATION_ERROR)
                        {
                            return H264BSD_MEMALLOC_ERROR;
                        }
                        else
                            return(H264BSD_PARAM_SET_ERROR);
                    }

                    if (spsId != pStorage->activeSpsId)
                    {
                        seqParamSet_t *oldSPS = NULL;
                        seqParamSet_t *newSPS = pStorage->activeSps;
                        u32 noOutputOfPriorPicsFlag = 1;

                        if(pStorage->oldSpsId < MAX_NUM_SEQ_PARAM_SETS)
                        {
                            oldSPS = pStorage->sps[pStorage->oldSpsId];
                        }

                        *readBytes = 0;
                        pStorage->prevBufNotFinished = HANTRO_TRUE;


                        if(nalUnit.nalUnitType == NAL_CODED_SLICE_IDR)
                        {
                            tmp =
                            h264bsdCheckPriorPicsFlag(&noOutputOfPriorPicsFlag,
                                                          &strm, newSPS,
                                                          pStorage->activePps,
                                                          nalUnit.nalUnitType);
                        }
                        else
                        {
                            tmp = HANTRO_NOK;
                        }

                        if((tmp != HANTRO_OK) ||
                           (noOutputOfPriorPicsFlag != 0) ||
                           (pStorage->dpb->noReordering) ||
                           (oldSPS == NULL) ||
                           (oldSPS->picWidthInMbs != newSPS->picWidthInMbs) ||
                           (oldSPS->picHeightInMbs != newSPS->picHeightInMbs) ||
                           (oldSPS->maxDpbSize != newSPS->maxDpbSize))
                        {
                            pStorage->dpb->flushed = 0;
                        }
                        else
                        {
                            h264bsdFlushDpb(pStorage->dpb);
                        }

                        pStorage->oldSpsId = pStorage->activeSpsId;

                        return(H264BSD_HDRS_RDY);
                    }
                }

                /* return error if second phase of
                 * initialization is not completed */
                if (pStorage->pendingActivation)
                {
                    EPRINT("Pending activation not completed");
                    return (H264BSD_ERROR);
                }
                tmp = h264bsdDecodeSliceHeader(&strm, pStorage->sliceHeader + 1,
                    pStorage->activeSps, pStorage->activePps, &nalUnit);
                if (tmp != HANTRO_OK)
                {
                    EPRINT("SLICE_HEADER");
                    return(H264BSD_ERROR);
                }
                if (h264bsdIsStartOfPicture(pStorage))
                {
                    if (!IS_IDR_NAL_UNIT(&nalUnit))
                    {
                        tmp = h264bsdCheckGapsInFrameNum(pStorage->dpb,
                            pStorage->sliceHeader[1].frameNum,
                            nalUnit.nalRefIdc != 0 ?
                            HANTRO_TRUE : HANTRO_FALSE,
                            pStorage->activeSps->
                            gapsInFrameNumValueAllowedFlag);
                        if (tmp != HANTRO_OK)
                        {
                            EPRINT("Gaps in frame num");
                            return(H264BSD_ERROR);
                        }
                    }
                    pStorage->currImage->data =
                        h264bsdAllocateDpbImage(pStorage->dpb);
                }

                /* store slice header to storage if successfully decoded */
                pStorage->sliceHeader[0] = pStorage->sliceHeader[1];
                pStorage->validSliceInAccessUnit = HANTRO_TRUE;
                pStorage->prevNalUnit[0] = nalUnit;

                h264bsdComputeSliceGroupMap(pStorage,
                    pStorage->sliceHeader->sliceGroupChangeCycle);

                h264bsdInitRefPicList(pStorage->dpb);
                tmp = h264bsdReorderRefPicList(pStorage->dpb,
                    &pStorage->sliceHeader->refPicListReordering,
                    pStorage->sliceHeader->frameNum,
                    pStorage->sliceHeader->numRefIdxL0Active);
                if (tmp != HANTRO_OK)
                {
                    EPRINT("Reordering");
                    return(H264BSD_ERROR);
                }

                DEBUG(("SLICE DATA, FIRST %d\n",
                        pStorage->sliceHeader->firstMbInSlice));
                tmp = h264bsdDecodeSliceData(&strm, pStorage,
                    pStorage->currImage, pStorage->sliceHeader);
          // in single slice mode every slice is a ready picture
#ifndef SINGLE_SLICE
                if (tmp != HANTRO_OK)
                {
                    EPRINT("SLICE_DATA");
                    h264bsdMarkSliceCorrupted(pStorage,
                        pStorage->sliceHeader->firstMbInSlice);
                    return(H264BSD_ERROR);
                };

                if (h264bsdIsEndOfPicture(pStorage))
                {
#endif
                    picReady = HANTRO_TRUE;
#ifndef SINGLE_SLICE
                    pStorage->skipRedundantSlices = HANTRO_TRUE;
                };
#endif
                break;

            case NAL_SEI:
                DEBUG(("SEI MESSAGE, NOT DECODED"));
                break;

            default:
                DEBUG(("NOT IMPLEMENTED YET %d\n",nalUnit.nalUnitType));
        }
    }

    if (picReady)
    {
        h264bsdFilterPicture(pStorage->currImage, pStorage->mb);
      
#ifdef EMIT_IMAGE_ASAP

      /*if (gLastSlice == 1){
        h264bsdWriteSliceMbData(
          pStorage->currImage, 
          pStorage->sliceHeader->firstMbInSlice, 
          (pStorage->currImage->width * pStorage->currImage->height) - 1,
          sliceData
        );
      }else{*/
      h264bsdWriteSliceMbData(
        pStorage->currImage, 
        pStorage->sliceHeader->firstMbInSlice, 
        pStorage->sliceHeader->firstMbInSlice + pStorage->slice->numDecodedMbs - 1,
        sliceData
      );
      //};
      
      //sliceData[18] = pStorage->sliceHeader->firstMbInSlice;
      //sliceData[19] = pStorage->sliceHeader->firstMbInSlice + pStorage->slice->numDecodedMbs - 1;

      extern_emit_image(
        pStorage->currImage->data, 
        pStorage->currImage->width * 16, 
        pStorage->currImage->height * 16, 
        sliceData
      );
#endif      

        h264bsdResetStorage(pStorage);

        picOrderCnt = h264bsdDecodePicOrderCnt(pStorage->poc,
            pStorage->activeSps, pStorage->sliceHeader, pStorage->prevNalUnit);

        if (pStorage->validSliceInAccessUnit)
        {
            if (pStorage->prevNalUnit->nalRefIdc)
            {
                tmp = h264bsdMarkDecRefPic(pStorage->dpb,
                    &pStorage->sliceHeader->decRefPicMarking,
                    pStorage->currImage, pStorage->sliceHeader->frameNum,
                    picOrderCnt,
                    IS_IDR_NAL_UNIT(pStorage->prevNalUnit) ?
                    HANTRO_TRUE : HANTRO_FALSE,
                    pStorage->currentPicId, pStorage->numConcealedMbs);
            }
            /* non-reference picture, just store for possible display
             * reordering */
            else
            {
                tmp = h264bsdMarkDecRefPic(pStorage->dpb, NULL,
                    pStorage->currImage, pStorage->sliceHeader->frameNum,
                    picOrderCnt,
                    IS_IDR_NAL_UNIT(pStorage->prevNalUnit) ?
                    HANTRO_TRUE : HANTRO_FALSE,
                    pStorage->currentPicId, pStorage->numConcealedMbs);
            }
        }

        pStorage->picStarted = HANTRO_FALSE;
        pStorage->validSliceInAccessUnit = HANTRO_FALSE;

        return(H264BSD_PIC_RDY);
    }
    else
        return(H264BSD_RDY);

}
/*------------------------------------------------------------------------------

    Function: h264bsdDecodeVlc

        Functional description:
            Decode a NAL unit until a slice header. This function calls other modules to perform
            tasks like
                * extract and decode NAL unit from the byte stream
                * decode parameter sets
                * decode slice header and slice data
                * conceal errors in the picture
                * perform deblocking filtering

            This function contains top level control logic of the decoder.

        Inputs:
            pStorage        pointer to storage data structure
            byteStrm        pointer to stream buffer given by application
            len             length of the buffer in bytes
            picId           identifier for a picture, assigned by the
                            application

        Outputs:
            readBytes       number of bytes read from the stream is stored
                            here

        Returns:
            H264BSD_RDY             decoding finished, nothing special
            H264BSD_PIC_RDY         decoding of a picture finished
            H264BSD_HDRS_RDY        param sets activated, information like
                                    picture dimensions etc can be read
            H264BSD_ERROR           error in decoding
            H264BSD_PARAM_SET_ERROR serius error in decoding, failed to
                                    activate param sets

------------------------------------------------------------------------------*/
u32 h264bsdDecode(decContainer_t * pDecCont, const u8 * byteStrm, u32 len,
                  u32 picId, u32 * readBytes)
{

/* Variables */

    u32 tmp, ppsId, spsId;
    u32 accessUnitBoundaryFlag = HANTRO_FALSE;
    u32 picReady = HANTRO_FALSE;
    storage_t *pStorage;
    nalUnit_t nalUnit;
    seqParamSet_t seqParamSet;
    picParamSet_t picParamSet;
    strmData_t strm;

    u32 ret = 0;

    DEBUG_PRINT(("h264bsdDecode\n"));

/* Code */
    ASSERT(pDecCont);
    ASSERT(byteStrm);
    ASSERT(len);
    ASSERT(readBytes);

    pStorage = &pDecCont->storage;
    ASSERT(pStorage);

    DEBUG_PRINT(("Valid slice in access unit %d\n",
                 pStorage->validSliceInAccessUnit));

    if(pDecCont->rlcMode)
    {
        pStorage->strm[0].removeEmul3Byte = 1;
        strm.removeEmul3Byte = 1;
    }
    else
    {
        pStorage->strm[0].removeEmul3Byte = 0;
        strm.removeEmul3Byte = 0;
    }

    /* if previous buffer was not finished and same pointer given -> skip NAL
     * unit extraction */
    if(pStorage->prevBufNotFinished && byteStrm == pStorage->prevBufPointer)
    {
        strm = pStorage->strm[0];
        strm.pStrmCurrPos = strm.pStrmBuffStart;
        strm.strmBuffReadBits = strm.bitPosInWord = 0;
        *readBytes = pStorage->prevBytesConsumed;
    }
    else
    {
        tmp =
            h264bsdExtractNalUnit(byteStrm, len, &strm, readBytes,
                                  pDecCont->rlcMode);
        if(tmp != HANTRO_OK)
        {
            ERROR_PRINT("BYTE_STREAM");
            return (H264BSD_ERROR);
        }
        /* store stream */
        pStorage->strm[0] = strm;
        pStorage->prevBytesConsumed = *readBytes;
        pStorage->prevBufPointer = byteStrm;
    }

    pStorage->prevBufNotFinished = HANTRO_FALSE;

    tmp = h264bsdDecodeNalUnit(&strm, &nalUnit);
    if(tmp != HANTRO_OK)
    {
        ret = H264BSD_ERROR;
        goto NEXT_NAL;
    }

    /* Discard unspecified, reserved, SPS extension and auxiliary picture slices */
    if(nalUnit.nalUnitType == 0 ||
        (nalUnit.nalUnitType >= 13 &&
         (pStorage->mvc == 0 ||
          (nalUnit.nalUnitType != 14 &&
           nalUnit.nalUnitType != 15 &&
           nalUnit.nalUnitType != 20))))
    {
        DEBUG_PRINT(("DISCARDED NAL (UNSPECIFIED, REGISTERED, SPS ext or AUX slice)\n"));
        ret = H264BSD_RDY;
        goto NEXT_NAL;
    }

    if(pDecCont->skipNonReference &&
       nalUnit.nalRefIdc == 0 )
    {
        DEBUG_PRINT(("DISCARDED NAL (NON-REFERENCE PICTURE)\n"));
        ret = H264BSD_NONREF_PIC_SKIPPED;
        goto NEXT_NAL;
    }

    if(!pStorage->checkedAub)
    {
        pStorage->aub->prevModFrameNum =
            pStorage->aub->prevFrameNum & ~pDecCont->frameNumMask;
        tmp = h264bsdCheckAccessUnitBoundary(&strm,
                                             &nalUnit,
                                             pStorage, &accessUnitBoundaryFlag);
        if(tmp != HANTRO_OK)
        {
            ERROR_PRINT("ACCESS UNIT BOUNDARY CHECK");
            if(tmp == PARAM_SET_ERROR)
                ret = (H264BSD_PARAM_SET_ERROR);
            else
                ret = (H264BSD_ERROR);
            goto NEXT_NAL;
        }
    }
    else
    {
        pStorage->checkedAub = 0;
    }

    if(accessUnitBoundaryFlag)
    {
        DEBUG_PRINT(("Access unit boundary, NAL TYPE %d\n",
                     nalUnit.nalUnitType));

        /* conceal if picture started and param sets activated */
        if(pStorage->picStarted && pStorage->activeSps != NULL)
        {
            if(pDecCont->rlcMode)   /* Error conceal in RLC mode */
            {

                DecAsicBuffers_t *pAsicBuff = pDecCont->asicBuff;

                ASSERT(pAsicBuff);
                ASSERT(pAsicBuff->mbCtrl.virtualAddress);
                DEBUG_PRINT(("CONCEALING..."));

                if(!pStorage->validSliceInAccessUnit)
                {
                    DEBUG_PRINT(("!validSliceunit\n"));
                    pStorage->currImage->data =
                        h264bsdAllocateDpbImage(pStorage->dpb);
                    h264bsdInitRefPicList(pStorage->dpb);

                    h264bsdConceal(pStorage, pAsicBuff, P_SLICE);
                }
                else
                {
                    DEBUG_PRINT(("validSliceunit\n"));
                    h264bsdConceal(pStorage, pAsicBuff,
                                   pStorage->sliceHeader->sliceType);
                }

                picReady = HANTRO_TRUE;

                /* current NAL unit should be decoded on next activation -> set
                 * readBytes to 0 */
                *readBytes = 0;
                pStorage->prevBufNotFinished = HANTRO_TRUE;
                DEBUG_PRINT(("...DONE\n"));

            }
            else    /* VLC  mode */
            {
                DEBUG_PRINT(("New access unit and previous not finished\n"));
                DEBUG_PRINT(("PICTURE FREEZE CONCEAL...\n"));

                if(!pStorage->validSliceInAccessUnit)
                {
                    DEBUG_PRINT(("!validSliceunit\n"));
                    if (!pStorage->view && !pStorage->secondField)
                    {
                        pStorage->currImage->data =
                            h264bsdAllocateDpbImage(pStorage->dpb);
                        pStorage->sliceHeader->fieldPicFlag = 0;
                    }
                    else if (pStorage->view)
                    {
                        pStorage->validSliceInAccessUnit = 1;
                        if (!pStorage->baseOppositeFieldPic)
                        {
                            pStorage->currImage->data =
                                h264bsdAllocateDpbImage(pStorage->dpb);
                        }
                        else
                        {
                            pStorage->baseOppositeFieldPic = 0;
                            pStorage->currImage->data =
                                pStorage->dpb->currentOut->data;
                        }
                        pStorage->sliceHeader = pStorage->sliceHeaders[0];
                    }
                    h264bsdInitRefPicList(pStorage->dpb);
                }

                pStorage->skipRedundantSlices = HANTRO_FALSE;

                /* current NAL unit should be decoded on next activation -> set
                 * readBytes to 0 */
                *readBytes = 0;
                pStorage->prevBufNotFinished = HANTRO_TRUE;
                DEBUG_PRINT(("...DONE\n"));

                return (H264BSD_NEW_ACCESS_UNIT);
            }
        }
        else
        {
            DEBUG_PRINT(("vali slice false\n"));
            pStorage->validSliceInAccessUnit = HANTRO_FALSE;
        }

        pStorage->skipRedundantSlices = HANTRO_FALSE;
    }

    if(!picReady)
    {
        DEBUG_PRINT(("nal unit type: %d\n", nalUnit.nalUnitType));

        switch (nalUnit.nalUnitType)
        {
        case NAL_SEQ_PARAM_SET:
        case NAL_SUBSET_SEQ_PARAM_SET:
            DEBUG_PRINT(("SEQ PARAM SET\n"));
            tmp = h264bsdDecodeSeqParamSet(&strm, &seqParamSet,
                nalUnit.nalUnitType == NAL_SEQ_PARAM_SET ? 0 : 1);
            if(tmp != HANTRO_OK)
            {
                ERROR_PRINT("SEQ_PARAM_SET decoding");
                FREE(seqParamSet.offsetForRefFrame);
                FREE(seqParamSet.vuiParameters);
                ret = H264BSD_ERROR;
            }
            else
            {
                tmp = h264bsdStoreSeqParamSet(pStorage, &seqParamSet);
                if(tmp != HANTRO_OK)
                {
                    ERROR_PRINT("SEQ_PARAM_SET allocation");
                    ret = H264BSD_ERROR;
                }
                if (nalUnit.nalUnitType == NAL_SUBSET_SEQ_PARAM_SET)
                {
                    pStorage->viewId[0] = seqParamSet.mvc.viewId[0];
                    pStorage->viewId[1] = seqParamSet.mvc.viewId[1];
                }
            }

            ret = H264BSD_RDY;
            goto NEXT_NAL;

        case NAL_PIC_PARAM_SET:
            DEBUG_PRINT(("PIC PARAM SET\n"));
            tmp = h264bsdDecodePicParamSet(&strm, &picParamSet);
            if(tmp != HANTRO_OK)
            {
                ERROR_PRINT("PIC_PARAM_SET decoding");
                FREE(picParamSet.runLength);
                FREE(picParamSet.topLeft);
                FREE(picParamSet.bottomRight);
                FREE(picParamSet.sliceGroupId);
                ret = H264BSD_ERROR;
            }
            else
            {
                tmp = h264bsdStorePicParamSet(pStorage, &picParamSet);
                if(tmp != HANTRO_OK)
                {
                    ERROR_PRINT("PIC_PARAM_SET allocation");
                    ret = H264BSD_ERROR;
                }
            }
            ret = H264BSD_RDY;
            goto NEXT_NAL;

        case NAL_CODED_SLICE_IDR:
            DEBUG_PRINT(("IDR "));
            /* fall through */
        case NAL_CODED_SLICE:
        case NAL_CODED_SLICE_EXT:
            DEBUG_PRINT(("decode slice header\n"));

            if (nalUnit.nalUnitType == NAL_CODED_SLICE_EXT)
            {
                /* base not yet initialized -> skip */
                if (pStorage->activeViewSps[0] == NULL)
                    goto NEXT_NAL;

                pStorage->view = 1;
                /* view_id not equal to view_id of the 1. non-base view or
                 * base view picture missing -> skip */
                if (nalUnit.viewId != pStorage->viewId[pStorage->view] ||
                    (pStorage->numViews && pStorage->nextView == 0))
                {
                    goto NEXT_NAL;
                }
            }
            else
                pStorage->view = 0;

            /* base view detected, but stereo expected -> go back and freeze
             * previous stereo view picture */
            if (pStorage->view == 0 && pStorage->numViews &&
                pStorage->nextView != 0 && pStorage->activeViewSps[0])
            {
                *readBytes = 0;
                pStorage->prevBufNotFinished = HANTRO_TRUE;
                pStorage->view = 1;
                pStorage->dpb = pStorage->dpbs[pStorage->view];

                pStorage->validSliceInAccessUnit = 1;

                if (!pStorage->baseOppositeFieldPic)
                {
                    pStorage->currImage->data =
                        h264bsdAllocateDpbImage(pStorage->dpb);
                }
                else
                {
                    pStorage->baseOppositeFieldPic = 0;
                    pStorage->currImage->data =
                        pStorage->dpb->currentOut->data;
                }
                h264bsdInitRefPicList(pStorage->dpb);

                return (H264BSD_NEW_ACCESS_UNIT);
            }

            /* picture successfully finished and still decoding same old
             * access unit -> no need to decode redundant slices */
            if(pStorage->skipRedundantSlices)
            {
                DEBUG_PRINT(("skipping redundant slice\n"));
                ret = H264BSD_RDY;
                goto NEXT_NAL;
            }

            pStorage->picStarted = HANTRO_TRUE;

            if(h264bsdIsStartOfPicture(pStorage))
            {
                pStorage->numConcealedMbs = 0;
                pStorage->currentPicId = picId;

                tmp = h264bsdCheckPpsId(&strm, &ppsId);
                ASSERT(tmp == HANTRO_OK);
                /* store old activeSpsId and return headers ready
                 * indication if activeSps changes */
                spsId = pStorage->activeViewSpsId[pStorage->view];

                tmp = h264bsdActivateParamSets(pStorage, ppsId,
                                               IS_IDR_NAL_UNIT(&nalUnit) ?
                                               HANTRO_TRUE : HANTRO_FALSE);
                if(tmp != HANTRO_OK || pStorage->activeSps == NULL ||
                   pStorage->activePps == NULL)
                {
                    ERROR_PRINT("Param set activation");
                    ret = H264BSD_PARAM_SET_ERROR;
                    if (pStorage->view &&
                        pStorage->activeSps == NULL)
                        pStorage->numViews = 0;
                    goto NEXT_NAL;
                }

                if(spsId != pStorage->activeSpsId)
                {
                    seqParamSet_t *oldSPS = NULL;
                    seqParamSet_t *newSPS = pStorage->activeSps;
                    u32 noOutputOfPriorPicsFlag = 1;

                    if(pStorage->oldSpsId < MAX_NUM_SEQ_PARAM_SETS)
                    {
                        oldSPS = pStorage->sps[pStorage->oldSpsId];
                    }

                    *readBytes = 0;
                    pStorage->prevBufNotFinished = HANTRO_TRUE;

                    if(IS_IDR_NAL_UNIT(&nalUnit))
                    {
                        tmp =
                            h264bsdCheckPriorPicsFlag(&noOutputOfPriorPicsFlag,
                                                      &strm, newSPS,
                                                      pStorage->activePps,
                                                      NAL_CODED_SLICE_IDR);
                                                      /*nalUnit.nalUnitType);*/
                    }
                    else
                    {
                        tmp = HANTRO_NOK;
                    }

                    if((tmp != HANTRO_OK) ||
                       (noOutputOfPriorPicsFlag != 0) ||
                       (pStorage->dpb->noReordering) ||
                       (oldSPS == NULL) ||
                       (oldSPS->picWidthInMbs != newSPS->picWidthInMbs) ||
                       (oldSPS->picHeightInMbs != newSPS->picHeightInMbs) ||
                       (oldSPS->maxDpbSize != newSPS->maxDpbSize))
                    {
                        pStorage->dpb->flushed = 0;
                    }
                    else
                    {
                        h264bsdFlushDpb(pStorage->dpb);
                    }

                    pStorage->oldSpsId = pStorage->activeSpsId;
                    pStorage->picStarted = HANTRO_FALSE;
                    return (H264BSD_HDRS_RDY);
                }

                if(pStorage->activePps->numSliceGroups != 1 &&
                   !pDecCont->rlcMode)
                {
                    pDecCont->reallocate = 1;
                    pDecCont->tryVlc = 0;
                    pStorage->picStarted = HANTRO_FALSE;
                    *readBytes = 0;
                    return (H264BSD_FMO);
                }

                if(pStorage->activePps->numSliceGroups == 1 &&
                   pDecCont->rlcMode && !pStorage->asoDetected)
                {
                    if(pDecCont->forceRlcMode)
                        pDecCont->tryVlc = 0;
                    else
                    {
                        DEBUG_PRINT(("h264bsdDecode: no FMO/ASO detected, switch to VLC\n"));
                        pDecCont->tryVlc = 1;

                        /* we have removed emulation prevevention 3B from stream,
                         * cannot go to VLC for this frame; but try the
                         * next one */

                        /* pDecCont->rlcMode = 0; */
                    }
                }
            }

            tmp = h264bsdDecodeSliceHeader(&strm, pStorage->sliceHeader + 1,
                                           pStorage->activeSps,
                                           pStorage->activePps, &nalUnit);
            if(tmp != HANTRO_OK)
            {
                ERROR_PRINT("SLICE_HEADER");
                ret = H264BSD_ERROR;
                goto NEXT_NAL;
            }

            if(h264bsdIsStartOfPicture(pStorage))
            {
                /* stereo view picture, non-matching field pic flag or bottom
                 * field flag -> freeze previous stereo view frame of field
                 * (frame/field and top/bottom info from base view) */
                if (pStorage->view &&
                    ((pStorage->sliceHeader[1].fieldPicFlag !=
                      pStorage->sliceHeaders[0][1].fieldPicFlag) ||
                     (pStorage->sliceHeader[1].bottomFieldFlag !=
                      pStorage->sliceHeaders[0][1].bottomFieldFlag)))
                {
                    pStorage->validSliceInAccessUnit = 1;
                    pStorage->sliceHeader = pStorage->sliceHeaders[0];

                    if (!pStorage->baseOppositeFieldPic)
                    {
                        pStorage->currImage->data =
                            h264bsdAllocateDpbImage(pStorage->dpb);
                    }
                    else
                    {
                        pStorage->currImage->data =
                            pStorage->dpb->currentOut->data;
                    }
                    h264bsdInitRefPicList(pStorage->dpb);

                    return (H264BSD_NEW_ACCESS_UNIT);
                }

                tmp = pStorage->secondField;
                if(pStorage->view ?
                    pStorage->baseOppositeFieldPic :
                    (pStorage->baseOppositeFieldPic =
                     h264bsdIsOppositeFieldPic(pStorage->sliceHeader + 1,
                                             pStorage->sliceHeader + 0,
                                             &pStorage->secondField,
                                             pStorage->dpb->prevRefFrameNum,
                                             pStorage->aub->newPicture)))
                {
                    /* TODO: make sure that currentOut->status[field] is
                     * EMPTY */
                    if(pStorage->dpb->delayedOut != 0)
                    {
                        /* we delayed the output while waiting for second field */
                        pStorage->dpb->outBuf[pStorage->dpb->delayedId].fieldPicture = 0;   /* mark both fields available */
                        DEBUG_PRINT(("Second field coming...\n"));
                    }
                    pStorage->currImage->data = pStorage->dpb->currentOut->data;
                }
                else
                {
                    if(pStorage->dpb->delayedOut != 0 ||
                        /* missing field and PP running */
                        ((pStorage->numViews == 0 ?
                            tmp : (pStorage->sliceHeader->fieldPicFlag &&
                            pStorage->view == 0)) &&
                         pDecCont->pp.decPpIf.ppStatus == DECPP_PIC_NOT_FINISHED))
                    {
                        pStorage->secondField = 0;
                        DEBUG_PRINT(("Second field missing...Output delayed stuff\n"));
                        *readBytes = 0;
                        pStorage->prevBufNotFinished = HANTRO_TRUE;
                        pStorage->dpb->delayedOut = 0;
                        pStorage->checkedAub = 1;
                        return (H264BSD_UNPAIRED_FIELD);
                    }

                    if(!IS_IDR_NAL_UNIT(&nalUnit) &&
                       !pDecCont->modeChange && !pDecCont->gapsCheckedForThis)
                    {
                        DEBUG_PRINT(("Check gaps in frame num; mode change %d\n",
                                     pDecCont->modeChange));
                        tmp = h264bsdCheckGapsInFrameNum(pStorage->dpb,
                                                         pStorage->
                                                         sliceHeader[1].
                                                         frameNum,
                                                         nalUnit.nalRefIdc !=
                                                         0 ? HANTRO_TRUE :
                                                         HANTRO_FALSE,
                                                         pStorage->activeSps->
                                                         gapsInFrameNumValueAllowedFlag);

                        pDecCont->gapsCheckedForThis = HANTRO_TRUE;
                        if(tmp != HANTRO_OK)
                        {
                            pDecCont->gapsCheckedForThis = HANTRO_FALSE;
                            ERROR_PRINT("Gaps in frame num");
                            ret = H264BSD_ERROR;
                            goto NEXT_NAL;
                        }
                    }

                    pStorage->currImage->data =
                        h264bsdAllocateDpbImage(pStorage->dpb);

#ifdef SET_EMPTY_PICTURE_DATA   /* USE THIS ONLY FOR DEBUGGING PURPOSES */
                    {
                        i32 bgd = SET_EMPTY_PICTURE_DATA;

                        DWLmemset(pStorage->currImage->data->virtualAddress,
                                  bgd, pStorage->currImage->data->size);
                    }
#endif
                }
            }
            else
            {
                if(!pDecCont->rlcMode &&
                   pStorage->sliceHeader[1].redundantPicCnt != 0)
                {
                    ret = H264BSD_RDY;
                    goto NEXT_NAL;
                }
            }

            DEBUG_PRINT(("vali slice TRUE\n"));

            /* store slice header to storage if successfully decoded */
            pStorage->sliceHeader[0] = pStorage->sliceHeader[1];
            pStorage->validSliceInAccessUnit = HANTRO_TRUE;
            pStorage->prevNalUnit[0] = nalUnit;

            if(IS_B_SLICE(pStorage->sliceHeader[1].sliceType))
            {
                if((pDecCont->h264ProfileSupport == H264_BASELINE_PROFILE) ||
                   (pDecCont->rlcMode != 0))
                {
                    ERROR_PRINT("B_SLICE not allowed in baseline decoder");
                    ret = H264BSD_ERROR;
                    goto NEXT_NAL;
                }

                if(pDecCont->asicBuff->enableDmvAndPoc == 0)
                {
                    DEBUG_PRINT(("B_SLICE in baseline stream!!! DMV and POC writing were not enabled!"));
                    DEBUG_PRINT(("B_SLICE decoding will not be accurate for a while!"));

                    /* enable DMV and POC writing */
                    pDecCont->asicBuff->enableDmvAndPoc = 1;
                }
            }

            /* For VLC mode, end SW decode here */
            if(!pDecCont->rlcMode)
            {
                DEBUG_PRINT(("\tVLC mode! Skip slice data decoding\n"));
                if(pDecCont->is8190 == 0)
                {
                    h264bsdInitRefPicList(pStorage->dpb);
                }

                SetPicNums(pStorage->dpb, pStorage->sliceHeader->frameNum);

                return (H264BSD_PIC_RDY);
            }
            /* TODO pitäskö siirtää pelkästään rlc moodille, note that
             * SetPicNums called only inside h264bsdReorderRefPicList() */

            h264bsdInitRefPicList(pStorage->dpb);
            tmp = h264bsdReorderRefPicList(pStorage->dpb,
                                           &pStorage->sliceHeader->
                                           refPicListReordering,
                                           pStorage->sliceHeader->frameNum,
                                           pStorage->sliceHeader->
                                           numRefIdxL0Active);
            if(tmp != HANTRO_OK)
            {
                ERROR_PRINT("h264bsdReorderRefPicList failed\n");
                ret = H264BSD_ERROR;
                goto NEXT_NAL;
            }

            h264bsdComputeSliceGroupMap(pStorage,
                                        pStorage->sliceHeader->
                                        sliceGroupChangeCycle);

            tmp = h264bsdDecodeSliceData(pDecCont, &strm,
                                         pStorage->sliceHeader);

            if(tmp != HANTRO_OK)
            {
                h264bsdMarkSliceCorrupted(pStorage,
                                          pStorage->sliceHeader->
                                          firstMbInSlice);
                return (H264BSD_ERROR);
            }

            if(h264bsdIsEndOfPicture(pStorage))
            {
                picReady = HANTRO_TRUE;
                DEBUG_PRINT(("Skip redundant RLC\n"));
                pStorage->skipRedundantSlices = HANTRO_TRUE;
            }
            break;

        case NAL_SEI:
            DEBUG_PRINT(("SEI MESSAGE, NOT DECODED\n"));
            ret = H264BSD_RDY;
            goto NEXT_NAL;
        case NAL_END_OF_SEQUENCE:
            DEBUG_PRINT(("END_OF_SEQUENCE, NOT DECODED\n"));
            ret = H264BSD_RDY;
            goto NEXT_NAL;
        case NAL_END_OF_STREAM:
            DEBUG_PRINT(("END_OF_STREAM, NOT DECODED\n"));
            ret = H264BSD_RDY;
            goto NEXT_NAL;
        case NAL_PREFIX:
            pStorage->view = 0;
            pStorage->nonInterViewRef = nalUnit.interViewFlag == 0;
            /* set flag to indicate that this is probably mvc stream, affects
             * base layer param set activation */
            pStorage->mvcStream = pStorage->mvc;
            goto NEXT_NAL;
        default:
            DEBUG_PRINT(("NOT IMPLEMENTED YET %d\n", nalUnit.nalUnitType));
            ret = H264BSD_RDY;
            goto NEXT_NAL;
        }
    }

    if(picReady)
    {
        return (H264BSD_PIC_RDY);
    }
    else
        return (H264BSD_RDY);

  NEXT_NAL:
    if(!pDecCont->rlcMode)
    {
        const u8 *next =
            h264bsdFindNextStartCode(strm.pStrmBuffStart, strm.strmBuffSize);

        if(next != NULL)
        {
            *readBytes = (u32) (next - byteStrm);
            pStorage->prevBytesConsumed = *readBytes;
        }
    }

    return ret;

}