1/* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h" 12 13#include <stdio.h> 14 15#include <algorithm> 16#include <vector> 17 18#include "webrtc/base/constructormagic.h" 19#include "webrtc/base/scoped_ptr.h" 20#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_fileutils.h" 21#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" 22#include "webrtc/test/testsupport/fileutils.h" 23 24namespace webrtc { 25namespace testing { 26namespace bwe { 27 28// The format of BWE test baseline files is extremely simple: 29// 1. All read/written entities are 32-bit unsigned integers in network byte 30// order (Big Endian). 31// 2. Files beging with a 2 word header containing a magic marker and file 32// format version indicator. The Magic marker reads "BWE!" in a hex dump. 33// 3. Each estimate is logged as a pair of words: time in milliseconds and 34// estimated bit rate, in bits per second. 35const uint32_t kMagicMarker = 0x42574521; 36const uint32_t kFileVersion1 = 0x00000001; 37const char kResourceSubDir[] = "remote_bitrate_estimator"; 38 39class BaseLineFileVerify : public BaseLineFileInterface { 40 public: 41 // If |allow_missing_file| is set, VerifyOrWrite() will return true even if 42 // the baseline file is missing. This is the default when verifying files, but 43 // not when updating (i.e. we always write it out if missing). 44 BaseLineFileVerify(const std::string& filepath, bool allow_missing_file) 45 : reader_(), 46 fail_to_read_response_(false) { 47 rtc::scoped_ptr<ResourceFileReader> reader; 48 reader.reset(ResourceFileReader::Create(filepath, "bin")); 49 if (!reader.get()) { 50 printf("WARNING: Missing baseline file for BWE test: %s.bin\n", 51 filepath.c_str()); 52 fail_to_read_response_ = allow_missing_file; 53 } else { 54 uint32_t magic_marker = 0; 55 uint32_t file_version = 0; 56 if (reader->Read(&magic_marker) && magic_marker == kMagicMarker && 57 reader->Read(&file_version) && file_version == kFileVersion1) { 58 reader_.swap(reader); 59 } else { 60 printf("WARNING: Bad baseline file header for BWE test: %s.bin\n", 61 filepath.c_str()); 62 } 63 } 64 } 65 virtual ~BaseLineFileVerify() {} 66 67 virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) { 68 if (reader_.get()) { 69 uint32_t read_ms = 0; 70 uint32_t read_bps = 0; 71 if (reader_->Read(&read_ms) && read_ms == time_ms && 72 reader_->Read(&read_bps) && read_bps == estimate_bps) { 73 } else { 74 printf("ERROR: Baseline differs starting at: %d ms (%d vs %d)!\n", 75 static_cast<uint32_t>(time_ms), estimate_bps, read_bps); 76 reader_.reset(NULL); 77 } 78 } 79 } 80 81 virtual bool VerifyOrWrite() { 82 if (reader_.get()) { 83 if (reader_->IsAtEnd()) { 84 return true; 85 } else { 86 printf("ERROR: Baseline file contains more data!\n"); 87 return false; 88 } 89 } 90 return fail_to_read_response_; 91 } 92 93 private: 94 rtc::scoped_ptr<ResourceFileReader> reader_; 95 bool fail_to_read_response_; 96 97 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileVerify); 98}; 99 100class BaseLineFileUpdate : public BaseLineFileInterface { 101 public: 102 BaseLineFileUpdate(const std::string& filepath, 103 BaseLineFileInterface* verifier) 104 : verifier_(verifier), 105 output_content_(), 106 filepath_(filepath) { 107 output_content_.push_back(kMagicMarker); 108 output_content_.push_back(kFileVersion1); 109 } 110 virtual ~BaseLineFileUpdate() {} 111 112 virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) { 113 verifier_->Estimate(time_ms, estimate_bps); 114 output_content_.push_back(static_cast<uint32_t>(time_ms)); 115 output_content_.push_back(estimate_bps); 116 } 117 118 virtual bool VerifyOrWrite() { 119 if (!verifier_->VerifyOrWrite()) { 120 std::string dir_path = webrtc::test::OutputPath() + kResourceSubDir; 121 if (!webrtc::test::CreateDir(dir_path)) { 122 printf("WARNING: Cannot create output dir: %s\n", dir_path.c_str()); 123 return false; 124 } 125 rtc::scoped_ptr<OutputFileWriter> writer; 126 writer.reset(OutputFileWriter::Create(filepath_, "bin")); 127 if (!writer.get()) { 128 printf("WARNING: Cannot create output file: %s.bin\n", 129 filepath_.c_str()); 130 return false; 131 } 132 printf("NOTE: Writing baseline file for BWE test: %s.bin\n", 133 filepath_.c_str()); 134 for (std::vector<uint32_t>::iterator it = output_content_.begin(); 135 it != output_content_.end(); ++it) { 136 writer->Write(*it); 137 } 138 return true; 139 } 140 printf("NOTE: No change, not writing: %s\n", filepath_.c_str()); 141 return true; 142 } 143 144 private: 145 rtc::scoped_ptr<BaseLineFileInterface> verifier_; 146 std::vector<uint32_t> output_content_; 147 std::string filepath_; 148 149 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileUpdate); 150}; 151 152BaseLineFileInterface* BaseLineFileInterface::Create( 153 const std::string& filename, bool write_output_file) { 154 std::string filepath = filename; 155 std::replace(filepath.begin(), filepath.end(), '/', '_'); 156 filepath = std::string(kResourceSubDir) + "/" + filepath; 157 158 rtc::scoped_ptr<BaseLineFileInterface> result; 159 result.reset(new BaseLineFileVerify(filepath, !write_output_file)); 160 if (write_output_file) { 161 // Takes ownership of the |verifier| instance. 162 result.reset(new BaseLineFileUpdate(filepath, result.release())); 163 } 164 return result.release(); 165} 166} // namespace bwe 167} // namespace testing 168} // namespace webrtc 169