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; }
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; }