Exemple #1
0
u32 broadwayDecode() {
    decInput.picId = picDecodeNumber;

    H264SwDecRet ret = H264SwDecDecode(decInst, &decInput, &decOutput);

    switch (ret) {
        case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
            /* Stream headers were successfully decoded, thus stream information is available for query now. */
            ret = H264SwDecGetInfo(decInst, &decInfo);
            if (ret != H264SWDEC_OK) {
                return -1;
            }

            picSize = decInfo.picWidth * decInfo.picHeight;
            picSize = (3 * picSize) / 2;

            broadwayOnHeadersDecoded();

            decInput.dataLen -= decOutput.pStrmCurrPos - decInput.pStream;
            decInput.pStream = decOutput.pStrmCurrPos;
            break;

        case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
            /* Picture is ready and more data remains in the input buffer,
             * update input structure.
             */
            decInput.dataLen -= decOutput.pStrmCurrPos - decInput.pStream;
            decInput.pStream = decOutput.pStrmCurrPos;

            /* fall through */

        case H264SWDEC_PIC_RDY:
            if (ret == H264SWDEC_PIC_RDY) {
                decInput.dataLen = 0;
            }

            /* Increment decoding number for every decoded picture */
            picDecodeNumber++;

            while (H264SwDecNextPicture(decInst, &decPicture, 0) == H264SWDEC_PIC_RDY) {
                // printf(" Decoded Picture Decode: %d, Display: %d, Type: %s\n", picDecodeNumber, picDisplayNumber, decPicture.isIdrPicture ? "IDR" : "NON-IDR");

                /* Increment display number for every displayed picture */
                picDisplayNumber++;

                broadwayOnPictureDecoded(decPicture.pOutputPicture, decInfo.picWidth, decInfo.picHeight);
            }
            break;

        case H264SWDEC_STRM_PROCESSED:
        case H264SWDEC_STRM_ERR:
            /* Input stream was decoded but no picture is ready, thus get more data. */
            decInput.dataLen = 0;
            break;
    }
    return ret;
}
Exemple #2
0
void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) {
    if (mSignalledError || mOutputPortSettingsChange != NONE) {
        return;
    }

    if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
        return;
    }

    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);

    if (mHeadersDecoded) {
        // Dequeue any already decoded output frames to free up space
        // in the output queue.

        drainAllOutputBuffers(false /* eos */);
    }

    H264SwDecRet ret = H264SWDEC_PIC_RDY;
    bool portWillReset = false;
    while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
            && outQueue.size() == kNumOutputBuffers) {

        if (mEOSStatus == INPUT_EOS_SEEN) {
            drainAllOutputBuffers(true /* eos */);
            return;
        }

        BufferInfo *inInfo = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
        ++mPicId;

        OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE;
        memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE));
        header->nTimeStamp = inHeader->nTimeStamp;
        header->nFlags = inHeader->nFlags;
        if (header->nFlags & OMX_BUFFERFLAG_EOS) {
            mEOSStatus = INPUT_EOS_SEEN;
        }
        mPicToHeaderMap.add(mPicId, header);
        inQueue.erase(inQueue.begin());

        H264SwDecInput inPicture;
        H264SwDecOutput outPicture;
        memset(&inPicture, 0, sizeof(inPicture));
        inPicture.dataLen = inHeader->nFilledLen;
        inPicture.pStream = inHeader->pBuffer + inHeader->nOffset;
        inPicture.picId = mPicId;
        inPicture.intraConcealmentMethod = 1;
        H264SwDecPicture decodedPicture;

        while (inPicture.dataLen > 0) {
            ret = H264SwDecDecode(mHandle, &inPicture, &outPicture);
            if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY ||
                ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) {
                inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream);
                inPicture.pStream = outPicture.pStrmCurrPos;
                if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) {
                    mHeadersDecoded = true;
                    H264SwDecInfo decoderInfo;
                    CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);

                    SoftVideoDecoderOMXComponent::CropSettingsMode cropSettingsMode =
                        handleCropParams(decoderInfo);
                    handlePortSettingsChange(
                            &portWillReset, decoderInfo.picWidth, decoderInfo.picHeight,
                            cropSettingsMode);
                }
            } else {
                if (portWillReset) {
                    if (H264SwDecNextPicture(mHandle, &decodedPicture, 0)
                        == H264SWDEC_PIC_RDY) {

                        // Save this output buffer; otherwise, it will be
                        // lost during dynamic port reconfiguration because
                        // OpenMAX client will delete _all_ output buffers
                        // in the process.
                        saveFirstOutputBuffer(
                            decodedPicture.picId,
                            (uint8_t *)decodedPicture.pOutputPicture);
                    }
                }
                inPicture.dataLen = 0;
                if (ret < 0) {
                    ALOGE("Decoder failed: %d", ret);

                    notify(OMX_EventError, OMX_ErrorUndefined,
                           ERROR_MALFORMED, NULL);

                    mSignalledError = true;
                    return;
                }
            }
        }
        inInfo->mOwnedByUs = false;
        notifyEmptyBufferDone(inHeader);

        if (portWillReset) {
            return;
        }

        if (mFirstPicture && !outQueue.empty()) {
            drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
            delete[] mFirstPicture;
            mFirstPicture = NULL;
            mFirstPictureId = -1;
        }

        drainAllOutputBuffers(false /* eos */);
    }
}
/*------------------------------------------------------------------------------

------------------------------------------------------------------------------*/
int main(int argc, char **argv)
{

    i32 instCount, instRunning;
    i32 i;
    u32 maxNumPics;
    u32 strmLen;
    H264SwDecRet ret;
    u32 numErrors = 0;
    u32 cropDisplay = 0;
    u32 disableOutputReordering = 0;
    FILE *finput;
    Decoder **decoder;
    char outFileName[256] = "out.yuv";


    if ( argc > 1 && strcmp(argv[1], "-T") == 0 )
    {
        fprintf(stderr, "%s\n", tagName);
        return 0;
    }

    if (argc < 2)
    {
        DEBUG((
            "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file1.264 [file2.264] .. [fileN.264]\n",
            argv[0]));
        DEBUG(("\t-Nn forces decoding to stop after n pictures\n"));
#if defined(_NO_OUT)
        DEBUG(("\t-Ooutfile output writing disabled at compile time\n"));
#else
        DEBUG(("\t-Ooutfile write output to \"outfile\" (default out.yuv)\n"));
        DEBUG(("\t-Onone does not write output\n"));
#endif
        DEBUG(("\t-C display cropped image (default decoded image)\n"));
        DEBUG(("\t-R disable DPB output reordering\n"));
        DEBUG(("\t-T to print tag name and exit\n"));
        exit(100);
    }

    instCount = argc - 1;

    /* read command line arguments */
    maxNumPics = 0;
    for (i = 1; i < (argc-1); i++)
    {
        if ( strncmp(argv[i], "-N", 2) == 0 )
        {
            maxNumPics = (u32)atoi(argv[i]+2);
            instCount--;
        }
        else if ( strncmp(argv[i], "-O", 2) == 0 )
        {
            strcpy(outFileName, argv[i]+2);
            instCount--;
        }
        else if ( strcmp(argv[i], "-C") == 0 )
        {
            cropDisplay = 1;
            instCount--;
        }
        else if ( strcmp(argv[i], "-R") == 0 )
        {
            disableOutputReordering = 1;
            instCount--;
        }
    }

    if (instCount < 1)
    {
        DEBUG(("No input files\n"));
        exit(100);
    }

    /* allocate memory for multiple decoder instances
     * one instance for every stream file */
    decoder = (Decoder **)malloc(sizeof(Decoder*)*(u32)instCount);
    if (decoder == NULL)
    {
        DEBUG(("Unable to allocate memory\n"));
        exit(100);
    }

    /* prepare each decoder instance */
    for (i = 0; i < instCount; i++)
    {
        decoder[i] = (Decoder *)calloc(1, sizeof(Decoder));

        /* open input file */
        finput = fopen(argv[argc-instCount+i],"rb");
        if (finput == NULL)
        {
            DEBUG(("Unable to open input file <%s>\n", argv[argc-instCount+i]));
            exit(100);
        }

        DEBUG(("Reading input file[%d] %s\n", i, argv[argc-instCount+i]));

        /* read input stream to buffer */
        fseek(finput,0L,SEEK_END);
        strmLen = (u32)ftell(finput);
        rewind(finput);
        decoder[i]->byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen);
        if (decoder[i]->byteStrmStart == NULL)
        {
            DEBUG(("Unable to allocate memory\n"));
            exit(100);
        }
        fread(decoder[i]->byteStrmStart, sizeof(u8), strmLen, finput);
        fclose(finput);

        /* open output file */
        if (strcmp(outFileName, "none") != 0)
        {
#if defined(_NO_OUT)
            decoder[i]->foutput = NULL;
#else
            sprintf(decoder[i]->outFileName, "%s%i", outFileName, i);
            decoder[i]->foutput = fopen(decoder[i]->outFileName, "wb");
            if (decoder[i]->foutput == NULL)
            {
                DEBUG(("Unable to open output file\n"));
                exit(100);
            }
#endif
        }

        ret = H264SwDecInit(&(decoder[i]->decInst), disableOutputReordering);

        if (ret != H264SWDEC_OK)
        {
            DEBUG(("Init failed %d\n", ret));
            exit(100);
        }

        decoder[i]->decInput.pStream = decoder[i]->byteStrmStart;
        decoder[i]->decInput.dataLen = strmLen;
        decoder[i]->decInput.intraConcealmentMethod = 0;

    }

    /* main decoding loop */
    do
    {
        /* decode once using each instance */
        for (i = 0; i < instCount; i++)
        {
            ret = H264SwDecDecode(decoder[i]->decInst,
                                &(decoder[i]->decInput),
                                &(decoder[i]->decOutput));

            switch(ret)
            {

                case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:

                    ret = H264SwDecGetInfo(decoder[i]->decInst,
                            &(decoder[i]->decInfo));
                    if (ret != H264SWDEC_OK)
                        exit(1);

                    if (cropDisplay && decoder[i]->decInfo.croppingFlag)
                    {
                        DEBUG(("Decoder[%d] Cropping params: (%d, %d) %dx%d\n",
                            i,
                            decoder[i]->decInfo.cropParams.cropLeftOffset,
                            decoder[i]->decInfo.cropParams.cropTopOffset,
                            decoder[i]->decInfo.cropParams.cropOutWidth,
                            decoder[i]->decInfo.cropParams.cropOutHeight));
                    }

                    DEBUG(("Decoder[%d] Width %d Height %d\n", i,
                        decoder[i]->decInfo.picWidth,
                        decoder[i]->decInfo.picHeight));

                    DEBUG(("Decoder[%d] videoRange %d, matricCoefficients %d\n",
                        i, decoder[i]->decInfo.videoRange,
                        decoder[i]->decInfo.matrixCoefficients));
                    decoder[i]->decInput.dataLen -=
                        (u32)(decoder[i]->decOutput.pStrmCurrPos -
                              decoder[i]->decInput.pStream);
                    decoder[i]->decInput.pStream =
                        decoder[i]->decOutput.pStrmCurrPos;
                    break;

                case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
                    decoder[i]->decInput.dataLen -=
                        (u32)(decoder[i]->decOutput.pStrmCurrPos -
                              decoder[i]->decInput.pStream);
                    decoder[i]->decInput.pStream =
                        decoder[i]->decOutput.pStrmCurrPos;
                    /* fall through */
                case H264SWDEC_PIC_RDY:
                    if (ret == H264SWDEC_PIC_RDY)
                        decoder[i]->decInput.dataLen = 0;

                    ret = H264SwDecGetInfo(decoder[i]->decInst,
                            &(decoder[i]->decInfo));
                    if (ret != H264SWDEC_OK)
                        exit(1);

                    while (H264SwDecNextPicture(decoder[i]->decInst,
                            &(decoder[i]->decPicture), 0) == H264SWDEC_PIC_RDY)
                    {
                        decoder[i]->picNumber++;

                        numErrors += decoder[i]->decPicture.nbrOfErrMBs;

                        DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
                            i, decoder[i]->picNumber,
                            decoder[i]->decPicture.isIdrPicture
                                ? "IDR" : "NON-IDR",
                            decoder[i]->decPicture.nbrOfErrMBs));
                        fflush(stdout);

                        CropWriteOutput(decoder[i]->foutput,
                                (u8*)decoder[i]->decPicture.pOutputPicture,
                                cropDisplay, &(decoder[i]->decInfo));
                    }

                    if (maxNumPics && decoder[i]->picNumber == maxNumPics)
                        decoder[i]->decInput.dataLen = 0;
                    break;

                case H264SWDEC_STRM_PROCESSED:
                case H264SWDEC_STRM_ERR:
                case H264SWDEC_PARAM_ERR:
                    decoder[i]->decInput.dataLen = 0;
                    break;

                default:
                    DEBUG(("Decoder[%d] FATAL ERROR\n", i));
                    exit(10);
                    break;

            }
        }

        /* check if any of the instances is still running (=has more data) */
        instRunning = instCount;
        for (i = 0; i < instCount; i++)
        {
            if (decoder[i]->decInput.dataLen == 0)
                instRunning--;
        }

    } while (instRunning);


    /* get last frames and close each instance */
    for (i = 0; i < instCount; i++)
    {
        while (H264SwDecNextPicture(decoder[i]->decInst,
                &(decoder[i]->decPicture), 1) == H264SWDEC_PIC_RDY)
        {
            decoder[i]->picNumber++;

            DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
                i, decoder[i]->picNumber,
                decoder[i]->decPicture.isIdrPicture
                    ? "IDR" : "NON-IDR",
                decoder[i]->decPicture.nbrOfErrMBs));
            fflush(stdout);

            CropWriteOutput(decoder[i]->foutput,
                    (u8*)decoder[i]->decPicture.pOutputPicture,
                    cropDisplay, &(decoder[i]->decInfo));
        }

        H264SwDecRelease(decoder[i]->decInst);

        if (decoder[i]->foutput)
            fclose(decoder[i]->foutput);

        free(decoder[i]->byteStrmStart);

        free(decoder[i]);
    }

    free(decoder);

    if (numErrors)
        return 1;
    else
        return 0;

}
H264_DECODE_STATUS_CODE_T VideoH264DecNALu(VIDEO_DECODE_PARAM_T *prParam)
{
    H264SwDecInput rDecInput;
    H264SwDecOutput rDecOutput;
    H264SwDecReturnBs rBsInfo;
    H264SwDecInfo rDecInfo;
    H264SwDecRet rDecResult = H264SWDEC_OK;
    kal_bool fgNotSupport = KAL_FALSE;
    //kal_bool fgCurBsBufferCacheable;
    kal_bool fgAgain = KAL_FALSE;
    kal_bool fgCurrentBsCacheable = KAL_FALSE;

    if ((prParam == NULL) || (!rH264SwCtrl.fgIsCodecInit))
    {
        drv_trace1(TRACE_GROUP_8, H264DEC_ARGUMENT_ERROR, __LINE__);
        ASSERT(0);
        return H264_STATUS_ERROR;
    }
    

    if (prParam->u4AddrOfNALu == 0)
    {
        drv_trace1(TRACE_GROUP_8, H264DEC_ARGUMENT_ERROR, __LINE__);
        ASSERT(0);
        return H264_STATUS_ERROR;        
    }

    drv_trace4(TRACE_GROUP_10,OPEN_API_ENTERVIDEOH264DECNALU, prParam->u4AddrOfNALu,prParam->u4LengthOfNALu,
        ((*((kal_uint8*)prParam->u4AddrOfNALu))>>5)&0x3,(*((kal_uint8*)prParam->u4AddrOfNALu))&0x1F);
    
    fgCurrentBsCacheable = OpenAPIIsExtBufferCacheable(prParam->u4AddrOfNALu, prParam->u4LengthOfNALu);

    if (fgCurrentBsCacheable)
    {
        //ASSERT(0);
        //return H264_STATUS_ERROR;
        if (rH264SwCtrl.fgBsBufferCacheable)
        {
            rDecInput.pStream = (u8 *)prParam->u4AddrOfNALu;
        }
        else
        {
            rDecInput.pStream = (u8 *)OpenAPIExtBufferCacheableSwitchAlignMemory((kal_uint32)prParam->u4AddrOfNALu,
                prParam->u4LengthOfNALu, OPEN_API_NON_CACHEABLE);
        }            
    }
    else
    {
        if (rH264SwCtrl.fgBsBufferCacheable)
        {
            rDecInput.pStream = (u8 *)OpenAPIExtBufferCacheableSwitchAlignMemory((kal_uint32)prParam->u4AddrOfNALu,
                                                                                                        prParam->u4LengthOfNALu, OPEN_API_CACHEABLE);
        }
        else
        {
            rDecInput.pStream = (u8 *)prParam->u4AddrOfNALu;
        }
    }

    rBsInfo.pBsAddr = (u8 *)prParam->u4AddrOfNALu;
    rBsInfo.BsTotalLen = prParam->u4LengthOfNALu;
    rBsInfo.NaluCnt = 1;
    rBsInfo.totalNalu = 1;
    rDecInput.dataLen = prParam->u4LengthOfNALu;
    rDecInput.pBsBuffer = &rBsInfo;

    /* decode one decoding unit */
    do
    {
        rDecResult = H264SwDecDecode(rH264SwCtrl.prH264DecInst, &rDecInput, &rDecOutput);
        drv_trace2(TRACE_GROUP_8, H264DEC_DECODE_RESULT, rDecResult, rDecInput.dataLen);
        VideoH264DecOutputPic(0);
        switch(rDecResult)
        {
        case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:            
            //decoding a frame, but buffer is too long, or below
            if (rDecOutput.pStrmCurrPos == rDecInput.pStream)
            {
                //only flush pic after change sps; need decoding next slice
                fgAgain = KAL_TRUE;
                break;
            }
            // do not break for the following action
        case H264SWDEC_PIC_RDY:
            //output pic            
            return H264_STATUS_DECODE_OK;
        case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
            if (H264SwDecGetInfo(rH264SwCtrl.prH264DecInst, &rDecInfo) != H264SWDEC_OK)
            {
                drv_trace1(TRACE_GROUP_8, H264DEC_ARGUMENT_ERROR, __LINE__);
                ASSERT(0);
                return H264_STATUS_ERROR;
            }
            drv_trace4(TRACE_GROUP_8, H264DEC_BITSTREAM_INFO, rDecInfo.picWidth, rDecInfo.picHeight,
                             rDecInfo.maxDpb, rDecInfo.profile);

            //we do not support to change resolution
            if (((rDecInfo.picWidth != rH264SwCtrl.u2FrameWidth) && rH264SwCtrl.u2FrameWidth)
                || ((rDecInfo.picHeight != rH264SwCtrl.u2FrameHeight) && rH264SwCtrl.u2FrameHeight))
            {
                drv_trace0(TRACE_GROUP_8, H264DEC_SUPPORT_ERROR);
                fgNotSupport = KAL_TRUE;
            }

            if (fgNotSupport)
            {
                drv_trace0(TRACE_GROUP_8, H264DEC_SUPPORT_ERROR);
               H264SwDecReturnBitstream(&rBsInfo);
               return H264_STATUS_ERROR;
            }
            drv_trace0(TRACE_GROUP_8, H264DEC_CHANGE_SPS);
            rH264SwCtrl.u2FrameHeight = (kal_uint16)rDecInfo.picHeight;
            rH264SwCtrl.u2FrameWidth = (kal_uint16)rDecInfo.picWidth;
            rH264SwCtrl.u4BufferSize = (((kal_uint32)rH264SwCtrl.u2FrameHeight *
                                                    (kal_uint32)rH264SwCtrl.u2FrameWidth) *3) >> 1;
            rH264SwCtrl.fgCropping = (rDecInfo.croppingFlag == 0) ? KAL_FALSE : KAL_TRUE;
            rH264SwCtrl.u2RealHeight = (kal_uint16)rDecInfo.cropParams.cropOutHeight;
            rH264SwCtrl.u2RealWidth = (kal_uint16)rDecInfo.cropParams.cropOutWidth;
            fgAgain = KAL_TRUE;
            break;
        case H264SWDEC_STRM_PROCESSED:
            return H264_STATUS_OK;
        case H264SWDEC_PARAM_ERR:
            drv_trace1(TRACE_GROUP_8, H264DEC_ARGUMENT_ERROR, __LINE__);
            ASSERT(0);
            return H264_STATUS_ERROR;
        case H264SWDEC_PARAMSET_ERROR:
            return H264_STATUS_SPS_ERROR;
        case H264SWDEC_STRM_ERR:
            fgAgain = KAL_FALSE;
            //return H264_STATUS_DECODE_ERROR;
            break;
        default:
            drv_trace0(TRACE_GROUP_8, H264DEC_DECODE_ERROR);
            return H264_STATUS_ERROR;
        }
    }while(fgAgain == KAL_TRUE);

    //ASSERT(0);

    return H264_STATUS_OK;
}
/*------------------------------------------------------------------------------

    Function name:  main

    Purpose:
        main function. Assuming that executable is named 'decoder' the usage
        is as follows

            decoder inputFileName

        , where inputFileName shall be name of file containing h264 stream
        data.

------------------------------------------------------------------------------*/
int main(int argc, char **argv)
{

    u8 *byteStrmStart;
    u8 *byteStrm;
    u32 strmLen;
    u32 picSize;
    H264SwDecInst decInst;
    H264SwDecRet ret;
    H264SwDecInput decInput;
    H264SwDecOutput decOutput;
    H264SwDecPicture decPicture;
    H264SwDecInfo decInfo;
    u32 picNumber;

    FILE *finput;
    FILE *foutput;

    /* Check that enough command line arguments given, if not -> print usage
     * information out */
    if (argc < 2)
    {
        printf( "Usage: %s file.h264\n", argv[0]);
        return -1;
    }

    /* open output file for writing, output file named out.yuv. If file open
     * fails -> exit */
    foutput = fopen("out.yuv", "wb");
    if (foutput == NULL)
    {
        printf("UNABLE TO OPEN OUTPUT FILE\n");
        return -1;
    }

    /* open input file for reading, file name given by user. If file open
     * fails -> exit */
    finput = fopen(argv[argc-1], "rb");
    if (finput == NULL)
    {
        printf("UNABLE TO OPEN INPUT FILE\n");
        return -1;
    }

    /* check size of the input file -> length of the stream in bytes */
    fseek(finput, 0L, SEEK_END);
    strmLen = (u32)ftell(finput);
    rewind(finput);

    /* allocate memory for stream buffer, exit if unsuccessful */
    byteStrm = byteStrmStart = (u8 *)H264SwDecMalloc(sizeof(u8), strmLen);
    if (byteStrm == NULL)
    {
        printf("UNABLE TO ALLOCATE MEMORY\n");
        return -1;
    }

    /* read input stream from file to buffer and close input file */
    fread(byteStrm, sizeof(u8), strmLen, finput);
    fclose(finput);

    /* initialize decoder. If unsuccessful -> exit */
    ret = H264SwDecInit(&decInst, 0);
    if (ret != H264SWDEC_OK)
    {
        printf("DECODER INITIALIZATION FAILED\n");
        return -1;
    }

    /* initialize H264SwDecDecode() input structure */
    decInput.pStream = byteStrmStart;
    decInput.dataLen = strmLen;
    decInput.intraConcealmentMethod = 0;

    picNumber = 0;

    /* For performance measurements, read the start time (in seconds) here.
     * The decoding time should be measured over several frames and after
     * that average fps (frames/second) can be calculated.
     *
     * startTime = GetTime();
     *
     * To prevent calculating file I/O latensies as a decoding time,
     * comment out WriteOutput function call. Also prints to stdout might
     * consume considerable amount of cycles during measurement */

    /* main decoding loop */
    do
    {
        /* call API function to perform decoding */
        ret = H264SwDecDecode(decInst, &decInput, &decOutput);

        switch(ret)
        {

            case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:

                /* picture dimensions are available for query now */
                ret = H264SwDecGetInfo(decInst, &decInfo);
                if (ret != H264SWDEC_OK)
                    return -1;

                /* picture size in pixels */
                picSize = decInfo.picWidth * decInfo.picHeight;
                /* memory needed for YCbCr 4:2:0 picture in bytes */
                picSize = (3 * picSize)/2;
                /* memory needed for 16-bit RGB picture in bytes
                 * picSize = (decInfo.picWidth * decInfo.picHeight) * 2; */

                printf("Width %d Height %d\n",
                    decInfo.picWidth, decInfo.picHeight);

                /* update H264SwDecDecode() input structure, number of bytes
                 * "consumed" is computed as difference between the new stream
                 * pointer and old stream pointer */
                decInput.dataLen -=
                    (u32)(decOutput.pStrmCurrPos - decInput.pStream);
                decInput.pStream = decOutput.pStrmCurrPos;
                break;

            case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
            case H264SWDEC_PIC_RDY:

                /* update H264SwDecDecode() input structure, number of bytes
                 * "consumed" is computed as difference between the new stream
                 * pointer and old stream pointer */
                decInput.dataLen -=
                    (u32)(decOutput.pStrmCurrPos - decInput.pStream);
                decInput.pStream = decOutput.pStrmCurrPos;

                /* use function H264SwDecNextPicture() to obtain next picture
                 * in display order. Function is called until no more images
                 * are ready for display */
                while (H264SwDecNextPicture(decInst, &decPicture, 0) ==
                    H264SWDEC_PIC_RDY) { picNumber++;

                    printf("PIC %d, type %s, concealed %d\n", picNumber,
                        decPicture.isIdrPicture ? "IDR" : "NON-IDR",
                        decPicture.nbrOfErrMBs);
                    fflush(stdout);

                    /* Do color conversion if needed to get display image
                     * in RGB-format
                     *
                     * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */

                    /* write next display image to output file */
                    WriteOutput(foutput, (u8*)decPicture.pOutputPicture,
                        picSize);
                }

                break;

            case H264SWDEC_EVALUATION_LIMIT_EXCEEDED:
                /* evaluation version of the decoder has limited decoding
                 * capabilities */
                printf("EVALUATION LIMIT REACHED\n");
                goto end;

            default:
                printf("UNRECOVERABLE ERROR\n");
                return -1;
        }
    /* keep decoding until all data from input stream buffer consumed */
    } while (decInput.dataLen > 0);

end:

    /* if output in display order is preferred, the decoder shall be forced
     * to output pictures remaining in decoded picture buffer. Use function
     * H264SwDecNextPicture() to obtain next picture in display order. Function
     * is called until no more images are ready for display. Second parameter
     * for the function is set to '1' to indicate that this is end of the
     * stream and all pictures shall be output */
    while (H264SwDecNextPicture(decInst, &decPicture, 1) ==
        H264SWDEC_PIC_RDY) {

        picNumber++;

        printf("PIC %d, type %s, concealed %d\n", picNumber,
            decPicture.isIdrPicture ? "IDR" : "NON-IDR",
            decPicture.nbrOfErrMBs);
        fflush(stdout);

        /* Do color conversion if needed to get display image
         * in RGB-format
         *
         * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */

        /* write next display image to output file */
        WriteOutput(foutput, (u8*)decPicture.pOutputPicture, picSize);
    }

    /* For performance measurements, read the end time (in seconds) here.
     *
     * endTime = GetTime();
     *
     * Now the performance can be calculated as frames per second:
     * fps = picNumber / (endTime - startTime); */


    /* release decoder instance */
    H264SwDecRelease(decInst);

    /* close output file */
    fclose(foutput);

    /* free byte stream buffer */
    free(byteStrmStart);

    return 0;

}