def tivo_compatible_video(vInfo, tsn, mime=''): message = (True, '') while True: codec = vInfo.get('vCodec', '') is4k = config.is4Ktivo(tsn) and codec == 'hevc' if mime == 'video/mp4': if not (is4k or codec == 'h264'): message = (False, 'vCodec %s not compatible' % codec) break if mime == 'video/bif': if codec != 'vc1': message = (False, 'vCodec %s not compatible' % codec) break if mime == 'video/x-tivo-mpeg-ts': if not (is4k or codec in ('h264', 'mpeg2video')): message = (False, 'vCodec %s not compatible' % codec) break if codec not in ('mpeg2video', 'mpeg1video'): message = (False, 'vCodec %s not compatible' % codec) break if vInfo['kbps'] != None: abit = max('0', vInfo['aKbps']) if (int(vInfo['kbps']) - int(abit) > config.strtod(config.getMaxVideoBR(tsn)) / 1000): message = (False, '%s kbps exceeds max video bitrate' % vInfo['kbps']) break else: message = (False, '%s kbps not supported' % vInfo['kbps']) break if config.isHDtivo(tsn): # HD Tivo detected, skipping remaining tests. break if not vInfo['vFps'] in ['29.97', '59.94']: message = (False, '%s vFps, should be 29.97' % vInfo['vFps']) break if ((config.get169Blacklist(tsn) and not config.get169Setting(tsn)) or (config.get169Letterbox(tsn) and config.get169Setting(tsn))): if vInfo['dar1'] and vInfo['dar1'] not in ('4:3', '8:9', '880:657'): message = (False, ('DAR %s not supported ' + 'by BLACKLIST_169 tivos') % vInfo['dar1']) break mode = (vInfo['vWidth'], vInfo['vHeight']) if mode not in [(720, 480), (704, 480), (544, 480), (528, 480), (480, 480), (352, 480), (352, 240)]: message = (False, '%s x %s not in supported modes' % mode) break return message
def tivo_compatable(inFile, tsn = ''): supportedModes = [[720, 480], [704, 480], [544, 480], [480, 480], [352, 480]] type, width, height, fps, millisecs, kbps, akbps, acodec, afreq, vpar = video_info(inFile) #print type, width, height, fps, millisecs, kbps, akbps, acodec if (inFile[-5:]).lower() == '.tivo': debug_write(__name__, fn_attr(), ['TRUE, ends with .tivo.', inFile]) return True if not type == 'mpeg2video': #print 'Not Tivo Codec' debug_write(__name__, fn_attr(), ['FALSE, type', type, 'not mpeg2video.', inFile]) return False if os.path.splitext(inFile)[-1].lower() in ('.ts', '.mpv'): debug_write(__name__, fn_attr(), ['FALSE, ext', os.path.splitext(inFile)[-1],\ 'not tivo compatible.', inFile]) return False if acodec == 'dca': debug_write(__name__, fn_attr(), ['FALSE, acodec', acodec, ', not supported.', inFile]) return False if acodec != None: if not akbps or int(akbps) > config.getMaxAudioBR(tsn): debug_write(__name__, fn_attr(), ['FALSE,', akbps, 'kbps exceeds max audio bitrate.', inFile]) return False if kbps != None: abit = max('0', akbps) if int(kbps)-int(abit) > config.strtod(config.getMaxVideoBR())/1000: debug_write(__name__, fn_attr(), ['FALSE,', kbps, 'kbps exceeds max video bitrate.', inFile]) return False else: debug_write(__name__, fn_attr(), ['FALSE,', kbps, 'kbps not supported.', inFile]) return False if config.isHDtivo(tsn): if vpar != 1.0: if config.getPixelAR(0): if vpar != None or config.getPixelAR(1) != 1.0: debug_write(__name__, fn_attr(), ['FALSE,', vpar, 'not correct PAR,', inFile]) return False debug_write(__name__, fn_attr(), ['TRUE, HD Tivo detected, skipping remaining tests', inFile]) return True if not fps == '29.97': #print 'Not Tivo fps' debug_write(__name__, fn_attr(), ['FALSE,', fps, 'fps, should be 29.97.', inFile]) return False for mode in supportedModes: if (mode[0], mode[1]) == (width, height): #print 'Is TiVo!' debug_write(__name__, fn_attr(), ['TRUE,', width, 'x', height, 'is valid.', inFile]) return True #print 'Not Tivo dimensions' debug_write(__name__, fn_attr(), ['FALSE,', width, 'x', height, 'not in supported modes.', inFile]) return False
def push_one_file(self, f): file_info = VideoDetails() file_info['valid'] = transcode.supported_format(f['path']) temp_share = config.get_server('temp_share', '') temp_share_path = '' if temp_share: for name, data in config.getShares(): if temp_share == name: temp_share_path = data.get('path') mime = 'video/mpeg' if config.isHDtivo(f['tsn']): for m in ['video/mp4', 'video/bif']: if transcode.tivo_compatible(f['path'], f['tsn'], m)[0]: mime = m break if (mime == 'video/mpeg' and transcode.mp4_remuxable(f['path'], f['tsn'])): new_path = transcode.mp4_remux(f['path'], f['name'], f['tsn'], temp_share_path) if new_path: mime = 'video/mp4' f['name'] = new_path if temp_share_path: ip = config.get_ip() port = config.getPort() container = quote(temp_share) + '/' f['url'] = 'http://%s:%s/%s' % (ip, port, container) if file_info['valid']: file_info.update(self.metadata_full(f['path'], f['tsn'], mime)) url = f['url'] + quote(f['name']) title = file_info['seriesTitle'] if not title: title = file_info['title'] source = file_info['seriesId'] if not source: source = title subtitle = file_info['episodeTitle'] try: m = mind.getMind(f['tsn']) m.pushVideo( tsn = f['tsn'], url = url, description = file_info['description'], duration = file_info['duration'] / 1000, size = file_info['size'], title = title, subtitle = subtitle, source = source, mime = mime, tvrating = file_info['tvRating']) except Exception, msg: logger.error(msg)
def select_videofps(inFile, tsn): type, width, height, fps, millisecs, kbps, akbps, acodec, afreq, vpar = video_info(inFile) vfps = '-r 29.97' #default if config.isHDtivo(tsn) and fps not in BAD_MPEG_FPS: vfps = ' ' if config.getVideoFPS(tsn) != None: vfps = '-r '+config.getVideoFPS(tsn) return vfps
def tivo_compatible_video(vInfo, tsn, mime=""): message = (True, "") while True: codec = vInfo.get("vCodec", "") is4k = config.is4Ktivo(tsn) and codec == "hevc" if mime == "video/mp4": if not (is4k or codec == "h264"): message = (False, "vCodec %s not compatible" % codec) break if mime == "video/bif": if codec != "vc1": message = (False, "vCodec %s not compatible" % codec) break if mime == "video/x-tivo-mpeg-ts": if not (is4k or codec in ("h264", "mpeg2video")): message = (False, "vCodec %s not compatible" % codec) break if codec not in ("mpeg2video", "mpeg1video"): message = (False, "vCodec %s not compatible" % codec) break if vInfo["kbps"] != None: abit = max("0", vInfo["aKbps"]) if int(vInfo["kbps"]) - int(abit) > config.strtod(config.getMaxVideoBR(tsn)) / 1000: message = (False, "%s kbps exceeds max video bitrate" % vInfo["kbps"]) break else: message = (False, "%s kbps not supported" % vInfo["kbps"]) break if config.isHDtivo(tsn): # HD Tivo detected, skipping remaining tests. break if not vInfo["vFps"] in ["29.97", "59.94"]: message = (False, "%s vFps, should be 29.97" % vInfo["vFps"]) break if (config.get169Blacklist(tsn) and not config.get169Setting(tsn)) or ( config.get169Letterbox(tsn) and config.get169Setting(tsn) ): if vInfo["dar1"] and vInfo["dar1"] not in ("4:3", "8:9", "880:657"): message = (False, ("DAR %s not supported " + "by BLACKLIST_169 tivos") % vInfo["dar1"]) break mode = (vInfo["vWidth"], vInfo["vHeight"]) if mode not in [(720, 480), (704, 480), (544, 480), (528, 480), (480, 480), (352, 480), (352, 240)]: message = (False, "%s x %s not in supported modes" % mode) break return message
def select_videofps(inFile, tsn): vInfo = video_info(inFile) fps = '-r 29.97' # default if config.isHDtivo(tsn) and vInfo['vFps'] in GOOD_MPEG_FPS: fps = ' ' video_fps = config.get_tsn('video_fps', tsn) if video_fps != None: fps = '-r ' + video_fps return fps
def select_videofps(inFile, tsn): vInfo = video_info(inFile) fps = "-r 29.97" # default if config.isHDtivo(tsn) and vInfo["vFps"] in GOOD_MPEG_FPS: fps = " " video_fps = config.get_tsn("video_fps", tsn) if video_fps != None: fps = "-r " + video_fps return fps
def select_videostr(inFile, tsn, mime=""): vInfo = video_info(inFile) if tivo_compatible_video(vInfo, tsn, mime)[0]: video_str = int(vInfo["kbps"]) if vInfo["aKbps"]: video_str -= int(vInfo["aKbps"]) video_str *= 1000 else: video_str = config.strtod(config.getVideoBR(tsn)) if config.isHDtivo(tsn) and vInfo["kbps"]: video_str = max(video_str, int(vInfo["kbps"]) * 1000) video_str = int(min(config.strtod(config.getMaxVideoBR(tsn)) * 0.95, video_str)) return video_str
def tivo_compatible_video(vInfo, tsn, mime=''): message = (True, '') while True: codec = vInfo.get('vCodec', '') is4k = config.is4Ktivo(tsn) and codec == 'hevc' if mime == 'video/x-tivo-mpeg-ts': if not (is4k or codec in ('h264', 'mpeg2video')): message = (False, 'vCodec %s not compatible' % codec) break if codec not in ('mpeg2video', 'mpeg1video'): message = (False, 'vCodec %s not compatible' % codec) break if vInfo['kbps'] != None: abit = max('0', vInfo['aKbps']) if (int(vInfo['kbps']) - int(abit) > config.strtod(config.getMaxVideoBR(tsn)) / 1000): message = (False, '%s kbps exceeds max video bitrate' % vInfo['kbps']) break else: message = (False, '%s kbps not supported' % vInfo['kbps']) break if config.isHDtivo(tsn): # HD Tivo detected, skipping remaining tests. break if not vInfo['vFps'] in ['29.97', '59.94']: message = (False, '%s vFps, should be 29.97' % vInfo['vFps']) break if ((config.get169Blacklist(tsn) and not config.get169Setting(tsn)) or (config.get169Letterbox(tsn) and config.get169Setting(tsn))): if vInfo['dar1'] and vInfo['dar1'] not in ('4:3', '8:9', '880:657'): message = ( False, ('DAR %s not supported ' + 'by BLACKLIST_169 tivos') % vInfo['dar1']) break mode = (vInfo['vWidth'], vInfo['vHeight']) if mode not in [(720, 480), (704, 480), (544, 480), (528, 480), (480, 480), (352, 480), (352, 240)]: message = (False, '%s x %s not in supported modes' % mode) break return message
def select_videostr(inFile, tsn, mime=''): vInfo = video_info(inFile) if tivo_compatible_video(vInfo, tsn, mime)[0]: video_str = int(vInfo['kbps']) if vInfo['aKbps']: video_str -= int(vInfo['aKbps']) video_str *= 1000 else: video_str = config.strtod(config.getVideoBR(tsn)) if config.isHDtivo(tsn) and vInfo['kbps']: video_str = max(video_str, int(vInfo['kbps']) * 1000) video_str = int( min(config.strtod(config.getMaxVideoBR(tsn)) * 0.95, video_str)) return video_str
def processDlRequest(self): while True: data = self.work_queue.get() for share_name, settings in config.getShares(): if settings['type'] == 'webvideo': break self.__logger.debug('Processing request: %s' % data) path = settings['path'] file_name = os.path.join(path, '%s-%s' % (data['bodyOfferId'].replace(':', '-'), data['url'].split('/')[-1])) status = self.downloadFile(data['url'], file_name) mime = 'video/mpeg' if status: tsn = data['bodyId'][4:] file_info = VideoDetails() if config.isHDtivo(tsn): for m in ['video/mp4', 'video/bif']: if tivo_compatible(file_name, tsn, m)[0]: mime = m break file_info.update(self.metadata_full(file_name, tsn, mime)) ip = config.get_ip() port = config.getPort() data['url'] = ('http://%s:%s' % (ip, port) + urllib.quote('/%s/%s' % (share_name, os.path.basename(file_name)))) data['duration'] = file_info['duration'] / 1000 data['size'] = file_info['size'] self.__logger.debug('Complete request: %s' % data) m = mind.getMind() m.completeDownloadRequest(data, status, mime) self.in_progress_lock.acquire() try: del self.in_progress[data['bodyOfferId']] finally: self.in_progress_lock.release()
def select_videostr(inFile, tsn): vInfo = video_info(inFile) if tivo_compatible_video(vInfo, tsn)[0]: video_str = int(vInfo["kbps"]) if vInfo["aKbps"]: video_str -= int(vInfo["aKbps"]) video_str *= 1000 else: video_str = config.strtod(config.getVideoBR(tsn)) if config.isHDtivo(tsn): if vInfo["kbps"] != None and config.getVideoPCT(tsn) > 0: video_percent = int(vInfo["kbps"]) * 10 * config.getVideoPCT(tsn) video_str = max(video_str, video_percent) video_str = int(min(config.strtod(config.getMaxVideoBR(tsn)) * 0.95, video_str)) return video_str
def push_one_file(self, f): file_info = VideoDetails() file_info["valid"] = transcode.supported_format(f["path"]) mime = "video/mpeg" if config.isHDtivo(f["tsn"]): for m in ["video/mp4", "video/bif"]: if transcode.tivo_compatible(f["path"], f["tsn"], m)[0]: mime = m break if mime == "video/mpeg" and transcode.mp4_remuxable(f["path"], f["tsn"]): new_path = transcode.mp4_remux(f["path"], f["name"], f["tsn"]) if new_path: mime = "video/mp4" f["name"] = new_path if file_info["valid"]: file_info.update(self.metadata_full(f["path"], f["tsn"], mime)) url = f["url"] + quote(f["name"]) title = file_info["seriesTitle"] if not title: title = file_info["title"] source = file_info["seriesId"] if not source: source = title subtitle = file_info["episodeTitle"] try: m = mind.getMind(f["tsn"]) m.pushVideo( tsn=f["tsn"], url=url, description=file_info["description"], duration=file_info["duration"] / 1000, size=file_info["size"], title=title, subtitle=subtitle, source=source, mime=mime, tvrating=file_info["tvRating"], ) except Exception, msg: logger.error(msg)
def push_one_file(self, f): file_info = VideoDetails() file_info['valid'] = transcode.supported_format(f['path']) mime = 'video/mpeg' if config.isHDtivo(f['tsn']): for m in ['video/mp4', 'video/bif']: if transcode.tivo_compatible(f['path'], f['tsn'], m)[0]: mime = m break if (mime == 'video/mpeg' and transcode.mp4_remuxable(f['path'], f['tsn'])): new_path = transcode.mp4_remux(f['path'], f['name'], f['tsn']) if new_path: mime = 'video/mp4' f['name'] = new_path if file_info['valid']: file_info.update(self.metadata_full(f['path'], f['tsn'], mime)) url = f['url'] + quote(f['name']) title = file_info['seriesTitle'] if not title: title = file_info['title'] source = file_info['seriesId'] if not source: source = title subtitle = file_info['episodeTitle'] try: m = mind.getMind(f['tsn']) m.pushVideo( tsn = f['tsn'], url = url, description = file_info['description'], duration = file_info['duration'] / 1000, size = file_info['size'], title = title, subtitle = subtitle, source = source, mime = mime, tvrating = file_info['tvRating']) except Exception, msg: logger.error(msg)
def select_videostr(inFile, tsn): vInfo = video_info(inFile) if tivo_compatible_video(vInfo, tsn)[0]: video_str = int(vInfo['kbps']) if vInfo['aKbps']: video_str -= int(vInfo['aKbps']) video_str *= 1000 else: video_str = config.strtod(config.getVideoBR(tsn)) if config.isHDtivo(tsn): if vInfo['kbps'] != None and config.getVideoPCT(tsn) > 0: video_percent = (int(vInfo['kbps']) * 10 * config.getVideoPCT(tsn)) video_str = max(video_str, video_percent) video_str = int( min(config.strtod(config.getMaxVideoBR(tsn)) * 0.95, video_str)) return video_str
def push_one_file(self, f): file_info = VideoDetails() file_info['valid'] = transcode.supported_format(f['path']) temp_share = config.get_server('temp_share', '') temp_share_path = '' remux_path = os.path.dirname(f['path']) if temp_share: for name, data in config.getShares(): if temp_share == name: temp_share_path = data.get('path') remux_path = temp_share_path mime = 'video/mpeg' if config.isHDtivo(f['tsn']): for m in ['video/mp4', 'video/bif']: if transcode.tivo_compatible(f['path'], f['tsn'], m)[0]: mime = m break if (mime == 'video/mpeg' and transcode.mp4_remuxable(f['path'], f['tsn'])): if config.get_freeSpace(remux_path, f['path']): new_path = transcode.mp4_remux(f['path'], f['name'], f['tsn'], temp_share_path) if new_path: mime = 'video/mp4' f['name'] = new_path if temp_share_path: ip = config.get_ip() port = config.getPort() container = quote(temp_share) + '/' f['url'] = 'http://%s:%s/%s' % (ip, port, container) else: logger.warning('Not enough disk space to perform remux, ' + 'transcoding instead.') if file_info['valid']: file_info.update(self.metadata_full(f['path'], f['tsn'], mime)) url = f['url'] + quote(f['name']) title = file_info['seriesTitle'] if not title: title = file_info['title'] source = file_info['seriesId'] if not source: source = title subtitle = file_info['episodeTitle'] try: m = mind.getMind(f['tsn']) m.pushVideo( tsn = f['tsn'], url = url, description = file_info['description'], duration = file_info['duration'] / 1000, size = file_info['size'], title = title, subtitle = subtitle, source = source, mime = mime, tvrating = file_info['tvRating']) except ValueError, msg: if 'usernamePasswordError' in msg: if f['name'].endswith('.pyTivo-temp'): fname = os.path.join(remux_path, os.path.basename(f['name'])) fname = unicode(fname, 'utf-8') os.remove(fname) logger.debug(fname + ' has been removed')
def select_aspect(inFile, tsn = ''): TIVO_WIDTH = config.getTivoWidth(tsn) TIVO_HEIGHT = config.getTivoHeight(tsn) vInfo = video_info(inFile) debug('tsn: %s' % tsn) aspect169 = config.get169Setting(tsn) debug('aspect169: %s' % aspect169) optres = config.getOptres(tsn) debug('optres: %s' % optres) if optres: optHeight = config.nearestTivoHeight(vInfo['vHeight']) optWidth = config.nearestTivoWidth(vInfo['vWidth']) if optHeight < TIVO_HEIGHT: TIVO_HEIGHT = optHeight if optWidth < TIVO_WIDTH: TIVO_WIDTH = optWidth if vInfo.get('par2'): par2 = vInfo['par2'] elif vInfo.get('par'): par2 = float(vInfo['par']) else: # Assume PAR = 1.0 par2 = 1.0 debug(('File=%s vCodec=%s vWidth=%s vHeight=%s vFps=%s millisecs=%s ' + 'TIVO_HEIGHT=%s TIVO_WIDTH=%s') % (inFile, vInfo['vCodec'], vInfo['vWidth'], vInfo['vHeight'], vInfo['vFps'], vInfo['millisecs'], TIVO_HEIGHT, TIVO_WIDTH)) if config.isHDtivo(tsn) and not optres: if vInfo['par']: npar = par2 # adjust for pixel aspect ratio, if set if npar < 1.0: return ['-s', '%dx%d' % (vInfo['vWidth'], math.ceil(vInfo['vHeight'] / npar))] elif npar > 1.0: # FFMPEG expects width to be a multiple of two return ['-s', '%dx%d' % (math.ceil(vInfo['vWidth']*npar/2.0)*2, vInfo['vHeight'])] if vInfo['vHeight'] <= TIVO_HEIGHT: # pass all resolutions to S3, except heights greater than # conf height return [] # else, resize video. d = gcd(vInfo['vHeight'], vInfo['vWidth']) rheight, rwidth = vInfo['vHeight'] / d, vInfo['vWidth'] / d debug('rheight=%s rwidth=%s' % (rheight, rwidth)) if (rwidth, rheight) in [(1, 1)] and vInfo['par1'] == '8:9': debug('File + PAR is within 4:3.') return ['-aspect', '4:3', '-s', '%sx%s' % (TIVO_WIDTH, TIVO_HEIGHT)] elif ((rwidth, rheight) in [(4, 3), (10, 11), (15, 11), (59, 54), (59, 72), (59, 36), (59, 54)] or vInfo['dar1'] == '4:3'): debug('File is within 4:3 list.') return ['-aspect', '4:3', '-s', '%sx%s' % (TIVO_WIDTH, TIVO_HEIGHT)] elif (((rwidth, rheight) in [(16, 9), (20, 11), (40, 33), (118, 81), (59, 27)] or vInfo['dar1'] == '16:9') and (aspect169 or config.get169Letterbox(tsn))): debug('File is within 16:9 list and 16:9 allowed.') if config.get169Blacklist(tsn) or (aspect169 and config.get169Letterbox(tsn)): aspect = '4:3' else: aspect = '16:9' return ['-aspect', aspect, '-s', '%sx%s' % (TIVO_WIDTH, TIVO_HEIGHT)] else: settings = ['-aspect'] multiplier16by9 = (16.0 * TIVO_HEIGHT) / (9.0 * TIVO_WIDTH) / par2 multiplier4by3 = (4.0 * TIVO_HEIGHT) / (3.0 * TIVO_WIDTH) / par2 ratio = vInfo['vWidth'] * 100 * par2 / vInfo['vHeight'] debug('par2=%.3f ratio=%.3f mult4by3=%.3f' % (par2, ratio, multiplier4by3)) # If video is wider than 4:3 add top and bottom padding if ratio > 133: # Might be 16:9 file, or just need padding on # top and bottom if aspect169 and ratio > 135: # If file would fall in 4:3 # assume it is supposed to be 4:3 if (config.get169Blacklist(tsn) or config.get169Letterbox(tsn)): settings.append('4:3') else: settings.append('16:9') if ratio > 177: # too short needs padding top and bottom settings += pad_TB(TIVO_WIDTH, TIVO_HEIGHT, multiplier16by9, vInfo) debug(('16:9 aspect allowed, file is wider ' + 'than 16:9 padding top and bottom\n%s') % ' '.join(settings)) else: # too skinny needs padding on left and right. settings += pad_LR(TIVO_WIDTH, TIVO_HEIGHT, multiplier16by9, vInfo) debug(('16:9 aspect allowed, file is narrower ' + 'than 16:9 padding left and right\n%s') % ' '.join(settings)) else: # this is a 4:3 file or 16:9 output not allowed if ratio > 135 and config.get169Letterbox(tsn): settings.append('16:9') multiplier = multiplier16by9 else: settings.append('4:3') multiplier = multiplier4by3 settings += pad_TB(TIVO_WIDTH, TIVO_HEIGHT, multiplier, vInfo) debug(('File is wider than 4:3 padding ' + 'top and bottom\n%s') % ' '.join(settings)) # If video is taller than 4:3 add left and right padding, this # is rare. All of these files will always be sent in an aspect # ratio of 4:3 since they are so narrow. else: settings.append('4:3') settings += pad_LR(TIVO_WIDTH, TIVO_HEIGHT, multiplier4by3, vInfo) debug('File is taller than 4:3 padding left and right\n%s' % ' '.join(settings)) return settings
def Push(self, handler, query): tsn = query['tsn'][0] for key in config.tivo_names: if config.tivo_names[key] == tsn: tsn = key break tivo_name = config.tivo_names.get(tsn, tsn) container = quote(query['Container'][0].split('/')[0]) ip = config.get_ip() port = config.getPort() baseurl = 'http://%s:%s' % (ip, port) if config.getIsExternal(tsn): exturl = config.get_server('externalurl') if exturl: baseurl = exturl else: ip = self.readip() baseurl = 'http://%s:%s' % (ip, port) path = self.get_local_base_path(handler, query) files = query.get('File', []) for f in files: file_path = path + os.path.normpath(f) file_info = VideoDetails() file_info['valid'] = transcode.supported_format(file_path) mime = 'video/mpeg' if config.isHDtivo(tsn): for m in ['video/mp4', 'video/bif']: if transcode.tivo_compatible(file_path, tsn, m)[0]: mime = m break if file_info['valid']: file_info.update(self.metadata_full(file_path, tsn, mime)) url = baseurl + '/%s%s' % (container, quote(f)) title = file_info['seriesTitle'] if not title: title = file_info['title'] source = file_info['seriesId'] if not source: source = title subtitle = file_info['episodeTitle'] try: m = mind.getMind(tsn) m.pushVideo( tsn = tsn, url = url, description = file_info['description'], duration = file_info['duration'] / 1000, size = file_info['size'], title = title, subtitle = subtitle, source = source, mime = mime, tvrating = file_info['tvRating']) except Exception, e: handler.send_response(500) handler.end_headers() handler.wfile.write('%s\n\n%s' % (e, traceback.format_exc() )) raise logger.info('[%s] Queued "%s" for Push to %s' % (time.strftime('%d/%b/%Y %H:%M:%S'), unicode(file_path, 'utf-8'), tivo_name))
def select_videofps(inFile, tsn): vInfo = video_info(inFile) fps = ['-r', '29.97'] # default if config.isHDtivo(tsn) and vInfo['vFps'] in GOOD_MPEG_FPS: fps = [] return fps
def select_aspect(inFile, tsn=""): TIVO_WIDTH = config.getTivoWidth(tsn) TIVO_HEIGHT = config.getTivoHeight(tsn) vInfo = video_info(inFile) debug("tsn: %s" % tsn) aspect169 = config.get169Setting(tsn) debug("aspect169: %s" % aspect169) optres = config.getOptres(tsn) debug("optres: %s" % optres) if optres: optHeight = config.nearestTivoHeight(vInfo["vHeight"]) optWidth = config.nearestTivoWidth(vInfo["vWidth"]) if optHeight < TIVO_HEIGHT: TIVO_HEIGHT = optHeight if optWidth < TIVO_WIDTH: TIVO_WIDTH = optWidth if vInfo.get("par2"): par2 = vInfo["par2"] elif vInfo.get("par"): par2 = float(vInfo["par"]) else: # Assume PAR = 1.0 par2 = 1.0 debug( ("File=%s vCodec=%s vWidth=%s vHeight=%s vFps=%s millisecs=%s " + "TIVO_HEIGHT=%s TIVO_WIDTH=%s") % ( inFile, vInfo["vCodec"], vInfo["vWidth"], vInfo["vHeight"], vInfo["vFps"], vInfo["millisecs"], TIVO_HEIGHT, TIVO_WIDTH, ) ) if config.isHDtivo(tsn) and not optres: if vInfo["par"]: npar = par2 # adjust for pixel aspect ratio, if set if npar < 1.0: return ["-s", "%dx%d" % (vInfo["vWidth"], math.ceil(vInfo["vHeight"] / npar))] elif npar > 1.0: # FFMPEG expects width to be a multiple of two return ["-s", "%dx%d" % (math.ceil(vInfo["vWidth"] * npar / 2.0) * 2, vInfo["vHeight"])] if vInfo["vHeight"] <= TIVO_HEIGHT: # pass all resolutions to S3, except heights greater than # conf height return [] # else, resize video. d = gcd(vInfo["vHeight"], vInfo["vWidth"]) rheight, rwidth = vInfo["vHeight"] / d, vInfo["vWidth"] / d debug("rheight=%s rwidth=%s" % (rheight, rwidth)) if (rwidth, rheight) in [(1, 1)] and vInfo["par1"] == "8:9": debug("File + PAR is within 4:3.") return ["-aspect", "4:3", "-s", "%sx%s" % (TIVO_WIDTH, TIVO_HEIGHT)] elif (rwidth, rheight) in [(4, 3), (10, 11), (15, 11), (59, 54), (59, 72), (59, 36), (59, 54)] or vInfo[ "dar1" ] == "4:3": debug("File is within 4:3 list.") return ["-aspect", "4:3", "-s", "%sx%s" % (TIVO_WIDTH, TIVO_HEIGHT)] elif ((rwidth, rheight) in [(16, 9), (20, 11), (40, 33), (118, 81), (59, 27)] or vInfo["dar1"] == "16:9") and ( aspect169 or config.get169Letterbox(tsn) ): debug("File is within 16:9 list and 16:9 allowed.") if config.get169Blacklist(tsn) or (aspect169 and config.get169Letterbox(tsn)): aspect = "4:3" else: aspect = "16:9" return ["-aspect", aspect, "-s", "%sx%s" % (TIVO_WIDTH, TIVO_HEIGHT)] else: settings = ["-aspect"] multiplier16by9 = (16.0 * TIVO_HEIGHT) / (9.0 * TIVO_WIDTH) / par2 multiplier4by3 = (4.0 * TIVO_HEIGHT) / (3.0 * TIVO_WIDTH) / par2 ratio = vInfo["vWidth"] * 100 * par2 / vInfo["vHeight"] debug("par2=%.3f ratio=%.3f mult4by3=%.3f" % (par2, ratio, multiplier4by3)) # If video is wider than 4:3 add top and bottom padding if ratio > 133: # Might be 16:9 file, or just need padding on # top and bottom if aspect169 and ratio > 135: # If file would fall in 4:3 # assume it is supposed to be 4:3 if config.get169Blacklist(tsn) or config.get169Letterbox(tsn): settings.append("4:3") else: settings.append("16:9") if ratio > 177: # too short needs padding top and bottom settings += pad_TB(TIVO_WIDTH, TIVO_HEIGHT, multiplier16by9, vInfo) debug( ("16:9 aspect allowed, file is wider " + "than 16:9 padding top and bottom\n%s") % " ".join(settings) ) else: # too skinny needs padding on left and right. settings += pad_LR(TIVO_WIDTH, TIVO_HEIGHT, multiplier16by9, vInfo) debug( ("16:9 aspect allowed, file is narrower " + "than 16:9 padding left and right\n%s") % " ".join(settings) ) else: # this is a 4:3 file or 16:9 output not allowed if ratio > 135 and config.get169Letterbox(tsn): settings.append("16:9") multiplier = multiplier16by9 else: settings.append("4:3") multiplier = multiplier4by3 settings += pad_TB(TIVO_WIDTH, TIVO_HEIGHT, multiplier, vInfo) debug(("File is wider than 4:3 padding " + "top and bottom\n%s") % " ".join(settings)) # If video is taller than 4:3 add left and right padding, this # is rare. All of these files will always be sent in an aspect # ratio of 4:3 since they are so narrow. else: settings.append("4:3") settings += pad_LR(TIVO_WIDTH, TIVO_HEIGHT, multiplier4by3, vInfo) debug("File is taller than 4:3 padding left and right\n%s" % " ".join(settings)) return settings
def select_aspect(inFile, tsn=''): TIVO_WIDTH = config.getTivoWidth(tsn) TIVO_HEIGHT = config.getTivoHeight(tsn) vInfo = video_info(inFile) debug('tsn: %s' % tsn) aspect169 = config.get169Setting(tsn) debug('aspect169: %s' % aspect169) optres = config.getOptres(tsn) debug('optres: %s' % optres) if optres: optHeight = config.nearestTivoHeight(vInfo['vHeight']) optWidth = config.nearestTivoWidth(vInfo['vWidth']) if optHeight < TIVO_HEIGHT: TIVO_HEIGHT = optHeight if optWidth < TIVO_WIDTH: TIVO_WIDTH = optWidth if vInfo.get('par2'): par2 = vInfo['par2'] elif vInfo.get('par'): par2 = float(vInfo['par']) else: # Assume PAR = 1.0 par2 = 1.0 debug(('File=%s vCodec=%s vWidth=%s vHeight=%s vFps=%s millisecs=%s ' + 'TIVO_HEIGHT=%s TIVO_WIDTH=%s') % (inFile, vInfo['vCodec'], vInfo['vWidth'], vInfo['vHeight'], vInfo['vFps'], vInfo['millisecs'], TIVO_HEIGHT, TIVO_WIDTH)) if config.isHDtivo(tsn) and not optres: if vInfo['par']: npar = par2 # adjust for pixel aspect ratio, if set if npar < 1.0: return [ '-s', '%dx%d' % (vInfo['vWidth'], math.ceil(vInfo['vHeight'] / npar)) ] elif npar > 1.0: # FFMPEG expects width to be a multiple of two return [ '-s', '%dx%d' % (math.ceil(vInfo['vWidth'] * npar / 2.0) * 2, vInfo['vHeight']) ] if vInfo['vHeight'] <= TIVO_HEIGHT: # pass all resolutions to S3, except heights greater than # conf height return [] # else, resize video. d = gcd(vInfo['vHeight'], vInfo['vWidth']) rheight, rwidth = vInfo['vHeight'] / d, vInfo['vWidth'] / d debug('rheight=%s rwidth=%s' % (rheight, rwidth)) if (rwidth, rheight) in [(1, 1)] and vInfo['par1'] == '8:9': debug('File + PAR is within 4:3.') return ['-aspect', '4:3', '-s', '%sx%s' % (TIVO_WIDTH, TIVO_HEIGHT)] elif ((rwidth, rheight) in [(4, 3), (10, 11), (15, 11), (59, 54), (59, 72), (59, 36), (59, 54)] or vInfo['dar1'] == '4:3'): debug('File is within 4:3 list.') return ['-aspect', '4:3', '-s', '%sx%s' % (TIVO_WIDTH, TIVO_HEIGHT)] elif (((rwidth, rheight) in [(16, 9), (20, 11), (40, 33), (118, 81), (59, 27)] or vInfo['dar1'] == '16:9') and (aspect169 or config.get169Letterbox(tsn))): debug('File is within 16:9 list and 16:9 allowed.') if config.get169Blacklist(tsn) or (aspect169 and config.get169Letterbox(tsn)): aspect = '4:3' else: aspect = '16:9' return ['-aspect', aspect, '-s', '%sx%s' % (TIVO_WIDTH, TIVO_HEIGHT)] else: settings = ['-aspect'] multiplier16by9 = (16.0 * TIVO_HEIGHT) / (9.0 * TIVO_WIDTH) / par2 multiplier4by3 = (4.0 * TIVO_HEIGHT) / (3.0 * TIVO_WIDTH) / par2 ratio = vInfo['vWidth'] * 100 * par2 / vInfo['vHeight'] debug('par2=%.3f ratio=%.3f mult4by3=%.3f' % (par2, ratio, multiplier4by3)) # If video is wider than 4:3 add top and bottom padding if ratio > 133: # Might be 16:9 file, or just need padding on # top and bottom if aspect169 and ratio > 135: # If file would fall in 4:3 # assume it is supposed to be 4:3 if (config.get169Blacklist(tsn) or config.get169Letterbox(tsn)): settings.append('4:3') else: settings.append('16:9') if ratio > 177: # too short needs padding top and bottom settings += pad_TB(TIVO_WIDTH, TIVO_HEIGHT, multiplier16by9, vInfo) debug(('16:9 aspect allowed, file is wider ' + 'than 16:9 padding top and bottom\n%s') % ' '.join(settings)) else: # too skinny needs padding on left and right. settings += pad_LR(TIVO_WIDTH, TIVO_HEIGHT, multiplier16by9, vInfo) debug(('16:9 aspect allowed, file is narrower ' + 'than 16:9 padding left and right\n%s') % ' '.join(settings)) else: # this is a 4:3 file or 16:9 output not allowed if ratio > 135 and config.get169Letterbox(tsn): settings.append('16:9') multiplier = multiplier16by9 else: settings.append('4:3') multiplier = multiplier4by3 settings += pad_TB(TIVO_WIDTH, TIVO_HEIGHT, multiplier, vInfo) debug( ('File is wider than 4:3 padding ' + 'top and bottom\n%s') % ' '.join(settings)) # If video is taller than 4:3 add left and right padding, this # is rare. All of these files will always be sent in an aspect # ratio of 4:3 since they are so narrow. else: settings.append('4:3') settings += pad_LR(TIVO_WIDTH, TIVO_HEIGHT, multiplier4by3, vInfo) debug('File is taller than 4:3 padding left and right\n%s' % ' '.join(settings)) return settings
def select_videofps(inFile, tsn): vInfo = video_info(inFile) fps = ["-r", "29.97"] # default if config.isHDtivo(tsn) and vInfo["vFps"] in GOOD_MPEG_FPS: fps = [] return fps
def select_aspect(inFile, tsn = ''): TIVO_WIDTH = config.getTivoWidth(tsn) TIVO_HEIGHT = config.getTivoHeight(tsn) type, width, height, fps, millisecs, kbps, akbps, acodec, afreq, vpar = video_info(inFile) debug_write(__name__, fn_attr(), ['tsn:', tsn]) aspect169 = config.get169Setting(tsn) debug_write(__name__, fn_attr(), ['aspect169:', aspect169]) optres = config.getOptres(tsn) debug_write(__name__, fn_attr(), ['optres:', optres]) if optres: optHeight = config.nearestTivoHeight(height) optWidth = config.nearestTivoWidth(width) if optHeight < TIVO_HEIGHT: TIVO_HEIGHT = optHeight if optWidth < TIVO_WIDTH: TIVO_WIDTH = optWidth d = gcd(height,width) ratio = (width*100)/height rheight, rwidth = height/d, width/d debug_write(__name__, fn_attr(), ['File=', inFile, ' Type=', type, ' width=', width, ' height=', height, ' fps=', fps, ' millisecs=', millisecs, ' ratio=', ratio, ' rheight=', rheight, ' rwidth=', rwidth, ' TIVO_HEIGHT=', TIVO_HEIGHT, 'TIVO_WIDTH=', TIVO_WIDTH]) multiplier16by9 = (16.0 * TIVO_HEIGHT) / (9.0 * TIVO_WIDTH) multiplier4by3 = (4.0 * TIVO_HEIGHT) / (3.0 * TIVO_WIDTH) if config.isHDtivo(tsn) and optres: if config.getPixelAR(0): if vpar == None: npar = config.getPixelAR(1) else: npar = vpar # adjust for pixel aspect ratio, if set, because TiVo expects square pixels if npar<1.0: return ['-s', str(width) + 'x' + str(int(math.ceil(height/npar)))] elif npar>1.0: # FFMPEG expects width to be a multiple of two return ['-s', str(int(math.ceil(width*npar/2.0)*2)) + 'x' + str(height)] if height <= TIVO_HEIGHT: # pass all resolutions to S3, except heights greater than conf height return [] # else, resize video. if (rwidth, rheight) in [(4, 3), (10, 11), (15, 11), (59, 54), (59, 72), (59, 36), (59, 54)]: debug_write(__name__, fn_attr(), ['File is within 4:3 list.']) return ['-aspect', '4:3', '-s', str(TIVO_WIDTH) + 'x' + str(TIVO_HEIGHT)] elif ((rwidth, rheight) in [(16, 9), (20, 11), (40, 33), (118, 81), (59, 27)]) and aspect169: debug_write(__name__, fn_attr(), ['File is within 16:9 list and 16:9 allowed.']) return ['-aspect', '16:9', '-s', str(TIVO_WIDTH) + 'x' + str(TIVO_HEIGHT)] else: settings = [] #If video is wider than 4:3 add top and bottom padding if (ratio > 133): #Might be 16:9 file, or just need padding on top and bottom if aspect169 and (ratio > 135): #If file would fall in 4:3 assume it is supposed to be 4:3 if (ratio > 177):#too short needs padding top and bottom endHeight = int(((TIVO_WIDTH*height)/width) * multiplier16by9) settings.append('-aspect') settings.append('16:9') if endHeight % 2: endHeight -= 1 if endHeight < TIVO_HEIGHT * 0.99: settings.append('-s') settings.append(str(TIVO_WIDTH) + 'x' + str(endHeight)) topPadding = ((TIVO_HEIGHT - endHeight)/2) if topPadding % 2: topPadding -= 1 settings.append('-padtop') settings.append(str(topPadding)) bottomPadding = (TIVO_HEIGHT - endHeight) - topPadding settings.append('-padbottom') settings.append(str(bottomPadding)) else: #if only very small amount of padding needed, then just stretch it settings.append('-s') settings.append(str(TIVO_WIDTH) + 'x' + str(TIVO_HEIGHT)) debug_write(__name__, fn_attr(), ['16:9 aspect allowed, file is wider than 16:9 padding top and bottom', ' '.join(settings)]) else: #too skinny needs padding on left and right. endWidth = int((TIVO_HEIGHT*width)/(height*multiplier16by9)) settings.append('-aspect') settings.append('16:9') if endWidth % 2: endWidth -= 1 if endWidth < (TIVO_WIDTH-10): settings.append('-s') settings.append(str(endWidth) + 'x' + str(TIVO_HEIGHT)) leftPadding = ((TIVO_WIDTH - endWidth)/2) if leftPadding % 2: leftPadding -= 1 settings.append('-padleft') settings.append(str(leftPadding)) rightPadding = (TIVO_WIDTH - endWidth) - leftPadding settings.append('-padright') settings.append(str(rightPadding)) else: #if only very small amount of padding needed, then just stretch it settings.append('-s') settings.append(str(TIVO_WIDTH) + 'x' + str(TIVO_HEIGHT)) debug_write(__name__, fn_attr(), ['16:9 aspect allowed, file is narrower than 16:9 padding left and right\n', ' '.join(settings)]) else: #this is a 4:3 file or 16:9 output not allowed settings.append('-aspect') settings.append('4:3') endHeight = int(((TIVO_WIDTH*height)/width) * multiplier4by3) if endHeight % 2: endHeight -= 1 if endHeight < TIVO_HEIGHT * 0.99: settings.append('-s') settings.append(str(TIVO_WIDTH) + 'x' + str(endHeight)) topPadding = ((TIVO_HEIGHT - endHeight)/2) if topPadding % 2: topPadding -= 1 settings.append('-padtop') settings.append(str(topPadding)) bottomPadding = (TIVO_HEIGHT - endHeight) - topPadding settings.append('-padbottom') settings.append(str(bottomPadding)) else: #if only very small amount of padding needed, then just stretch it settings.append('-s') settings.append(str(TIVO_WIDTH) + 'x' + str(TIVO_HEIGHT)) debug_write(__name__, fn_attr(), ['File is wider than 4:3 padding top and bottom\n', ' '.join(settings)]) return settings #If video is taller than 4:3 add left and right padding, this is rare. All of these files will always be sent in #an aspect ratio of 4:3 since they are so narrow. else: endWidth = int((TIVO_HEIGHT*width)/(height*multiplier4by3)) settings.append('-aspect') settings.append('4:3') if endWidth % 2: endWidth -= 1 if endWidth < (TIVO_WIDTH * 0.99): settings.append('-s') settings.append(str(endWidth) + 'x' + str(TIVO_HEIGHT)) leftPadding = ((TIVO_WIDTH - endWidth)/2) if leftPadding % 2: leftPadding -= 1 settings.append('-padleft') settings.append(str(leftPadding)) rightPadding = (TIVO_WIDTH - endWidth) - leftPadding settings.append('-padright') settings.append(str(rightPadding)) else: #if only very small amount of padding needed, then just stretch it settings.append('-s') settings.append(str(TIVO_WIDTH) + 'x' + str(TIVO_HEIGHT)) debug_write(__name__, fn_attr(), ['File is taller than 4:3 padding left and right\n', ' '.join(settings)]) return settings