[XviD-devel] Bitstream problems for RISC architectures

Eric R. Smith ersmith at hfx.eastlink.ca
Thu Apr 3 23:40:45 CEST 2003


I've been porting XviD to a RISC architecture and ran into a problem 
with the bitstream code. The version currently in CVS (and also in the 
0.9.1 release) does loads of a uint32_t from arbitrary addresses. This 
works on the x86, but not on many RISCs, where uint32_t accesses must be 
32 bit aligned.

The solution is quite straightforward: it's just to start the stream at 
the previous word boundary and skip the necessary number of bits at the 
beginning of the stream. Once the stream is aligned it will stay 
aligned. I've appended a patch below. I've verified that this still 
works on the x86 (and in fact is very slightly faster, since even when 
unaligned loads are allowed they are slower than aligned ones). I've 
only tested the decoder; I don't know if any more changes may be 
necessary to the encoder.

(Incidentally, kudos for the very clean and easy to follow code; XviD is 
the best written video codec I've come across!)

Regards,
Eric

Index: src/global.h
===================================================================
RCS file: /xvid/xvidcore/src/global.h,v
retrieving revision 1.21
diff -u -b -r1.21 global.h
--- src/global.h	21 Feb 2003 14:49:28 -0000	1.21
+++ src/global.h	3 Apr 2003 22:41:14 -0000
@@ -94,6 +94,7 @@
  	uint32_t *tail;
  	uint32_t *start;
  	uint32_t length;
+	uint32_t initpos;
  }
  Bitstream;

Index: src/bitstream/bitstream.h
===================================================================
RCS file: /xvid/xvidcore/src/bitstream/bitstream.h,v
retrieving revision 1.17
diff -u -b -r1.17 bitstream.h
--- src/bitstream/bitstream.h	15 Feb 2003 15:22:18 -0000	1.17
+++ src/bitstream/bitstream.h	3 Apr 2003 22:41:14 -0000
@@ -173,23 +173,29 @@
  			  uint32_t length)
  {
  	uint32_t tmp;
+        size_t bitpos;
+        ptr_t adjbitstream = (ptr_t)bitstream;

-	bs->start = bs->tail = (uint32_t *) bitstream;
+        /* Start the stream on a uint32_t boundary, by rounding down to the
+           previous uint32_t and skipping the intervening bytes. */
+        bitpos = ((sizeof(uint32_t)-1) & (size_t)bitstream);
+        adjbitstream = adjbitstream - bitpos;
+	bs->start = bs->tail = (uint32_t *) adjbitstream;

-	tmp = *(uint32_t *) bitstream;
+	tmp = *bs->start;
  #ifndef ARCH_IS_BIG_ENDIAN
  	BSWAP(tmp);
  #endif
  	bs->bufa = tmp;

-	tmp = *((uint32_t *) bitstream + 1);
+	tmp = *(bs->start + 1);
  #ifndef ARCH_IS_BIG_ENDIAN
  	BSWAP(tmp);
  #endif
  	bs->bufb = tmp;

  	bs->buf = 0;
-	bs->pos = 0;
+	bs->pos = bs->initpos = bitpos*8;
  	bs->length = length;
  }

@@ -216,7 +222,7 @@
  	bs->bufb = tmp;

  	bs->buf = 0;
-	bs->pos = 0;
+	bs->pos = bs->initpos;
  }


@@ -309,7 +315,7 @@
  static uint32_t __inline
  BitstreamPos(const Bitstream * const bs)
  {
-	return 8 * ((ptr_t)bs->tail - (ptr_t)bs->start) + bs->pos;
+	return 8 * ((ptr_t)bs->tail - (ptr_t)bs->start) + bs->pos - bs->initpos;
  }


@@ -332,7 +338,9 @@

  		len += (bs->pos + 7) / 8;
  	}
-
+        if (bs->initpos) {
+            len -= bs->initpos/8;  /* initpos is always on a byte 
boundary */
+        }
  	return len;
  }




More information about the XviD-devel mailing list