views:

52

answers:

1

While working on decoding some video streaming standards I have noticed a lot of instances where the bits of an Integer value are provided in anything from 2-6 bytes but separated by reserved bits, as follows:

// Specification (16 bits)
// -----------------------
// Reserved         1  bit
// Value A [6-7]    2  bit
// Reserved         2  bit
// Value A [4-5]    2  bit
// Reserved         3  bit
// Value A [0-3]    4  bit
// Reserved         2  bit

For Example, the value 185 (10111001 or 0xB9) would be stored as follows in a two byte array:

01000110 00100100

I know this is nuts, but this is the way these guys have coded their data stream. It can be extracted using the following bit operations

int w = 0;
w |= (0x60 & data[0]) >>> 5;  // extract the first 2 bits shifted to the front
w <<= 2;                      // bump them up 2 bits for the next section
w |= (0x06 & data[0]) >>> 1;  // extract the next 2 bits shifted to the front
w <<= 4;                      // bump them up 4 bits for the last section
w |= (0x3C & data[0]) >>> 2;  // extract the last 4 bits shifted to the front

// w now will equal 10111001 (185)

What I would like to be able to do is create a method that would accept a byte array of undetermined length and an Int representing a mask of the bits that constitue the value we are trying to extract derived from the specification provided. Something like this

public static void testMethod() {

    byte[] data = new byte[] {0x46, 0x24}; // 01000110 00100100 
    int mask = 0x663C;                     // 01100110 00111100
    int x = readIntFromMaskedBytes(data, mask);

}

public static int readIntFromMaskedBytes(byte[] data, int mask) {
    int result = 0;

    // use the mask to extract the marks bits from each
    // byte and shift them appropriately to form an int

    return result;
}

I have completed the project I was working on using the original "manual" approach, but I am not satisfied that it is as clean as it could be due to the sheer number of these occurrences and their complexity. I would love to come up with a more generic method that could accomplish the same thing.

Unfortunately I'm still a newbie when it comes to this complexity of bit shifting and I was hoping someone could provide some advice or suggestions on how best to accomplish this.

Xela

Note - Excuse any syntax errors in the pseudo-code above it is only design to serve as an explanation of the use case.

+1  A: 

Actually, I tend to think that the inline mask and shift approach (if implemented a bit more cleanly than your pseudocode) is better than trying to write a general purpose method. For an experienced developer of low-level bit bashing code, reading mask-and-shift code should be no problem. The trouble with a general purpose method along the lines you are proposing is that it will be significantly less efficient ... and difficult for the JIT compiler to optimize.

BTW, this is how I'd write the code.

// extract and assemble xxxx from yyyy 
int w = ((0x003C & data[0]) >> 2) | 
        ((0x0600 & data[0]) >> 6) | 
        ((0x6000 & data[0]) >> 7);

EDIT

I would still like to understand how such a generic approach could be coded though, as a learning exercise.

Something like this:

public static int readIntFromMaskedBytes(int data, int mask) {
    int result = 0;
    int shift = 0;
    while (mask != 0) {
        if (mask & 1) {
            result |= (data & 1) << shift++;
        }
        data >>>= 1;
        mask >>>= 1;
    }
}

As you can see, that will take up to 32 loop iterations to give you the answer. For your example, I'd say this approach is roughly 10 times slower than the original version.

Stephen C
Thanks for the response Stephen, I'll certainly take your comments into account. I would still like to understand how such a generic approach could be coded though, as a learning exercise.
Xela
Outstanding. I'll play with this in the morning, but will continue to use the direct approach in the production code as you suggest. Thanks for your advice Stephen.
Xela