vidindex improvements (#30196)

* vidindex improvements

* fix spelling
old-commit-hash: 6f98a987af
laptop
Greg Hogan 2 years ago committed by GitHub
parent fa245bfab0
commit a62749f527
  1. 29
      tools/lib/vidindex.py

@ -1,11 +1,17 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
import os
import struct import struct
from enum import IntEnum from enum import IntEnum
from typing import Tuple from typing import Tuple
from openpilot.tools.lib.filereader import FileReader from openpilot.tools.lib.filereader import FileReader
DEBUG = int(os.getenv("DEBUG", "0"))
# compare to ffmpeg parsing
# ffmpeg -i <input.hevc> -c copy -bsf:v trace_headers -f null - 2>&1 | grep -B4 -A32 '] 0 '
# H.265 specification # H.265 specification
# https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-201802-S!!PDF-E&type=items # https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-201802-S!!PDF-E&type=items
@ -143,15 +149,9 @@ def get_ue(dat: bytes, start_idx: int, skip_bits: int) -> Tuple[int, int]:
raise VideoFileInvalid("invalid exponential-golomb code") raise VideoFileInvalid("invalid exponential-golomb code")
def require_nal_unit_start(dat: bytes, nal_unit_start: int) -> None: def require_nal_unit_start(dat: bytes, nal_unit_start: int) -> None:
if nal_unit_start >= len(dat):
raise ValueError("start index must be less than data length")
if nal_unit_start < 1: if nal_unit_start < 1:
raise ValueError("start index must be greater than zero") raise ValueError("start index must be greater than zero")
if dat[nal_unit_start-1] != 0x00:
raise VideoFileInvalid("start code must be preceded by 0x00")
if dat[nal_unit_start:nal_unit_start + NAL_UNIT_START_CODE_SIZE] != NAL_UNIT_START_CODE: if dat[nal_unit_start:nal_unit_start + NAL_UNIT_START_CODE_SIZE] != NAL_UNIT_START_CODE:
raise VideoFileInvalid("data must begin with start code") raise VideoFileInvalid("data must begin with start code")
@ -163,6 +163,8 @@ def get_hevc_nal_unit_length(dat: bytes, nal_unit_start: int) -> int:
# length of NAL unit is byte count up to next NAL unit start index # length of NAL unit is byte count up to next NAL unit start index
nal_unit_len = (pos if pos != -1 else len(dat)) - nal_unit_start nal_unit_len = (pos if pos != -1 else len(dat)) - nal_unit_start
if DEBUG:
print(" nal_unit_len:", nal_unit_len)
return nal_unit_len return nal_unit_len
def get_hevc_nal_unit_type(dat: bytes, nal_unit_start: int) -> HevcNalUnitType: def get_hevc_nal_unit_type(dat: bytes, nal_unit_start: int) -> HevcNalUnitType:
@ -177,7 +179,10 @@ def get_hevc_nal_unit_type(dat: bytes, nal_unit_start: int) -> HevcNalUnitType:
nal_unit_header = dat[header_start:header_start + NAL_UNIT_HEADER_SIZE] nal_unit_header = dat[header_start:header_start + NAL_UNIT_HEADER_SIZE]
if len(nal_unit_header) != 2: if len(nal_unit_header) != 2:
raise VideoFileInvalid("data to short to contain nal unit header") raise VideoFileInvalid("data to short to contain nal unit header")
return HevcNalUnitType((nal_unit_header[0] >> 1) & 0x3F) nal_unit_type = HevcNalUnitType((nal_unit_header[0] >> 1) & 0x3F)
if DEBUG:
print(" nal_unit_type:", nal_unit_type.name, f"({nal_unit_type.value})")
return nal_unit_type
def get_hevc_slice_type(dat: bytes, nal_unit_start: int, nal_unit_type: HevcNalUnitType) -> Tuple[int, bool]: def get_hevc_slice_type(dat: bytes, nal_unit_start: int, nal_unit_type: HevcNalUnitType) -> Tuple[int, bool]:
# 7.3.2.9 Slice segment layer RBSP syntax # 7.3.2.9 Slice segment layer RBSP syntax
@ -248,6 +253,8 @@ def get_hevc_slice_type(dat: bytes, nal_unit_start: int, nal_unit_type: HevcNalU
# 2 | I (I slice) # 2 | I (I slice)
# unsigned integer 0-th order Exp-Golomb-coded syntax element with the left bit first # unsigned integer 0-th order Exp-Golomb-coded syntax element with the left bit first
slice_type, _ = get_ue(dat, rbsp_start, skip_bits) slice_type, _ = get_ue(dat, rbsp_start, skip_bits)
if DEBUG:
print(" slice_type:", slice_type, f"(first slice: {is_first_slice})")
if slice_type > 2: if slice_type > 2:
raise VideoFileInvalid("slice_type must be 0, 1, or 2") raise VideoFileInvalid("slice_type must be 0, 1, or 2")
return slice_type, is_first_slice return slice_type, is_first_slice
@ -259,11 +266,14 @@ def hevc_index(hevc_file_name: str, allow_corrupt: bool=False) -> Tuple[list, in
if len(dat) < NAL_UNIT_START_CODE_SIZE + 1: if len(dat) < NAL_UNIT_START_CODE_SIZE + 1:
raise VideoFileInvalid("data is too short") raise VideoFileInvalid("data is too short")
if dat[0] != 0x00:
raise VideoFileInvalid("first byte must be 0x00")
prefix_dat = b"" prefix_dat = b""
frame_types = list() frame_types = list()
i = 1 # skip past first byte 0x00
try: try:
i = 1 # skip past first byte 0x00 (verified by get_hevc_nal_info)
while i < len(dat): while i < len(dat):
require_nal_unit_start(dat, i) require_nal_unit_start(dat, i)
nal_unit_len = get_hevc_nal_unit_length(dat, i) nal_unit_len = get_hevc_nal_unit_length(dat, i)
@ -275,9 +285,10 @@ def hevc_index(hevc_file_name: str, allow_corrupt: bool=False) -> Tuple[list, in
if is_first_slice: if is_first_slice:
frame_types.append((slice_type, i)) frame_types.append((slice_type, i))
i += nal_unit_len i += nal_unit_len
except Exception: except Exception as e:
if not allow_corrupt: if not allow_corrupt:
raise raise
print(f"ERROR: NAL unit skipped @ {i}\n", str(e))
return frame_types, len(dat), prefix_dat return frame_types, len(dat), prefix_dat

Loading…
Cancel
Save