diff -r 000000000000 -r 951a5db380a0 videoeditorengine/h263decoder/src/vdeti.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/h263decoder/src/vdeti.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,445 @@ +/* +* Copyright (c) 2010 Ixonos Plc. +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - Initial contribution +* +* Contributors: +* Ixonos Plc +* +* Description: +* Frame decoding function. +* +*/ + + + +/* + * Includes + */ + +#include "h263dconfig.h" +#include "vdeti.h" +#include "debug.h" +#include "sync.h" +#include "vde.h" +#include "vdemain.h" +#include "core.h" +/* MVE */ +#include "MPEG4Transcoder.h" + +/* + * Local function prototype + */ + +static int vdeSeekNextValidDecodingStartPosition( + vdeInstance_t *instance, CMPEG4Transcoder *hTranscoder); + + +/* + * Functions visible outside this module + */ + +/* {{-output"vdeDecodeFrame.txt"}} */ +/* + * vdeDecodeFrame + * + * Parameters: + * hInstance instance data + * + * Function: + * This function decodes the bitstream by using + * vdcDecodeFrame until it gets at least one decoded frame. It also shows + * the resulting frames (by calling renDraw). + * In addition, the function handles the parameter updating synchronization + * by calling the VDE Queue module. + * + * This function is intended to be called from the thread main function. + * It won't return until it gets a new decoded frame. If the bitstream + * is totally corrupted, this feature might cause a considerable delay + * in the execution of the thread main function. + * + * Returns: + * VDE_OK if the function was successful + * VDE_OK_EOS if the end of stream has been reached + * VDE_OK_BUT_FRAME_USELESS if the function behaved normally, but no + * decoding output was produced due to too + * corrupted input frame + * VDE_ERROR if a fatal error, from which the decoder + * cannot be restored, has occured + * VDE_ERROR_HALTED the instance is halted, it should be closed + * + * + */ + + +int vdeDecodeFrame(vdeHInstance_t hInstance, int /*aStartByteIndex*/, int /*aStartBitIndex*/, CMPEG4Transcoder *hTranscoder) +/* {{-output"vdeDecodeFrame.txt"}} */ +{ + int + sncCode, /* sync code from which to start decoding */ + numOutputFrames, /* number of output frames, 2 for PB-frames, + 1 otherwise */ + fOutputUseless, /* 1 if frame(s) too corrupted to display, + 0 otherwise */ + i, /* loop variable */ + vdcStatus, /* return value of vdcDecodeFrame or + vdcDecodeMPEGVop */ + fFullPictureFreeze = 0; /* set to 1 if full-picture freeze is + going on as described in section L.4 + of the H.263 recommendation */ + + vdeInstance_t + *instance = (vdeInstance_t *) hInstance; + /* pointer to instance structure */ + + /* MVE */ + int StartByteIndex ; + int StartBitIndex ; + + instance->fPrevFrameDecoded = 0; + + /* If the instance is in the EOS state */ + if (instance->state == VDE_STATE_EOS) { + + /* If MPEG-4 stream, visual_object_sequence_end_code terminates + a visual session, and therefore we return. + If H.263 stream, EOS (End of Sequence) has no semantics, and + therefore we return only if MoVi buffers wrapper indicates so. */ + if (instance->fMPEG4) + /* Return an indication that the stream has ended */ + return VDE_OK_EOS; + } + + /* If the instance is in the "Halted" state */ + if (instance->state == VDE_STATE_HALTED) { + + /* If the current frame is INTRA */ + if (vdcIsINTRA(instance->vdcHInstance, instance->inBuffer->baseAddr, 20)) { + /* Reset the state and try to decode */ + instance->state = VDE_STATE_MIDDLE; + deb("vdeDecodeFrame: Trying to recover from halted state.\n"); + } + + else { + deb("vdeDecodeFrame: ERROR - already halted.\n"); + /* Return an indication that the stream cannot be decoded further */ + return VDE_ERROR_HALTED; + } + } + + /* If the instance state indicates that we should resynchronize to INTRA + frame */ + if (instance->state == VDE_STATE_RESYNC) { + + /* If the current frame is INTRA */ + if (vdcIsINTRA(instance->vdcHInstance, instance->inBuffer->baseAddr, 20)) { + /* Reset the state and continue decoding */ + instance->state = VDE_STATE_MIDDLE; + } + + else + return VDE_OK; + } + + /* Read a synchronization code from the current position of the + bitstream or seek the next valid sync code to start decoding */ + sncCode = vdeSeekNextValidDecodingStartPosition(instance, hTranscoder); + + /* If error in seeking sync code */ + if (sncCode < 0) + /* Return error */ + return sncCode; + + /* Else if sync code not found + Note: Can only happen in "one frame per one input bit buffer" case, + i.e. not in videophone */ + else if (sncCode == SNC_NO_SYNC) + /* Note: One could send a INTRA picture request if such a service is + available. However, it is assumed that the service is not available + in this non-videophone application, and therefore no update is + requested. */ + + /* Return indication of useless (too corrupted) frame */ + return VDE_OK_BUT_FRAME_USELESS; + + /* Set the instance to the "Middle" state */ + instance->state = VDE_STATE_MIDDLE; + + /* If the synchronization code == EOS */ + if (sncCode == SNC_EOS) { + + /* Set the instance to the EOS state */ + instance->state = VDE_STATE_EOS; + + /* Return an indication that the stream ended */ + return VDE_OK_EOS; + } + + /* MVE */ + StartByteIndex = instance->inBuffer->getIndex; + StartBitIndex = instance->inBuffer->bitIndex; + + + + + /* Decode a frame */ + + if (instance->fMPEG4) { + + vdcStatus = vdcDecodeMPEGVop(instance->vdcHInstance, instance->inBuffer, + instance->outBuffer, instance->bufEdit, instance->iColorEffect, instance->iGetDecodedFrame, + StartByteIndex, StartBitIndex, hTranscoder); + } + else + { + + + vdcStatus = vdcDecodeFrame(instance->vdcHInstance, instance->inBuffer, + instance->outBuffer, instance->bufEdit, instance->iColorEffect,instance->iGetDecodedFrame, hTranscoder); + + } + + + if (vdcStatus < 0) { + deb("vdeDecodeFrame: ERROR - vdcDecodeFrame failed.\n"); + + instance->state = VDE_STATE_HALTED; + + if (vdcStatus == VDC_ERR_NO_INTRA) + return VDE_ERROR_NO_INTRA; + + return VDE_ERROR_HALTED; + } + + /* If EOS occured */ + if (vdcIsEOSReached(instance->vdcHInstance)) + instance->state = VDE_STATE_EOS; + + /* If the decoded frame is totally corrupted */ + if ((vdcStatus == VDC_OK_BUT_FRAME_USELESS) || (vdcStatus == VDC_OK_BUT_NOT_CODED)) { + + /* If continuous input buffer */ + + fOutputUseless = 1; + } + + else { + fOutputUseless = 0; + instance->fPrevFrameDecoded = 1; + } + + + /* If H.263 bitstream and decoding (partially) successful */ + if (!instance->fMPEG4 && !fOutputUseless) { + } + + /* + * Return decoded images to the image store and + * send them to Video Renderer if needed + */ + + numOutputFrames = vdcGetNumberOfOutputFrames(instance->vdcHInstance); + + /* Loop to handle each output frame separately */ + for (i = 0; i < numOutputFrames; i++) { + vdeImsItem_t *imsItem; + + imsItem = vdcGetImsItem(instance->vdcHInstance, i); + + vdeAssert(imsItem); + + /* If the frame is useless */ + if (fOutputUseless) { + + /* Return the image buffer to the "Free" store */ + if (vdeImsPutFree(&instance->imageStore, imsItem) < 0) { + deb("vdeDecodeFrame: ERROR - vdeImsPutFree failed.\n"); + instance->state = VDE_STATE_HALTED; + return VDE_ERROR_HALTED; + } + } + + /* Else the frame is ok */ + else { + + vdeImb_t *imb; + + vdeImsStoreItemToImageBuffer(imsItem, &imb); + + + /* If full-picture freeze requested */ + if (fFullPictureFreeze) { + + /* Return the image buffer to the image buffer store + but don't send it to the renderer */ + if (vdeImsPut(&instance->imageStore, imsItem) < 0) { + deb("vdeDecodeFrame: ERROR - vdeImsPut failed.\n"); + instance->state = VDE_STATE_HALTED; + return VDE_ERROR_HALTED; + } + } + + /* Else normal displaying */ + else { + h263dFrameType_t frameType; + int renStatus; + u_int32 renHandle; + + /* Get renderer for the output frame */ + frameType.scope = H263D_FTYPE_NDEF; + frameType.width = renDriBitmapWidth(imb->drawItem); + frameType.height = renDriBitmapHeight(imb->drawItem); + + renStatus = vdeFrtGetItem(&instance->renStore, &frameType, &renHandle); + + if (renStatus == VDE_OK_NOT_AVAILABLE) + renHandle = 0; + + + if (renStatus >= 0) { + /* Return the image buffer to the image buffer store + and send it to the renderer (if possible) */ + if (vdeImsPut(&instance->imageStore, imsItem) < 0) { + deb("vdeDecodeFrame: ERROR - vdeImsPut failed.\n"); + instance->state = VDE_STATE_HALTED; + return VDE_ERROR_HALTED; + } + } + + else { + deb("vdeDecodeFrame: ERROR - vdeFrtGetItem failed.\n"); + instance->state = VDE_STATE_HALTED; + return VDE_ERROR_HALTED; + } + } + + } + } + + // fatal errors were returned already earlier + switch ( vdcStatus ) + { + case VDC_OK_BUT_FRAME_USELESS: + { + return VDE_OK_BUT_FRAME_USELESS; + } +// break; + case VDC_OK_BUT_NOT_CODED: + { + return VDE_OK_BUT_NOT_CODED; + } +// break; + default: + { + break; +// return VDE_OK; + } + } + +return VDE_OK; +} + + +/* + * Local functions + */ + +/* + * vdeSeekNextValidDecodingStartPosition + * + * Parameters: + * instance instance data + * + * Function: + * This function seeks the next synchronization position from the bitstream + * (starting from the current position) from which the decoder can start + * decoding. + * + * Returns: + * VDE_ERROR if a fatal error, from which the decoder + * cannot be restored, has occured + * + * SNC_NO_SYNC if no suitable sync code was found + * (can happen only in non-videophone case + * where only one frame is in one bit input + * buffer) + * + * SNC_PSC H.263 Picture Start Code found + * + * SNC_EOS H.263 End of Sequence found or + * MPEG-4 EOB found + * + * SNC_GBSC H.263 GBSC found + * + * SNC_VOP MPEG-4 VOP + * SNC_GOV MPEG-4 GOV + * + * + */ + +static int vdeSeekNextValidDecodingStartPosition( + vdeInstance_t *instance, CMPEG4Transcoder *hTranscoder) +{ + int + sncCode = SNC_NO_SYNC; /* sync code in current position */ + int16 + error = 0; /* error code returned from sync module */ + + /* Note: For the first INTRA of the stream, + do the H.263 vs. non-H.263 stream decision in a higher level, + now assume that there has simply been a bit error in the header, + and one should try from the next PSC */ + + if (instance->fMPEG4) { + vdcInstance_t* vdcinst = (vdcInstance_t *) instance->vdcHInstance; + int fcode = vdcinst->pictureParam.fcode_forward; + + while (sncCode != SNC_VOP && + sncCode != SNC_GOV && + sncCode != SNC_EOB && + sncCode != SNC_VIDPACK) { + + sncCode = sncSeekMPEGStartCode(instance->inBuffer, (fcode ? fcode : 1), 1 /* VPs not relevant at this stage */, 0, &error); + if (error == ERR_BIB_NOT_ENOUGH_DATA) + return SNC_NO_SYNC; + else if (error) + return VDE_ERROR; + else if (sncCode == SNC_VOS) + { + /* Visual Object Sequence start code found, VOS + VO + VOL headers have to be parsed now.. */ + /* (The bitstream may contain multiple instances of VOS start codes before Visual + Object Sequence end code) */ + if (vdcDecodeMPEGVolHeader(vdcinst, instance->inBuffer, hTranscoder) != 0) + return VDE_ERROR; + } + } + + if (sncCode == SNC_EOB) + sncCode = SNC_EOS; + } + else + { + while ( + sncCode != SNC_PSC && + sncCode != SNC_EOS && + sncCode != SNC_GBSC ) { + + sncCode = sncSeekSync(instance->inBuffer, &error); + if (error == ERR_BIB_NOT_ENOUGH_DATA) + return SNC_NO_SYNC; + else if (error) + return VDE_ERROR; + } + } + + return sncCode; +} + + +// End of file