Parsing unknown superboxes with known 1st sub box. #175

This commit is contained in:
jevans 2014-02-16 20:05:39 -05:00
commit 3c333e999d
2 changed files with 41 additions and 1 deletions

View file

@ -164,12 +164,32 @@ class Jp2kBox(object):
# Call the proper parser for the given box with ID "T".
try:
box = _BOX_WITH_ID[box_id].parse(fptr, start, num_bytes)
except KeyError:
except KeyError as err:
msg = 'Unrecognized box ({0}) encountered.'.format(box_id)
warnings.warn(msg)
box = Jp2kBox(box_id, offset=start, length=num_bytes,
longname='Unknown box')
if fptr.tell() != start + 8:
# If the file pointer has advanced, then the KeyError
# ocurred during the parsing of the box.
pass
else:
# Could it be a superbox with recognizable child boxes?
# Peek ahead to see.
pos = fptr.tell()
read_buffer = fptr.read(8)
sub_length, sub_id = struct.unpack('>I4s', read_buffer)
sub_id = sub_id.decode('utf-8')
# Regardless of whether or not we recognize the box, rewind back
# to properly advance to the next box.
fptr.seek(pos)
# Now process any child boxes if we actually did recognize it.
if sub_id in _BOX_WITH_ID.keys():
box.box = box.parse_superbox(fptr)
superbox.append(box)
# Position to the start of the next box.

View file

@ -4,6 +4,7 @@ Test suite specifically targeting JPX box layout.
"""
import os
import shutil
import struct
import sys
import tempfile
@ -202,6 +203,25 @@ class TestJPX(unittest.TestCase):
self.assertEqual(jpx.box[2].standard_flag,
(5, 42, 45, 2, 18, 19, 1, 8, 12, 31, 20))
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
def test_unknown_superbox(self):
"""Verify that we can handle an unknown superbox."""
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
with open(self.jpxfile, 'rb') as ifile:
tfile.write(ifile.read())
# Add the header for an unknwon superbox.
write_buffer = struct.pack('>I4s', 20, 'grp '.encode())
tfile.write(write_buffer)
write_buffer = struct.pack('>I4sI', 12, 'free'.encode(), 0)
tfile.write(write_buffer)
tfile.flush()
with self.assertWarns(UserWarning):
jpx = Jp2k(tfile.name)
self.assertEqual(jpx.box[-1].box_id, 'grp ')
self.assertEqual(jpx.box[-1].box[0].box_id, 'free')
def test_free_box(self):
"""Verify that we can handle a free box."""
j = Jp2k(self.jpxfile)