1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <deque> 8 #include <ostream> 9 10 #include "base/at_exit.h" 11 #include "base/bind.h" 12 #include "base/command_line.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/strings/string_number_conversions.h" 15 #include "base/time/time.h" 16 #include "media/base/video_frame.h" 17 #include "media/tools/shader_bench/cpu_color_painter.h" 18 #include "media/tools/shader_bench/gpu_color_painter.h" 19 #include "media/tools/shader_bench/painter.h" 20 #include "media/tools/shader_bench/window.h" 21 #include "ui/gfx/native_widget_types.h" 22 #include "ui/gl/gl_bindings.h" 23 #include "ui/gl/gl_context.h" 24 #include "ui/gl/gl_implementation.h" 25 #include "ui/gl/gl_surface.h" 26 27 #if defined(TOOLKIT_GTK) 28 #include <gtk/gtk.h> 29 #endif 30 31 static const int kNumFramesToPaint = 500; 32 static base::TimeTicks g_start_; 33 static base::TimeTicks g_end_; 34 35 long CalculateYUVFrameSize(FILE* file_handle, int num_frames) { 36 fseek(file_handle, 0, SEEK_END); 37 long file_size = (long) ftell(file_handle); 38 rewind(file_handle); 39 return file_size / num_frames; 40 } 41 42 void GetFrames(std::string file_name, 43 int width, int height, int num_frames, 44 std::deque<scoped_refptr<media::VideoFrame> >& out_frames) { 45 FILE* file_handle = fopen(file_name.c_str(), "rb"); 46 if (!file_handle) { 47 printf("Could not open %s\n", file_name.c_str()); 48 exit(1); 49 } 50 51 long frame_size = CalculateYUVFrameSize(file_handle, num_frames); 52 53 gfx::Size size(width, height); 54 for (int i = 0; i < num_frames; i++) { 55 scoped_refptr<media::VideoFrame> video_frame = 56 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size, 57 gfx::Rect(size), size, 58 base::TimeDelta()); 59 long bytes_read = 60 fread(video_frame->data(0), 1, frame_size, file_handle); 61 62 if (bytes_read != frame_size) { 63 printf("Could not read %s\n", file_name.c_str()); 64 fclose(file_handle); 65 exit(1); 66 } 67 out_frames.push_back(video_frame); 68 } 69 70 fclose(file_handle); 71 } 72 73 void TestFinished() { 74 g_end_ = base::TimeTicks::HighResNow(); 75 double time_in_seconds = 76 static_cast<double>((g_end_ - g_start_).InMilliseconds()) / 1000; 77 double fps = kNumFramesToPaint / time_in_seconds; 78 printf("Printed %f frames per second.\n", fps); 79 } 80 81 void RunTest(media::Window* window, Painter* painter) { 82 g_start_ = base::TimeTicks::HighResNow(); 83 window->Start(kNumFramesToPaint, base::Bind(&TestFinished), painter); 84 } 85 86 int main(int argc, char** argv) { 87 // Read arguments. 88 if (argc == 1) { 89 printf("Usage: %s --file=FILE --wxh=DIMENSIONS --frames=NUM_FRAMES\n" 90 "FILE is a raw .yuv file with 1+ frames in it\n" 91 "DIMENSIONS is the width and height of the frame in pixels\n" 92 "NUM_FRAMES is the number of frames in FILE\n", argv[0]); 93 return 1; 94 } 95 96 // Read command line. 97 #if defined(TOOLKIT_GTK) 98 gtk_init(&argc, &argv); 99 #endif 100 CommandLine::Init(argc, argv); 101 102 // Determine file name. 103 std::string file_name = 104 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("file"); 105 106 // Determine number of frames. 107 int num_frames = 0; 108 std::string str_num_frames = 109 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("frames"); 110 base::StringToInt(str_num_frames, &num_frames); 111 112 // Determine video dimensions. 113 int width = 0; 114 int height = 0; 115 std::string dimensions = 116 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("wxh"); 117 int x_index = dimensions.find('x'); 118 std::string str_width = dimensions.substr(0, x_index); 119 std::string str_height = 120 dimensions.substr(x_index + 1, dimensions.length() - x_index - 1); 121 base::StringToInt(str_width, &width); 122 base::StringToInt(str_height, &height); 123 124 // Process files. 125 std::deque<scoped_refptr<media::VideoFrame> > frames; 126 GetFrames(file_name, width, height, num_frames, frames); 127 128 // Initialize window and graphics context. 129 base::AtExitManager at_exit_manager; 130 gfx::GLSurface::InitializeOneOff(); 131 scoped_ptr<media::Window> window(new media::Window(width, height)); 132 gfx::GLSurface* surface = 133 gfx::GLSurface::CreateViewGLSurface(window->PluginWindow()).get(); 134 gfx::GLContext* context = gfx::GLContext::CreateGLContext( 135 NULL, surface, gfx::PreferDiscreteGpu).get(); 136 context->MakeCurrent(surface); 137 // This sets D3DPRESENT_INTERVAL_IMMEDIATE on Windows. 138 context->SetSwapInterval(0); 139 140 // Initialize and name GPU painters. 141 static const struct { 142 const char* name; 143 GPUPainter* painter; 144 } painters[] = { 145 { "CPU CSC + GPU Render", new CPUColorPainter() }, 146 { "GPU CSC/Render", new GPUColorWithLuminancePainter() }, 147 }; 148 149 // Run GPU painter tests. 150 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(painters); i++) { 151 scoped_ptr<GPUPainter> painter(painters[i].painter); 152 painter->LoadFrames(&frames); 153 painter->SetGLContext(surface, context); 154 painter->Initialize(width, height); 155 printf("Running %s tests...", painters[i].name); 156 RunTest(window.get(), painter.get()); 157 } 158 159 return 0; 160 } 161