def setUp(self): self.tempdir = tempfile.mkdtemp() # Generate source file self.srcfilename = os.path.join(self.tempdir, "src.mkv") f = open(self.srcfilename, "wb") d = '*' * (1024 * 1024) for i in range(0, 10): f.write(d) f.write(d[:34235]) f.close() self.f = open(self.srcfilename, "rb") self.destfilename = os.path.join(self.tempdir, "dest.mkv") self.g = open(self.destfilename, "wb") self.c = SmartCachingStream(self.f, blocksize=65536)
def gui_vod_event_callback(self, d, event, params): """ Also called by SwarmPlayer """ print >> sys.stderr, "videoplay: gui_vod_event:", event if event == VODEVENT_START: filename = params["filename"] mimetype = params["mimetype"] stream = params["stream"] length = params["length"] if filename: self.play_file(filename) else: if d.get_def().get_live(): cachestream = stream blocksize = d.get_def().get_piece_length() else: if d.get_def().get_def_type() == "swift": piecelen = 2 ** 16 else: piecelen = d.get_def().get_piece_length() if False and piecelen > 2 ** 17: # Arno, 2010-01-21: # Workaround for streams with really large piece # sizes. For some content/containers, VLC can do # GET X-, GET X+10K-, GET X+20K HTTP requests # and we would answer these by putting megabytes # into the stream buffer, of which only 10K would be # used. This kills performance. Hence I add a caching # stream that tries to resolve answers from its internal # buffer, before reading the engine's stream. # This works, but only if the HTTP server doesn't # read too aggressively, i.e., uses small blocksize. # cachestream = SmartCachingStream(stream) blocksize = max(32768, piecelen / 8) else: cachestream = stream blocksize = piecelen if d.get_def().get_live() and is_ogg(d.get_def().get_name_as_unicode()): # Live Ogg stream. To support this we need to do # two things: # 1. Write Ogg headers (stored in .tstream) # 2. Find first Ogg page in stream. cachestream = OggMagicLiveStream(d.get_def(), stream) # Estimate duration. Video player (e.g. VLC) often can't tell # when streaming. estduration = None if d.get_def().get_def_type() == "torrent": if d.get_def().get_live(): # Set correct Ogg MIME type if is_ogg(d.get_def().get_name_as_unicode()): mimetype = 'application/ogg' else: file = None if d.get_def().is_multifile_torrent(): file = d.get_selected_files()[0] bitrate = d.get_def().get_bitrate(file) if bitrate is not None: estduration = float(length) / float(bitrate) # Set correct Ogg MIME type if file is None: if is_ogg(d.get_def().get_name_as_unicode()): mimetype = 'application/ogg' else: if is_ogg(file): mimetype = 'application/ogg' streaminfo = {'mimetype': mimetype, 'stream': cachestream, 'length':length, 'blocksize':blocksize, 'estduration':estduration} if d.get_def().get_def_type() == "swift": streaminfo['url'] = params['url'] self.play_stream(streaminfo) elif event == VODEVENT_PAUSE: if self.videoframe is not None: self.videoframe.get_videopanel().Pause(gui_vod_event=True) elif event == VODEVENT_RESUME: if self.videoframe is not None: self.videoframe.get_videopanel().Resume()
class TestCachingStream(unittest.TestCase): """ Note: CachingStream currently actually reads 4x the blocksize into the buffer, so the tests are slightly different than suggested, but in any case all should pass. """ def setUp(self): self.tempdir = tempfile.mkdtemp() # Generate source file self.srcfilename = os.path.join(self.tempdir, "src.mkv") f = open(self.srcfilename, "wb") d = '*' * (1024 * 1024) for i in range(0, 10): f.write(d) f.write(d[:34235]) f.close() self.f = open(self.srcfilename, "rb") self.destfilename = os.path.join(self.tempdir, "dest.mkv") self.g = open(self.destfilename, "wb") self.c = SmartCachingStream(self.f, blocksize=65536) def tearDown(self): try: shutil.rmtree(self.tempdir, ignore_errors=True) except: print_exc() def test_sequential_2xblocksize(self): while True: data = self.c.read(65536 * 2) if len(data) == 0: break self.g.write(data) if DEBUG: print >> sys.stderr, ".", self.g.close() self.cmp_files() def test_sequential_halfxblocksize(self): while True: data = self.c.read(32768) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data) if len(data) == 0: break self.g.write(data) if DEBUG: print >> sys.stderr, ".", self.g.close() self.cmp_files() def test_sequential_bs32767(self): while True: data = self.c.read(32767) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data) if len(data) == 0: break self.g.write(data) if DEBUG: print >> sys.stderr, ".", self.g.close() self.cmp_files() def test_sequential_readnseek(self): pos = 0 while True: data = self.c.read(32767) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data) if len(data) == 0: break self.g.write(data) pos += len(data) self.c.seek(pos) if DEBUG: print >> sys.stderr, ".", self.g.close() self.cmp_files() def test_read1sttwice(self): data1 = self.c.read(32768) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data1) self.c.seek(0) data2 = self.c.read(32768) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data2) self.assert_(data1 == data2) def test_inside_1stblock(self): data1 = self.c.read(32768) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data1) self.c.seek(16384) data2 = self.c.read(16384) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data2) self.assert_(data1[16384:] == data2) self.c.seek(10000) data3 = self.c.read(20000) if DEBUG: print >> sys.stderr, "test: Got bytes", len(data3) self.assert_(data1[10000:10000 + 20000] == data3) def cmp_files(self): f1 = open(self.srcfilename, "rb") f2 = open(self.destfilename, "rb") while True: data1 = f1.read(65536) data2 = f2.read(65536) if len(data1) == 0: break self.assert_(data1 == data2) f1.close() f2.close()