heic重构建
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
# pyheic_struct/parser.py
|
||||
|
||||
import struct
|
||||
from typing import List, BinaryIO
|
||||
from io import BytesIO
|
||||
|
||||
from base import Box
|
||||
from base import Box, FullBox
|
||||
from heic_types import (
|
||||
ItemLocationBox, PrimaryItemBox, ItemInfoBox, ItemPropertiesBox,
|
||||
ItemPropertyContainerBox, ItemPropertyAssociationBox, ImageSpatialExtentsBox,
|
||||
ItemReferenceBox # <-- Import the new class
|
||||
ItemReferenceBox, ItemInfoEntryBox # <-- 导入新的 'infe' 盒
|
||||
)
|
||||
|
||||
BOX_TYPE_MAP = {
|
||||
@@ -17,12 +19,15 @@ BOX_TYPE_MAP = {
|
||||
'ipco': ItemPropertyContainerBox,
|
||||
'ipma': ItemPropertyAssociationBox,
|
||||
'ispe': ImageSpatialExtentsBox,
|
||||
'iref': ItemReferenceBox, # <-- Register the new class
|
||||
'iref': ItemReferenceBox,
|
||||
'infe': ItemInfoEntryBox, # <-- 注册新的 'infe' 盒
|
||||
}
|
||||
|
||||
# 'iref' is also a container.
|
||||
# 'iinf' IS a container (它包含 'infe' 盒)
|
||||
CONTAINER_BOXES = {'meta', 'moov', 'trak', 'iprp', 'ipco', 'dinf', 'fiinf', 'ipro', 'iinf', 'iref'}
|
||||
FULL_BOXES = {'meta', 'hdlr', 'pitm', 'iinf', 'iloc', 'ipma', 'ispe', 'iref'}
|
||||
# 几乎所有语义盒都是 FullBox
|
||||
FULL_BOXES = {'meta', 'hdlr', 'pitm', 'iinf', 'iloc', 'ipma', 'ispe', 'iref', 'infe'}
|
||||
|
||||
def parse_boxes(stream: BinaryIO, max_size: int) -> List[Box]:
|
||||
"""
|
||||
@@ -59,16 +64,40 @@ def parse_boxes(stream: BinaryIO, max_size: int) -> List[Box]:
|
||||
if len(raw_data) < content_size: break
|
||||
|
||||
box_class = BOX_TYPE_MAP.get(box_type, Box)
|
||||
|
||||
if box_class == Box and box_type in FULL_BOXES:
|
||||
box_class = FullBox
|
||||
|
||||
box = box_class(size, box_type, current_offset_in_stream, raw_data)
|
||||
|
||||
if box.type in CONTAINER_BOXES:
|
||||
child_stream = BytesIO(box.raw_data)
|
||||
parse_size = len(box.raw_data)
|
||||
if box.type in FULL_BOXES:
|
||||
# Skip version/flags from the beginning of the raw_data
|
||||
child_stream.read(4)
|
||||
parse_size -= 4
|
||||
|
||||
if box.is_full_box:
|
||||
# 跳过 4 字节的 version/flags
|
||||
if parse_size >= 4:
|
||||
child_stream.read(4)
|
||||
parse_size -= 4
|
||||
|
||||
# --- START FIX ---
|
||||
# 'iinf' 盒在 version/flags 之后还有一个 item_count 字段
|
||||
# 我们必须在解析它的子盒之前跳过它
|
||||
if box.type == 'iinf':
|
||||
if box.version == 0:
|
||||
if parse_size >= 2:
|
||||
child_stream.read(2) # 跳过 16-bit item_count
|
||||
parse_size -= 2
|
||||
else:
|
||||
if parse_size >= 4:
|
||||
child_stream.read(4) # 跳过 32-bit item_count
|
||||
parse_size -= 4
|
||||
# --- END FIX ---
|
||||
|
||||
box.children = parse_boxes(child_stream, parse_size)
|
||||
|
||||
# 调用钩子
|
||||
box._post_parse_initialization()
|
||||
|
||||
boxes.append(box)
|
||||
stream.seek(current_offset_in_stream + size)
|
||||
|
||||
Reference in New Issue
Block a user