2008-09-02 2 views
25

Я читаю несколько протоколов MPEG Transport Stream по UDP, и у него есть некоторые фанковые битовые поля в нем (например, длина 13). Я использую библиотеку «struct», чтобы выполнить широкую распаковку, но есть ли простой способ сказать «Захватить следующие 13 бит» вместо того, чтобы вручную манипулировать манипуляциями с битами? Мне бы хотелось что-то вроде того, как C бит полей (без необходимости возвращаться на C).Каков наилучший способ обработки бит-полей в Python?

Предложения?

ответ

25

Модуль bitstring предназначен для решения именно этой проблемы. Это позволит вам читать, изменять и строить данные с использованием битов в качестве основных строительных блоков. Последние версии для 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.

+0

Я думаю, что пакет [11:24] .uint должен быть пакетом [12:24] .uint. Поле длиной 13 бит, начинается с бит 12, заканчивается на бит 24. – 2012-07-17 14:59:27

Смежные вопросы