videoeditorengine/h263decoder/src/sync_mpeg.cpp
changeset 0 951a5db380a0
--- /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