diff -r 000000000000 -r 951a5db380a0 videoeditorengine/h263decoder/src/sync_mpeg.cpp --- /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