webrtc_m130/webrtc/tools/psnr_ssim_analyzer/psnr_ssim_analyzer.cc
mcasas@webrtc.org 6e2d012b58 Add support for YUV4MPEG file reading to tools files.
This CL adds support for reading .y4m files to the infra in
video_quality_analysis.cc, adding new functions 
ExtractFrameFromYuvFile() and ExtractFrameFromY4mFile(),
instad of the previous ExtractFrameFromI420(). The decision
as to which one to use is taken from the file extension,
if it is .y4m then is considered a YUV4MPEG file, otherwise
is taken as a raw .yuv file.

It also removes the pseudo duplicated function 
GetNextI420Frame(), that is used from psnr_ssim_analyzer.c,
and adds support for y4m files there.

Tested/validated via local compile-run.

YUV4MPEG is a trivial container with a file header
and a per-frame header, see [1]

[1]
http://wiki.multimedia.cx/index.php?title=YUV4MPEG2

BUG=https://code.google.com/p/chromium/issues/detail?id=343504



git-svn-id: http://webrtc.googlecode.com/svn/trunk@5702 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-03-14 12:45:45 +00:00

133 lines
4.9 KiB
C++

/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <string>
#include <vector>
#include "webrtc/tools/frame_analyzer/video_quality_analysis.h"
#include "webrtc/tools/simple_command_line_parser.h"
#define MAX_NUM_FRAMES_PER_FILE INT_MAX
void CompareFiles(const char* reference_file_name, const char* test_file_name,
const char* results_file_name, int width, int height) {
// Check if the reference_file_name ends with "y4m".
bool y4m_mode = false;
if (std::string(reference_file_name).find("y4m") != std::string::npos){
y4m_mode = true;
}
FILE* results_file = fopen(results_file_name, "w");
int size = webrtc::test::GetI420FrameSize(width, height);
// Allocate buffers for test and reference frames.
uint8* test_frame = new uint8[size];
uint8* ref_frame = new uint8[size];
bool read_result = true;
for(int frame_counter = 0; frame_counter < MAX_NUM_FRAMES_PER_FILE;
++frame_counter){
read_result &= (y4m_mode) ? webrtc::test::ExtractFrameFromY4mFile(
reference_file_name, width, height, frame_counter, ref_frame):
webrtc::test::ExtractFrameFromYuvFile(reference_file_name, width,
height, frame_counter, ref_frame);
read_result &= webrtc::test::ExtractFrameFromYuvFile(test_file_name, width,
height, frame_counter, test_frame);
if (!read_result)
break;
// Calculate the PSNR and SSIM.
double result_psnr = webrtc::test::CalculateMetrics(
webrtc::test::kPSNR, ref_frame, test_frame, width, height);
double result_ssim = webrtc::test::CalculateMetrics(
webrtc::test::kSSIM, ref_frame, test_frame, width, height);
fprintf(results_file, "Frame: %d, PSNR: %f, SSIM: %f\n", frame_counter,
result_psnr, result_ssim);
}
delete[] test_frame;
delete[] ref_frame;
fclose(results_file);
}
/*
* A tool running PSNR and SSIM analysis on two videos - a reference video and a
* test video. The two videos should be I420 YUV videos.
* The tool just runs PSNR and SSIM on the corresponding frames in the test and
* the reference videos until either the first or the second video runs out of
* frames. The result is written in a results text file in the format:
* Frame: <frame_number>, PSNR: <psnr_value>, SSIM: <ssim_value>
* Frame: <frame_number>, ........
*
* The max value for PSNR is 48.0 (between equal frames), as for SSIM it is 1.0.
*
* Usage:
* psnr_ssim_analyzer --reference_file=<name_of_file> --test_file=<name_of_file>
* --results_file=<name_of_file> --width=<width_of_frames>
* --height=<height_of_frames>
*/
int main(int argc, char** argv) {
std::string program_name = argv[0];
std::string usage = "Runs PSNR and SSIM on two I420 videos and write the"
"results in a file.\n"
"Example usage:\n" + program_name + " --reference_file=ref.yuv "
"--test_file=test.yuv --results_file=results.txt --width=320 "
"--height=240\n"
"Command line flags:\n"
" - width(int): The width of the reference and test files. Default: -1\n"
" - height(int): The height of the reference and test files. "
" Default: -1\n"
" - reference_file(string): The reference YUV file to compare against."
" Default: ref.yuv\n"
" - test_file(string): The test YUV file to run the analysis for."
" Default: test_file.yuv\n"
" - results_file(string): The full name of the file where the results "
"will be written. Default: results.txt\n";
webrtc::test::CommandLineParser parser;
// Init the parser and set the usage message
parser.Init(argc, argv);
parser.SetUsageMessage(usage);
parser.SetFlag("width", "-1");
parser.SetFlag("height", "-1");
parser.SetFlag("results_file", "results.txt");
parser.SetFlag("reference_file", "ref.yuv");
parser.SetFlag("test_file", "test.yuv");
parser.SetFlag("results_file", "results.txt");
parser.SetFlag("help", "false");
parser.ProcessFlags();
if (parser.GetFlag("help") == "true") {
parser.PrintUsageMessage();
}
parser.PrintEnteredFlags();
int width = strtol((parser.GetFlag("width")).c_str(), NULL, 10);
int height = strtol((parser.GetFlag("height")).c_str(), NULL, 10);
if (width <= 0 || height <= 0) {
fprintf(stderr, "Error: width or height cannot be <= 0!\n");
return -1;
}
CompareFiles(parser.GetFlag("reference_file").c_str(),
parser.GetFlag("test_file").c_str(),
parser.GetFlag("results_file").c_str(), width, height);
}