Improve VideoSendStreamTest::MaxPacketSize

This CL was submitted as issue https://webrtc-codereview.appspot.com/4849004/, but was reverted because of flakiness. This new issue will correct that.

Patch Set 1 contains the code that was submitted in 4849004.

BUG=2428
R=pbos@webrtc.org, phoglund@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/5399004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5251 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sprang@webrtc.org 2013-12-10 10:05:17 +00:00
parent 917306d3fd
commit 8b8819262f
4 changed files with 221 additions and 12 deletions

View File

@ -0,0 +1,93 @@
/*
* 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/test/configurable_frame_size_encoder.h"
#include <string.h>
#include "webrtc/common_video/interface/video_image.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace webrtc {
namespace test {
ConfigurableFrameSizeEncoder::ConfigurableFrameSizeEncoder(
uint32_t max_frame_size)
: callback_(NULL),
max_frame_size_(max_frame_size),
current_frame_size_(max_frame_size),
buffer_(new uint8_t[max_frame_size]) {
memset(buffer_.get(), 0, max_frame_size);
}
ConfigurableFrameSizeEncoder::~ConfigurableFrameSizeEncoder() {}
int32_t ConfigurableFrameSizeEncoder::InitEncode(
const VideoCodec* codec_settings,
int32_t number_of_cores,
uint32_t max_payload_size) {
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::Encode(
const I420VideoFrame& inputImage,
const CodecSpecificInfo* codecSpecificInfo,
const std::vector<VideoFrameType>* frame_types) {
EncodedImage encodedImage(
buffer_.get(), current_frame_size_, max_frame_size_);
encodedImage._completeFrame = true;
encodedImage._encodedHeight = inputImage.height();
encodedImage._encodedWidth = inputImage.width();
encodedImage._frameType = kKeyFrame;
encodedImage._timeStamp = inputImage.timestamp();
encodedImage.capture_time_ms_ = inputImage.render_time_ms();
RTPFragmentationHeader* fragmentation = NULL;
callback_->Encoded(encodedImage, codecSpecificInfo, fragmentation);
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::RegisterEncodeCompleteCallback(
EncodedImageCallback* callback) {
callback_ = callback;
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::Release() {
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::SetChannelParameters(uint32_t packet_loss,
int rtt) {
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::SetRates(uint32_t new_bit_rate,
uint32_t frame_rate) {
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::SetPeriodicKeyFrames(bool enable) {
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::CodecConfigParameters(uint8_t* buffer,
int32_t size) {
return WEBRTC_VIDEO_CODEC_OK;
}
int32_t ConfigurableFrameSizeEncoder::SetFrameSize(uint32_t size) {
assert(size <= max_frame_size_);
current_frame_size_ = size;
return WEBRTC_VIDEO_CODEC_OK;
}
} // namespace test
} // namespace webrtc

View File

@ -0,0 +1,61 @@
/*
* 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.
*/
#ifndef WEBRTC_TEST_CONFIGURABLE_FRAME_SIZE_ENCODER_H_
#define WEBRTC_TEST_CONFIGURABLE_FRAME_SIZE_ENCODER_H_
#include <vector>
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
namespace webrtc {
namespace test {
class ConfigurableFrameSizeEncoder : public VideoEncoder {
public:
explicit ConfigurableFrameSizeEncoder(uint32_t max_frame_size);
virtual ~ConfigurableFrameSizeEncoder();
virtual int32_t InitEncode(const VideoCodec* codec_settings,
int32_t number_of_cores,
uint32_t max_payload_size) OVERRIDE;
virtual int32_t Encode(const I420VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<VideoFrameType>* frame_types)
OVERRIDE;
virtual int32_t RegisterEncodeCompleteCallback(EncodedImageCallback* callback)
OVERRIDE;
virtual int32_t Release() OVERRIDE;
virtual int32_t SetChannelParameters(uint32_t packet_loss, int rtt) OVERRIDE;
virtual int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) OVERRIDE;
virtual int32_t SetPeriodicKeyFrames(bool enable) OVERRIDE;
virtual int32_t CodecConfigParameters(uint8_t* buffer, int32_t size) OVERRIDE;
int32_t SetFrameSize(uint32_t size);
private:
EncodedImageCallback* callback_;
const uint32_t max_frame_size_;
uint32_t current_frame_size_;
scoped_ptr<uint8_t[]> buffer_;
};
} // namespace test
} // namespace webrtc
#endif // WEBRTC_TEST_CONFIGURABLE_FRAME_SIZE_ENCODER_H_

View File

@ -14,6 +14,8 @@
'target_name': 'webrtc_test_common', 'target_name': 'webrtc_test_common',
'type': 'static_library', 'type': 'static_library',
'sources': [ 'sources': [
'configurable_frame_size_encoder.cc',
'configurable_frame_size_encoder.h',
'direct_transport.cc', 'direct_transport.cc',
'direct_transport.h', 'direct_transport.h',
'fake_audio_device.cc', 'fake_audio_device.cc',

View File

@ -24,6 +24,7 @@
#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/test/direct_transport.h" #include "webrtc/test/direct_transport.h"
#include "webrtc/test/fake_encoder.h" #include "webrtc/test/fake_encoder.h"
#include "webrtc/test/configurable_frame_size_encoder.h"
#include "webrtc/test/frame_generator_capturer.h" #include "webrtc/test/frame_generator_capturer.h"
#include "webrtc/test/null_transport.h" #include "webrtc/test/null_transport.h"
#include "webrtc/test/rtp_rtcp_observer.h" #include "webrtc/test/rtp_rtcp_observer.h"
@ -528,47 +529,99 @@ TEST_F(VideoSendStreamTest, RetransmitsNackOverRtxWithPacing) {
TestNackRetransmission(kSendRtxSsrc, kSendRtxPayloadType, true); TestNackRetransmission(kSendRtxSsrc, kSendRtxPayloadType, true);
} }
TEST_F(VideoSendStreamTest, MaxPacketSize) { TEST_F(VideoSendStreamTest, FragmentsAccordingToMaxPacketSize) {
class PacketSizeObserver : public test::RtpRtcpObserver { // Observer that verifies that the expected number of packets and bytes
// arrive for each frame size, from start_size to stop_size.
class FrameFragmentationObserver : public test::RtpRtcpObserver,
public EncodedFrameObserver {
public: public:
PacketSizeObserver(size_t max_length) : RtpRtcpObserver(30 * 1000), FrameFragmentationObserver(size_t max_packet_size,
max_length_(max_length), accumulated_size_(0) {} uint32_t start_size,
uint32_t stop_size,
test::ConfigurableFrameSizeEncoder* encoder)
: RtpRtcpObserver(30 * 1000),
max_packet_size_(max_packet_size),
accumulated_size_(0),
accumulated_payload_(0),
stop_size_(stop_size),
current_size_rtp_(start_size),
current_size_frame_(start_size),
encoder_(encoder) {
// Fragmentation required, this test doesn't make sense without it.
assert(stop_size > max_packet_size);
}
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
RTPHeader header; RTPHeader header;
EXPECT_TRUE( EXPECT_TRUE(
parser_->Parse(packet, static_cast<int>(length), &header)); parser_->Parse(packet, static_cast<int>(length), &header));
EXPECT_LE(length, max_length_); EXPECT_LE(length, max_packet_size_);
accumulated_size_ += length; accumulated_size_ += length;
// Payload size = packet size - minus RTP header, padding and one byte
// generic header.
accumulated_payload_ +=
length - (header.headerLength + header.paddingLength + 1);
// Marker bit set indicates last fragment of a packet // Marker bit set indicates last packet of a frame.
if (header.markerBit) { if (header.markerBit) {
if (accumulated_size_ + length > max_length_) { EXPECT_GE(accumulated_size_, current_size_rtp_);
// The packet was fragmented, total size was larger than max size, EXPECT_EQ(accumulated_payload_, current_size_rtp_);
// but size of individual fragments were within size limit => pass!
// Last packet of frame; reset counters.
accumulated_size_ = 0;
accumulated_payload_ = 0;
if (current_size_rtp_ == stop_size_) {
// Done! (Don't increase size again, might arrive more @ stop_size).
observation_complete_->Set(); observation_complete_->Set();
} else {
// Increase next expected frame size.
++current_size_rtp_;
} }
accumulated_size_ = 0; // Last fragment, reset packet size
} }
return SEND_PACKET; return SEND_PACKET;
} }
virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
// Increase frame size for next encoded frame, in the context of the
// encoder thread.
if (current_size_frame_ < stop_size_) {
++current_size_frame_;
}
encoder_->SetFrameSize(current_size_frame_);
}
private: private:
size_t max_length_; size_t max_packet_size_;
size_t accumulated_size_; size_t accumulated_size_;
size_t accumulated_payload_;
uint32_t stop_size_;
uint32_t current_size_rtp_;
uint32_t current_size_frame_;
test::ConfigurableFrameSizeEncoder* encoder_;
}; };
// Use a fake encoder to output a frame of every size in the range [90, 290],
// for each size making sure that the exact number of payload bytes received
// is correct and that packets are fragmented to respect max packet size.
static const uint32_t kMaxPacketSize = 128; static const uint32_t kMaxPacketSize = 128;
static const uint32_t start = 90;
static const uint32_t stop = 290;
PacketSizeObserver observer(kMaxPacketSize); test::ConfigurableFrameSizeEncoder encoder(stop);
encoder.SetFrameSize(start);
FrameFragmentationObserver observer(kMaxPacketSize, start, stop, &encoder);
Call::Config call_config(observer.SendTransport()); Call::Config call_config(observer.SendTransport());
scoped_ptr<Call> call(Call::Create(call_config)); scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.encoder = &encoder;
send_config.rtp.max_packet_size = kMaxPacketSize; send_config.rtp.max_packet_size = kMaxPacketSize;
send_config.post_encode_callback = &observer;
RunSendTest(call.get(), send_config, &observer); RunSendTest(call.get(), send_config, &observer);
} }