Index: media/bench/bench.cc |
=================================================================== |
--- media/bench/bench.cc (revision 17367) |
+++ media/bench/bench.cc (working copy) |
@@ -6,6 +6,8 @@ |
// measure decoding performance between different FFmpeg compile and run-time |
// options. We also use this tool to measure performance regressions when |
// testing newer builds of FFmpeg from trunk. |
+// |
+// This tool requires FFMPeg DLL's built with --enable-protocol=file. |
#include <iomanip> |
#include <iostream> |
@@ -26,6 +28,7 @@ |
const wchar_t kVideoThreads[] = L"video-threads"; |
const wchar_t kFast2[] = L"fast2"; |
const wchar_t kSkip[] = L"skip"; |
+const wchar_t kFlush[] = L"flush"; |
} // namespace switches |
int main(int argc, const char** argv) { |
@@ -43,8 +46,10 @@ |
<< "Decode video using N threads\n" |
<< " --fast2 " |
<< "Enable fast2 flag\n" |
+ << " --flush " |
+ << "Flush last frame\n" |
<< " --skip=[1|2|3] " |
- << "1=loop nonref, 2=loop, 3= frame nonref" << std::endl; |
+ << "1=loop nonref, 2=loop, 3= frame nonref\n" << std::endl; |
return 1; |
} |
@@ -86,6 +91,11 @@ |
fast2 = true; |
} |
+ bool flush = false; |
+ if (cmd_line->HasSwitch(switches::kFlush)) { |
+ flush = true; |
+ } |
+ |
int skip = 0; |
if (cmd_line->HasSwitch(switches::kSkip)) { |
std::wstring skip_opt(cmd_line->GetSwitchValue(switches::kSkip)); |
@@ -123,9 +133,13 @@ |
std::cout << " "; |
} |
- // Print out stream information |
- std::cout << "Stream #" << i << ": " << codec->name << " (" |
- << codec->long_name << ")" << std::endl; |
+ if (codec_context->codec_type == CODEC_TYPE_UNKNOWN) { |
+ std::cout << "Stream #" << i << ": Unknown" << std::endl; |
+ } else { |
+ // Print out stream information |
+ std::cout << "Stream #" << i << ": " << codec->name << " (" |
+ << codec->long_name << ")" << std::endl; |
+ } |
} |
// Only continue if we found our target stream. |
@@ -179,10 +193,22 @@ |
// Stats collector. |
std::vector<double> decode_times; |
decode_times.reserve(4096); |
- |
// Parse through the entire stream until we hit EOF. |
base::TimeTicks start = base::TimeTicks::HighResNow(); |
- while (av_read_frame(format_context, &packet) >= 0) { |
+ size_t frames = 0; |
+ int read_result = 0; |
+ do { |
+ read_result = av_read_frame(format_context, &packet); |
+ |
+ if (read_result < 0) { |
+ if (flush) { |
+ packet.stream_index = target_stream; |
+ packet.size = 0; |
+ } else { |
+ break; |
+ } |
+ } |
+ |
// Only decode packets from our target stream. |
if (packet.stream_index == target_stream) { |
int result = -1; |
@@ -191,14 +217,23 @@ |
int size_out = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
result = avcodec_decode_audio3(codec_context, samples, &size_out, |
&packet); |
+ if (size_out) { |
+ ++frames; |
+ read_result = 0; // Force continuation. |
+ } |
} else if (target_codec == CODEC_TYPE_VIDEO) { |
int got_picture = 0; |
result = avcodec_decode_video2(codec_context, frame, &got_picture, |
&packet); |
+ if (got_picture) { |
+ ++frames; |
+ read_result = 0; // Force continuation. |
+ } |
} else { |
NOTREACHED(); |
} |
base::TimeDelta delta = base::TimeTicks::HighResNow() - decode_start; |
+ |
decode_times.push_back(delta.InMillisecondsF()); |
// Make sure our decoding went OK. |
@@ -207,45 +242,48 @@ |
return 1; |
} |
} |
- |
// Free our packet. |
av_free_packet(&packet); |
- } |
+ } while (read_result >= 0); |
base::TimeDelta total = base::TimeTicks::HighResNow() - start; |
- // Calculate the sum. The numbers are very consistent and the we're not too |
- // worried about floating point error here. |
+ // Calculate the sum of times. Note that some of these may be zero. |
double sum = 0; |
for (size_t i = 0; i < decode_times.size(); ++i) { |
sum += decode_times[i]; |
} |
- // Calculate the average. |
- double average = sum / decode_times.size(); |
- |
- // Calculate the sum of the squared differences. |
- double squared_sum = 0; |
- for (size_t i = 0; i < decode_times.size(); ++i) { |
- double difference = decode_times[i] - average; |
- squared_sum += difference * difference; |
- } |
- |
- // Calculate the standard deviation (jitter). |
- double stddev = sqrt(squared_sum / decode_times.size()); |
- |
- // Print our results. |
+ // Print our results. |
std::cout.setf(std::ios::fixed); |
std::cout.precision(3); |
std::cout << std::endl; |
- std::cout << " Frames:" << std::setw(10) << decode_times.size() |
+ std::cout << " Frames:" << std::setw(10) << frames |
<< std::endl; |
std::cout << " Total:" << std::setw(10) << total.InMillisecondsF() |
<< " ms" << std::endl; |
std::cout << " Summation:" << std::setw(10) << sum |
<< " ms" << std::endl; |
- std::cout << " Average:" << std::setw(10) << average |
- << " ms" << std::endl; |
- std::cout << " StdDev:" << std::setw(10) << stddev |
- << " ms" << std::endl; |
+ |
+ if (frames > 0u) { |
+ // Calculate the average time per frame. |
+ double average = sum / frames; |
+ |
+ // Calculate the sum of the squared differences. |
+ // Standard deviation will only be accurate if no threads are used. |
+ // TODO(fbarchard): Rethink standard deviation calculation. |
+ double squared_sum = 0; |
+ for (size_t i = 0; i < frames; ++i) { |
+ double difference = decode_times[i] - average; |
+ squared_sum += difference * difference; |
+ } |
+ |
+ // Calculate the standard deviation (jitter). |
+ double stddev = sqrt(squared_sum / frames); |
+ |
+ std::cout << " Average:" << std::setw(10) << average |
+ << " ms" << std::endl; |
+ std::cout << " StdDev:" << std::setw(10) << stddev |
+ << " ms" << std::endl; |
+ } |
return 0; |
} |