def _play_thread_run(self): process_frame = self.process_frame ff_opts = {'sync': 'video', 'an': True, 'sn': True, 'paused': True} ifmt, icodec = self.file_fmt, self.icodec use_dshow = self.use_dshow if ifmt: ff_opts['f'] = ifmt if use_dshow: ff_opts['f'] = 'dshow' if icodec: ff_opts['vcodec'] = icodec ipix_fmt, iw, ih, _ = self.metadata_play ff_opts['x'] = iw ff_opts['y'] = ih lib_opts = {} if use_dshow: rate = self.dshow_rate if self.dshow_opt: fmt, size, (rmin, rmax) = self.parse_dshow_opt(self.dshow_opt) lib_opts['pixel_format'] = fmt lib_opts['video_size'] = '{}x{}'.format(*size) if rate: rate = min(max(rate, rmin), rmax) lib_opts['framerate'] = '{}'.format(rate) elif rate: lib_opts['framerate'] = '{}'.format(rate) fname = self.play_filename if use_dshow: fname = 'video={}'.format(self.dshow_true_filename) ffplayer = MediaPlayer(fname, callback=self.player_callback, ff_opts=ff_opts, lib_opts=lib_opts) # wait for media to init pixel fmt src_fmt = '' s = clock() while self.play_state == 'starting' and clock() - s < 5.: src_fmt = ffplayer.get_metadata().get('src_pix_fmt') if src_fmt: break time.sleep(0.01) if not src_fmt: raise ValueError("Player failed, couldn't get pixel type") if ipix_fmt: src_fmt = ipix_fmt fmt = { 'gray': 'gray', 'rgb24': 'rgb24', 'bgr24': 'rgb24', 'rgba': 'rgba', 'bgra': 'rgba' }.get(src_fmt, 'yuv420p') ffplayer.set_output_pix_fmt(fmt) ffplayer.toggle_pause() Logger.info('FFmpeg Player: input, output formats are: {}, {}'.format( src_fmt, fmt)) # wait for first frame img = None s = clock() ivl_start = None while self.play_state == 'starting' and clock() - s < 5.: img, val = ffplayer.get_frame() if val == 'eof': raise ValueError("Player failed, reached eof") if img: ivl_start = clock() break time.sleep(0.01) rate = ffplayer.get_metadata().get('frame_rate') if rate == (0, 0) or not rate or not rate[1]: raise ValueError("Player failed, couldn't read frame rate") if not img: raise ValueError("Player failed, couldn't read frame") # ready to start rate = rate[0] / float(rate[1]) w, h = img[0].get_size() fmt = img[0].get_pixel_format() use_rt = self.use_real_time Clock.schedule_once( partial(eat_first, self.update_metadata, rate=rate, w=w, h=h, fmt=fmt), 0) Clock.schedule_once(self.complete_start) # started process_frame(img[0], {'t': ivl_start if use_rt else img[1]}) min_sleep = 1 / (rate * 8.) self.setattr_in_kivy_thread('ts_play', ivl_start) self.setattr_in_kivy_thread('frames_played', 1) count = 1 while self.play_state != 'stopping': img, val = ffplayer.get_frame() ivl_end = clock() if ivl_end - ivl_start >= 1.: real_rate = count / (ivl_end - ivl_start) self.setattr_in_kivy_thread('real_rate', real_rate) count = 0 ivl_start = ivl_end if val == 'paused': raise ValueError("Player {} got {}".format(self, val)) if val == 'eof': break if not img: time.sleep(min(val, min_sleep) if val else min_sleep) continue elif val: ts = clock() leftover = val while leftover > min_sleep and \ self.play_state != 'stopping': time.sleep(min_sleep) leftover = max(val - (clock() - ts), 0) count += 1 self.increment_in_kivy_thread('frames_played') process_frame(img[0], {'t': ivl_end if use_rt else img[1]})