[downloader/f4m] Tolerate truncate segments when testing
Replaces #9216 Fixes #9214 and test_Bloomberg partially
This commit is contained in:
		
							parent
							
								
									7e8ddca1bb
								
							
						
					
					
						commit
						1b405bb47d
					
				
					 1 changed files with 32 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -23,26 +23,38 @@ from ..utils import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DataTruncatedError(Exception):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FlvReader(io.BytesIO):
 | 
			
		||||
    """
 | 
			
		||||
    Reader for Flv files
 | 
			
		||||
    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
 | 
			
		||||
    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):
 | 
			
		||||
        return compat_struct_unpack('!I', self.read(4))[0]
 | 
			
		||||
        return compat_struct_unpack('!I', self.read_bytes(4))[0]
 | 
			
		||||
 | 
			
		||||
    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):
 | 
			
		||||
        res = b''
 | 
			
		||||
        while True:
 | 
			
		||||
            char = self.read(1)
 | 
			
		||||
            char = self.read_bytes(1)
 | 
			
		||||
            if char == b'\x00':
 | 
			
		||||
                break
 | 
			
		||||
            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)
 | 
			
		||||
        """
 | 
			
		||||
        real_size = size = self.read_unsigned_int()
 | 
			
		||||
        box_type = self.read(4)
 | 
			
		||||
        box_type = self.read_bytes(4)
 | 
			
		||||
        header_end = 8
 | 
			
		||||
        if size == 1:
 | 
			
		||||
            real_size = self.read_unsigned_long_long()
 | 
			
		||||
            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):
 | 
			
		||||
        # version
 | 
			
		||||
        self.read_unsigned_char()
 | 
			
		||||
        # flags
 | 
			
		||||
        self.read(3)
 | 
			
		||||
        self.read_bytes(3)
 | 
			
		||||
        quality_entry_count = self.read_unsigned_char()
 | 
			
		||||
        # QualityEntryCount
 | 
			
		||||
        for i in range(quality_entry_count):
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +97,7 @@ class FlvReader(io.BytesIO):
 | 
			
		|||
        # version
 | 
			
		||||
        self.read_unsigned_char()
 | 
			
		||||
        # flags
 | 
			
		||||
        self.read(3)
 | 
			
		||||
        self.read_bytes(3)
 | 
			
		||||
        # time scale
 | 
			
		||||
        self.read_unsigned_int()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +131,7 @@ class FlvReader(io.BytesIO):
 | 
			
		|||
        # version
 | 
			
		||||
        self.read_unsigned_char()
 | 
			
		||||
        # flags
 | 
			
		||||
        self.read(3)
 | 
			
		||||
        self.read_bytes(3)
 | 
			
		||||
 | 
			
		||||
        self.read_unsigned_int()  # BootstrapinfoVersion
 | 
			
		||||
        # Profile,Live,Update,Reserved
 | 
			
		||||
| 
						 | 
				
			
			@ -374,7 +386,17 @@ class F4mFD(FragmentFD):
 | 
			
		|||
                down.close()
 | 
			
		||||
                reader = FlvReader(down_data)
 | 
			
		||||
                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':
 | 
			
		||||
                        dest_stream.write(box_data)
 | 
			
		||||
                        break
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue