私はUDP上でいくつかのMPEGトランスポートストリームプロトコルを読んでおり、そこにいくつかのファンキーなビットフィールドがあります(例えば長さ13)。私は、広い展開を行うために "構造体"ライブラリを使用していますが、手作業でビット操作を微調整するよりも、 "次の13ビットを掴む"と言う簡単な方法はありますか?私はCがビットフィールドを行う方法(Cに戻らずに)のようにしたいと思います。PythonでBit Field操作を行う最良の方法は何ですか?
提案?
私はUDP上でいくつかのMPEGトランスポートストリームプロトコルを読んでおり、そこにいくつかのファンキーなビットフィールドがあります(例えば長さ13)。私は、広い展開を行うために "構造体"ライブラリを使用していますが、手作業でビット操作を微調整するよりも、 "次の13ビットを掴む"と言う簡単な方法はありますか?私はCがビットフィールドを行う方法(Cに戻らずに)のようにしたいと思います。PythonでBit Field操作を行う最良の方法は何ですか?
提案?
よくある質問です。過去に私に奉仕してくれたASPN Cookbookのエントリがあります。
そしてbitstringモジュールは、まさにこの問題に対処するために設計されてextensive page of requirements one person would like to see from a module doing this.
があります。これは、ビットを基本ビルディングブロックとして使用して、データの読み込み、変更、構築を可能にします。最新バージョンはPython 2.6以降(Python 3を含む)用ですが、バージョン1.0はPython 2.4と2.5もサポートしています。
あなたのための関連する例は、トランスポートストリームから全てのヌルパケットを取り除きれ、これをあるかもしれない(そして恐らく、あなたの13ビットのフィールドを使用しています?):ここで
from bitstring import Bits, BitStream
# Opening from a file means that it won't be all read into memory
s = Bits(filename='test.ts')
outfile = open('test_nonull.ts', 'wb')
# Cut the stream into 188 byte packets
for packet in s.cut(188*8):
# Take a 13 bit slice and interpret as an unsigned integer
PID = packet[11:24].uint
# Write out the packet if the PID doesn't indicate a 'null' packet
if PID != 8191:
# The 'bytes' property converts back to a string.
outfile.write(packet.bytes)
は、ビットストリームからの読み込みを含む別の例です:
# You can create from hex, binary, integers, strings, floats, files...
# This has a hex code followed by two 12 bit integers
s = BitStream('0x000001b3, uint:12=352, uint:12=288')
# Append some other bits
s += '0b11001, 0xff, int:5=-3'
# read back as 32 bits of hex, then two 12 bit unsigned integers
start_code, width, height = s.readlist('hex:32, 2*uint:12')
# Skip some bits then peek at next bit value
s.pos += 4
if s.peek(1):
flags = s.read(9)
あなたは、ビットレベルでなど、スライス、削除、逆転、上書きする標準スライス表記を使用することができ、およびビットレベル見つけ、置き換える、などの機能を分割があります。異なるエンディアンもサポートされています。
# Replace every '1' bit by 3 bits
s.replace('0b1', '0b001')
# Find all occurrences of a bit sequence
bitposlist = list(s.findall('0b01000'))
# Reverse bits in place
s.reverse()
完全なドキュメントはhereです。
パケット[11:24] .uintはパケット[12:24] .uintでなければならないと思います。フィールドは13ビット長で、ビット12で始まり、ビット24で終わります。 –
これは実際にコメントであって答えではありませんが、実際は[11:24]です。インデックスはゼロに基づいており、エンドインデックス(Pythonや他の多くの言語では標準的な使用法です)には含まれません。したがって、最初のビットのスライスは[0:1]ですが、[12:24]は13ビットから24ビットまでの12ビットスライスになります。長さは常に2つのインデックス間の差であることに注意してください。 –