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 c1911ca81c7033e3e063d11338f5d5461d674f18..25de981e754c32ccb414333e73d8ae8abae72683 100644 |
--- a/webrtc/tools/frame_analyzer/video_quality_analysis.cc |
+++ b/webrtc/tools/frame_analyzer/video_quality_analysis.cc |
@@ -13,7 +13,10 @@ |
#include <assert.h> |
#include <stdio.h> |
#include <stdlib.h> |
+#include <algorithm> |
#include <string> |
+#include <map> |
+#include <utility> |
#define STATS_LINE_LENGTH 32 |
#define Y4M_FILE_HEADER_MAX_SIZE 200 |
@@ -224,8 +227,12 @@ double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type, |
return result; |
} |
-void RunAnalysis(const char* reference_file_name, const char* test_file_name, |
- const char* stats_file_name, int width, int height, |
+void RunAnalysis(const char* reference_file_name, |
+ const char* test_file_name, |
+ const char* stats_file_reference_name, |
+ const char* stats_file_test_name, |
+ int width, |
+ int height, |
ResultsContainer* results) { |
// Check if the reference_file_name ends with "y4m". |
bool y4m_mode = false; |
@@ -234,7 +241,8 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name, |
} |
int size = GetI420FrameSize(width, height); |
- FILE* stats_file = fopen(stats_file_name, "r"); |
+ FILE* stats_file_ref = fopen(stats_file_reference_name, "r"); |
+ FILE* stats_file_test = fopen(stats_file_test_name, "r"); |
// String buffer for the lines in the stats file. |
char line[STATS_LINE_LENGTH]; |
@@ -244,10 +252,29 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name, |
uint8_t* reference_frame = new uint8_t[size]; |
int previous_frame_number = -1; |
+ // Maps barcode id to the frame id for the reference video. |
+ // In case two frames have same id, then we only save the first one. |
phoglund
2016/12/08 09:55:44
Add: "This can happen if there are freezes in the
mandermo
2016/12/08 18:08:31
It can also happen that the camera captures two fr
phoglund
2016/12/12 12:46:20
I don't understand when you say the frames have th
|
+ std::map<int, int> ref_barcode_to_frame; |
// While there are entries in the stats file. |
- while (GetNextStatsLine(stats_file, line)) { |
+ while (GetNextStatsLine(stats_file_ref, line)) { |
+ int extracted_ref_frame = ExtractFrameSequenceNumber(line); |
+ int decoded_frame_number = ExtractDecodedFrameNumber(line); |
+ |
+ // Insert will only add if it is not in map already, so we only keep first. |
phoglund
2016/12/08 09:55:44
nit: End this sentence at the ,
mandermo
2016/12/08 18:08:31
Done.
|
+ ref_barcode_to_frame.insert( |
+ std::make_pair(decoded_frame_number, extracted_ref_frame)); |
+ } |
+ |
+ while (GetNextStatsLine(stats_file_test, line)) { |
int extracted_test_frame = ExtractFrameSequenceNumber(line); |
int decoded_frame_number = ExtractDecodedFrameNumber(line); |
+ auto it = ref_barcode_to_frame.find(decoded_frame_number); |
+ if (it == ref_barcode_to_frame.end()) { |
+ // Not found in the reference video. |
+ // TODO(mandermo) print |
phoglund
2016/12/08 09:55:44
Yeah, print an error here and continue. You'll hav
phoglund
2016/12/12 12:46:20
Please address
|
+ continue; |
+ } |
+ int extracted_ref_frame = it->second; |
// If there was problem decoding the barcode in this frame or the frame has |
// been duplicated, continue. |
@@ -263,17 +290,17 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name, |
test_frame); |
if (y4m_mode) { |
ExtractFrameFromY4mFile(reference_file_name, width, height, |
- decoded_frame_number, reference_frame); |
+ extracted_ref_frame, reference_frame); |
} else { |
ExtractFrameFromYuvFile(reference_file_name, width, height, |
- decoded_frame_number, reference_frame); |
+ extracted_ref_frame, reference_frame); |
} |
// Calculate the PSNR and SSIM. |
- double result_psnr = CalculateMetrics(kPSNR, reference_frame, test_frame, |
- width, height); |
- double result_ssim = CalculateMetrics(kSSIM, reference_frame, test_frame, |
- width, height); |
+ double result_psnr = |
+ CalculateMetrics(kPSNR, reference_frame, test_frame, width, height); |
+ double result_ssim = |
+ CalculateMetrics(kSSIM, reference_frame, test_frame, width, height); |
previous_frame_number = decoded_frame_number; |
@@ -287,62 +314,111 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name, |
} |
// Cleanup. |
- fclose(stats_file); |
+ fclose(stats_file_ref); |
+ fclose(stats_file_test); |
delete[] test_frame; |
delete[] reference_frame; |
} |
void PrintMaxRepeatedAndSkippedFrames(const std::string& label, |
- const std::string& stats_file_name) { |
- PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_name); |
+ const std::string& stats_file_ref_name, |
+ const std::string& stats_file_test_name) { |
+ PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_ref_name, |
+ stats_file_test_name); |
} |
-void PrintMaxRepeatedAndSkippedFrames(FILE* output, const std::string& label, |
- const std::string& stats_file_name) { |
- FILE* stats_file = fopen(stats_file_name.c_str(), "r"); |
- if (stats_file == NULL) { |
- fprintf(stderr, "Couldn't open stats file for reading: %s\n", |
- stats_file_name.c_str()); |
+namespace { |
+std::vector<std::pair<int, int> > GetBarcodeNrToFrequency(FILE* file) { |
phoglund
2016/12/08 09:55:44
Number
phoglund
2016/12/08 09:55:44
I would love to have unit tests for these guys sin
mandermo
2016/12/08 18:08:31
I agree the code needs to be easier to test. Maybe
phoglund
2016/12/12 12:46:20
Errors are not returned up the chain today, and I
|
+ std::vector<std::pair<int, int> > frame_cnt; |
phoglund
2016/12/08 09:55:44
It feels a lot more natural to make this a map. Fr
phoglund
2016/12/08 09:55:44
frame_frequency?
mandermo
2016/12/08 18:08:30
frame_frequency.insert(std::pair<int, int>(decoded
mandermo
2016/12/08 18:08:31
Maybe it is more of a frame count than a frequency
phoglund
2016/12/12 12:46:20
Right, it's actually a vector of frame "clusters",
mandermo
2016/12/21 16:42:06
I have renamed the function now and added a commen
|
+ char line[STATS_LINE_LENGTH]; |
+ while (GetNextStatsLine(file, line)) { |
+ int decoded_frame_number = ExtractDecodedFrameNumber(line); |
+ 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; |
+ } |
+ } |
+ return frame_cnt; |
+} |
+} // namespace |
+ |
+void PrintMaxRepeatedAndSkippedFrames(FILE* output, |
+ const std::string& label, |
+ const std::string& stats_file_ref_name, |
+ const std::string& stats_file_test_name) { |
+ FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r"); |
+ FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r"); |
+ if (stats_file_ref == NULL) { |
+ fprintf(stderr, "Couldn't open reference stats file for reading: %s\n", |
+ stats_file_ref_name.c_str()); |
+ return; |
+ } |
+ if (stats_file_test == NULL) { |
+ fprintf(stderr, "Couldn't open test stats file for reading: %s\n", |
+ stats_file_test_name.c_str()); |
+ fclose(stats_file_ref); |
return; |
} |
- char line[STATS_LINE_LENGTH]; |
- int repeated_frames = 1; |
int max_repeated_frames = 1; |
int max_skipped_frames = 1; |
- int previous_frame_number = -1; |
- while (GetNextStatsLine(stats_file, line)) { |
- int decoded_frame_number = ExtractDecodedFrameNumber(line); |
+ std::vector<std::pair<int, int> > frame_cnt_ref = |
phoglund
2016/12/08 09:55:44
frame_frequency_ref
mandermo
2016/12/08 18:08:30
Maybe it is more of a frame count than a frequency
|
+ GetBarcodeNrToFrequency(stats_file_ref); |
- if (decoded_frame_number == -1) { |
- continue; |
- } |
+ std::vector<std::pair<int, int> > frame_cnt_test = |
+ GetBarcodeNrToFrequency(stats_file_test); |
- // Calculate how many frames a cluster of repeated frames contains. |
- if (decoded_frame_number == previous_frame_number) { |
- ++repeated_frames; |
- if (repeated_frames > max_repeated_frames) { |
- max_repeated_frames = repeated_frames; |
- } |
- } else { |
- repeated_frames = 1; |
+ fclose(stats_file_ref); |
+ fclose(stats_file_test); |
+ |
+ auto it_ref = frame_cnt_ref.begin(); |
+ auto it_test = frame_cnt_test.begin(); |
+ auto end_ref = frame_cnt_ref.end(); |
+ auto end_test = frame_cnt_test.end(); |
+ |
+ if (it_test != end_test) { |
phoglund
2016/12/08 09:55:44
if (it_test == end_test) the test file is empty, w
mandermo
2016/12/08 18:08:31
Done. Should I print to output or to stderr like t
|
+ while (it_ref != end_ref && it_ref->first != it_test->first) { |
phoglund
2016/12/08 09:55:44
It's hard to read what happens here. Maybe extract
mandermo
2016/12/08 18:08:31
Commented the code better.
mandermo
2016/12/08 18:08:31
Done. Should I print to output or to stderr like t
|
+ ++it_ref; |
+ } |
+ if (it_ref == end_ref) { |
+ fprintf(stderr, |
+ "The barcode in the test videos first frame is not in the " |
+ "reference video."); |
+ return; |
} |
+ max_repeated_frames = |
phoglund
2016/12/08 09:55:44
Also not sure if this algorithm is correct. To com
mandermo
2016/12/08 18:08:30
Lets make the unittests and see what output we get
phoglund
2016/12/12 12:46:20
Ok, I think counting the frame clusters like your
mandermo
2016/12/21 16:42:06
Done.
|
+ std::max(max_repeated_frames, it_test->second - it_ref->second + 1); |
+ } |
- // Calculate how much frames have been skipped. |
- if (decoded_frame_number != 0 && previous_frame_number != -1) { |
- int skipped_frames = decoded_frame_number - previous_frame_number - 1; |
- if (skipped_frames > max_skipped_frames) { |
- max_skipped_frames = skipped_frames; |
- } |
+ for (;;) { |
+ ++it_test; |
+ if (it_test == end_test) { |
+ break; |
} |
- previous_frame_number = decoded_frame_number; |
+ int skipped_frames = 0; |
+ ++it_ref; |
+ while (it_ref != end_ref && it_ref->first != it_test->first) { |
+ skipped_frames += it_ref->second; |
+ ++it_ref; |
+ } |
+ if (it_ref == end_ref) { |
+ fprintf(stderr, |
+ "The barcode in the test video is not in the reference video."); |
+ return; |
+ } |
+ if (skipped_frames > max_skipped_frames) { |
+ max_skipped_frames = skipped_frames; |
+ } |
+ max_repeated_frames = |
+ std::max(max_repeated_frames, it_test->second - it_ref->second + 1); |
} |
+ |
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); |
- fclose(stats_file); |
} |
void PrintAnalysisResults(const std::string& label, ResultsContainer* results) { |