--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/h263decoder/src/sync_mpeg.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,648 @@
+/*
+* 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:
+* MPEG-4 sync code functions.
+*
+*/
+
+
+#include "h263dConfig.h"
+
+#include "sync.h"
+#include "errcodes.h"
+#include "debug.h"
+#include "mpegcons.h"
+#include "biblin.h"
+
+
+/*
+ * Global functions
+ */
+
+/* {{-output"sncCheckMpegVOP.txt"}} */
+/*
+ *
+ * sncCheckMpegVOP
+ *
+ * Parameters:
+ * buffer a pointer to a bit buffer structure
+ * error error code
+ *
+ * Function:
+ * This function checks if the GOV, VOP start codes
+ * are the next codes in the bit buffer.
+ * NO stuffing is allowed before the code, the routine checks from the
+ * current position in the buffer-
+ * The code is not flushed from the buffer.
+ *
+ * Returns:
+ * SNC_NO_SYNC if no sync code is found
+ * SNC_PSC if GOV or VOP start code is found
+ *
+ * Error codes:
+ * Error codes returned by bibFlushBits/bibGetBits/bibShowBits.
+ *
+ *
+ *
+ */
+
+int sncCheckMpegVOP(bibBuffer_t *buffer, int16 *error)
+/* {{-output"sncCheckMpegVOP.txt"}} */
+{
+ u_int32 bits;
+ int16 newError = 0;
+ int numBitsGot, bitErrorIndication = 0;
+
+ bits = bibShowBits(32, buffer, &numBitsGot, &bitErrorIndication, &newError);
+
+ if ((newError == ERR_BIB_NOT_ENOUGH_DATA) && (numBitsGot > 0 )) {
+ /* Still bits in the buffer */
+ deb("sncCheckSync: bibShowReturned not enough data but there are "
+ "still bits in the buffer --> error cleared.\n");
+ return SNC_NO_SYNC;
+ } else if (newError) {
+ *error = newError;
+ return SNC_NO_SYNC;
+ }
+
+ if (bits == MP4_GROUP_START_CODE || bits == MP4_VOP_START_CODE || bits == MP4_EOB_CODE)
+ return SNC_PSC;
+ else
+ return SNC_NO_SYNC;
+}
+
+/* {{-output"sncCheckMpegSync.txt"}} */
+/*
+ *
+ * sncCheckMpegSync
+ *
+ * Parameters:
+ * buffer a pointer to a bit buffer structure
+ * f_code f_code of the last P-vop
+ * error error code
+ *
+ * Function:
+ * This function checks if the GOV, VOP or Video Pcaket start codes
+ * are the next codes in the bit buffer.
+ * Stuffing is needed before the code and the number of stuffing bits
+ * is returned in numStuffBits parameter.
+ * The code is not flushed from the buffer.
+ *
+ * Returns:
+ * SNC_NO_SYNC if no sync code is found
+ * SNC_GOV if GOV start code is found
+ * SNC_VOP if VOP start code is found
+ * SNC_VOS if VOS start code is found
+ * SNC_VIDPACK if Video Packet start code is found
+ * SNC_STUFFING if there is a bit with the value zero
+ * followed by less than 7 bits with the
+ * value one starting from the current position
+ * and after them the buffer (picture segment) ends
+ *
+ * Error codes:
+ * Error codes returned by bibFlushBits/bibGetBits/bibShowBits.
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+int sncCheckMpegSync(bibBuffer_t *buffer, int f_code, int16 *error)
+/* {{-output"sncCheckMpegSync.txt"}} */
+{
+ u_int32 result, bits, start_code_val;
+ int numBitsGot, i, shift_bits;
+ int16 newError = 0;
+ int bitErrorIndication = 0;
+
+ shift_bits = 32-(16+f_code);
+
+ bits = bibShowBits(32, buffer, &numBitsGot, &bitErrorIndication, &newError);
+
+ if ( buffer->error )
+ {
+ // out of bits
+ *error = (int16)buffer->error;
+ return SNC_NO_SYNC;
+ }
+
+
+ for(i = 0; i <= 8; i++) {
+
+ /* if stuffing is correct */
+ if ( (i==0) || ((bits >> (32-i)) == (u_int32) ((1 << (i-1))-1)) ) {
+
+ result = bits << i;
+
+ if ((result >> 8) == 1) {
+
+ /* Stuff start code */
+ if (i != 0) {
+ bibFlushBits(i, buffer, &numBitsGot, &bitErrorIndication, &newError);
+ if (newError) {
+ *error = newError;
+ return SNC_NO_SYNC;
+ }
+ }
+
+ /* Check start code */
+ start_code_val =
+ bibShowBits(32, buffer, &numBitsGot, &bitErrorIndication, &newError);
+ if ((newError == ERR_BIB_NOT_ENOUGH_DATA) && (numBitsGot > 0 )) {
+ /* Still bits in the buffer */
+ deb("sncCheckSync: bibShowReturned not enough data but there are "
+ "still bits in the buffer --> error cleared.\n");
+ if (i) bibRewindBits(i, buffer, &newError);
+ return SNC_NO_SYNC;
+ } else if (newError) {
+ *error = newError;
+ if (i) bibRewindBits(i, buffer, &newError);
+ return SNC_NO_SYNC;
+ }
+
+ if (start_code_val == MP4_VOP_START_CODE) {
+ return SNC_VOP;
+ } else if (start_code_val == MP4_VOS_START_CODE) {
+ return SNC_VOS;
+ } else if (start_code_val == MP4_GROUP_START_CODE) {
+ return SNC_GOV;
+ } else if (start_code_val == MP4_USER_DATA_START_CODE) {
+ return SNC_USERDATA;
+ } else if (start_code_val == MP4_EOB_CODE) {
+ return SNC_EOB;
+ } else if (((start_code_val >> (32-MP4_VID_START_CODE_LENGTH)) == MP4_VID_START_CODE) ||
+ ((start_code_val >> (32-MP4_VOL_START_CODE_LENGTH)) == MP4_VOL_START_CODE)) {
+ return SNC_VID;
+ } else {
+ if (i) bibRewindBits(i, buffer, &newError);
+ continue;
+ }
+
+ } else if (f_code && ((result >> shift_bits) == 1)) {
+ if (i != 0) {
+ /* Stuff start code */
+ bibFlushBits(i, buffer, &numBitsGot, &bitErrorIndication, &newError);
+ if (newError) {
+ *error = newError;
+ return SNC_NO_SYNC;
+ }
+ }
+ return SNC_VIDPACK;
+ }
+ }
+ }
+
+ return SNC_NO_SYNC;
+}
+
+
+/* {{-output"sncRewindAndSeekNewMPEGSync.txt"}} */
+/*
+ * sncRewindAndSeekNewMPEGSync
+ *
+ *
+ * Parameters:
+ * numBitsToRewind the number of bits to rewind before seeking
+ * the synchronization code,
+ * if negative, a default number of bits is
+ * rewinded. It is recommended to use
+ * the SNC_DEFAULT_REWIND definition to represent
+ * negative values in order to increase code
+ * readability.
+ * buffer a pointer to a bit buffer structure
+ * f_code f_code of the last P-vop
+ * error error code
+ *
+ * Function:
+ * This function is intended to be called after bit error detection.
+ * It rewinds some (already read) bits in order not to miss any sync code.
+ * Then, this function finds the next GOV, VOP or Video Packet start code
+ * which is not within the rewinded bits. The function discards the bits
+ * before the synchronization code but does not remove the found code from
+ * the buffer.
+ *
+ *
+ * Returns:
+ * SNC_NO_SYNC if no sync code was found and
+ * no more bits are available
+ * SNC_GOV if GOV start code is found
+ * SNC_VOP if VOP start code is found
+ * SNC_VIDPACK if Video Packet start code is found
+ *
+ * Error codes:
+ * Error codes returned by bibFlushBits/bibGetBits/bibShowBits.
+ *
+ *
+ *
+ */
+
+int sncRewindAndSeekNewMPEGSync(int numBitsToRewind, bibBuffer_t *buffer,
+ int f_code, int16 *error)
+/* {{-output"sncRewindAndSeekNewMPEGSync.txt"}} */
+{
+ int sncCode; /* found sync code */
+ u_int32 numRewindableBits; /* number of bits which can be rewinded */
+ u_int32 bitPosBeforeRewinding; /* initial buffer bit index */
+ u_int32 syncStartBitPos; /* 1st bit index in found sync code */
+ u_int32 syncEndBitPos;
+ int nb = 0;
+ int bei = 0;
+
+ *error = 0;
+
+ /* If default number of rewinded bits requested */
+ if (numBitsToRewind < 0)
+ /* 32 bits is considered to be enough */
+ numBitsToRewind = 32;
+
+ numRewindableBits = bibNumberOfRewBits(buffer);
+
+ if (numRewindableBits < (u_int32) numBitsToRewind)
+ numBitsToRewind = (int) numRewindableBits;
+
+ bitPosBeforeRewinding = bibNumberOfFlushedBits(buffer);
+
+ if (numBitsToRewind) bibRewindBits(numBitsToRewind, buffer, error);
+ if (*error)
+ return SNC_NO_SYNC;
+
+ /* Loop */
+ do {
+
+ /* Seek the next synchronization code */
+ sncCode = sncSeekMPEGStartCode (buffer, f_code, 0 /* this method used with DP and VP => VP resync is relevant */, 0, error);
+ if (*error)
+ return sncCode;
+
+ syncStartBitPos = bibNumberOfFlushedBits(buffer);
+
+ syncEndBitPos = syncStartBitPos +
+ (u_int32) ((sncCode == SNC_VIDPACK) ? (16 + f_code) : 32);
+
+ if (syncEndBitPos <= bitPosBeforeRewinding)
+ bibFlushBits( 1, buffer, &nb, &bei, error );
+
+ /* While the found sync code has been previously read */
+ } while (syncEndBitPos <= bitPosBeforeRewinding);
+
+ return sncCode;
+}
+
+/* {{-output"sncSeekMPEGSync.txt"}} */
+/*
+ * sncSeekMPEGSync
+ *
+ *
+ * Parameters:
+ * buffer a pointer to a bit buffer structure
+ * f_code f_code of the last P-vop
+ * error error code
+ *
+ * Function:
+ * Then, this function finds the next GOV, VOP or Video Packet start code
+ * from the buffer. The function discards the bits before the sync code
+ * but does not remove the found code from the buffer.
+ *
+ * Returns:
+ * SNC_NO_SYNC if no sync code was found and
+ * no more bits are available
+ * SNC_GOV if GOV start code is found
+ * SNC_VOP if VOP start code is found
+ * SNC_VOS if VOS start code is found
+ * SNC_VIDPACK if Video Packet start code is found
+ *
+ * Error codes:
+ * Error codes returned by bibFlushBits/bibGetBits/bibShowBits.
+ *
+ *
+ */
+
+int sncSeekMPEGSync(bibBuffer_t *buffer, int f_code, int16 *error)
+/* {{-output"sncSeekMPEGSync.txt"}} */
+{
+ u_int32 result;
+ int numBitsGot, shift_bits;
+ int16 newError = 0;
+ int bitErrorIndication = 0;
+
+ shift_bits = 32-(16+f_code);
+
+ for (;;) {
+
+ bitErrorIndication = 0;
+
+ result = bibShowBits(32, buffer, &numBitsGot, &bitErrorIndication, &newError);
+
+
+ if (newError == ERR_BIB_NOT_ENOUGH_DATA && numBitsGot) {
+ /* Use the available bits */
+ result <<= (32 - numBitsGot);
+ newError = 0;
+ } else if (newError) {
+ deb("sncSeekSync: ERROR - bibShowBits failed.\n");
+ *error = newError;
+ return SNC_NO_SYNC;
+ }
+
+ if (result == MP4_GROUP_START_CODE)
+ return SNC_GOV;
+ else if (result == MP4_VOP_START_CODE)
+ return SNC_VOP;
+ else if (result == MP4_VOS_START_CODE)
+ return SNC_VOS;
+ else if (result == MP4_EOB_CODE)
+ return SNC_EOB;
+ else if (f_code && ((result >> shift_bits) == 1))
+ return SNC_VIDPACK;
+ else if ( buffer->error )
+ {
+ // out of bits
+ *error = (int16)buffer->error;
+ return SNC_NO_SYNC;
+ }
+
+
+ bibFlushBits(1, buffer, &numBitsGot, &bitErrorIndication, error);
+ }
+}
+
+ /* {{-output"sncSeekMPEGStartCode.txt"}} */
+/*
+ * sncSeekMPEGStartCode
+ *
+ *
+ * Parameters:
+ * buffer a pointer to a bit buffer structure
+ * f_code f_code of the last P-vop
+ * skipVPSync nonzero if Video Packet sync codes can be skipped
+ * error error code
+ *
+ * Function:
+ * This function finds the next GOV, VOP or Video Packet start code
+ * from the buffer in byte-aligned positions. The function discards the bits before the sync code
+ * but does not remove the found code from the buffer.
+ *
+ * Returns:
+ * SNC_NO_SYNC if no sync code was found and
+ * no more bits are available
+ * SNC_GOV if GOV start code is found
+ * SNC_VOP if VOP start code is found
+ * SNC_VOS if VOS start code is found
+ * SNC_VIDPACK if Video Packet start code is found
+ *
+ * Error codes:
+ * Error codes returned by bibFlushBits/bibGetBits/bibShowBits.
+ *
+ *
+ */
+
+int sncSeekMPEGStartCode(bibBuffer_t *buffer, int f_code, int skipVPSync, int checkUD, int16 *error)
+/* {{-output"sncSeekMPEGSync.txt"}} */
+{
+ u_int32 result;
+ int numBitsGot, shift_bits;
+ int16 newError = 0;
+ int bitErrorIndication = 0;
+ int flush = 8;
+ const u_int32 MAX_MPEG4_START_CODE = 0x000001ff;
+ shift_bits = 32-(16+f_code);
+
+ /* start codes are always byte aligned */
+ /* move to the next byte aligned position, if not already there */
+ if (buffer->bitIndex != 7)
+ {
+ bibForwardBits(buffer->bitIndex + 1, buffer);
+ }
+
+ for (;;)
+ {
+ bitErrorIndication = 0;
+ result = bibShowBits(32, buffer, &numBitsGot, &bitErrorIndication, &newError);
+
+
+ if ( buffer->error )
+ {
+ // out of bits
+ *error = (int16)buffer->error;
+ return SNC_NO_SYNC;
+ }
+
+ /* don't check all start codes, if it is not one of them */
+ if (result <= MAX_MPEG4_START_CODE)
+ {
+ if (result == MP4_GROUP_START_CODE)
+ return SNC_GOV;
+ else if (result == MP4_VOP_START_CODE)
+ return SNC_VOP;
+ else if (result == MP4_VOS_START_CODE)
+ return SNC_VOS;
+ else if (result == MP4_EOB_CODE)
+ return SNC_EOB;
+ else if ( checkUD && (result == MP4_USER_DATA_START_CODE) )
+ return SNC_USERDATA;
+
+ }
+ else if (!skipVPSync && f_code && ((result >> shift_bits) == 1))
+ {
+ return SNC_VIDPACK;
+ }
+
+ // we continue here after either if all the if-else's inside the if above are false or if the last else-if is false
+
+ // Note! the following optimization is based on MPEG-4 sync code prefix 0x000001. It doesn't work with any other prefixes.
+ if ( !skipVPSync )
+ {
+ flush = 8;
+ // a small optimization could be reached also with video packet sync markers, but is probably not worth the effort since
+ // it seems that it could be used to shift at most 16 bits at least in cases with typical f_code values
+ // idea:
+ // at least if fcode == 15, possible vp resync markers are in the form
+ // 00008xxx, 00009xxx, 0000axxx, 0000bxxx, 0000cxxx, 0000dxxx, 0000exxx, 0000fxxx
+ // the shifting above already removes the 15 lowest bits => 16th bit must be 1 and 16 highest bits
+ // should be 0
+ // in the old way, the sync code from 00008xxx is found in the following steps
+ // 8xxxyyyy, 008xxxyy, => match
+ // hence we can skip 16 bits (or f-code dependent nr of bits) if
+ // a) 32nd bit is 1
+ // If 32nd bit is 0, we can skip the 16-(nr of successive 0-MSB bits)
+ }
+
+ // then check for the other sync codes
+
+ // the 1st check here is needed to optimize the checking: in hopeless cases only a single check is needed
+ else if ( (result & 0x000000ff) <= 1 )
+ {
+ // the 1st check is needed to optimize the checking: in hopeless cases only a single check is needed
+ if ( ((result & 0x000000ff ) == 1) && ((result & 0x00ffff00 ) > 0))
+ {
+ // yyxxxx01, where one of the x != 0 => hopeless
+ flush = 32;
+ }
+ else if ( (result & 0x0000ffff ) == 0 )
+ {
+ // xxxx0000 => could be the 1st 2 bytes of sync code
+ flush = 16;
+ }
+ else if ( (result & 0x000000ff) == 0 )
+ {
+ // yyyyxx00, where xx != 00 (checked above), could be the 1st byte of sync code
+ flush = 24;
+ }
+ else if ( (result & 0x00ffffff) == 1 )
+ {
+ // xx000001 => shift 1 byte
+ flush = 8;
+ }
+ else
+ {
+ // this looks duplicate to the 1st one, but is kept here for simplicity. The 1st one is there since it is the most probable and
+ // hence most cases fall under it. If it was not there, then in most cases all the if's were evaluated and that means extra processing
+ flush = 32;
+ }
+ }
+ else
+ {
+ // hopeless
+ flush = 32;
+ }
+
+ // flush bits
+ bibFlushBits(flush, buffer, &numBitsGot, &bitErrorIndication, error);
+ }
+}
+
+
+/* {{-output"sncSeekBitPattern.txt"}} */
+/*
+ * sncSeekBitPattern
+ *
+ *
+ * Parameters:
+ * buffer a pointer to a bit buffer structure
+ * error error code
+ * BitPattern to bit pattern to be found
+ * BitPatternLength length of the bit pattern to be found
+ *
+ * Function:
+ * This function finds the next occurance of the given BitPattern
+ * from the buffer. The function discards the bits before the BitPattern
+ * but does not remove the found code from the buffer.
+ *
+ * Returns:
+ * SNC_NO_SYNC if the bit pattern was not found and
+ * no more bits are available
+ * SNC_PATTERN if the BitPattern is found
+ *
+ * Error codes:
+ * Error codes returned by bibFlushBits/bibGetBits/bibShowBits.
+ *
+ *
+ */
+
+int sncSeekBitPattern(bibBuffer_t *buffer, u_int32 BitPattern, int BitPatternLength, int16 *error)
+/* {{-output"sncSeekBitPattern.txt"}} */
+{
+ u_int32 result;
+ int numBitsGot;
+ int16 newError = 0;
+ int bitErrorIndication = 0;
+
+ for (;;) {
+
+ bitErrorIndication = 0;
+
+ result = bibShowBits(32, buffer, &numBitsGot, &bitErrorIndication, &newError);
+
+ if (newError == ERR_BIB_NOT_ENOUGH_DATA && numBitsGot >= BitPatternLength) {
+ /* Use the available bits */
+ result <<= (32 - numBitsGot);
+ newError = 0;
+ } else if (newError) {
+ deb("sncSeekBitPattern: ERROR - bibShowBits failed.\n");
+ *error = newError;
+ return SNC_NO_SYNC;
+ }
+
+ if ((result >> (32 - BitPatternLength)) == BitPattern)
+ return SNC_PATTERN;
+ else if (result == MP4_GROUP_START_CODE)
+ return SNC_GOV;
+ else if (result == MP4_VOP_START_CODE)
+ return SNC_VOP;
+ else if (result == MP4_EOB_CODE)
+ return SNC_EOB;
+ else if ( buffer->error )
+ {
+ // out of bits
+ *error = (int16)buffer->error;
+ return SNC_NO_SYNC;
+ }
+
+ bibFlushBits(1, buffer, &numBitsGot, &bitErrorIndication, error);
+ }
+}
+
+/* {{-output"sncRewindStuffing.txt"}} */
+/*
+ * sncRewindStuffing
+ *
+ *
+ * Parameters:
+ * buffer a pointer to a bit buffer structure
+ * error error code
+ *
+ * Function:
+ * This function recognizes and rewinds the stuffing bits (1..8) from
+ * the current position of the buffer.
+ *
+ * Returns:
+ * SNC_NO_SYNC if the stuffing was not found
+ * SNC_PATTERN if the stuffing has been rewinded successfully
+ *
+ * Error codes:
+ * Error codes returned by bibFlushBits/bibGetBits/bibShowBits.
+ *
+ *
+ */
+
+int sncRewindStuffing(bibBuffer_t *buffer, int16 *error)
+/* {{-output"sncRewindStuffing.txt"}} */
+{
+ u_int32 result;
+ int numBitsGot, i;
+ int16 newError = 0;
+ int bitErrorIndication = 0;
+
+ bibRewindBits(8, buffer, &newError);
+ result = bibGetBits(8, buffer, &numBitsGot, &bitErrorIndication, &newError);
+ if (newError) {
+ deb("sncRewindStuffing: ERROR - bibShowBits failed.\n");
+ *error = newError;
+ return SNC_NO_SYNC;
+ }
+
+ for(i = 1; i <= 8; i++) {
+ /* if stuffing is correct */
+ if ((result & (1 << (i-1))) == 0) {
+ bibRewindBits(i, buffer, &newError);
+ return SNC_PATTERN;
+ }
+ }
+
+ return SNC_NO_SYNC;
+}
+// End of File