6

私はBitStreamStreamと呼ばれるC#ライブラリを見ています。これにより、標準のC#オブジェクトに任意の数のビットを読み書きできます。奇妙な設計上の決定に気づきました。

空のバイトにビットを追加すると、そのビットはバイトのMSBに追加されます。例えば:

var s = new BitStream();
s.Write(true);
Debug.Assert(s.ToByteArray()[0] == 0x80);  // and not 0x01

var s = new BitStream();
s.Write(0x7,0,4);
s.Write(0x3,0,4);
Debug.Assert(s.ToByteArray()[0] == 0x73); // and not 0x37

ただし、数値のビットを入力として参照する場合入力数値の最初のビットはLSBです。例えば

//s.Write(int input,int bit_offset, int count_bits)
//when referencing the LSB and the next bit we'll write
s.Write(data,0,2); //and not s.Write(data,data_bits_number,data_bits_number-2)

それは私には矛盾しているようです。この場合、前の例のようにバイトを「段階的に」コピーすると(最初の4ビット、次に最後の4ビット)、元のバイトは取得されません。それを「逆方向」にコピーする必要があります(最初に最後の4ビット、次に最初の4ビット)。

私が見逃しているそのデザインの理由はありますか?この動作を伴うビットストリームの他の実装はありますか?そのための設計上の考慮事項は何ですか?

ffmpegビットストリームは、私が一貫していると考える方法で動作しているようです。関数内ポインターを使用ORする前に、バイトをシフトする量を確認してください。srcput_bits

補足として:

追加された最初のバイトは、バイト配列の最初のバイトです。例えば

var s = new BitStream();
s.Write(0x1,0,4);
s.Write(0x2,0,4);
s.Write(0x3,0,4);
Debug.Assert(s.ToByteArray()[0] == 0x12); // and not s.ToByteArray()[1] == 0x12
4

3 に答える 3

3

いくつかの追加の考慮事項を次に示します。

ブール値の場合 - true または false を表すために必要なビットは 1 つだけです。そのビットがストリームの先頭に追加されると、ビット ストリームは「1」になります。そのストリームをバイト長に拡張すると、それらのビットが最初からストリームに存在していなかったとしても、ストリームの最後に 0 ビットのパディングが強制されます。ストリーム内の位置は、ビットの値と同様に重要な情報であり、「1000000」または 0x80 のビット ストリームは、ストリームの後続のリーダーが最初に読み取ったビットが追加された最初のビットであるという期待を保護します。

第 2 に、整数などの他のデータ型は表現するのにより多くのビットを必要とするため、ブール値よりもストリーム内でより多くのスペースを占有します。異なるサイズのデータ​​型を同じストリームに混在させることは、それらがバイト境界で整列されていない場合、非常に扱いにくい場合があります。

最後に、Intel x86 を使用している場合、CPU アーキテクチャは「リトルエンディアン」です。これは、説明したように LSB が最初であることを意味します。値をビッグ エンディアンとしてストリームに格納する必要がある場合は、コードに変換レイヤーを追加する必要があります。これは、上記で示したように、一度に 1 バイトずつストリームにプッシュする順序で行います。 . これは面倒ですが、ビッグエンディアンの Unix ボックスと相互運用する必要がある場合や、プロトコル仕様で必要とされる場合に、一般的に必要になります。

それが役立つことを願っています!

于 2010-02-22T22:17:40.783 に答える
1

私はエラザールに同意します。

彼/彼女が指摘するように、これはリーダーとライターがビット順序について合意していない場合です。実際、それらは互換性がありません。

于 2010-03-25T11:51:41.687 に答える