OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ | 11 #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ |
12 #define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ | 12 #define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ |
13 | 13 |
14 #include <memory> | 14 #include <memory> |
15 #include <string> | 15 #include <string> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 #include "webrtc/api/video/video_frame.h" | 18 #include "webrtc/api/video/video_frame.h" |
19 #include "webrtc/base/buffer.h" | 19 #include "webrtc/base/buffer.h" |
20 #include "webrtc/base/checks.h" | 20 #include "webrtc/base/checks.h" |
| 21 #include "webrtc/base/sequenced_task_checker.h" |
| 22 #include "webrtc/base/task_queue.h" |
21 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 23 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
22 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | |
23 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" | 24 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" |
24 #include "webrtc/modules/video_coding/codecs/test/stats.h" | 25 #include "webrtc/modules/video_coding/codecs/test/stats.h" |
| 26 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
25 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" | 27 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" |
26 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" | 28 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" |
27 #include "webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.h" | 29 #include "webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.h" |
28 #include "webrtc/test/testsupport/frame_reader.h" | 30 #include "webrtc/test/testsupport/frame_reader.h" |
29 #include "webrtc/test/testsupport/frame_writer.h" | 31 #include "webrtc/test/testsupport/frame_writer.h" |
30 | 32 |
31 namespace webrtc { | 33 namespace webrtc { |
32 | 34 |
33 class VideoBitrateAllocator; | 35 class VideoBitrateAllocator; |
34 | 36 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 // Regarding packet loss: Note that keyframes are excluded (first or all | 125 // Regarding packet loss: Note that keyframes are excluded (first or all |
124 // depending on the ExcludeFrameTypes setting). This is because if key frames | 126 // depending on the ExcludeFrameTypes setting). This is because if key frames |
125 // would be altered, all the following delta frames would be pretty much | 127 // would be altered, all the following delta frames would be pretty much |
126 // worthless. VP8 has an error-resilience feature that makes it able to handle | 128 // worthless. VP8 has an error-resilience feature that makes it able to handle |
127 // packet loss in key non-first keyframes, which is why only the first is | 129 // packet loss in key non-first keyframes, which is why only the first is |
128 // excluded by default. | 130 // excluded by default. |
129 // Packet loss in such important frames is handled on a higher level in the | 131 // Packet loss in such important frames is handled on a higher level in the |
130 // Video Engine, where signaling would request a retransmit of the lost packets, | 132 // Video Engine, where signaling would request a retransmit of the lost packets, |
131 // since they're so important. | 133 // since they're so important. |
132 // | 134 // |
133 // Note this class is not thread safe in any way and is meant for simple testing | 135 // This class should be run on a single thread or a task queue. |
134 // purposes. | |
135 class VideoProcessor { | 136 class VideoProcessor { |
136 public: | 137 public: |
137 virtual ~VideoProcessor() {} | 138 virtual ~VideoProcessor() {} |
138 | 139 |
139 // Sets up callbacks and initializes the encoder and decoder. | 140 // Sets up callbacks and initializes the codecs. |
140 virtual void Init() = 0; | 141 virtual void Init() = 0; |
141 | 142 |
| 143 // Deregisters callbacks and releases codecs. |
| 144 // Must only be called after Init() has been called. |
| 145 virtual void Release() = 0; |
| 146 |
142 // Processes a single frame. Returns true as long as there's more frames | 147 // Processes a single frame. Returns true as long as there's more frames |
143 // available in the source clip. | 148 // available in the source clip. Must only be called after Init() has been |
| 149 // called, and before Release() has been called. |
144 // Frame number must be an integer >= 0. | 150 // Frame number must be an integer >= 0. |
145 virtual bool ProcessFrame(int frame_number) = 0; | 151 virtual bool ProcessFrame(int frame_number) = 0; |
146 | 152 |
147 // Updates the encoder with the target bit rate and the frame rate. | 153 // Updates the encoder with the target bit rate and the frame rate. |
148 virtual void SetRates(int bit_rate, int frame_rate) = 0; | 154 virtual void SetRates(int bit_rate, int frame_rate) = 0; |
149 | 155 |
150 // Return the size of the encoded frame in bytes. Dropped frames by the | 156 // Return the size of the encoded frame in bytes. Dropped frames by the |
151 // encoder are regarded as zero size. | 157 // encoder are regarded as zero size. |
152 virtual size_t EncodedFrameSize(int frame_number) = 0; | 158 virtual size_t EncodedFrameSize(int frame_number) = 0; |
153 | 159 |
(...skipping 18 matching lines...) Expand all Loading... |
172 VideoProcessorImpl(webrtc::VideoEncoder* encoder, | 178 VideoProcessorImpl(webrtc::VideoEncoder* encoder, |
173 webrtc::VideoDecoder* decoder, | 179 webrtc::VideoDecoder* decoder, |
174 FrameReader* analysis_frame_reader, | 180 FrameReader* analysis_frame_reader, |
175 FrameWriter* analysis_frame_writer, | 181 FrameWriter* analysis_frame_writer, |
176 PacketManipulator* packet_manipulator, | 182 PacketManipulator* packet_manipulator, |
177 const TestConfig& config, | 183 const TestConfig& config, |
178 Stats* stats, | 184 Stats* stats, |
179 FrameWriter* source_frame_writer, | 185 FrameWriter* source_frame_writer, |
180 IvfFileWriter* encoded_frame_writer, | 186 IvfFileWriter* encoded_frame_writer, |
181 FrameWriter* decoded_frame_writer); | 187 FrameWriter* decoded_frame_writer); |
182 virtual ~VideoProcessorImpl(); | 188 ~VideoProcessorImpl() override; |
183 void Init() override; | |
184 bool ProcessFrame(int frame_number) override; | |
185 | 189 |
186 private: | 190 private: |
187 // Container that holds per-frame information that needs to be stored between | 191 // Container that holds per-frame information that needs to be stored between |
188 // calls to Encode and Decode, as well as the corresponding callbacks. It is | 192 // calls to Encode and Decode, as well as the corresponding callbacks. It is |
189 // not directly used for statistics -- for that, test::FrameStatistic is used. | 193 // not directly used for statistics -- for that, test::FrameStatistic is used. |
190 struct FrameInfo { | 194 struct FrameInfo { |
191 FrameInfo() | 195 FrameInfo() |
192 : timestamp(0), | 196 : encode_start_ns(0), |
193 encode_start_ns(0), | |
194 decode_start_ns(0), | 197 decode_start_ns(0), |
195 encoded_frame_size(0), | 198 encoded_frame_size(0), |
196 encoded_frame_type(kVideoFrameDelta), | 199 encoded_frame_type(kVideoFrameDelta), |
197 decoded_width(0), | 200 decoded_width(0), |
198 decoded_height(0), | 201 decoded_height(0), |
199 manipulated_length(0), | 202 manipulated_length(0), |
200 qp_encoder(0), | 203 qp_encoder(0), |
201 qp_bitstream(0) {} | 204 qp_bitstream(0) {} |
202 | 205 |
203 uint32_t timestamp; | |
204 int64_t encode_start_ns; | 206 int64_t encode_start_ns; |
205 int64_t decode_start_ns; | 207 int64_t decode_start_ns; |
206 size_t encoded_frame_size; | 208 size_t encoded_frame_size; |
207 FrameType encoded_frame_type; | 209 FrameType encoded_frame_type; |
208 int decoded_width; | 210 int decoded_width; |
209 int decoded_height; | 211 int decoded_height; |
210 size_t manipulated_length; | 212 size_t manipulated_length; |
211 int qp_encoder; | 213 int qp_encoder; |
212 int qp_bitstream; | 214 int qp_bitstream; |
213 }; | 215 }; |
214 | 216 |
215 // Callback class required to implement according to the VideoEncoder API. | 217 // Callback adapter class for encoder callback. |
| 218 // Will post the callback on the task queue it was created on, if such a |
| 219 // queue exists. |
216 class VideoProcessorEncodeCompleteCallback | 220 class VideoProcessorEncodeCompleteCallback |
217 : public webrtc::EncodedImageCallback { | 221 : public webrtc::EncodedImageCallback { |
218 public: | 222 public: |
219 explicit VideoProcessorEncodeCompleteCallback(VideoProcessorImpl* vp) | 223 explicit VideoProcessorEncodeCompleteCallback( |
220 : video_processor_(vp) {} | 224 VideoProcessorImpl* video_processor) |
| 225 : video_processor_(video_processor), |
| 226 task_queue_(rtc::TaskQueue::Current()) {} |
| 227 |
221 Result OnEncodedImage( | 228 Result OnEncodedImage( |
222 const webrtc::EncodedImage& encoded_image, | 229 const webrtc::EncodedImage& encoded_image, |
223 const webrtc::CodecSpecificInfo* codec_specific_info, | 230 const webrtc::CodecSpecificInfo* codec_specific_info, |
224 const webrtc::RTPFragmentationHeader* fragmentation) override { | 231 const webrtc::RTPFragmentationHeader* fragmentation) override { |
225 // Forward to parent class. | |
226 RTC_CHECK(codec_specific_info); | 232 RTC_CHECK(codec_specific_info); |
| 233 |
| 234 if (task_queue_ && !task_queue_->IsCurrent()) { |
| 235 task_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>( |
| 236 new EncodeCallbackTask(video_processor_, encoded_image, |
| 237 codec_specific_info, fragmentation))); |
| 238 return Result(Result::OK, 0); |
| 239 } |
| 240 |
227 video_processor_->FrameEncoded(codec_specific_info->codecType, | 241 video_processor_->FrameEncoded(codec_specific_info->codecType, |
228 encoded_image, fragmentation); | 242 encoded_image, fragmentation); |
229 return Result(Result::OK, 0); | 243 return Result(Result::OK, 0); |
230 } | 244 } |
231 | 245 |
232 private: | 246 private: |
| 247 class EncodeCallbackTask : public rtc::QueuedTask { |
| 248 public: |
| 249 EncodeCallbackTask(VideoProcessorImpl* video_processor, |
| 250 const webrtc::EncodedImage& encoded_image, |
| 251 const webrtc::CodecSpecificInfo* codec_specific_info, |
| 252 const webrtc::RTPFragmentationHeader* fragmentation) |
| 253 : video_processor_(video_processor), |
| 254 buffer_(encoded_image._buffer, encoded_image._length), |
| 255 encoded_image_(encoded_image), |
| 256 codec_specific_info_(*codec_specific_info) { |
| 257 encoded_image_._buffer = buffer_.data(); |
| 258 RTC_CHECK(fragmentation); |
| 259 fragmentation_.CopyFrom(*fragmentation); |
| 260 } |
| 261 |
| 262 bool Run() override { |
| 263 video_processor_->FrameEncoded(codec_specific_info_.codecType, |
| 264 encoded_image_, &fragmentation_); |
| 265 return true; |
| 266 } |
| 267 |
| 268 private: |
| 269 VideoProcessorImpl* const video_processor_; |
| 270 rtc::Buffer buffer_; |
| 271 webrtc::EncodedImage encoded_image_; |
| 272 const webrtc::CodecSpecificInfo codec_specific_info_; |
| 273 webrtc::RTPFragmentationHeader fragmentation_; |
| 274 }; |
| 275 |
233 VideoProcessorImpl* const video_processor_; | 276 VideoProcessorImpl* const video_processor_; |
| 277 rtc::TaskQueue* const task_queue_; |
234 }; | 278 }; |
235 | 279 |
236 // Callback class required to implement according to the VideoDecoder API. | 280 // Callback adapter class for decoder callback. |
| 281 // Will post the callback on the task queue it was created on, if such a |
| 282 // queue exists. |
237 class VideoProcessorDecodeCompleteCallback | 283 class VideoProcessorDecodeCompleteCallback |
238 : public webrtc::DecodedImageCallback { | 284 : public webrtc::DecodedImageCallback { |
239 public: | 285 public: |
240 explicit VideoProcessorDecodeCompleteCallback(VideoProcessorImpl* vp) | 286 explicit VideoProcessorDecodeCompleteCallback( |
241 : video_processor_(vp) {} | 287 VideoProcessorImpl* video_processor) |
| 288 : video_processor_(video_processor), |
| 289 task_queue_(rtc::TaskQueue::Current()) {} |
| 290 |
242 int32_t Decoded(webrtc::VideoFrame& image) override { | 291 int32_t Decoded(webrtc::VideoFrame& image) override { |
243 // Forward to parent class. | 292 if (task_queue_ && !task_queue_->IsCurrent()) { |
| 293 task_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>( |
| 294 new DecodeCallbackTask(video_processor_, image))); |
| 295 return 0; |
| 296 } |
| 297 |
244 video_processor_->FrameDecoded(image); | 298 video_processor_->FrameDecoded(image); |
245 return 0; | 299 return 0; |
246 } | 300 } |
| 301 |
247 int32_t Decoded(webrtc::VideoFrame& image, | 302 int32_t Decoded(webrtc::VideoFrame& image, |
248 int64_t decode_time_ms) override { | 303 int64_t decode_time_ms) override { |
249 return Decoded(image); | 304 return Decoded(image); |
250 } | 305 } |
| 306 |
251 void Decoded(webrtc::VideoFrame& image, | 307 void Decoded(webrtc::VideoFrame& image, |
252 rtc::Optional<int32_t> decode_time_ms, | 308 rtc::Optional<int32_t> decode_time_ms, |
253 rtc::Optional<uint8_t> qp) override { | 309 rtc::Optional<uint8_t> qp) override { |
254 Decoded(image, | 310 Decoded(image); |
255 decode_time_ms ? static_cast<int32_t>(*decode_time_ms) : -1); | |
256 } | 311 } |
257 | 312 |
258 private: | 313 private: |
| 314 class DecodeCallbackTask : public rtc::QueuedTask { |
| 315 public: |
| 316 DecodeCallbackTask(VideoProcessorImpl* video_processor, |
| 317 const webrtc::VideoFrame& image) |
| 318 : video_processor_(video_processor), image_(image) {} |
| 319 |
| 320 bool Run() override { |
| 321 video_processor_->FrameDecoded(image_); |
| 322 return true; |
| 323 } |
| 324 |
| 325 private: |
| 326 VideoProcessorImpl* const video_processor_; |
| 327 webrtc::VideoFrame image_; |
| 328 }; |
| 329 |
259 VideoProcessorImpl* const video_processor_; | 330 VideoProcessorImpl* const video_processor_; |
| 331 rtc::TaskQueue* const task_queue_; |
260 }; | 332 }; |
261 | 333 |
| 334 // Implements VideoProcessor. |
| 335 void Init() override; |
| 336 void Release() override; |
| 337 bool ProcessFrame(int frame_number) override; |
| 338 void SetRates(int bit_rate, int frame_rate) override; |
| 339 size_t EncodedFrameSize(int frame_number) override; |
| 340 FrameType EncodedFrameType(int frame_number) override; |
| 341 int GetQpFromEncoder(int frame_number) override; |
| 342 int GetQpFromBitstream(int frame_number) override; |
| 343 int NumberDroppedFrames() override; |
| 344 int NumberSpatialResizes() override; |
| 345 |
262 // Invoked by the callback when a frame has completed encoding. | 346 // Invoked by the callback when a frame has completed encoding. |
263 void FrameEncoded(webrtc::VideoCodecType codec, | 347 void FrameEncoded(webrtc::VideoCodecType codec, |
264 const webrtc::EncodedImage& encodedImage, | 348 const webrtc::EncodedImage& encodedImage, |
265 const webrtc::RTPFragmentationHeader* fragmentation); | 349 const webrtc::RTPFragmentationHeader* fragmentation); |
266 | 350 |
267 // Invoked by the callback when a frame has completed decoding. | 351 // Invoked by the callback when a frame has completed decoding. |
268 void FrameDecoded(const webrtc::VideoFrame& image); | 352 void FrameDecoded(const webrtc::VideoFrame& image); |
269 | 353 |
270 // Updates the encoder with the target bit rate and the frame rate. | 354 webrtc::VideoEncoder* const encoder_ PT_GUARDED_BY(task_checker_); |
271 void SetRates(int bit_rate, int frame_rate) override; | 355 webrtc::VideoDecoder* const decoder_ PT_GUARDED_BY(task_checker_); |
272 | 356 const std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_ |
273 // Return the size of the encoded frame in bytes. | 357 PT_GUARDED_BY(task_checker_); |
274 size_t EncodedFrameSize(int frame_number) override; | |
275 | |
276 // Return the encoded frame type (key or delta). | |
277 FrameType EncodedFrameType(int frame_number) override; | |
278 | |
279 // Return the qp used by encoder. | |
280 int GetQpFromEncoder(int frame_number) override; | |
281 | |
282 // Return the qp from the qp parser. | |
283 int GetQpFromBitstream(int frame_number) override; | |
284 | |
285 // Return the number of dropped frames. | |
286 int NumberDroppedFrames() override; | |
287 | |
288 // Return the number of spatial resizes. | |
289 int NumberSpatialResizes() override; | |
290 | |
291 webrtc::VideoEncoder* const encoder_; | |
292 webrtc::VideoDecoder* const decoder_; | |
293 const std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_; | |
294 | 358 |
295 // Adapters for the codec callbacks. | 359 // Adapters for the codec callbacks. |
296 const std::unique_ptr<EncodedImageCallback> encode_callback_; | 360 std::unique_ptr<EncodedImageCallback> encode_callback_ |
297 const std::unique_ptr<DecodedImageCallback> decode_callback_; | 361 GUARDED_BY(task_checker_); |
| 362 std::unique_ptr<DecodedImageCallback> decode_callback_ |
| 363 GUARDED_BY(task_checker_); |
298 | 364 |
299 PacketManipulator* const packet_manipulator_; | 365 PacketManipulator* const packet_manipulator_ PT_GUARDED_BY(task_checker_); |
300 const TestConfig& config_; | 366 const TestConfig& config_; |
301 | 367 |
302 // These (mandatory) file manipulators are used for, e.g., objective PSNR and | 368 // These (mandatory) file manipulators are used for, e.g., objective PSNR and |
303 // SSIM calculations at the end of a test run. | 369 // SSIM calculations at the end of a test run. |
304 FrameReader* const analysis_frame_reader_; | 370 FrameReader* const analysis_frame_reader_ PT_GUARDED_BY(task_checker_); |
305 FrameWriter* const analysis_frame_writer_; | 371 FrameWriter* const analysis_frame_writer_ PT_GUARDED_BY(task_checker_); |
| 372 const int num_frames_; |
306 | 373 |
307 // These (optional) file writers are used for persistently storing the output | 374 // These (optional) file writers are used for persistently storing the output |
308 // of the coding pipeline at different stages: pre encode (source), post | 375 // of the coding pipeline at different stages: pre encode (source), post |
309 // encode (encoded), and post decode (decoded). The purpose is to give the | 376 // encode (encoded), and post decode (decoded). The purpose is to give the |
310 // experimenter an option to subjectively evaluate the quality of the | 377 // experimenter an option to subjectively evaluate the quality of the |
311 // encoding, given the test settings. Each frame writer is enabled by being | 378 // encoding, given the test settings. Each frame writer is enabled by being |
312 // non-null. | 379 // non-null. |
313 FrameWriter* const source_frame_writer_; | 380 FrameWriter* const source_frame_writer_ PT_GUARDED_BY(task_checker_); |
314 IvfFileWriter* const encoded_frame_writer_; | 381 IvfFileWriter* const encoded_frame_writer_ PT_GUARDED_BY(task_checker_); |
315 FrameWriter* const decoded_frame_writer_; | 382 FrameWriter* const decoded_frame_writer_ PT_GUARDED_BY(task_checker_); |
316 | 383 |
317 bool initialized_; | 384 bool initialized_ GUARDED_BY(task_checker_); |
318 | 385 |
319 // Frame metadata for all frames that have been added through a call to | 386 // Frame metadata for all frames that have been added through a call to |
320 // ProcessFrames(). We need to store this metadata over the course of the | 387 // ProcessFrames(). We need to store this metadata over the course of the |
321 // test run, to support pipelining HW codecs. | 388 // test run, to support pipelining HW codecs. |
322 std::vector<FrameInfo> frame_infos_; | 389 std::vector<FrameInfo> frame_infos_ GUARDED_BY(task_checker_); |
323 int last_encoded_frame_num_; | 390 int last_inputed_frame_num_ GUARDED_BY(task_checker_); |
324 int last_decoded_frame_num_; | 391 int last_encoded_frame_num_ GUARDED_BY(task_checker_); |
| 392 int last_decoded_frame_num_ GUARDED_BY(task_checker_); |
325 | 393 |
326 // Keep track of if we have excluded the first key frame from packet loss. | 394 // Keep track of if we have excluded the first key frame from packet loss. |
327 bool first_key_frame_has_been_excluded_; | 395 bool first_key_frame_has_been_excluded_ GUARDED_BY(task_checker_); |
328 | 396 |
329 // Keep track of the last successfully decoded frame, since we write that | 397 // Keep track of the last successfully decoded frame, since we write that |
330 // frame to disk when decoding fails. | 398 // frame to disk when decoding fails. |
331 rtc::Buffer last_decoded_frame_buffer_; | 399 rtc::Buffer last_decoded_frame_buffer_ GUARDED_BY(task_checker_); |
332 | 400 |
333 // Statistics. | 401 // Statistics. |
334 Stats* stats_; | 402 Stats* stats_ PT_GUARDED_BY(task_checker_); |
335 int num_dropped_frames_; | 403 int num_dropped_frames_ GUARDED_BY(task_checker_); |
336 int num_spatial_resizes_; | 404 int num_spatial_resizes_ GUARDED_BY(task_checker_); |
| 405 |
| 406 rtc::SequencedTaskChecker task_checker_; |
337 }; | 407 }; |
338 | 408 |
339 } // namespace test | 409 } // namespace test |
340 } // namespace webrtc | 410 } // namespace webrtc |
341 | 411 |
342 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ | 412 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ |
OLD | NEW |