2015-10-15 2 views
1

Я пытаюсь разобрать необработанный двоичный файл в Python с известными заголовками и длинами.Разбор необработанного двоичного файла для нескольких наборов видеокадров

Данные представляют собой 6-канальное мультиплексированное видео.

Файл следует следующие правила для отдельных кадров:

  • Байт 1: Указывает канал # (например, 0xE0, 0xE1, 0xE2 ...)
  • Б 4 & 5: Представляют длины данные изображения
  • Bytes 6: Length: Данные изображения
  • Конец данных изображения дополняется 0xFF, так что каждый фрагмент изображения начинается с первого байта в 16-байтовых строках.

Начало данных изображения

E0 01 00 00 D2 59 80 C1 27 3F EC BB 31 7B 3F EC 

BB 31 7B 0F 9B 90 5D A8 81 AA 5F A9 C1 D2 4B B9 

9D 0A 8D 1B 8F 89 44 FF 4E 86 92 AD 00 90 5B A8 

Конец данных изображения

67 49 0B B5 BC 82 38 AE 5E 46 49 86 6A FF 24 97 

69 8C 6F 17 6D 67 B5 11 C7 E5 FB E3 3F 65 1F 22 

5C F3 7C D0 7C 49 2F CD 26 37 4D 40 FF FF FF FF 

Исходные файлы несколько GB большой. Каков наилучший способ разобрать каждый канал в отдельный файл? Кроме того, как я могу обрабатывать несколько файлов одновременно, сохраняя файлы в соответствии с именем ввода?

ответ

0

Разбор крошечных фрагментов двоичных файлов с несколькими ГБ, вероятно, не является чем-то вроде того, что Python будет очень быстрым, поскольку для этого потребуется тонна вызовов функций и создания объектов, что означает много оперативной памяти и накладных расходов процессора. Если вам нужна более высокая производительность или контроль над управлением памятью, лучше всего это сделать на языке более низкого уровня (C, C++, Go, Rust).

Однако, вы можете сделать такого рода вещи в Python с использованием модуля struct, что-то вроде этого:

header = struct.Struct('>BBBH') 
data = b'\xE0\x01\x00\x00\xD2\x59\x80...' # read this from input file 
view = memoryview(data) 
offset = 0 
while offset < len(data): 
    channel, _, _, length = header.unpack(view[offset:offset + header.size]) 
    write_output(channel, view[header.size:header.size + length]) 
    offset += length 

Things отметить:

  • Определить, является ли длина в большой Endian или little endian (< vs > в строке формата)
  • Использование memoryview - это способ избежать частичного копирования и создания объектов - надеюсь он делает это более эффективный
  • Вы хотите сохранить выходной файл (ы) с открытым - я просто спрятано это за write_output() выше
  • Если вход мульти-GB, вы, вероятно, хотите, чтобы прочитать вход файл в кусках 1 МБ или что-то разумное, а не все сразу
  • Будьте осторожны с байтами против строк (различная обработка на Python 2.x vs 3.x)
  • Если вам нужно больше узнать об открытии, чтении, и писать файлы, не стесняйтесь публиковать более конкретные вопросы

Что касается пакетной обработки sever al файлов сразу, лучший выбор - модуль multiprocessing. Это займет некоторое время, чтобы окунуться в голову, но после этого он довольно прост в использовании.

+0

Что вы предложите использовать в C++? – user2079221

+0

Я никогда не использовал iostreams на C++, поэтому лично я мог бы сделать это на C и просто использовать fopen(), fread() с unsigned char (byte) buffer. Чтение 64 КБ или 1 МБ за раз или что-то в этом роде. –