#!/usr/bin/env python # Copyright (c) 2011 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. import os import gviz_api import webrtc.data_helper def main(): """ This Python script displays a web page with test created with the video_quality_measurement program, which is a tool in WebRTC. The script requires on two external files and one Python library: - A HTML template file with layout and references to the json variables defined in this script - A data file in Python format, containing the following: - test_configuration - a dictionary of test configuration names and values. - frame_data_types - a dictionary that maps the different metrics to their data types. - frame_data - a list of dictionaries where each dictionary maps a metric to it's value. - The gviz_api.py of the Google Visualization Python API, available at http://code.google.com/p/google-visualization-python/ The HTML file is shipped with the script, while the data file must be generated by running video_quality_measurement with the --python flag specified. """ print 'Content-type: text/html\n' # the newline is required! page_template_filename = '../templates/chart_page_template.html' # The data files must be located in the project tree for app engine being # able to access them. data_filenames = ['../data/vp8_sw.py', '../data/vp8_hw.py'] # Will contain info/error messages to be displayed on the resulting page. messages = [] # Load the page HTML template. try: f = open(page_template_filename) page_template = f.read() f.close() except IOError as e: ShowErrorPage('Cannot open page template file: %s
Details: %s' % (page_template_filename, e)) return # Read data from external Python script files. First check that they exist. for filename in data_filenames: if not os.path.exists(filename): messages.append('Cannot open data file: %s' % filename) data_filenames.remove(filename) # Read data from all existing input files. data_list = [] test_configurations = [] names = [] for filename in data_filenames: read_vars = {} # empty dictionary to load the data into. execfile(filename, read_vars, read_vars) test_configuration = read_vars['test_configuration'] table_description = read_vars['frame_data_types'] table_data = read_vars['frame_data'] # Verify the data in the file loaded properly. if not table_description or not table_data: messages.append('Invalid input file: %s. Missing description list or ' 'data dictionary variables.' % filename) continue # Frame numbers appear as number type in the data, but Chart API requires # values of the X-axis to be of string type. # Change the frame_number column data type: table_description['frame_number'] = ('string', 'Frame number') # Convert all the values to string types: for row in table_data: row['frame_number'] = str(row['frame_number']) # Store the unique data from this file in the high level lists. test_configurations.append(test_configuration) data_list.append(table_data) # Name of the test run must be present. test_name = FindConfiguration(test_configuration, 'name') if not test_name: messages.append('Invalid input file: %s. Missing configuration key ' '"name"', filename) continue names.append(test_name) # Create data helper and build data tables for each graph. helper = webrtc.data_helper.DataHelper(data_list, table_description, names, messages) # Loading it into gviz_api.DataTable objects and create JSON strings. description, data = helper.CreateConfigurationTable(test_configurations) configurations = gviz_api.DataTable(description, data) json_configurations = configurations.ToJSon() # pylint: disable=W0612 description, data = helper.CreateData('ssim') ssim = gviz_api.DataTable(description, data) # pylint: disable=W0612 json_ssim_data = ssim.ToJSon(helper.GetOrdering(description)) description, data = helper.CreateData('psnr') psnr = gviz_api.DataTable(description, data) # pylint: disable=W0612 json_psnr_data = psnr.ToJSon(helper.GetOrdering(description)) description, data = helper.CreateData('packets_dropped') packet_loss = gviz_api.DataTable(description, data) # pylint: disable=W0612 json_packet_loss_data = packet_loss.ToJSon(helper.GetOrdering(description)) description, data = helper.CreateData('bit_rate') # Add a column of data points for the desired bit rate to be plotted. # (uses test configuration from the last data set, assuming it is the same # for all of them) desired_bit_rate = FindConfiguration(test_configuration, 'bit_rate_in_kbps') if not desired_bit_rate: ShowErrorPage('Cannot configuration field named "bit_rate_in_kbps"') return desired_bit_rate = int(desired_bit_rate) # Add new column data type description. description['desired_bit_rate'] = ('number', 'Desired bit rate (kbps)') for row in data: row['desired_bit_rate'] = desired_bit_rate bit_rate = gviz_api.DataTable(description, data) # pylint: disable=W0612 json_bit_rate_data = bit_rate.ToJSon(helper.GetOrdering(description)) # Format the messages list with newlines. messages = '\n'.join(messages) # Put the variables as JSon strings into the template. print page_template % vars() def FindConfiguration(configuration, name): """ Finds a configuration value using it's name. Returns the first configuration with a matching name. Returns None if no matching configuration is found. """ return_value = None for row in configuration: if row['name'] == name: return_value = row['value'] break return return_value def ShowErrorPage(error_message): print '%s' % error_message if __name__ == '__main__': main()