/* * Copyright (c) 2013 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 "webrtc/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h" #include #include #include #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_fileutils.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "webrtc/test/testsupport/fileutils.h" namespace webrtc { namespace testing { namespace bwe { // The format of BWE test baseline files is extremely simple: // 1. All read/written entities are 32-bit unsigned integers in network byte // order (Big Endian). // 2. Files beging with a 2 word header containing a magic marker and file // format version indicator. The Magic marker reads "BWE!" in a hex dump. // 3. Each estimate is logged as a pair of words: time in milliseconds and // estimated bit rate, in bits per second. const uint32_t kMagicMarker = 0x42574521; const uint32_t kFileVersion1 = 0x00000001; const char kResourceSubDir[] = "remote_bitrate_estimator"; class BaseLineFileVerify : public BaseLineFileInterface { public: // If |allow_missing_file| is set, VerifyOrWrite() will return true even if // the baseline file is missing. This is the default when verifying files, but // not when updating (i.e. we always write it out if missing). BaseLineFileVerify(const std::string& filepath, bool allow_missing_file) : reader_(), fail_to_read_response_(false) { rtc::scoped_ptr reader; reader.reset(ResourceFileReader::Create(filepath, "bin")); if (!reader.get()) { printf("WARNING: Missing baseline file for BWE test: %s.bin\n", filepath.c_str()); fail_to_read_response_ = allow_missing_file; } else { uint32_t magic_marker = 0; uint32_t file_version = 0; if (reader->Read(&magic_marker) && magic_marker == kMagicMarker && reader->Read(&file_version) && file_version == kFileVersion1) { reader_.swap(reader); } else { printf("WARNING: Bad baseline file header for BWE test: %s.bin\n", filepath.c_str()); } } } virtual ~BaseLineFileVerify() {} virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) { if (reader_.get()) { uint32_t read_ms = 0; uint32_t read_bps = 0; if (reader_->Read(&read_ms) && read_ms == time_ms && reader_->Read(&read_bps) && read_bps == estimate_bps) { } else { printf("ERROR: Baseline differs starting at: %d ms (%d vs %d)!\n", static_cast(time_ms), estimate_bps, read_bps); reader_.reset(NULL); } } } virtual bool VerifyOrWrite() { if (reader_.get()) { if (reader_->IsAtEnd()) { return true; } else { printf("ERROR: Baseline file contains more data!\n"); return false; } } return fail_to_read_response_; } private: rtc::scoped_ptr reader_; bool fail_to_read_response_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileVerify); }; class BaseLineFileUpdate : public BaseLineFileInterface { public: BaseLineFileUpdate(const std::string& filepath, BaseLineFileInterface* verifier) : verifier_(verifier), output_content_(), filepath_(filepath) { output_content_.push_back(kMagicMarker); output_content_.push_back(kFileVersion1); } virtual ~BaseLineFileUpdate() {} virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) { verifier_->Estimate(time_ms, estimate_bps); output_content_.push_back(static_cast(time_ms)); output_content_.push_back(estimate_bps); } virtual bool VerifyOrWrite() { if (!verifier_->VerifyOrWrite()) { std::string dir_path = webrtc::test::OutputPath() + kResourceSubDir; if (!webrtc::test::CreateDir(dir_path)) { printf("WARNING: Cannot create output dir: %s\n", dir_path.c_str()); return false; } rtc::scoped_ptr writer; writer.reset(OutputFileWriter::Create(filepath_, "bin")); if (!writer.get()) { printf("WARNING: Cannot create output file: %s.bin\n", filepath_.c_str()); return false; } printf("NOTE: Writing baseline file for BWE test: %s.bin\n", filepath_.c_str()); for (std::vector::iterator it = output_content_.begin(); it != output_content_.end(); ++it) { writer->Write(*it); } return true; } printf("NOTE: No change, not writing: %s\n", filepath_.c_str()); return true; } private: rtc::scoped_ptr verifier_; std::vector output_content_; std::string filepath_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileUpdate); }; BaseLineFileInterface* BaseLineFileInterface::Create( const std::string& filename, bool write_output_file) { std::string filepath = filename; std::replace(filepath.begin(), filepath.end(), '/', '_'); filepath = std::string(kResourceSubDir) + "/" + filepath; rtc::scoped_ptr result; result.reset(new BaseLineFileVerify(filepath, !write_output_file)); if (write_output_file) { // Takes ownership of the |verifier| instance. result.reset(new BaseLineFileUpdate(filepath, result.release())); } return result.release(); } } // namespace bwe } // namespace testing } // namespace webrtc