| #!/usr/bin/env python |
| ## Copyright (c) 2019, Alliance for Open Media. All rights reserved |
| ## |
| ## This source code is subject to the terms of the BSD 2 Clause License and |
| ## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| ## was not distributed with this source code in the LICENSE file, you can |
| ## obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| ## Media Patent License 1.0 was not distributed with this source code in the |
| ## PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| ## |
| __author__ = "maggie.sun@intel.com, ryan.lei@intel.com" |
| |
| import os |
| import re |
| import logging |
| from Config import BinPath, LoggerName, LogCmdOnly, FFMPEG |
| from Utils import GetShortContentName, ExecuteCmd |
| |
| subloggername = "CalcQtyMetrics_FFMPEGTool" |
| loggername = LoggerName + '.' + '%s' % subloggername |
| logger = logging.getLogger(loggername) |
| |
| |
| FFMPEGMetricsFullList = ['PSNR_Y', 'PSNR_U', 'PSNR_V'] |
| |
| def ParseFfmpegLogFile(psnr_log): |
| floats = len(FFMPEGMetricsFullList) * [0.0] |
| flog = open(psnr_log, 'r') |
| cnt = 0 |
| for line in flog: |
| cnt += 1 |
| item = re.findall(r"psnr_y:(\d+\.?\d*)", line) |
| floats[0] += 0 if len(item) == 0 else float(item[0]) |
| item = re.findall(r"psnr_u:(\d+\.?\d*)", line) |
| floats[1] += 0 if len(item) == 0 else float(item[0]) |
| item = re.findall(r"psnr_v:(\d+\.?\d*)", line) |
| floats[2] += 0 if len(item) == 0 else float(item[0]) |
| |
| floats = [float(i) / cnt for i in floats] |
| |
| print_str = "FFMPEG quality metrics: " |
| for metrics, idx in zip(FFMPEGMetricsFullList, range(len(FFMPEGMetricsFullList))): |
| print_str += "%s = %2.5f, " % (metrics, floats[idx]) |
| logger.info(print_str) |
| |
| return floats[0:len(FFMPEGMetricsFullList)] |
| |
| |
| def GetFfmpegLogFile(recfile, path): |
| filename = GetShortContentName(recfile, False) + '_psnr.log' |
| file = os.path.join(path, filename) |
| return file |
| |
| ################################################################################ |
| ##################### Exposed Functions ######################################## |
| def FFMPEG_CalQualityMetrics(origfile, recfile, num, w, h, logfilePath): |
| #calculate psnr using ffmpeg filter to get psnr_u and psnr_v |
| #here we have to pass the psnr_log file name to FFMPEG without the target |
| #log path first, then copy the result psnr log to the target log path after |
| #the ffmpeg call. it doesn't work if the full path is directly passed to FFMPEG |
| psnr_log = GetFfmpegLogFile(recfile, BinPath) |
| psnr_log = os.path.basename(psnr_log) |
| args = " -s %dx%d -pix_fmt yuv420p -i %s -s %dx%d -pix_fmt yuv420p -i %s" \ |
| " -frames:v %d -lavfi psnr=%s -f null -" % \ |
| (w, h, origfile, w, h, recfile, num, psnr_log) |
| cmd = FFMPEG + args |
| ExecuteCmd(cmd, LogCmdOnly) |
| #move the psnr log to the target log path |
| target = os.path.join(logfilePath, psnr_log) |
| cmd = "move %s %s" % (psnr_log, target) |
| ExecuteCmd(cmd, LogCmdOnly) |
| |
| def FFMPEG_GatherQualityMetrics(recfile, logfilePath): |
| psnr_log = GetFfmpegLogFile(recfile, logfilePath) |
| results = ParseFfmpegLogFile(psnr_log) |
| return results |