--- /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