| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 (width_ + 1) / 2); | 79 (width_ + 1) / 2); |
| 80 return frame_.get(); | 80 return frame_.get(); |
| 81 } | 81 } |
| 82 | 82 |
| 83 private: | 83 private: |
| 84 const int width_; | 84 const int width_; |
| 85 const int height_; | 85 const int height_; |
| 86 std::unique_ptr<VideoFrame> frame_; | 86 std::unique_ptr<VideoFrame> frame_; |
| 87 }; | 87 }; |
| 88 | 88 |
| 89 class PacketizationCallback : public VCMPacketizationCallback { | 89 class EncodedImageCallbackImpl : public EncodedImageCallback { |
| 90 public: | 90 public: |
| 91 explicit PacketizationCallback(Clock* clock) | 91 explicit EncodedImageCallbackImpl(Clock* clock) |
| 92 : clock_(clock), start_time_ms_(clock_->TimeInMilliseconds()) {} | 92 : clock_(clock), start_time_ms_(clock_->TimeInMilliseconds()) {} |
| 93 | 93 |
| 94 virtual ~PacketizationCallback() {} | 94 virtual ~EncodedImageCallbackImpl() {} |
| 95 | 95 |
| 96 int32_t SendData(uint8_t payload_type, | 96 int32_t Encoded(const EncodedImage& encoded_image, |
| 97 const EncodedImage& encoded_image, | 97 const CodecSpecificInfo* codec_specific_info, |
| 98 const RTPFragmentationHeader* fragmentation_header, | 98 const RTPFragmentationHeader* fragmentation) override { |
| 99 const RTPVideoHeader* rtp_video_header) override { | 99 assert(codec_specific_info); |
| 100 assert(rtp_video_header); | 100 frame_data_.push_back( |
| 101 frame_data_.push_back(FrameData(encoded_image._length, *rtp_video_header)); | 101 FrameData(encoded_image._length, *codec_specific_info)); |
| 102 return 0; | 102 return 0; |
| 103 } | 103 } |
| 104 | 104 |
| 105 void Reset() { | 105 void Reset() { |
| 106 frame_data_.clear(); | 106 frame_data_.clear(); |
| 107 start_time_ms_ = clock_->TimeInMilliseconds(); | 107 start_time_ms_ = clock_->TimeInMilliseconds(); |
| 108 } | 108 } |
| 109 | 109 |
| 110 float FramerateFpsWithinTemporalLayer(int temporal_layer) { | 110 float FramerateFpsWithinTemporalLayer(int temporal_layer) { |
| 111 return CountFramesWithinTemporalLayer(temporal_layer) * | 111 return CountFramesWithinTemporalLayer(temporal_layer) * |
| (...skipping 11 matching lines...) Expand all Loading... |
| 123 info.framerate_fps[tl] = FramerateFpsWithinTemporalLayer(tl); | 123 info.framerate_fps[tl] = FramerateFpsWithinTemporalLayer(tl); |
| 124 info.bitrate_kbps[tl] = BitrateKbpsWithinTemporalLayer(tl); | 124 info.bitrate_kbps[tl] = BitrateKbpsWithinTemporalLayer(tl); |
| 125 } | 125 } |
| 126 return info; | 126 return info; |
| 127 } | 127 } |
| 128 | 128 |
| 129 private: | 129 private: |
| 130 struct FrameData { | 130 struct FrameData { |
| 131 FrameData() {} | 131 FrameData() {} |
| 132 | 132 |
| 133 FrameData(size_t payload_size, const RTPVideoHeader& rtp_video_header) | 133 FrameData(size_t payload_size, const CodecSpecificInfo& codec_specific_info) |
| 134 : payload_size(payload_size), rtp_video_header(rtp_video_header) {} | 134 : payload_size(payload_size), |
| 135 codec_specific_info(codec_specific_info) {} |
| 135 | 136 |
| 136 size_t payload_size; | 137 size_t payload_size; |
| 137 RTPVideoHeader rtp_video_header; | 138 CodecSpecificInfo codec_specific_info; |
| 138 }; | 139 }; |
| 139 | 140 |
| 140 int64_t interval_ms() { | 141 int64_t interval_ms() { |
| 141 int64_t diff = (clock_->TimeInMilliseconds() - start_time_ms_); | 142 int64_t diff = (clock_->TimeInMilliseconds() - start_time_ms_); |
| 142 EXPECT_GT(diff, 0); | 143 EXPECT_GT(diff, 0); |
| 143 return diff; | 144 return diff; |
| 144 } | 145 } |
| 145 | 146 |
| 146 int CountFramesWithinTemporalLayer(int temporal_layer) { | 147 int CountFramesWithinTemporalLayer(int temporal_layer) { |
| 147 int frames = 0; | 148 int frames = 0; |
| 148 for (size_t i = 0; i < frame_data_.size(); ++i) { | 149 for (size_t i = 0; i < frame_data_.size(); ++i) { |
| 149 EXPECT_EQ(kRtpVideoVp8, frame_data_[i].rtp_video_header.codec); | 150 EXPECT_EQ(kVideoCodecVP8, frame_data_[i].codec_specific_info.codecType); |
| 150 const uint8_t temporal_idx = | 151 const uint8_t temporal_idx = |
| 151 frame_data_[i].rtp_video_header.codecHeader.VP8.temporalIdx; | 152 frame_data_[i].codec_specific_info.codecSpecific.VP8.temporalIdx; |
| 152 if (temporal_idx <= temporal_layer || temporal_idx == kNoTemporalIdx) | 153 if (temporal_idx <= temporal_layer || temporal_idx == kNoTemporalIdx) |
| 153 frames++; | 154 frames++; |
| 154 } | 155 } |
| 155 return frames; | 156 return frames; |
| 156 } | 157 } |
| 157 | 158 |
| 158 size_t SumPayloadBytesWithinTemporalLayer(int temporal_layer) { | 159 size_t SumPayloadBytesWithinTemporalLayer(int temporal_layer) { |
| 159 size_t payload_size = 0; | 160 size_t payload_size = 0; |
| 160 for (size_t i = 0; i < frame_data_.size(); ++i) { | 161 for (size_t i = 0; i < frame_data_.size(); ++i) { |
| 161 EXPECT_EQ(kRtpVideoVp8, frame_data_[i].rtp_video_header.codec); | 162 EXPECT_EQ(kVideoCodecVP8, frame_data_[i].codec_specific_info.codecType); |
| 162 const uint8_t temporal_idx = | 163 const uint8_t temporal_idx = |
| 163 frame_data_[i].rtp_video_header.codecHeader.VP8.temporalIdx; | 164 frame_data_[i].codec_specific_info.codecSpecific.VP8.temporalIdx; |
| 164 if (temporal_idx <= temporal_layer || temporal_idx == kNoTemporalIdx) | 165 if (temporal_idx <= temporal_layer || temporal_idx == kNoTemporalIdx) |
| 165 payload_size += frame_data_[i].payload_size; | 166 payload_size += frame_data_[i].payload_size; |
| 166 } | 167 } |
| 167 return payload_size; | 168 return payload_size; |
| 168 } | 169 } |
| 169 | 170 |
| 170 Clock* clock_; | 171 Clock* clock_; |
| 171 int64_t start_time_ms_; | 172 int64_t start_time_ms_; |
| 172 vector<FrameData> frame_data_; | 173 vector<FrameData> frame_data_; |
| 173 }; | 174 }; |
| 174 | 175 |
| 175 class TestVideoSender : public ::testing::Test { | 176 class TestVideoSender : public ::testing::Test { |
| 176 protected: | 177 protected: |
| 177 // Note: simulated clock starts at 1 seconds, since parts of webrtc use 0 as | 178 // Note: simulated clock starts at 1 seconds, since parts of webrtc use 0 as |
| 178 // a special case (e.g. frame rate in media optimization). | 179 // a special case (e.g. frame rate in media optimization). |
| 179 TestVideoSender() : clock_(1000), packetization_callback_(&clock_) {} | 180 TestVideoSender() : clock_(1000), encoded_frame_callback_(&clock_) {} |
| 180 | 181 |
| 181 void SetUp() override { | 182 void SetUp() override { |
| 182 sender_.reset( | 183 sender_.reset( |
| 183 new VideoSender(&clock_, &post_encode_callback_, nullptr, nullptr)); | 184 new VideoSender(&clock_, &encoded_frame_callback_, nullptr, nullptr)); |
| 184 EXPECT_EQ(0, sender_->RegisterTransportCallback(&packetization_callback_)); | |
| 185 } | 185 } |
| 186 | 186 |
| 187 void AddFrame() { | 187 void AddFrame() { |
| 188 assert(generator_.get()); | 188 assert(generator_.get()); |
| 189 sender_->AddVideoFrame(*generator_->NextFrame(), NULL, NULL); | 189 sender_->AddVideoFrame(*generator_->NextFrame(), NULL, NULL); |
| 190 } | 190 } |
| 191 | 191 |
| 192 SimulatedClock clock_; | 192 SimulatedClock clock_; |
| 193 PacketizationCallback packetization_callback_; | 193 EncodedImageCallbackImpl encoded_frame_callback_; |
| 194 MockEncodedImageCallback post_encode_callback_; | |
| 195 // Used by subclassing tests, need to outlive sender_. | 194 // Used by subclassing tests, need to outlive sender_. |
| 196 std::unique_ptr<VideoEncoder> encoder_; | 195 std::unique_ptr<VideoEncoder> encoder_; |
| 197 std::unique_ptr<VideoSender> sender_; | 196 std::unique_ptr<VideoSender> sender_; |
| 198 std::unique_ptr<FrameGenerator> generator_; | 197 std::unique_ptr<FrameGenerator> generator_; |
| 199 }; | 198 }; |
| 200 | 199 |
| 201 class TestVideoSenderWithMockEncoder : public TestVideoSender { | 200 class TestVideoSenderWithMockEncoder : public TestVideoSender { |
| 202 protected: | 201 protected: |
| 203 void SetUp() override { | 202 void SetUp() override { |
| 204 TestVideoSender::SetUp(); | 203 TestVideoSender::SetUp(); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 VideoCodingModule::Codec(kVideoCodecVP8, &codec); | 407 VideoCodingModule::Codec(kVideoCodecVP8, &codec); |
| 409 codec.width = width; | 408 codec.width = width; |
| 410 codec.height = height; | 409 codec.height = height; |
| 411 codec.codecSpecific.VP8.numberOfTemporalLayers = temporal_layers; | 410 codec.codecSpecific.VP8.numberOfTemporalLayers = temporal_layers; |
| 412 return codec; | 411 return codec; |
| 413 } | 412 } |
| 414 | 413 |
| 415 void InsertFrames(float framerate, float seconds) { | 414 void InsertFrames(float framerate, float seconds) { |
| 416 for (int i = 0; i < seconds * framerate; ++i) { | 415 for (int i = 0; i < seconds * framerate; ++i) { |
| 417 clock_.AdvanceTimeMilliseconds(1000.0f / framerate); | 416 clock_.AdvanceTimeMilliseconds(1000.0f / framerate); |
| 418 EXPECT_CALL(post_encode_callback_, Encoded(_, NULL, NULL)) | |
| 419 .WillOnce(Return(0)); | |
| 420 AddFrame(); | 417 AddFrame(); |
| 421 // SetChannelParameters needs to be called frequently to propagate | 418 // SetChannelParameters needs to be called frequently to propagate |
| 422 // framerate from the media optimization into the encoder. | 419 // framerate from the media optimization into the encoder. |
| 423 // Note: SetChannelParameters fails if less than 2 frames are in the | 420 // Note: SetChannelParameters fails if less than 2 frames are in the |
| 424 // buffer since it will fail to calculate the framerate. | 421 // buffer since it will fail to calculate the framerate. |
| 425 if (i != 0) { | 422 if (i != 0) { |
| 426 EXPECT_EQ(VCM_OK, sender_->SetChannelParameters( | 423 EXPECT_EQ(VCM_OK, sender_->SetChannelParameters( |
| 427 available_bitrate_kbps_ * 1000, 0, 200)); | 424 available_bitrate_kbps_ * 1000, 0, 200)); |
| 428 } | 425 } |
| 429 } | 426 } |
| 430 } | 427 } |
| 431 | 428 |
| 432 Vp8StreamInfo SimulateWithFramerate(float framerate) { | 429 Vp8StreamInfo SimulateWithFramerate(float framerate) { |
| 433 const float short_simulation_interval = 5.0; | 430 const float short_simulation_interval = 5.0; |
| 434 const float long_simulation_interval = 10.0; | 431 const float long_simulation_interval = 10.0; |
| 435 // It appears that this 5 seconds simulation is needed to allow | 432 // It appears that this 5 seconds simulation is needed to allow |
| 436 // bitrate and framerate to stabilize. | 433 // bitrate and framerate to stabilize. |
| 437 InsertFrames(framerate, short_simulation_interval); | 434 InsertFrames(framerate, short_simulation_interval); |
| 438 packetization_callback_.Reset(); | 435 encoded_frame_callback_.Reset(); |
| 439 | 436 |
| 440 InsertFrames(framerate, long_simulation_interval); | 437 InsertFrames(framerate, long_simulation_interval); |
| 441 return packetization_callback_.CalculateVp8StreamInfo(); | 438 return encoded_frame_callback_.CalculateVp8StreamInfo(); |
| 442 } | 439 } |
| 443 | 440 |
| 444 protected: | 441 protected: |
| 445 VideoCodec codec_; | 442 VideoCodec codec_; |
| 446 int codec_bitrate_kbps_; | 443 int codec_bitrate_kbps_; |
| 447 int available_bitrate_kbps_; | 444 int available_bitrate_kbps_; |
| 448 }; | 445 }; |
| 449 | 446 |
| 450 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) | 447 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) |
| 451 #define MAYBE_FixedTemporalLayersStrategy DISABLED_FixedTemporalLayersStrategy | 448 #define MAYBE_FixedTemporalLayersStrategy DISABLED_FixedTemporalLayersStrategy |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 } | 500 } |
| 504 { | 501 { |
| 505 // TODO(andresp): Find out why this fails with framerate = 7.5 | 502 // TODO(andresp): Find out why this fails with framerate = 7.5 |
| 506 Vp8StreamInfo expected = {{7.0, 7.0, 7.0}, {high_b, high_b, high_b}}; | 503 Vp8StreamInfo expected = {{7.0, 7.0, 7.0}, {high_b, high_b, high_b}}; |
| 507 EXPECT_THAT(SimulateWithFramerate(7.0), MatchesVp8StreamInfo(expected)); | 504 EXPECT_THAT(SimulateWithFramerate(7.0), MatchesVp8StreamInfo(expected)); |
| 508 } | 505 } |
| 509 } | 506 } |
| 510 } // namespace | 507 } // namespace |
| 511 } // namespace vcm | 508 } // namespace vcm |
| 512 } // namespace webrtc | 509 } // namespace webrtc |
| OLD | NEW |