def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): # The openh264 configuration file system requires that one executes # in the tool directory. commandline = ( 'cd %s && %s %s ' '-org %s ' '-bf %s ' '-sw %d -sh %d ' '-dw 0 %d -dh 0 %d ' '-rc 0 -maxbrTotal %d -tarb %d ' '-ltarb 0 %d ' '-lmaxb 0 %d ' '%s ' % ( encoder.Tool('.'), encoder.Tool('h264enc'), encoder.Tool('openh264.cfg'), # Configuration file os.path.join(os.getenv('WORKDIR'), videofile.filename), encodedfile, videofile.width, videofile.height, videofile.width, videofile.height, bitrate, bitrate, bitrate, bitrate, parameters.ToString())) return commandline
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): # The openh264 configuration file system requires that one executes # in the tool directory. commandline = ( 'cd %s && %s %s ' '-org %s ' '-bf %s ' '-sw %d -sh %d ' '-dw 0 %d -dh 0 %d ' '-maxbrTotal 0 -tarb %d ' '-ltarb 0 %d ' '-lmaxb 0 0 ' '-numtl 1 ' '-frin %d -frout 0 %d ' #this is to set the frame rate '-fs 0 ' #disable FrameSkip with this option '-aq 0 ' #disable AdaptiveQuantizaion with this option '%s ' % ( encoder.Tool('.'), encoder.Tool('h264enc'), encoder.Tool('openh264.cfg'), # Configuration file os.path.join(os.getenv('WORKDIR'), videofile.filename), encodedfile, videofile.width, videofile.height, videofile.width, videofile.height, bitrate, bitrate, videofile.framerate, videofile.framerate, parameters.ToString())) return commandline
def VideoFilesEqual(old_encoded_file, new_encoded_file, extension): if extension == 'webm': # Matroska files contain UIDs that vary even if the video content # is the same. So we must use vpxdec --md5 instead. old_checksum = subprocess.check_output( (encoder.Tool('vpxdec'), '--md5', old_encoded_file)) new_checksum = subprocess.check_output( (encoder.Tool('vpxdec'), '--md5', new_encoded_file)) return old_checksum == new_checksum else: return filecmp.cmp(old_encoded_file, new_encoded_file)
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): commandline = ( '%s -loglevel warning -s %dx%d -i %s -codec:v %s %s -b:v %dk -y %s' % (encoder.Tool('ffmpeg'), videofile.width, videofile.height, videofile.filename, self.codecname, parameters.ToString(), bitrate, encodedfile)) return commandline
def EncoderVersion(self): version_output = subprocess.check_output( [encoder.Tool('ffmpeg'), '-version']) match = re.match('(ffmpeg .*) Copyright', version_output) if match: return match.group(0) raise encoder.Error('ffmpeg did not find its version string')
def _DecodeFile(self, videofile, encodedfile, workdir): tempyuvfile = os.path.join(workdir, videofile.basename + 'tempyuvfile.yuv') if os.path.isfile(tempyuvfile): print "Removing tempfile before decode:", tempyuvfile os.unlink(tempyuvfile) commandline = self.DecodeCommandLine(videofile, encodedfile, tempyuvfile) print commandline with open(os.path.devnull, 'r') as nullinput: subprocess_cpu_start = os.times()[2] returncode = subprocess.call(commandline, shell=True, stdin=nullinput) if returncode: raise Exception('Decode failed with returncode %d' % returncode) subprocess_cpu = os.times()[2] - subprocess_cpu_start print "Decode took %f seconds" % subprocess_cpu commandline = encoder.Tool("psnr") + " %s %s %d %d 9999" % ( videofile.filename, tempyuvfile, videofile.width, videofile.height) print commandline psnr = subprocess.check_output(commandline, shell=True, stdin=nullinput) commandline = ['md5sum', tempyuvfile] md5 = subprocess.check_output(commandline, shell=False) yuv_md5 = md5.split(' ')[0] os.unlink(tempyuvfile) return psnr, subprocess_cpu, yuv_md5
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): # The use-vbv-maxrate flag controls whether vbv-maxrate/vbv-bufsize # are used. They may be unneeded. # Still no opinion: '--no-scenecut --keyint infinite ' if parameters.HasValue('use-vbv-maxrate'): parameters = parameters.RemoveValue('use-vbv-maxrate') parameters = parameters.ChangeValue('vbv-maxrate', str(bitrate)) parameters = parameters.ChangeValue('vbv-bufsize', str(bitrate)) commandline = ('%(x264)s ' '--bitrate %(bitrate)d --fps %(framerate)d ' '--threads 1 ' '--input-res %(width)dx%(height)d ' '--quiet ' '%(parameters)s ' '-o %(outputfile)s %(inputfile)s') % { 'x264': encoder.Tool('x264'), 'bitrate': bitrate, 'framerate': videofile.framerate, 'width': videofile.width, 'height': videofile.height, 'outputfile': encodedfile, 'inputfile': videofile.filename, 'parameters': parameters.ToString() } return commandline
def DecodeCommandLine(self, videofile, encodedfile, yuvfile): # Because of a bug in the ffmpeg decoder, we're using JM decoder. # ffmpeg sometimes produces a decoded YUV file slightly shorter # than the expected size. commandline = '%s -b %s -o %s' % (encoder.Tool('TAppDecoderStatic'), encodedfile, yuvfile) return commandline
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): # TODO(hta): Merge the common parts of this with vp8.Execute. commandline = ( '%s %s -s %dx%d -i %s -codec:v %s -b:v %dk -y -s 352x288 %s' % (encoder.Tool('ffmpeg'), parameters.ToString(), videofile.width, videofile.height, videofile.filename, self.codecname, bitrate, encodedfile)) return commandline
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): commandline = (encoder.Tool('vpxenc') + ' ' + parameters.ToString() + ' --target-bitrate=' + str(bitrate) + ' --fps=' + str(videofile.framerate) + '/1' + ' -w ' + str(videofile.width) + ' -h ' + str(videofile.height) + ' ' + videofile.filename + ' --codec=vp8 ' + ' -o ' + encodedfile) return commandline
def EncoderVersion(self): try: subprocess.check_output([encoder.Tool('TAppEncoderStatic')]) except subprocess.CalledProcessError, err: helptext = str(err.output) for line in helptext.split('\n'): if re.match('HM software:', line): return line raise encoder.Error('HM version string not found')
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): commandline = ( '%s --SourceWidth=%d ---SourceHeight=%d ' '-c %s ' '--FrameRate=%d --InputFile=%s ' '--FramesToBeEncoded=%d ' '--IntraPeriod=-1 ' '%s --TargetBitrate=%d --BitstreamFile=%s' % ( encoder.Tool('TAppEncoderStatic'), videofile.width, videofile.height, encoder.Tool('hevc_ra_main.cfg'), # Configuration file videofile.framerate, videofile.filename, videofile.FrameCount(), parameters.ToString(), bitrate, encodedfile)) return commandline
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): # This is exactly the same as vp8.Execute, except that there is # no target-bitrate parameter. # TODO(hta): Redefine "parameters" so that the removal can be specified. commandline = (encoder.Tool('vpxenc-mpeg') + ' ' + parameters.ToString() + ' --fps=' + str(videofile.framerate) + '/1' + ' -w ' + str(videofile.width) + ' -h ' + str(videofile.height) + ' ' + videofile.filename + ' --codec=vp8 ' + ' -o ' + encodedfile) return commandline
def EncoderVersion(self): # The vpxenc command line tool outputs the version number of the # encoder as part of its error message on illegal arguments. try: subprocess.check_output([encoder.Tool('vpxenc')], stderr=subprocess.STDOUT) except Exception, err: version_output = str(err.output) for line in version_output.split('\n'): match = re.match(r'\s+vp9\s+- (.+)$', line) if match: return match.group(1) raise encoder.Error('Did not find vp9 version string')
def ResultData(self, encodedfile): commandline = '%s -show_frames -of json %s' % (encoder.Tool('ffprobe'), encodedfile) ffprobeinfo = subprocess.check_output(commandline, shell=True) probeinfo = ast.literal_eval(ffprobeinfo) pos = 0 frameinfo = [] for frame in probeinfo['frames']: if pos != 0: frameinfo.append({'size': 8*(int(frame['pkt_pos']) - pos)}) pos = int(frame['pkt_pos']) frameinfo.append({'size': 8*(os.path.getsize(encodedfile) - pos)}) return {'frame': frameinfo}
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): commandline = ('%(x265)s ' '--bitrate %(bitrate)d --fps %(framerate)d ' '--threads 1 ' '--input-res %(width)dx%(height)d ' '%(parameters)s ' '-o %(outputfile)s %(inputfile)s') % { 'x265': encoder.Tool('x265'), 'bitrate': bitrate, 'framerate': videofile.framerate, 'width': videofile.width, 'height': videofile.height, 'outputfile': encodedfile, 'inputfile': videofile.filename, 'parameters': parameters.ToString() } return commandline
def FfmpegFrameInfo(encodedfile): # Uses the ffprobe tool to give frame info. commandline = '%s -loglevel warning -show_frames -of json %s' % ( encoder.Tool('ffprobe'), encodedfile) ffprobeinfo = subprocess.check_output(commandline, shell=True) probeinfo = json.loads(ffprobeinfo) previous_position = 0 frameinfo = [] for frame in probeinfo['frames']: current_position = int(frame['pkt_pos']) if previous_position != 0: frameinfo.append( {'size': 8 * (current_position - previous_position)}) previous_position = current_position frameinfo.append( {'size': 8 * (os.path.getsize(encodedfile) - previous_position)}) return frameinfo
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): commandline = ( '%(tool)s ' '--width %(width)d --height %(height)d ' '--src_framerate %(framerate)d --tgt_framerate %(framerate)d ' '--input_chroma_format YUV_420P --bitrate %(bitrate)d ' '%(parameters)s ' '--input %(inputfile)s --output %(outputfile)s' % { 'tool': encoder.Tool('avcenc'), 'width': videofile.width, 'height': videofile.height, 'framerate': videofile.framerate, 'bitrate': bitrate * 1000, # Bitrate is in bits/sec, not kilobits. 'parameters': parameters.ToString(), 'inputfile': videofile.filename, 'outputfile': encodedfile }) return commandline
def Execute(self, parameters, bitrate, videofile, workdir): encodedfile = '%s/%s.%s' % (workdir, videofile.basename, self.extension) subprocess_cpu = self._EncodeFile(parameters, bitrate, videofile, encodedfile) result = {} result['encode_cputime'] = subprocess_cpu bitrate = videofile.MeasuredBitrate(os.path.getsize(encodedfile)) tempyuvfile = "%s/%stempyuvfile.yuv" % (workdir, videofile.basename) if os.path.isfile(tempyuvfile): print "Removing tempfile before decode:", tempyuvfile os.unlink(tempyuvfile) commandline = self.DecodeCommandLine(videofile, encodedfile, tempyuvfile) print commandline with open('/dev/null', 'r') as nullinput: subprocess_cpu_start = os.times()[2] returncode = subprocess.call(commandline, shell=True, stdin=nullinput) if returncode: raise Exception('Decode failed with returncode %d' % returncode) subprocess_cpu = os.times()[2] - subprocess_cpu_start print "Decode took %f seconds" % subprocess_cpu result['decode_cputime'] = subprocess_cpu commandline = encoder.Tool("psnr") + " %s %s %d %d 9999" % ( videofile.filename, tempyuvfile, videofile.width, videofile.height) print commandline psnr = subprocess.check_output(commandline, shell=True, stdin=nullinput) os.unlink(tempyuvfile) print "Bitrate", bitrate, "PSNR", psnr result['bitrate'] = int(bitrate) result['psnr'] = float(psnr) result['cliptime'] = videofile.ClipTime() result.update(self.ResultData(encodedfile)) return result
def EncodeCommandLine(self, parameters, bitrate, videofile, encodedfile): commandline = ('%(x264)s ' '--vbv-maxrate %(bitrate)d --vbv-bufsize %(bitrate)d ' '--bitrate %(bitrate)d --fps %(framerate)d ' '--threads 1 ' '--profile baseline --no-scenecut --keyint infinite ' '--input-res %(width)dx%(height)d ' '--tune psnr ' '%(parameters)s ' '-o %(outputfile)s %(inputfile)s') % { 'x264': encoder.Tool('x264'), 'bitrate': bitrate, 'framerate': videofile.framerate, 'width': videofile.width, 'height': videofile.height, 'outputfile': encodedfile, 'inputfile': videofile.filename, 'parameters': parameters.ToString() } return commandline
def DecodeCommandLine(self, videofile, encodedfile, yuvfile): commandline = "%s -loglevel warning -codec:v h264 -i %s %s" % ( encoder.Tool('ffmpeg'), encodedfile, yuvfile) return commandline
def EncoderVersion(self): version_output = subprocess.check_output( [encoder.Tool('x264'), '--version']) # The version is the first line of output. return version_output.split('\n')[0]
def DecodeCommandLine(self, videofile, encodedfile, yuvfile): # The special thing here is that it rescales back to the original size. commandline = "%s -i %s -s %sx%s %s" % (encoder.Tool('ffmpeg'), encodedfile, videofile.width, videofile.height, yuvfile) return commandline
def DecodeCommandLine(self, videofile, encodedfile, yuvfile): commandline = "%s --BitstreamFile=%s --ReconFile=%s" % ( encoder.Tool('TAppDecoderStatic'), encodedfile, yuvfile) return commandline
def DecodeCommandLine(self, videofile, encodedfile, yuvfile): commandline = '%s -i %s %s' % (encoder.Tool("ffmpeg"), encodedfile, yuvfile) return commandline
def EncoderVersion(self): version_output = subprocess.check_output( [encoder.Tool('x265'), '--version'], stderr=subprocess.STDOUT) # The version is the first line of output. version = version_output.split('\n')[0] return version.replace('[info]: ', '')
def DecodeCommandLine(self, videofile, encodedfile, yuvfile): commandline = '%s %s --i420 -o %s' % (encoder.Tool("vpxdec"), encodedfile, yuvfile) return commandline