| Index: webrtc/tools/frame_analyzer/video_quality_analysis.cc
|
| diff --git a/webrtc/tools/frame_analyzer/video_quality_analysis.cc b/webrtc/tools/frame_analyzer/video_quality_analysis.cc
|
| index dfb7d900657540ca87adc6e38e79b143a721abe6..09594787c369614ccc9827a02debfd7b3c77c26b 100644
|
| --- a/webrtc/tools/frame_analyzer/video_quality_analysis.cc
|
| +++ b/webrtc/tools/frame_analyzer/video_quality_analysis.cc
|
| @@ -327,23 +327,32 @@ void PrintMaxRepeatedAndSkippedFrames(const std::string& label,
|
| stats_file_test_name);
|
| }
|
|
|
| -namespace {
|
| -// Clusters the frames in the file. First in the pair is the frame number and
|
| -// second is the number
|
| -// of frames in that cluster. So if first frame in video has number 100 and it
|
| -// is repeated 3 after
|
| -// each other, then the first entry in the returned vector has first set to 100
|
| -// and second set
|
| -// to 3.
|
| -std::vector<std::pair<int, int> > CalculateFrameClusters(FILE* file) {
|
| +std::vector<std::pair<int, int> > CalculateFrameClusters(
|
| + FILE* file,
|
| + int* num_decode_errors) {
|
| + if (num_decode_errors) {
|
| + *num_decode_errors = 0;
|
| + }
|
| std::vector<std::pair<int, int> > frame_cnt;
|
| char line[STATS_LINE_LENGTH];
|
| while (GetNextStatsLine(file, line)) {
|
| - int decoded_frame_number = ExtractDecodedFrameNumber(line);
|
| - if (decoded_frame_number == -1) {
|
| - continue;
|
| + int decoded_frame_number;
|
| + if (IsThereBarcodeError(line)) {
|
| + decoded_frame_number = DECODE_ERROR;
|
| + if (num_decode_errors) {
|
| + ++*num_decode_errors;
|
| + }
|
| + } else {
|
| + decoded_frame_number = ExtractDecodedFrameNumber(line);
|
| }
|
| - if (frame_cnt.empty() || frame_cnt.back().first != decoded_frame_number) {
|
| + if (frame_cnt.size() >= 2 && decoded_frame_number != DECODE_ERROR &&
|
| + frame_cnt.back().first == DECODE_ERROR &&
|
| + frame_cnt[frame_cnt.size() - 2].first == decoded_frame_number) {
|
| + // Handle when there is a decoding error inside a cluster of frames.
|
| + frame_cnt[frame_cnt.size() - 2].second += frame_cnt.back().second + 1;
|
| + frame_cnt.pop_back();
|
| + } else if (frame_cnt.empty() ||
|
| + frame_cnt.back().first != decoded_frame_number) {
|
| frame_cnt.push_back(std::make_pair(decoded_frame_number, 1));
|
| } else {
|
| ++frame_cnt.back().second;
|
| @@ -351,7 +360,6 @@ std::vector<std::pair<int, int> > CalculateFrameClusters(FILE* file) {
|
| }
|
| return frame_cnt;
|
| }
|
| -} // namespace
|
|
|
| void PrintMaxRepeatedAndSkippedFrames(FILE* output,
|
| const std::string& label,
|
| @@ -372,13 +380,16 @@ void PrintMaxRepeatedAndSkippedFrames(FILE* output,
|
| }
|
|
|
| int max_repeated_frames = 1;
|
| - int max_skipped_frames = 1;
|
| + int max_skipped_frames = 0;
|
| +
|
| + int decode_errors_ref = 0;
|
| + int decode_errors_test = 0;
|
|
|
| std::vector<std::pair<int, int> > frame_cnt_ref =
|
| - CalculateFrameClusters(stats_file_ref);
|
| + CalculateFrameClusters(stats_file_ref, &decode_errors_ref);
|
|
|
| std::vector<std::pair<int, int> > frame_cnt_test =
|
| - CalculateFrameClusters(stats_file_test);
|
| + CalculateFrameClusters(stats_file_test, &decode_errors_test);
|
|
|
| fclose(stats_file_ref);
|
| fclose(stats_file_test);
|
| @@ -393,9 +404,19 @@ void PrintMaxRepeatedAndSkippedFrames(FILE* output,
|
| return;
|
| }
|
|
|
| + while (it_test != end_test && it_test->first == DECODE_ERROR) {
|
| + ++it_test;
|
| + }
|
| +
|
| + if (it_test == end_test) {
|
| + fprintf(stderr, "Test video only has barcode decode errors\n");
|
| + return;
|
| + }
|
| +
|
| // Find the first frame in the reference video that match the first frame in
|
| // the test video.
|
| - while (it_ref != end_ref && it_ref->first != it_test->first) {
|
| + while (it_ref != end_ref &&
|
| + (it_ref->first == DECODE_ERROR || it_ref->first != it_test->first)) {
|
| ++it_ref;
|
| }
|
| if (it_ref == end_ref) {
|
| @@ -405,33 +426,58 @@ void PrintMaxRepeatedAndSkippedFrames(FILE* output,
|
| return;
|
| }
|
|
|
| + int total_skipped_frames = 0;
|
| for (;;) {
|
| max_repeated_frames =
|
| std::max(max_repeated_frames, it_test->second - it_ref->second + 1);
|
| +
|
| + bool passed_error = false;
|
| +
|
| ++it_test;
|
| + while (it_test != end_test && it_test->first == DECODE_ERROR) {
|
| + ++it_test;
|
| + passed_error = true;
|
| + }
|
| if (it_test == end_test) {
|
| break;
|
| }
|
| +
|
| int skipped_frames = 0;
|
| ++it_ref;
|
| - while (it_ref != end_ref && it_ref->first != it_test->first) {
|
| - skipped_frames += it_ref->second;
|
| - ++it_ref;
|
| + for (; it_ref != end_ref; ++it_ref) {
|
| + if (it_ref->first != DECODE_ERROR && it_ref->first >= it_test->first) {
|
| + break;
|
| + }
|
| + ++skipped_frames;
|
| }
|
| - if (it_ref == end_ref) {
|
| - fprintf(stderr,
|
| - "The barcode in the test video is not in the reference video.\n");
|
| - return;
|
| + if (passed_error) {
|
| + // If we pass an error in the test video, then we are conservative
|
| + // and will not calculate skipped frames for that part.
|
| + skipped_frames = 0;
|
| }
|
| - if (skipped_frames > max_skipped_frames) {
|
| - max_skipped_frames = skipped_frames;
|
| + if (it_ref != end_ref && it_ref->first == it_test->first) {
|
| + total_skipped_frames += skipped_frames;
|
| + if (skipped_frames > max_skipped_frames) {
|
| + max_skipped_frames = skipped_frames;
|
| + }
|
| + continue;
|
| }
|
| + fprintf(stderr,
|
| + "Found barcode %d in test video, which is not in reference video",
|
| + it_test->first);
|
| + return;
|
| }
|
|
|
| fprintf(output, "RESULT Max_repeated: %s= %d\n", label.c_str(),
|
| max_repeated_frames);
|
| fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(),
|
| max_skipped_frames);
|
| + fprintf(output, "RESULT Total_skipped: %s= %d\n", label.c_str(),
|
| + total_skipped_frames);
|
| + fprintf(output, "RESULT Decode_errors_reference: %s= %d\n", label.c_str(),
|
| + decode_errors_ref);
|
| + fprintf(output, "RESULT Decode_errors_test: %s= %d\n", label.c_str(),
|
| + decode_errors_test);
|
| }
|
|
|
| void PrintAnalysisResults(const std::string& label, ResultsContainer* results) {
|
|
|