Adding a receive side API for buffering mode.
At the same time, renaming the send side API. Review URL: https://webrtc-codereview.appspot.com/1104004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3525 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -553,6 +553,10 @@ public:
|
||||
virtual void SetNackSettings(size_t max_nack_list_size,
|
||||
int max_packet_age_to_nack) = 0;
|
||||
|
||||
// Setting a desired delay to the VCM receiver. Video rendering will be
|
||||
// delayed by at least desired_delay_ms.
|
||||
virtual int SetMinReceiverDelay(int desired_delay_ms) = 0;
|
||||
|
||||
// Enables recording of debugging information.
|
||||
virtual int StartDebugRecording(const char* file_name_utf8) = 0;
|
||||
|
||||
|
@ -772,10 +772,9 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(VCMEncodedFrame* encoded_frame,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void VCMJitterBuffer::EnableMaxJitterEstimate(bool enable,
|
||||
uint32_t initial_delay_ms) {
|
||||
void VCMJitterBuffer::SetMaxJitterEstimate(uint32_t initial_delay_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
jitter_estimate_.EnableMaxJitterEstimate(enable, initial_delay_ms);
|
||||
jitter_estimate_.SetMaxJitterEstimate(initial_delay_ms);
|
||||
}
|
||||
|
||||
uint32_t VCMJitterBuffer::EstimatedJitterMs() {
|
||||
|
@ -127,10 +127,10 @@ class VCMJitterBuffer {
|
||||
VCMFrameBufferEnum InsertPacket(VCMEncodedFrame* frame,
|
||||
const VCMPacket& packet);
|
||||
|
||||
// Enable a max filter on the jitter estimate, and setting of the initial
|
||||
// delay (only when in max mode). When disabled (default), the last jitter
|
||||
// Enable a max filter on the jitter estimate by setting an initial
|
||||
// non-zero delay. When set to zero (default), the last jitter
|
||||
// estimate will be used.
|
||||
void EnableMaxJitterEstimate(bool enable, uint32_t initial_delay_ms);
|
||||
void SetMaxJitterEstimate(uint32_t initial_delay_ms);
|
||||
|
||||
// Returns the estimated jitter in milliseconds.
|
||||
uint32_t EstimatedJitterMs();
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum { kMaxNumberOfFrames = 100 };
|
||||
enum { kMaxNumberOfFrames = 300 };
|
||||
enum { kStartNumberOfFrames = 6 };
|
||||
enum { kMaxVideoDelayMs = 2000 };
|
||||
|
||||
|
@ -277,25 +277,15 @@ TEST_F(TestRunningJitterBuffer, JitterEstimateMode) {
|
||||
InsertFrame(kVideoFrameDelta);
|
||||
EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
|
||||
// Set kMaxEstimate with a 2 seconds initial delay.
|
||||
jitter_buffer_->EnableMaxJitterEstimate(true, 2000u);
|
||||
jitter_buffer_->SetMaxJitterEstimate(2000u);
|
||||
EXPECT_EQ(2000u, jitter_buffer_->EstimatedJitterMs());
|
||||
InsertFrame(kVideoFrameDelta);
|
||||
EXPECT_EQ(2000u, jitter_buffer_->EstimatedJitterMs());
|
||||
// Set kMaxEstimate with a 0S initial delay.
|
||||
jitter_buffer_->EnableMaxJitterEstimate(true, 0u);
|
||||
EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
|
||||
// Jitter cannot decrease.
|
||||
InsertFrames(2, kVideoFrameDelta);
|
||||
uint32_t je1 = jitter_buffer_->EstimatedJitterMs();
|
||||
InsertFrames(2, kVideoFrameDelta);
|
||||
EXPECT_GE(je1, jitter_buffer_->EstimatedJitterMs());
|
||||
|
||||
// Set kLastEstimate mode (initial delay is arbitrary in this case and will
|
||||
// be ignored).
|
||||
jitter_buffer_->EnableMaxJitterEstimate(false, 2000u);
|
||||
EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
|
||||
InsertFrames(10, kVideoFrameDelta);
|
||||
EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
|
||||
}
|
||||
|
||||
TEST_F(TestJitterBufferNack, TestEmptyPackets) {
|
||||
|
@ -409,10 +409,9 @@ VCMJitterEstimator::UpdateMaxFrameSize(WebRtc_UWord32 frameSizeBytes)
|
||||
}
|
||||
}
|
||||
|
||||
void VCMJitterEstimator::EnableMaxJitterEstimate(bool enable,
|
||||
uint32_t initial_delay_ms)
|
||||
void VCMJitterEstimator::SetMaxJitterEstimate(uint32_t initial_delay_ms)
|
||||
{
|
||||
if (enable) {
|
||||
if (initial_delay_ms > 0) {
|
||||
_maxJitterEstimateMs = initial_delay_ms;
|
||||
_jitterEstimateMode = kMaxEstimate;
|
||||
} else {
|
||||
|
@ -64,10 +64,10 @@ public:
|
||||
|
||||
void UpdateMaxFrameSize(WebRtc_UWord32 frameSizeBytes);
|
||||
|
||||
// Enable a max filter on the jitter estimate, and setting of the initial
|
||||
// delay (only when in max mode). When disabled (default), the last jitter
|
||||
// Set a max filter on the jitter estimate by setting an initial
|
||||
// non-zero delay. When set to zero (default), the last jitter
|
||||
// estimate will be used.
|
||||
void EnableMaxJitterEstimate(bool enable, uint32_t initial_delay_ms);
|
||||
void SetMaxJitterEstimate(uint32_t initial_delay_ms);
|
||||
|
||||
// A constant describing the delay from the jitter buffer
|
||||
// to the delay on the receiving side which is not accounted
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum { kMaxReceiverDelayMs = 10000 };
|
||||
|
||||
VCMReceiver::VCMReceiver(VCMTiming* timing,
|
||||
Clock* clock,
|
||||
int32_t vcm_id,
|
||||
@ -34,7 +36,8 @@ VCMReceiver::VCMReceiver(VCMTiming* timing,
|
||||
jitter_buffer_(clock_, vcm_id, receiver_id, master),
|
||||
timing_(timing),
|
||||
render_wait_event_(),
|
||||
state_(kPassive) {}
|
||||
state_(kPassive),
|
||||
max_video_delay_ms_(kMaxVideoDelayMs) {}
|
||||
|
||||
VCMReceiver::~VCMReceiver() {
|
||||
render_wait_event_.Set();
|
||||
@ -108,20 +111,21 @@ int32_t VCMReceiver::InsertPacket(const VCMPacket& packet, uint16_t frame_width,
|
||||
jitter_buffer_.Flush();
|
||||
timing_->Reset(clock_->TimeInMilliseconds());
|
||||
return VCM_FLUSH_INDICATOR;
|
||||
} else if (render_time_ms < now_ms - kMaxVideoDelayMs) {
|
||||
} else if (render_time_ms < now_ms - max_video_delay_ms_) {
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
|
||||
VCMId(vcm_id_, receiver_id_),
|
||||
"This frame should have been rendered more than %u ms ago."
|
||||
"Flushing jitter buffer and resetting timing.",
|
||||
kMaxVideoDelayMs);
|
||||
max_video_delay_ms_);
|
||||
jitter_buffer_.Flush();
|
||||
timing_->Reset(clock_->TimeInMilliseconds());
|
||||
return VCM_FLUSH_INDICATOR;
|
||||
} else if (timing_->TargetVideoDelay() > kMaxVideoDelayMs) {
|
||||
} else if (static_cast<int>(timing_->TargetVideoDelay()) >
|
||||
max_video_delay_ms_) {
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
|
||||
VCMId(vcm_id_, receiver_id_),
|
||||
"More than %u ms target delay. Flushing jitter buffer and"
|
||||
"resetting timing.", kMaxVideoDelayMs);
|
||||
"resetting timing.", max_video_delay_ms_);
|
||||
jitter_buffer_.Flush();
|
||||
timing_->Reset(clock_->TimeInMilliseconds());
|
||||
return VCM_FLUSH_INDICATOR;
|
||||
@ -402,6 +406,17 @@ VCMReceiverState VCMReceiver::State() const {
|
||||
return state_;
|
||||
}
|
||||
|
||||
int VCMReceiver::SetMinReceiverDelay(int desired_delay_ms) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
if (desired_delay_ms < 0 || desired_delay_ms > kMaxReceiverDelayMs) {
|
||||
return -1;
|
||||
}
|
||||
jitter_buffer_.SetMaxJitterEstimate(desired_delay_ms);
|
||||
max_video_delay_ms_ = desired_delay_ms + kMaxVideoDelayMs;
|
||||
timing_->SetMaxVideoDelay(max_video_delay_ms_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VCMReceiver::UpdateState(VCMReceiverState new_state) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
assert(!(state_ == kPassive && new_state == kWaitForPrimaryDecode));
|
||||
|
@ -69,6 +69,9 @@ class VCMReceiver {
|
||||
VCMReceiver& dual_receiver) const;
|
||||
VCMReceiverState State() const;
|
||||
|
||||
// Receiver video delay.
|
||||
int SetMinReceiverDelay(int desired_delay_ms);
|
||||
|
||||
private:
|
||||
VCMEncodedFrame* FrameForDecoding(uint16_t max_wait_time_ms,
|
||||
int64_t nextrender_time_ms,
|
||||
@ -90,6 +93,7 @@ class VCMReceiver {
|
||||
VCMTiming* timing_;
|
||||
VCMEvent render_wait_event_;
|
||||
VCMReceiverState state_;
|
||||
int max_video_delay_ms_;
|
||||
|
||||
static int32_t receiver_id_counter_;
|
||||
};
|
||||
|
@ -34,7 +34,8 @@ _renderDelayMs(kDefaultRenderDelayMs),
|
||||
_minTotalDelayMs(0),
|
||||
_requiredDelayMs(0),
|
||||
_currentDelayMs(0),
|
||||
_prevFrameTimestamp(0)
|
||||
_prevFrameTimestamp(0),
|
||||
_maxVideoDelayMs(kMaxVideoDelayMs)
|
||||
{
|
||||
if (masterTiming == NULL)
|
||||
{
|
||||
@ -131,7 +132,7 @@ void VCMTiming::UpdateCurrentDelay(WebRtc_UWord32 frameTimestamp)
|
||||
WebRtc_Word64 delayDiffMs = static_cast<WebRtc_Word64>(targetDelayMs) -
|
||||
_currentDelayMs;
|
||||
// Never change the delay with more than 100 ms every second. If we're changing the
|
||||
// delay in too large steps we will get noticable freezes. By limiting the change we
|
||||
// delay in too large steps we will get noticeable freezes. By limiting the change we
|
||||
// can increase the delay in smaller steps, which will be experienced as the video is
|
||||
// played in slow motion. When lowering the delay the video will be played at a faster
|
||||
// pace.
|
||||
@ -249,7 +250,7 @@ VCMTiming::RenderTimeMsInternal(WebRtc_UWord32 frameTimestamp, WebRtc_Word64 now
|
||||
{
|
||||
WebRtc_Word64 estimatedCompleteTimeMs =
|
||||
_tsExtrapolator->ExtrapolateLocalTime(frameTimestamp);
|
||||
if (estimatedCompleteTimeMs - nowMs > kMaxVideoDelayMs)
|
||||
if (estimatedCompleteTimeMs - nowMs > _maxVideoDelayMs)
|
||||
{
|
||||
if (_master)
|
||||
{
|
||||
@ -323,6 +324,12 @@ VCMTiming::EnoughTimeToDecode(WebRtc_UWord32 availableProcessingTimeMs) const
|
||||
return static_cast<WebRtc_Word32>(availableProcessingTimeMs) - maxDecodeTimeMs > 0;
|
||||
}
|
||||
|
||||
void VCMTiming::SetMaxVideoDelay(int maxVideoDelayMs)
|
||||
{
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
_maxVideoDelayMs = maxVideoDelayMs;
|
||||
}
|
||||
|
||||
WebRtc_UWord32
|
||||
VCMTiming::TargetVideoDelay() const
|
||||
{
|
||||
|
@ -82,6 +82,9 @@ public:
|
||||
// certain amount of processing time.
|
||||
bool EnoughTimeToDecode(WebRtc_UWord32 availableProcessingTimeMs) const;
|
||||
|
||||
// Set the max allowed video delay.
|
||||
void SetMaxVideoDelay(int maxVideoDelayMs);
|
||||
|
||||
enum { kDefaultRenderDelayMs = 10 };
|
||||
enum { kDelayMaxChangeMsPerS = 100 };
|
||||
|
||||
@ -104,6 +107,7 @@ private:
|
||||
WebRtc_UWord32 _requiredDelayMs;
|
||||
WebRtc_UWord32 _currentDelayMs;
|
||||
WebRtc_UWord32 _prevFrameTimestamp;
|
||||
int _maxVideoDelayMs;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -1389,6 +1389,10 @@ void VideoCodingModuleImpl::SetNackSettings(
|
||||
max_packet_age_to_nack);
|
||||
}
|
||||
|
||||
int VideoCodingModuleImpl::SetMinReceiverDelay(int desired_delay_ms) {
|
||||
return _receiver.SetMinReceiverDelay(desired_delay_ms);
|
||||
}
|
||||
|
||||
int VideoCodingModuleImpl::StartDebugRecording(const char* file_name_utf8) {
|
||||
CriticalSectionScoped cs(_sendCritSect);
|
||||
_encoderInputFile = fopen(file_name_utf8, "wb");
|
||||
|
@ -262,6 +262,9 @@ public:
|
||||
virtual void SetNackSettings(size_t max_nack_list_size,
|
||||
int max_packet_age_to_nack);
|
||||
|
||||
// Set the video delay for the receiver (default = 0).
|
||||
virtual int SetMinReceiverDelay(int desired_delay_ms);
|
||||
|
||||
// Enables recording of debugging information.
|
||||
virtual int StartDebugRecording(const char* file_name_utf8);
|
||||
|
||||
|
@ -287,4 +287,11 @@ TEST_F(TestVideoCodingModule, PaddingOnlyAndVideo) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestVideoCodingModule, ReceiverDelay) {
|
||||
EXPECT_EQ(0, vcm_->SetMinReceiverDelay(0));
|
||||
EXPECT_EQ(0, vcm_->SetMinReceiverDelay(5000));
|
||||
EXPECT_EQ(-1, vcm_->SetMinReceiverDelay(-100));
|
||||
EXPECT_EQ(-1, vcm_->SetMinReceiverDelay(10010));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
Reference in New Issue
Block a user