Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Side by Side Diff: media/bench/bench.cc

Issue 171113: media_bench optionally dump raw output to a file.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Standalone benchmarking application based on FFmpeg. This tool is used to 5 // Standalone benchmarking application based on FFmpeg. This tool is used to
6 // measure decoding performance between different FFmpeg compile and run-time 6 // measure decoding performance between different FFmpeg compile and run-time
7 // options. We also use this tool to measure performance regressions when 7 // options. We also use this tool to measure performance regressions when
8 // testing newer builds of FFmpeg from trunk. 8 // testing newer builds of FFmpeg from trunk.
9 // 9 //
10 // This tool requires FFMPeg DLL's built with --enable-protocol=file. 10 // This tool requires FFMPeg DLL's built with --enable-protocol=file.
11 11
12 #include <iomanip> 12 #include <iomanip>
13 #include <iostream> 13 #include <iostream>
14 #include <string> 14 #include <string>
15 15
16 #include "base/at_exit.h" 16 #include "base/at_exit.h"
17 #include "base/basictypes.h" 17 #include "base/basictypes.h"
18 #include "base/command_line.h" 18 #include "base/command_line.h"
19 #include "base/file_path.h" 19 #include "base/file_path.h"
20 #include "base/file_util.h"
20 #include "base/logging.h" 21 #include "base/logging.h"
21 #include "base/string_util.h" 22 #include "base/string_util.h"
22 #include "base/time.h" 23 #include "base/time.h"
23 #include "media/base/media.h" 24 #include "media/base/media.h"
24 #include "media/filters/ffmpeg_common.h" 25 #include "media/filters/ffmpeg_common.h"
26 #include "media/filters/ffmpeg_video_decoder.h"
scherkus (not reviewing) 2009/09/03 22:03:36 hmm.. don't think you need to include this
25 27
26 namespace switches { 28 namespace switches {
27 const wchar_t kStream[] = L"stream"; 29 const wchar_t kStream[] = L"stream";
28 const wchar_t kVideoThreads[] = L"video-threads"; 30 const wchar_t kVideoThreads[] = L"video-threads";
29 const wchar_t kFast2[] = L"fast2"; 31 const wchar_t kFast2[] = L"fast2";
30 const wchar_t kSkip[] = L"skip"; 32 const wchar_t kSkip[] = L"skip";
31 const wchar_t kFlush[] = L"flush"; 33 const wchar_t kFlush[] = L"flush";
32 } // namespace switches 34 } // namespace switches
33 35
34 int main(int argc, const char** argv) { 36 int main(int argc, const char** argv) {
35 base::AtExitManager exit_manager; 37 base::AtExitManager exit_manager;
36 38
37 CommandLine::Init(argc, argv); 39 CommandLine::Init(argc, argv);
38 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 40 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
39 41
40 std::vector<std::wstring> filenames(cmd_line->GetLooseValues()); 42 std::vector<std::wstring> filenames(cmd_line->GetLooseValues());
41 if (filenames.empty()) { 43 if (filenames.empty()) {
42 std::cerr << "Usage: media_bench [OPTIONS] FILE\n" 44 std::cerr << "Usage: media_bench [OPTIONS] FILE [DUMPFILE]\n"
43 << " --stream=[audio|video] " 45 << " --stream=[audio|video] "
44 << "Benchmark either the audio or video stream\n" 46 << "Benchmark either the audio or video stream\n"
45 << " --video-threads=N " 47 << " --video-threads=N "
46 << "Decode video using N threads\n" 48 << "Decode video using N threads\n"
47 << " --fast2 " 49 << " --fast2 "
48 << "Enable fast2 flag\n" 50 << "Enable fast2 flag\n"
49 << " --flush " 51 << " --flush "
50 << "Flush last frame\n" 52 << "Flush last frame\n"
51 << " --skip=[1|2|3] " 53 << " --skip=[1|2|3] "
52 << "1=loop nonref, 2=loop, 3= frame nonref\n" << std::endl; 54 << "1=loop nonref, 2=loop, 3= frame nonref\n" << std::endl;
53 return 1; 55 return 1;
54 } 56 }
55 57
56 // Initialize our media library (try loading DLLs, etc.) before continuing. 58 // Initialize our media library (try loading DLLs, etc.) before continuing.
57 // We use an empty file path as the parameter to force searching of the 59 // We use an empty file path as the parameter to force searching of the
58 // default locations for necessary DLLs and DSOs. 60 // default locations for necessary DLLs and DSOs.
59 if (media::InitializeMediaLibrary(FilePath()) == false) { 61 if (media::InitializeMediaLibrary(FilePath()) == false) {
60 std::cerr << "Unable to initialize the media library."; 62 std::cerr << "Unable to initialize the media library.";
61 return 1; 63 return 1;
62 } 64 }
63 65
64 // Retrieve command line options. 66 // Retrieve command line options.
65 std::string path(WideToUTF8(filenames[0])); 67 std::string in_path(WideToUTF8(filenames[0]));
68 std::string out_path;
69 if (filenames.size() > 1) {
70 out_path = WideToUTF8(filenames[1]);
71 }
66 CodecType target_codec = CODEC_TYPE_UNKNOWN; 72 CodecType target_codec = CODEC_TYPE_UNKNOWN;
67 int video_threads = 0; 73 int video_threads = 0;
68 74
69 // Determine whether to benchmark audio or video decoding. 75 // Determine whether to benchmark audio or video decoding.
70 std::wstring stream(cmd_line->GetSwitchValue(switches::kStream)); 76 std::wstring stream(cmd_line->GetSwitchValue(switches::kStream));
71 if (!stream.empty()) { 77 if (!stream.empty()) {
72 if (stream.compare(L"audio") == 0) { 78 if (stream.compare(L"audio") == 0) {
73 target_codec = CODEC_TYPE_AUDIO; 79 target_codec = CODEC_TYPE_AUDIO;
74 } else if (stream.compare(L"video") == 0) { 80 } else if (stream.compare(L"video") == 0) {
75 target_codec = CODEC_TYPE_VIDEO; 81 target_codec = CODEC_TYPE_VIDEO;
(...skipping 25 matching lines...) Expand all
101 std::wstring skip_opt(cmd_line->GetSwitchValue(switches::kSkip)); 107 std::wstring skip_opt(cmd_line->GetSwitchValue(switches::kSkip));
102 if (!StringToInt(WideToUTF16Hack(skip_opt), &skip)) { 108 if (!StringToInt(WideToUTF16Hack(skip_opt), &skip)) {
103 skip = 0; 109 skip = 0;
104 } 110 }
105 } 111 }
106 112
107 // Register FFmpeg and attempt to open file. 113 // Register FFmpeg and attempt to open file.
108 avcodec_init(); 114 avcodec_init();
109 av_register_all(); 115 av_register_all();
110 AVFormatContext* format_context = NULL; 116 AVFormatContext* format_context = NULL;
111 if (av_open_input_file(&format_context, path.c_str(), NULL, 0, NULL) < 0) { 117 if (av_open_input_file(&format_context, in_path.c_str(), NULL, 0, NULL) < 0) {
112 std::cerr << "Could not open " << path << std::endl; 118 std::cerr << "Could not open " << in_path << std::endl;
113 return 1; 119 return 1;
114 } 120 }
115 121
122 // Open output file.
123 FILE *output = NULL;
scherkus (not reviewing) 2009/09/03 22:03:36 pointer goes with typename
124 if (!out_path.empty()) {
125 output = file_util::OpenFile(out_path.c_str(), "wb");
126 if (!output) {
127 LOG(ERROR) << "could not open output";
128 return 1;
129 }
130 }
131
116 // Parse a little bit of the stream to fill out the format context. 132 // Parse a little bit of the stream to fill out the format context.
117 if (av_find_stream_info(format_context) < 0) { 133 if (av_find_stream_info(format_context) < 0) {
118 std::cerr << "Could not find stream info for " << path << std::endl; 134 std::cerr << "Could not find stream info for " << in_path << std::endl;
119 return 1; 135 return 1;
120 } 136 }
121 137
122 // Find our target stream. 138 // Find our target stream.
123 int target_stream = -1; 139 int target_stream = -1;
124 for (size_t i = 0; i < format_context->nb_streams; ++i) { 140 for (size_t i = 0; i < format_context->nb_streams; ++i) {
125 AVCodecContext* codec_context = format_context->streams[i]->codec; 141 AVCodecContext* codec_context = format_context->streams[i]->codec;
126 AVCodec* codec = avcodec_find_decoder(codec_context->codec_id); 142 AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
127 143
128 // See if we found our target codec. 144 // See if we found our target codec.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 if (packet.stream_index == target_stream) { 229 if (packet.stream_index == target_stream) {
214 int result = -1; 230 int result = -1;
215 base::TimeTicks decode_start = base::TimeTicks::HighResNow(); 231 base::TimeTicks decode_start = base::TimeTicks::HighResNow();
216 if (target_codec == CODEC_TYPE_AUDIO) { 232 if (target_codec == CODEC_TYPE_AUDIO) {
217 int size_out = AVCODEC_MAX_AUDIO_FRAME_SIZE; 233 int size_out = AVCODEC_MAX_AUDIO_FRAME_SIZE;
218 result = avcodec_decode_audio3(codec_context, samples, &size_out, 234 result = avcodec_decode_audio3(codec_context, samples, &size_out,
219 &packet); 235 &packet);
220 if (size_out) { 236 if (size_out) {
221 ++frames; 237 ++frames;
222 read_result = 0; // Force continuation. 238 read_result = 0; // Force continuation.
239
240 if (output) {
241 if (fwrite(samples, 1, size_out, output) !=
242 static_cast<size_t>(size_out)) {
243 std::cerr << "could not write data after " << size_out;
244 return 1;
245 }
246 }
223 } 247 }
224 } else if (target_codec == CODEC_TYPE_VIDEO) { 248 } else if (target_codec == CODEC_TYPE_VIDEO) {
225 int got_picture = 0; 249 int got_picture = 0;
226 result = avcodec_decode_video2(codec_context, frame, &got_picture, 250 result = avcodec_decode_video2(codec_context, frame, &got_picture,
227 &packet); 251 &packet);
228 if (got_picture) { 252 if (got_picture) {
229 ++frames; 253 ++frames;
230 read_result = 0; // Force continuation. 254 read_result = 0; // Force continuation.
255
256 // TODO(fbarchard): support formats other than YV12.
scherkus (not reviewing) 2009/09/03 22:03:36 this comment is out of date
257 if (output) {
258 for (int plane = 0; plane < 3; ++plane) {
259 const uint8* source = frame->data[plane];
260 const size_t source_stride = frame->linesize[plane];
261 size_t bytes_per_line = codec_context->width;
262 size_t copy_lines = codec_context->height;
263 if (plane != 0) {
264 switch (codec_context->pix_fmt) {
265 case PIX_FMT_YUV420P:
266 case PIX_FMT_YUVJ420P:
267 bytes_per_line /= 2;
268 copy_lines = (copy_lines + 1) / 2;
269 break;
270 case PIX_FMT_YUV422P:
271 case PIX_FMT_YUVJ422P:
272 bytes_per_line /= 2;
273 copy_lines = copy_lines;
scherkus (not reviewing) 2009/09/03 22:03:36 redundant?
274 break;
275 case PIX_FMT_YUV444P:
276 case PIX_FMT_YUVJ444P:
277 copy_lines = copy_lines;
scherkus (not reviewing) 2009/09/03 22:03:36 redundant?
278 break;
279 default:
280 std::cerr << "unknown video format: "
281 << codec_context->pix_fmt;
282 return 1;
283 }
284 }
285 for (size_t i = 0; i < copy_lines; ++i) {
286 if (fwrite(source, 1, bytes_per_line, output) !=
287 bytes_per_line) {
288 std::cerr << "could not write data after "
289 << bytes_per_line;
290 return 1;
291 }
292 source += source_stride;
293 }
294 }
295 }
231 } 296 }
232 } else { 297 } else {
233 NOTREACHED(); 298 NOTREACHED();
234 } 299 }
235 base::TimeDelta delta = base::TimeTicks::HighResNow() - decode_start; 300 base::TimeDelta delta = base::TimeTicks::HighResNow() - decode_start;
236 301
237 decode_times.push_back(delta.InMillisecondsF()); 302 decode_times.push_back(delta.InMillisecondsF());
238 303
239 // Make sure our decoding went OK. 304 // Make sure our decoding went OK.
240 if (result < 0) { 305 if (result < 0) {
241 std::cerr << "Error while decoding" << std::endl; 306 std::cerr << "Error while decoding" << std::endl;
242 return 1; 307 return 1;
243 } 308 }
244 } 309 }
245 // Free our packet. 310 // Free our packet.
246 av_free_packet(&packet); 311 av_free_packet(&packet);
247 } while (read_result >= 0); 312 } while (read_result >= 0);
248 base::TimeDelta total = base::TimeTicks::HighResNow() - start; 313 base::TimeDelta total = base::TimeTicks::HighResNow() - start;
249 314
315 if (output)
316 file_util::CloseFile(output);
317
250 // Calculate the sum of times. Note that some of these may be zero. 318 // Calculate the sum of times. Note that some of these may be zero.
251 double sum = 0; 319 double sum = 0;
252 for (size_t i = 0; i < decode_times.size(); ++i) { 320 for (size_t i = 0; i < decode_times.size(); ++i) {
253 sum += decode_times[i]; 321 sum += decode_times[i];
254 } 322 }
255 323
256 // Print our results. 324 // Print our results.
257 std::cout.setf(std::ios::fixed); 325 std::cout.setf(std::ios::fixed);
258 std::cout.precision(2); 326 std::cout.precision(2);
259 std::cout << std::endl; 327 std::cout << std::endl;
(...skipping 20 matching lines...) Expand all
280 // Calculate the standard deviation (jitter). 348 // Calculate the standard deviation (jitter).
281 double stddev = sqrt(squared_sum / frames); 349 double stddev = sqrt(squared_sum / frames);
282 350
283 std::cout << " Average:" << std::setw(10) << average 351 std::cout << " Average:" << std::setw(10) << average
284 << " ms" << std::endl; 352 << " ms" << std::endl;
285 std::cout << " StdDev:" << std::setw(10) << stddev 353 std::cout << " StdDev:" << std::setw(10) << stddev
286 << " ms" << std::endl; 354 << " ms" << std::endl;
287 } 355 }
288 return 0; 356 return 0;
289 } 357 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698