Пример #1
0
void SoftAVC::drainAllOutputBuffers(bool eos) {
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
    H264SwDecPicture decodedPicture;

    if (mHeadersDecoded) {
        while (!outQueue.empty()
                && H264SWDEC_PIC_RDY == H264SwDecNextPicture(
                    mHandle, &decodedPicture, eos /* flush */)) {
            int32_t picId = decodedPicture.picId;
            uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
            drainOneOutputBuffer(picId, data);
        }
    }

    if (!eos) {
        return;
    }

    while (!outQueue.empty()) {
        BufferInfo *outInfo = *outQueue.begin();
        outQueue.erase(outQueue.begin());
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

        outHeader->nTimeStamp = 0;
        outHeader->nFilledLen = 0;
        outHeader->nFlags = OMX_BUFFERFLAG_EOS;

        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);

        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
    }
}
Пример #2
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;
}
Пример #3
0
bool SoftAVC::drainAllOutputBuffers() {
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
    H264SwDecPicture decodedPicture;

    while (!outQueue.empty()) {
        BufferInfo *outInfo = *outQueue.begin();
        outQueue.erase(outQueue.begin());
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
        if (mHeadersDecoded &&
            H264SWDEC_PIC_RDY ==
                H264SwDecNextPicture(mHandle, &decodedPicture, 1 /* flush */)) {

            int32_t picId = decodedPicture.picId;
            CHECK(mPicToHeaderMap.indexOfKey(picId) >= 0);

            memcpy(outHeader->pBuffer + outHeader->nOffset,
                decodedPicture.pOutputPicture,
                mPictureSize);

            OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
            outHeader->nTimeStamp = header->nTimeStamp;
            outHeader->nFlags = header->nFlags;
            outHeader->nFilledLen = mPictureSize;
            mPicToHeaderMap.removeItem(picId);
            delete header;
        } else if (mFirstPicture) {

            // Sending the saved output buffer because of dynamic port reconfiguration
            drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
            delete[] mFirstPicture;
            mFirstPicture = NULL;
            mFirstPictureId = -1;
        } else {
            outHeader->nTimeStamp = 0;
            outHeader->nFilledLen = 0;
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
            mEOSStatus = OUTPUT_FRAMES_FLUSHED;
        }

        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);
    }

    return true;
}
static void VideoH264DecOutputPic(kal_uint32 u4FlushBuffer)
{
    H264SwDecPicture rDecPic;
    kal_uint32 u4OutAddr;

    if (!rH264SwCtrl.pfnOutputOneFrame)
    {
        ASSERT(0);
        return;
    }

    while (H264SwDecNextPicture(rH264SwCtrl.prH264DecInst, &rDecPic,
                                                u4FlushBuffer) == H264SWDEC_PIC_RDY)
    {
   	kal_bool fgError = KAL_FALSE;
        drv_trace1(TRACE_GROUP_8, H264DEC_OUTPUT_IDR, rDecPic.isIdrPicture);
        if (rDecPic.isEOF) break;
        if (rH264SwCtrl.fgFrmBufferSwitch == KAL_TRUE)
        {
            if (rH264SwCtrl.fgFrmBufferCacheable == KAL_TRUE)
            {
                u4OutAddr = OpenAPIExtBufferCacheableSwitch((kal_uint32)rDecPic.pOutputPicture,
                                                                rH264SwCtrl.u4BufferSize, OPEN_API_NON_CACHEABLE);
            }
            else
            {
                u4OutAddr = OpenAPIExtBufferCacheableSwitch((kal_uint32)rDecPic.pOutputPicture,
                                                                rH264SwCtrl.u4BufferSize, OPEN_API_CACHEABLE);
            }
        }
        else
        {
            u4OutAddr = (kal_uint32)rDecPic.pOutputPicture;
        }
        if (rDecPic.nbrOfErrMBs > 0)
        {
            fgError = KAL_TRUE;
        }
        drv_trace4(TRACE_GROUP_8, H264DEC_DISPLAY_INFO, u4OutAddr, rDecPic.displayWidth, 
                            rDecPic.displayHeight, u4FlushBuffer);
        drv_trace2(TRACE_GROUP_10,OPEN_API_OUTPUTFRAME, u4OutAddr,0);
        rH264SwCtrl.pfnOutputOneFrame(u4OutAddr, fgError);
    }
}
Пример #5
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;

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

    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;

}