| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | |
| 3 # | |
| 4 # Use of this source code is governed by a BSD-style license | |
| 5 # that can be found in the LICENSE file in the root of the source | |
| 6 # tree. An additional intellectual property rights grant can be found | |
| 7 # in the file PATENTS. All contributing project authors may | |
| 8 # be found in the AUTHORS file in the root of the source tree. | |
| 9 | |
| 10 import os | |
| 11 import gviz_api | |
| 12 import webrtc.data_helper | |
| 13 | |
| 14 def main(): | |
| 15 """ | |
| 16 This Python script displays a web page with test created with the | |
| 17 video_quality_measurement program, which is a tool in WebRTC. | |
| 18 | |
| 19 The script requires on two external files and one Python library: | |
| 20 - A HTML template file with layout and references to the json variables | |
| 21 defined in this script | |
| 22 - A data file in Python format, containing the following: | |
| 23 - test_configuration - a dictionary of test configuration names and values. | |
| 24 - frame_data_types - a dictionary that maps the different metrics to their | |
| 25 data types. | |
| 26 - frame_data - a list of dictionaries where each dictionary maps a metric to | |
| 27 it's value. | |
| 28 - The gviz_api.py of the Google Visualization Python API, available at | |
| 29 http://code.google.com/p/google-visualization-python/ | |
| 30 | |
| 31 The HTML file is shipped with the script, while the data file must be | |
| 32 generated by running video_quality_measurement with the --python flag | |
| 33 specified. | |
| 34 """ | |
| 35 print 'Content-type: text/html\n' # the newline is required! | |
| 36 | |
| 37 page_template_filename = '../templates/chart_page_template.html' | |
| 38 # The data files must be located in the project tree for app engine being | |
| 39 # able to access them. | |
| 40 data_filenames = ['../data/vp8_sw.py', '../data/vp8_hw.py'] | |
| 41 # Will contain info/error messages to be displayed on the resulting page. | |
| 42 messages = [] | |
| 43 # Load the page HTML template. | |
| 44 try: | |
| 45 f = open(page_template_filename) | |
| 46 page_template = f.read() | |
| 47 f.close() | |
| 48 except IOError as e: | |
| 49 ShowErrorPage('Cannot open page template file: %s<br>Details: %s' % | |
| 50 (page_template_filename, e)) | |
| 51 return | |
| 52 | |
| 53 # Read data from external Python script files. First check that they exist. | |
| 54 for filename in data_filenames: | |
| 55 if not os.path.exists(filename): | |
| 56 messages.append('Cannot open data file: %s' % filename) | |
| 57 data_filenames.remove(filename) | |
| 58 | |
| 59 # Read data from all existing input files. | |
| 60 data_list = [] | |
| 61 test_configurations = [] | |
| 62 names = [] | |
| 63 | |
| 64 for filename in data_filenames: | |
| 65 read_vars = {} # empty dictionary to load the data into. | |
| 66 execfile(filename, read_vars, read_vars) | |
| 67 | |
| 68 test_configuration = read_vars['test_configuration'] | |
| 69 table_description = read_vars['frame_data_types'] | |
| 70 table_data = read_vars['frame_data'] | |
| 71 | |
| 72 # Verify the data in the file loaded properly. | |
| 73 if not table_description or not table_data: | |
| 74 messages.append('Invalid input file: %s. Missing description list or ' | |
| 75 'data dictionary variables.' % filename) | |
| 76 continue | |
| 77 | |
| 78 # Frame numbers appear as number type in the data, but Chart API requires | |
| 79 # values of the X-axis to be of string type. | |
| 80 # Change the frame_number column data type: | |
| 81 table_description['frame_number'] = ('string', 'Frame number') | |
| 82 # Convert all the values to string types: | |
| 83 for row in table_data: | |
| 84 row['frame_number'] = str(row['frame_number']) | |
| 85 | |
| 86 # Store the unique data from this file in the high level lists. | |
| 87 test_configurations.append(test_configuration) | |
| 88 data_list.append(table_data) | |
| 89 # Name of the test run must be present. | |
| 90 test_name = FindConfiguration(test_configuration, 'name') | |
| 91 if not test_name: | |
| 92 messages.append('Invalid input file: %s. Missing configuration key ' | |
| 93 '"name"', filename) | |
| 94 continue | |
| 95 names.append(test_name) | |
| 96 | |
| 97 # Create data helper and build data tables for each graph. | |
| 98 helper = webrtc.data_helper.DataHelper(data_list, table_description, | |
| 99 names, messages) | |
| 100 | |
| 101 # Loading it into gviz_api.DataTable objects and create JSON strings. | |
| 102 description, data = helper.CreateConfigurationTable(test_configurations) | |
| 103 configurations = gviz_api.DataTable(description, data) | |
| 104 json_configurations = configurations.ToJSon() # pylint: disable=W0612 | |
| 105 | |
| 106 description, data = helper.CreateData('ssim') | |
| 107 ssim = gviz_api.DataTable(description, data) | |
| 108 # pylint: disable=W0612 | |
| 109 json_ssim_data = ssim.ToJSon(helper.GetOrdering(description)) | |
| 110 | |
| 111 description, data = helper.CreateData('psnr') | |
| 112 psnr = gviz_api.DataTable(description, data) | |
| 113 # pylint: disable=W0612 | |
| 114 json_psnr_data = psnr.ToJSon(helper.GetOrdering(description)) | |
| 115 | |
| 116 description, data = helper.CreateData('packets_dropped') | |
| 117 packet_loss = gviz_api.DataTable(description, data) | |
| 118 # pylint: disable=W0612 | |
| 119 json_packet_loss_data = packet_loss.ToJSon(helper.GetOrdering(description)) | |
| 120 | |
| 121 description, data = helper.CreateData('bit_rate') | |
| 122 # Add a column of data points for the desired bit rate to be plotted. | |
| 123 # (uses test configuration from the last data set, assuming it is the same | |
| 124 # for all of them) | |
| 125 desired_bit_rate = FindConfiguration(test_configuration, 'bit_rate_in_kbps') | |
| 126 if not desired_bit_rate: | |
| 127 ShowErrorPage('Cannot configuration field named "bit_rate_in_kbps"') | |
| 128 return | |
| 129 desired_bit_rate = int(desired_bit_rate) | |
| 130 # Add new column data type description. | |
| 131 description['desired_bit_rate'] = ('number', 'Desired bit rate (kbps)') | |
| 132 for row in data: | |
| 133 row['desired_bit_rate'] = desired_bit_rate | |
| 134 bit_rate = gviz_api.DataTable(description, data) | |
| 135 # pylint: disable=W0612 | |
| 136 json_bit_rate_data = bit_rate.ToJSon(helper.GetOrdering(description)) | |
| 137 | |
| 138 # Format the messages list with newlines. | |
| 139 messages = '\n'.join(messages) | |
| 140 | |
| 141 # Put the variables as JSon strings into the template. | |
| 142 print page_template % vars() | |
| 143 | |
| 144 def FindConfiguration(configuration, name): | |
| 145 """ Finds a configuration value using it's name. | |
| 146 Returns the first configuration with a matching name. Returns None if no | |
| 147 matching configuration is found. """ | |
| 148 return_value = None | |
| 149 for row in configuration: | |
| 150 if row['name'] == name: | |
| 151 return_value = row['value'] | |
| 152 break | |
| 153 return return_value | |
| 154 | |
| 155 def ShowErrorPage(error_message): | |
| 156 print '<html><body>%s</body></html>' % error_message | |
| 157 | |
| 158 if __name__ == '__main__': | |
| 159 main() | |
| OLD | NEW |