1 /* 2 * Copyright (c) 2012 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 #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ 12 #define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ 13 14 #include <string> 15 16 #include "webrtc/common_video/interface/i420_video_frame.h" 17 #include "webrtc/common_video/libyuv/include/scaler.h" 18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 19 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" 20 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" 21 #include "webrtc/modules/video_coding/codecs/test/stats.h" 22 #include "webrtc/system_wrappers/interface/tick_util.h" 23 #include "webrtc/test/testsupport/frame_reader.h" 24 #include "webrtc/test/testsupport/frame_writer.h" 25 26 namespace webrtc { 27 namespace test { 28 29 // Defines which frame types shall be excluded from packet loss and when. 30 enum ExcludeFrameTypes { 31 // Will exclude the first keyframe in the video sequence from packet loss. 32 // Following keyframes will be targeted for packet loss. 33 kExcludeOnlyFirstKeyFrame, 34 // Exclude all keyframes from packet loss, no matter where in the video 35 // sequence they occur. 36 kExcludeAllKeyFrames 37 }; 38 // Returns a string representation of the enum value. 39 const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e); 40 41 // Test configuration for a test run 42 struct TestConfig { 43 TestConfig(); 44 ~TestConfig(); 45 46 // Name of the test. This is purely metadata and does not affect 47 // the test in any way. 48 std::string name; 49 50 // More detailed description of the test. This is purely metadata and does 51 // not affect the test in any way. 52 std::string description; 53 54 // Number of this test. Useful if multiple runs of the same test with 55 // different configurations shall be managed. 56 int test_number; 57 58 // File to process for the test. This must be a video file in the YUV format. 59 std::string input_filename; 60 61 // File to write to during processing for the test. Will be a video file 62 // in the YUV format. 63 std::string output_filename; 64 65 // Path to the directory where encoded files will be put 66 // (absolute or relative to the executable). Default: "out". 67 std::string output_dir; 68 69 // Configurations related to networking. 70 NetworkingConfig networking_config; 71 72 // Decides how the packet loss simulations shall exclude certain frames 73 // from packet loss. Default: kExcludeOnlyFirstKeyFrame. 74 ExcludeFrameTypes exclude_frame_types; 75 76 // The length of a single frame of the input video file. This value is 77 // calculated out of the width and height according to the video format 78 // specification. Must be set before processing. 79 int frame_length_in_bytes; 80 81 // Force the encoder and decoder to use a single core for processing. 82 // Using a single core is necessary to get a deterministic behavior for the 83 // encoded frames - using multiple cores will produce different encoded frames 84 // since multiple cores are competing to consume the byte budget for each 85 // frame in parallel. 86 // If set to false, the maximum number of available cores will be used. 87 // Default: false. 88 bool use_single_core; 89 90 // If set to a value >0 this setting forces the encoder to create a keyframe 91 // every Nth frame. Note that the encoder may create a keyframe in other 92 // locations in addition to the interval that is set using this parameter. 93 // Forcing key frames may also affect encoder planning optimizations in 94 // a negative way, since it will suddenly be forced to produce an expensive 95 // key frame. 96 // Default: 0. 97 int keyframe_interval; 98 99 // The codec settings to use for the test (target bitrate, video size, 100 // framerate and so on). This struct must be created and filled in using 101 // the VideoCodingModule::Codec() method. 102 webrtc::VideoCodec* codec_settings; 103 104 // If printing of information to stdout shall be performed during processing. 105 bool verbose; 106 }; 107 108 // Returns a string representation of the enum value. 109 const char* VideoCodecTypeToStr(webrtc::VideoCodecType e); 110 111 // Handles encoding/decoding of video using the VideoEncoder/VideoDecoder 112 // interfaces. This is done in a sequential manner in order to be able to 113 // measure times properly. 114 // The class processes a frame at the time for the configured input file. 115 // It maintains state of where in the source input file the processing is at. 116 // 117 // Regarding packet loss: Note that keyframes are excluded (first or all 118 // depending on the ExcludeFrameTypes setting). This is because if key frames 119 // would be altered, all the following delta frames would be pretty much 120 // worthless. VP8 has an error-resilience feature that makes it able to handle 121 // packet loss in key non-first keyframes, which is why only the first is 122 // excluded by default. 123 // Packet loss in such important frames is handled on a higher level in the 124 // Video Engine, where signaling would request a retransmit of the lost packets, 125 // since they're so important. 126 // 127 // Note this class is not thread safe in any way and is meant for simple testing 128 // purposes. 129 class VideoProcessor { 130 public: 131 virtual ~VideoProcessor() {} 132 133 // Performs initial calculations about frame size, sets up callbacks etc. 134 // Returns false if an error has occurred, in addition to printing to stderr. 135 virtual bool Init() = 0; 136 137 // Processes a single frame. Returns true as long as there's more frames 138 // available in the source clip. 139 // Frame number must be an integer >=0. 140 virtual bool ProcessFrame(int frame_number) = 0; 141 142 // Updates the encoder with the target bit rate and the frame rate. 143 virtual void SetRates(int bit_rate, int frame_rate) = 0; 144 145 // Return the size of the encoded frame in bytes. Dropped frames by the 146 // encoder are regarded as zero size. 147 virtual int EncodedFrameSize() = 0; 148 149 // Return the number of dropped frames. 150 virtual int NumberDroppedFrames() = 0; 151 152 // Return the number of spatial resizes. 153 virtual int NumberSpatialResizes() = 0; 154 }; 155 156 class VideoProcessorImpl : public VideoProcessor { 157 public: 158 VideoProcessorImpl(webrtc::VideoEncoder* encoder, 159 webrtc::VideoDecoder* decoder, 160 FrameReader* frame_reader, 161 FrameWriter* frame_writer, 162 PacketManipulator* packet_manipulator, 163 const TestConfig& config, 164 Stats* stats); 165 virtual ~VideoProcessorImpl(); 166 virtual bool Init() OVERRIDE; 167 virtual bool ProcessFrame(int frame_number) OVERRIDE; 168 169 private: 170 // Invoked by the callback when a frame has completed encoding. 171 void FrameEncoded(webrtc::EncodedImage* encodedImage); 172 // Invoked by the callback when a frame has completed decoding. 173 void FrameDecoded(const webrtc::I420VideoFrame& image); 174 // Used for getting a 32-bit integer representing time 175 // (checks the size is within signed 32-bit bounds before casting it) 176 int GetElapsedTimeMicroseconds(const webrtc::TickTime& start, 177 const webrtc::TickTime& stop); 178 // Updates the encoder with the target bit rate and the frame rate. 179 virtual void SetRates(int bit_rate, int frame_rate) OVERRIDE; 180 // Return the size of the encoded frame in bytes. 181 virtual int EncodedFrameSize() OVERRIDE; 182 // Return the number of dropped frames. 183 virtual int NumberDroppedFrames() OVERRIDE; 184 // Return the number of spatial resizes. 185 virtual int NumberSpatialResizes() OVERRIDE; 186 187 webrtc::VideoEncoder* encoder_; 188 webrtc::VideoDecoder* decoder_; 189 FrameReader* frame_reader_; 190 FrameWriter* frame_writer_; 191 PacketManipulator* packet_manipulator_; 192 const TestConfig& config_; 193 Stats* stats_; 194 195 EncodedImageCallback* encode_callback_; 196 DecodedImageCallback* decode_callback_; 197 // Buffer used for reading the source video file: 198 uint8_t* source_buffer_; 199 // Keep track of the last successful frame, since we need to write that 200 // when decoding fails: 201 uint8_t* last_successful_frame_buffer_; 202 webrtc::I420VideoFrame source_frame_; 203 // To keep track of if we have excluded the first key frame from packet loss: 204 bool first_key_frame_has_been_excluded_; 205 // To tell the decoder previous frame have been dropped due to packet loss: 206 bool last_frame_missing_; 207 // If Init() has executed successfully. 208 bool initialized_; 209 int encoded_frame_size_; 210 int prev_time_stamp_; 211 int num_dropped_frames_; 212 int num_spatial_resizes_; 213 int last_encoder_frame_width_; 214 int last_encoder_frame_height_; 215 Scaler scaler_; 216 217 // Statistics 218 double bit_rate_factor_; // multiply frame length with this to get bit rate 219 webrtc::TickTime encode_start_; 220 webrtc::TickTime decode_start_; 221 222 // Callback class required to implement according to the VideoEncoder API. 223 class VideoProcessorEncodeCompleteCallback 224 : public webrtc::EncodedImageCallback { 225 public: 226 explicit VideoProcessorEncodeCompleteCallback(VideoProcessorImpl* vp) 227 : video_processor_(vp) {} 228 virtual int32_t Encoded( 229 webrtc::EncodedImage& encoded_image, 230 const webrtc::CodecSpecificInfo* codec_specific_info = NULL, 231 const webrtc::RTPFragmentationHeader* fragmentation = NULL) OVERRIDE; 232 233 private: 234 VideoProcessorImpl* video_processor_; 235 }; 236 237 // Callback class required to implement according to the VideoDecoder API. 238 class VideoProcessorDecodeCompleteCallback 239 : public webrtc::DecodedImageCallback { 240 public: 241 explicit VideoProcessorDecodeCompleteCallback(VideoProcessorImpl* vp) 242 : video_processor_(vp) { 243 } 244 virtual int32_t Decoded(webrtc::I420VideoFrame& image) OVERRIDE; 245 246 private: 247 VideoProcessorImpl* video_processor_; 248 }; 249 }; 250 251 } // namespace test 252 } // namespace webrtc 253 254 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ 255