[downloader/f4m] Tolerate truncate segments when testing
Replaces #9216 Fixes #9214 and test_Bloomberg partiallypull/9466/head
parent
7e8ddca1bb
commit
1b405bb47d
|
@ -23,26 +23,38 @@ from ..utils import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DataTruncatedError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FlvReader(io.BytesIO):
|
class FlvReader(io.BytesIO):
|
||||||
"""
|
"""
|
||||||
Reader for Flv files
|
Reader for Flv files
|
||||||
The file format is documented in https://www.adobe.com/devnet/f4v.html
|
The file format is documented in https://www.adobe.com/devnet/f4v.html
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def read_bytes(self, n):
|
||||||
|
data = self.read(n)
|
||||||
|
if len(data) < n:
|
||||||
|
raise DataTruncatedError(
|
||||||
|
'FlvReader error: need %d bytes while only %d bytes got' % (
|
||||||
|
n, len(data)))
|
||||||
|
return data
|
||||||
|
|
||||||
# Utility functions for reading numbers and strings
|
# Utility functions for reading numbers and strings
|
||||||
def read_unsigned_long_long(self):
|
def read_unsigned_long_long(self):
|
||||||
return compat_struct_unpack('!Q', self.read(8))[0]
|
return compat_struct_unpack('!Q', self.read_bytes(8))[0]
|
||||||
|
|
||||||
def read_unsigned_int(self):
|
def read_unsigned_int(self):
|
||||||
return compat_struct_unpack('!I', self.read(4))[0]
|
return compat_struct_unpack('!I', self.read_bytes(4))[0]
|
||||||
|
|
||||||
def read_unsigned_char(self):
|
def read_unsigned_char(self):
|
||||||
return compat_struct_unpack('!B', self.read(1))[0]
|
return compat_struct_unpack('!B', self.read_bytes(1))[0]
|
||||||
|
|
||||||
def read_string(self):
|
def read_string(self):
|
||||||
res = b''
|
res = b''
|
||||||
while True:
|
while True:
|
||||||
char = self.read(1)
|
char = self.read_bytes(1)
|
||||||
if char == b'\x00':
|
if char == b'\x00':
|
||||||
break
|
break
|
||||||
res += char
|
res += char
|
||||||
|
@ -53,18 +65,18 @@ class FlvReader(io.BytesIO):
|
||||||
Read a box and return the info as a tuple: (box_size, box_type, box_data)
|
Read a box and return the info as a tuple: (box_size, box_type, box_data)
|
||||||
"""
|
"""
|
||||||
real_size = size = self.read_unsigned_int()
|
real_size = size = self.read_unsigned_int()
|
||||||
box_type = self.read(4)
|
box_type = self.read_bytes(4)
|
||||||
header_end = 8
|
header_end = 8
|
||||||
if size == 1:
|
if size == 1:
|
||||||
real_size = self.read_unsigned_long_long()
|
real_size = self.read_unsigned_long_long()
|
||||||
header_end = 16
|
header_end = 16
|
||||||
return real_size, box_type, self.read(real_size - header_end)
|
return real_size, box_type, self.read_bytes(real_size - header_end)
|
||||||
|
|
||||||
def read_asrt(self):
|
def read_asrt(self):
|
||||||
# version
|
# version
|
||||||
self.read_unsigned_char()
|
self.read_unsigned_char()
|
||||||
# flags
|
# flags
|
||||||
self.read(3)
|
self.read_bytes(3)
|
||||||
quality_entry_count = self.read_unsigned_char()
|
quality_entry_count = self.read_unsigned_char()
|
||||||
# QualityEntryCount
|
# QualityEntryCount
|
||||||
for i in range(quality_entry_count):
|
for i in range(quality_entry_count):
|
||||||
|
@ -85,7 +97,7 @@ class FlvReader(io.BytesIO):
|
||||||
# version
|
# version
|
||||||
self.read_unsigned_char()
|
self.read_unsigned_char()
|
||||||
# flags
|
# flags
|
||||||
self.read(3)
|
self.read_bytes(3)
|
||||||
# time scale
|
# time scale
|
||||||
self.read_unsigned_int()
|
self.read_unsigned_int()
|
||||||
|
|
||||||
|
@ -119,7 +131,7 @@ class FlvReader(io.BytesIO):
|
||||||
# version
|
# version
|
||||||
self.read_unsigned_char()
|
self.read_unsigned_char()
|
||||||
# flags
|
# flags
|
||||||
self.read(3)
|
self.read_bytes(3)
|
||||||
|
|
||||||
self.read_unsigned_int() # BootstrapinfoVersion
|
self.read_unsigned_int() # BootstrapinfoVersion
|
||||||
# Profile,Live,Update,Reserved
|
# Profile,Live,Update,Reserved
|
||||||
|
@ -374,7 +386,17 @@ class F4mFD(FragmentFD):
|
||||||
down.close()
|
down.close()
|
||||||
reader = FlvReader(down_data)
|
reader = FlvReader(down_data)
|
||||||
while True:
|
while True:
|
||||||
_, box_type, box_data = reader.read_box_info()
|
try:
|
||||||
|
_, box_type, box_data = reader.read_box_info()
|
||||||
|
except DataTruncatedError:
|
||||||
|
if test:
|
||||||
|
# In tests, segments may be truncated, and thus
|
||||||
|
# FlvReader may not be able to parse the whole
|
||||||
|
# chunk. If so, write the segment as is
|
||||||
|
# See https://github.com/rg3/youtube-dl/issues/9214
|
||||||
|
dest_stream.write(down_data)
|
||||||
|
break
|
||||||
|
raise
|
||||||
if box_type == b'mdat':
|
if box_type == b'mdat':
|
||||||
dest_stream.write(box_data)
|
dest_stream.write(box_data)
|
||||||
break
|
break
|
||||||
|
|
Loading…
Reference in New Issue