在解码某些视频流标准时,我注意到很多实例,这些实例在2-6个字节中提供了整数值的位,但在保留位,如下所示:

// 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

例如,值185(10111001 或者 0xB9)将在两个字节阵列中存储如下:

01000110 00100100

我知道这很疯狂,但这就是这些家伙编码数据流的方式。它可以使用以下位操作提取

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)

我想做的是创建一种方法,该方法将接受一个不确定的长度的字节数组和代表构成我们试图从所提供的规范中提取的值的位掩码的int。这样的东西

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;
}

我已经完成了我正在使用原始“手动”方法的项目,但是我不满意它是由于这些事件的庞大数量及其复杂性而造成的。我很想想出一种可以完成同一件事的更通用的方法。

不幸的是,当涉及到一些变化的复杂性时,我仍然是新手,我希望有人可以为如何最好地做到这一点提供一些建议或建议。

Xela

注意 - 请原谅上述伪代码中的任何语法错误,仅作为用例的解释而设计。

有帮助吗?

解决方案

实际上,我倾向于认为内联掩码和移位方法(如果实现比您的伪代码更干净)比尝试编写通用方法更好。对于经验丰富的低级位击打代码的经验丰富的开发人员,读取口罩和换档代码应该没问题。沿着您提出的一行的通用方法的麻烦是,它的效率将显着降低……而对于JIT编译器来说,很难进行优化。

顺便说一句,这就是我写代码的方式。

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

编辑

我仍然想了解如何将这种通用方法作为一种学习练习进行编码。

这样的事情:

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;
    }
}

如您所见,最多将需要32个循环迭代来给您答案。就您的示例而言,我会说这种方法比原始版本慢10倍。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top