diff options
Diffstat (limited to 'youtube_dl')
| -rw-r--r-- | youtube_dl/downloader/f4m.py | 42 | 
1 files changed, 32 insertions, 10 deletions
| diff --git a/youtube_dl/downloader/f4m.py b/youtube_dl/downloader/f4m.py index 3d9337afa..314def4cb 100644 --- a/youtube_dl/downloader/f4m.py +++ b/youtube_dl/downloader/f4m.py @@ -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 | 
