#!/usr/bin/env python
# Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import json
import optparse
import os
import shutil
import subprocess
import sys
import tempfile

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

# Chrome browsertests will throw away stderr; avoid that output gets lost.
sys.stderr = sys.stdout


def _ParseArgs():
    """Registers the command-line options."""
    usage = 'usage: %prog [options]'
    parser = optparse.OptionParser(usage=usage)

    parser.add_option('--label',
                      type='string',
                      default='MY_TEST',
                      help=('Label of the test, used to identify different '
                            'tests. Default: %default'))
    parser.add_option('--ref_video',
                      type='string',
                      help='Reference video to compare with (YUV).')
    parser.add_option('--test_video',
                      type='string',
                      help=('Test video to be compared with the reference '
                            'video (YUV).'))
    parser.add_option('--frame_analyzer',
                      type='string',
                      help='Path to the frame analyzer executable.')
    parser.add_option('--aligned_output_file',
                      type='string',
                      help='Path for output aligned YUV or Y4M file.')
    parser.add_option('--vmaf', type='string', help='Path to VMAF executable.')
    parser.add_option('--vmaf_model',
                      type='string',
                      help='Path to VMAF model.')
    parser.add_option('--vmaf_phone_model',
                      action='store_true',
                      help='Whether to use phone model in VMAF.')
    parser.add_option(
        '--yuv_frame_width',
        type='int',
        default=640,
        help='Width of the YUV file\'s frames. Default: %default')
    parser.add_option(
        '--yuv_frame_height',
        type='int',
        default=480,
        help='Height of the YUV file\'s frames. Default: %default')
    parser.add_option('--chartjson_result_file',
                      type='str',
                      default=None,
                      help='Where to store perf results in chartjson format.')
    options, _ = parser.parse_args()

    if not options.ref_video:
        parser.error('You must provide a path to the reference video!')
    if not os.path.exists(options.ref_video):
        parser.error('Cannot find the reference video at %s' %
                     options.ref_video)

    if not options.test_video:
        parser.error('You must provide a path to the test video!')
    if not os.path.exists(options.test_video):
        parser.error('Cannot find the test video at %s' % options.test_video)

    if not options.frame_analyzer:
        parser.error(
            'You must provide the path to the frame analyzer executable!')
    if not os.path.exists(options.frame_analyzer):
        parser.error('Cannot find frame analyzer executable at %s!' %
                     options.frame_analyzer)

    if options.vmaf and not options.vmaf_model:
        parser.error('You must provide a path to a VMAF model to use VMAF.')

    return options


def _DevNull():
    """On Windows, sometimes the inherited stdin handle from the parent process
  fails. Workaround this by passing null to stdin to the subprocesses commands.
  This function can be used to create the null file handler.
  """
    return open(os.devnull, 'r')


def _RunFrameAnalyzer(options, yuv_directory=None):
    """Run frame analyzer to compare the videos and print output."""
    cmd = [
        options.frame_analyzer,
        '--label=%s' % options.label,
        '--reference_file=%s' % options.ref_video,
        '--test_file=%s' % options.test_video,
        '--width=%d' % options.yuv_frame_width,
        '--height=%d' % options.yuv_frame_height,
    ]
    if options.chartjson_result_file:
        cmd.append('--chartjson_result_file=%s' %
                   options.chartjson_result_file)
    if options.aligned_output_file:
        cmd.append('--aligned_output_file=%s' % options.aligned_output_file)
    if yuv_directory:
        cmd.append('--yuv_directory=%s' % yuv_directory)
    frame_analyzer = subprocess.Popen(cmd,
                                      stdin=_DevNull(),
                                      stdout=sys.stdout,
                                      stderr=sys.stderr)
    frame_analyzer.wait()
    if frame_analyzer.returncode != 0:
        print('Failed to run frame analyzer.')
    return frame_analyzer.returncode


def _RunVmaf(options, yuv_directory, logfile):
    """ Run VMAF to compare videos and print output.

  The yuv_directory is assumed to have been populated with a reference and test
  video in .yuv format, with names according to the label.
  """
    cmd = [
        options.vmaf,
        'yuv420p',
        str(options.yuv_frame_width),
        str(options.yuv_frame_height),
        os.path.join(yuv_directory, "ref.yuv"),
        os.path.join(yuv_directory, "test.yuv"),
        options.vmaf_model,
        '--log',
        logfile,
        '--log-fmt',
        'json',
    ]
    if options.vmaf_phone_model:
        cmd.append('--phone-model')

    vmaf = subprocess.Popen(cmd,
                            stdin=_DevNull(),
                            stdout=sys.stdout,
                            stderr=sys.stderr)
    vmaf.wait()
    if vmaf.returncode != 0:
        print('Failed to run VMAF.')
        return 1

    # Read per-frame scores from VMAF output and print.
    with open(logfile) as f:
        vmaf_data = json.load(f)
        vmaf_scores = []
        for frame in vmaf_data['frames']:
            vmaf_scores.append(frame['metrics']['vmaf'])
        print('RESULT VMAF: %s=' % options.label, vmaf_scores)

    return 0


def main():
    """The main function.

  A simple invocation is:
  ./webrtc/rtc_tools/compare_videos.py
  --ref_video=<path_and_name_of_reference_video>
  --test_video=<path_and_name_of_test_video>
  --frame_analyzer=<path_and_name_of_the_frame_analyzer_executable>

  Running vmaf requires the following arguments:
  --vmaf, --vmaf_model, --yuv_frame_width, --yuv_frame_height
  """
    options = _ParseArgs()

    if options.vmaf:
        try:
            # Directory to save temporary YUV files for VMAF in frame_analyzer.
            yuv_directory = tempfile.mkdtemp()
            _, vmaf_logfile = tempfile.mkstemp()

            # Run frame analyzer to compare the videos and print output.
            if _RunFrameAnalyzer(options, yuv_directory=yuv_directory) != 0:
                return 1

            # Run VMAF for further video comparison and print output.
            return _RunVmaf(options, yuv_directory, vmaf_logfile)
        finally:
            shutil.rmtree(yuv_directory)
            os.remove(vmaf_logfile)
    else:
        return _RunFrameAnalyzer(options)

    return 0


if __name__ == '__main__':
    sys.exit(main())
