VCM/JB:Removing hybrid and setting a decodable state.
Review URL: https://webrtc-codereview.appspot.com/1283004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3834 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -106,7 +106,8 @@ VCMJitterBuffer::VCMJitterBuffer(Clock* clock,
|
|||||||
nack_seq_nums_(),
|
nack_seq_nums_(),
|
||||||
max_nack_list_size_(0),
|
max_nack_list_size_(0),
|
||||||
max_packet_age_to_nack_(0),
|
max_packet_age_to_nack_(0),
|
||||||
waiting_for_key_frame_(false) {
|
waiting_for_key_frame_(false),
|
||||||
|
decode_with_errors_(false) {
|
||||||
memset(frame_buffers_, 0, sizeof(frame_buffers_));
|
memset(frame_buffers_, 0, sizeof(frame_buffers_));
|
||||||
memset(receive_statistics_, 0, sizeof(receive_statistics_));
|
memset(receive_statistics_, 0, sizeof(receive_statistics_));
|
||||||
|
|
||||||
@ -151,6 +152,7 @@ void VCMJitterBuffer::CopyFrom(const VCMJitterBuffer& rhs) {
|
|||||||
first_packet_ = rhs.first_packet_;
|
first_packet_ = rhs.first_packet_;
|
||||||
last_decoded_state_ = rhs.last_decoded_state_;
|
last_decoded_state_ = rhs.last_decoded_state_;
|
||||||
num_not_decodable_packets_ = rhs.num_not_decodable_packets_;
|
num_not_decodable_packets_ = rhs.num_not_decodable_packets_;
|
||||||
|
decode_with_errors_ = rhs.decode_with_errors_;
|
||||||
assert(max_nack_list_size_ == rhs.max_nack_list_size_);
|
assert(max_nack_list_size_ == rhs.max_nack_list_size_);
|
||||||
assert(max_packet_age_to_nack_ == rhs.max_packet_age_to_nack_);
|
assert(max_packet_age_to_nack_ == rhs.max_packet_age_to_nack_);
|
||||||
memcpy(receive_statistics_, rhs.receive_statistics_,
|
memcpy(receive_statistics_, rhs.receive_statistics_,
|
||||||
@ -445,7 +447,7 @@ VCMEncodedFrame* VCMJitterBuffer::GetCompleteFrameForDecoding(
|
|||||||
waiting_for_key_frame_ = true;
|
waiting_for_key_frame_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameList::iterator it = FindOldestCompleteContinuousFrame(false);
|
FrameList::iterator it = FindOldestCompleteContinuousFrame();
|
||||||
if (it == frame_list_.end()) {
|
if (it == frame_list_.end()) {
|
||||||
if (max_wait_time_ms == 0) {
|
if (max_wait_time_ms == 0) {
|
||||||
crit_sect_->Leave();
|
crit_sect_->Leave();
|
||||||
@ -469,7 +471,7 @@ VCMEncodedFrame* VCMJitterBuffer::GetCompleteFrameForDecoding(
|
|||||||
// Finding oldest frame ready for decoder, but check
|
// Finding oldest frame ready for decoder, but check
|
||||||
// sequence number and size
|
// sequence number and size
|
||||||
CleanUpOldOrEmptyFrames();
|
CleanUpOldOrEmptyFrames();
|
||||||
it = FindOldestCompleteContinuousFrame(false);
|
it = FindOldestCompleteContinuousFrame();
|
||||||
if (it == frame_list_.end()) {
|
if (it == frame_list_.end()) {
|
||||||
wait_time_ms = end_wait_time_ms - clock_->TimeInMilliseconds();
|
wait_time_ms = end_wait_time_ms - clock_->TimeInMilliseconds();
|
||||||
} else {
|
} else {
|
||||||
@ -749,7 +751,7 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(VCMEncodedFrame* encoded_frame,
|
|||||||
// triggered, as the body of the function is empty.
|
// triggered, as the body of the function is empty.
|
||||||
// TODO(mikhal): Update when decodable is enabled.
|
// TODO(mikhal): Update when decodable is enabled.
|
||||||
buffer_return = frame->InsertPacket(packet, now_ms,
|
buffer_return = frame->InsertPacket(packet, now_ms,
|
||||||
nack_mode_ == kNackHybrid,
|
decode_with_errors_,
|
||||||
rtt_ms_);
|
rtt_ms_);
|
||||||
ret = buffer_return;
|
ret = buffer_return;
|
||||||
if (buffer_return > 0) {
|
if (buffer_return > 0) {
|
||||||
@ -995,9 +997,7 @@ VCMEncodedFrame* VCMJitterBuffer::GetFrameForDecodingNACK() {
|
|||||||
if (last_decoded_state_.in_initial_state()) {
|
if (last_decoded_state_.in_initial_state()) {
|
||||||
waiting_for_key_frame_ = true;
|
waiting_for_key_frame_ = true;
|
||||||
}
|
}
|
||||||
// Allow for a decodable frame when in Hybrid mode.
|
FrameList::iterator it = FindOldestCompleteContinuousFrame();
|
||||||
bool enable_decodable = nack_mode_ == kNackHybrid ? true : false;
|
|
||||||
FrameList::iterator it = FindOldestCompleteContinuousFrame(enable_decodable);
|
|
||||||
if (it == frame_list_.end()) {
|
if (it == frame_list_.end()) {
|
||||||
// If we didn't find one we're good with a complete key/decodable frame.
|
// If we didn't find one we're good with a complete key/decodable frame.
|
||||||
it = find_if(frame_list_.begin(), frame_list_.end(),
|
it = find_if(frame_list_.begin(), frame_list_.end(),
|
||||||
@ -1208,7 +1208,7 @@ VCMFrameBufferEnum VCMJitterBuffer::UpdateFrameState(VCMFrameBuffer* frame) {
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const FrameList::iterator it = FindOldestCompleteContinuousFrame(false);
|
const FrameList::iterator it = FindOldestCompleteContinuousFrame();
|
||||||
VCMFrameBuffer* old_frame = NULL;
|
VCMFrameBuffer* old_frame = NULL;
|
||||||
if (it != frame_list_.end()) {
|
if (it != frame_list_.end()) {
|
||||||
old_frame = *it;
|
old_frame = *it;
|
||||||
@ -1224,8 +1224,7 @@ VCMFrameBufferEnum VCMJitterBuffer::UpdateFrameState(VCMFrameBuffer* frame) {
|
|||||||
|
|
||||||
// Find oldest complete frame used for getting next frame to decode
|
// Find oldest complete frame used for getting next frame to decode
|
||||||
// Must be called under critical section
|
// Must be called under critical section
|
||||||
FrameList::iterator VCMJitterBuffer::FindOldestCompleteContinuousFrame(
|
FrameList::iterator VCMJitterBuffer::FindOldestCompleteContinuousFrame() {
|
||||||
bool enable_decodable) {
|
|
||||||
// If we have more than one frame done since last time, pick oldest.
|
// If we have more than one frame done since last time, pick oldest.
|
||||||
VCMFrameBuffer* oldest_frame = NULL;
|
VCMFrameBuffer* oldest_frame = NULL;
|
||||||
FrameList::iterator it = frame_list_.begin();
|
FrameList::iterator it = frame_list_.begin();
|
||||||
@ -1239,7 +1238,7 @@ FrameList::iterator VCMJitterBuffer::FindOldestCompleteContinuousFrame(
|
|||||||
VCMFrameBufferStateEnum state = oldest_frame->GetState();
|
VCMFrameBufferStateEnum state = oldest_frame->GetState();
|
||||||
// Is this frame complete or decodable and continuous?
|
// Is this frame complete or decodable and continuous?
|
||||||
if ((state == kStateComplete ||
|
if ((state == kStateComplete ||
|
||||||
(enable_decodable && state == kStateDecodable)) &&
|
(decode_with_errors_ && state == kStateDecodable)) &&
|
||||||
last_decoded_state_.ContinuousFrame(oldest_frame)) {
|
last_decoded_state_.ContinuousFrame(oldest_frame)) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -29,9 +29,6 @@ namespace webrtc {
|
|||||||
|
|
||||||
enum VCMNackMode {
|
enum VCMNackMode {
|
||||||
kNack,
|
kNack,
|
||||||
// TODO(holmer): There is no longer a hybrid NACK mode. We should remove this
|
|
||||||
// and replace it with a jitter buffer API for setting allowing decode errors.
|
|
||||||
kNackHybrid,
|
|
||||||
kNoNack
|
kNoNack
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -161,6 +158,8 @@ class VCMJitterBuffer {
|
|||||||
// Returns a list of the sequence numbers currently missing.
|
// Returns a list of the sequence numbers currently missing.
|
||||||
uint16_t* GetNackList(uint16_t* nack_list_size, bool* request_key_frame);
|
uint16_t* GetNackList(uint16_t* nack_list_size, bool* request_key_frame);
|
||||||
|
|
||||||
|
// Enable/disable decoding with errors.
|
||||||
|
void DecodeWithErrors(bool enable) {decode_with_errors_ = enable;}
|
||||||
int64_t LastDecodedTimestamp() const;
|
int64_t LastDecodedTimestamp() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -210,8 +209,8 @@ class VCMJitterBuffer {
|
|||||||
VCMFrameBufferEnum UpdateFrameState(VCMFrameBuffer* frame);
|
VCMFrameBufferEnum UpdateFrameState(VCMFrameBuffer* frame);
|
||||||
|
|
||||||
// Finds the oldest complete frame, used for getting next frame to decode.
|
// Finds the oldest complete frame, used for getting next frame to decode.
|
||||||
// Can return a decodable, incomplete frame if |enable_decodable| is true.
|
// Can return a decodable, incomplete frame when enabled.
|
||||||
FrameList::iterator FindOldestCompleteContinuousFrame(bool enable_decodable);
|
FrameList::iterator FindOldestCompleteContinuousFrame();
|
||||||
|
|
||||||
void CleanUpOldOrEmptyFrames();
|
void CleanUpOldOrEmptyFrames();
|
||||||
|
|
||||||
@ -296,6 +295,7 @@ class VCMJitterBuffer {
|
|||||||
int max_packet_age_to_nack_; // Measured in sequence numbers.
|
int max_packet_age_to_nack_; // Measured in sequence numbers.
|
||||||
bool waiting_for_key_frame_;
|
bool waiting_for_key_frame_;
|
||||||
|
|
||||||
|
bool decode_with_errors_;
|
||||||
DISALLOW_COPY_AND_ASSIGN(VCMJitterBuffer);
|
DISALLOW_COPY_AND_ASSIGN(VCMJitterBuffer);
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -375,8 +375,7 @@ TEST_F(TestRunningJitterBuffer, StatisticsTest) {
|
|||||||
|
|
||||||
TEST_F(TestJitterBufferNack, EmptyPackets) {
|
TEST_F(TestJitterBufferNack, EmptyPackets) {
|
||||||
// Make sure empty packets doesn't clog the jitter buffer.
|
// Make sure empty packets doesn't clog the jitter buffer.
|
||||||
jitter_buffer_->SetNackMode(kNackHybrid, media_optimization::kLowRttNackMs,
|
jitter_buffer_->SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
|
||||||
-1);
|
|
||||||
EXPECT_GE(InsertFrames(kMaxNumberOfFrames, kFrameEmpty), kNoError);
|
EXPECT_GE(InsertFrames(kMaxNumberOfFrames, kFrameEmpty), kNoError);
|
||||||
InsertFrame(kVideoFrameKey);
|
InsertFrame(kVideoFrameKey);
|
||||||
EXPECT_TRUE(DecodeCompleteFrame());
|
EXPECT_TRUE(DecodeCompleteFrame());
|
||||||
|
@ -637,7 +637,7 @@ VideoCodingModuleImpl::SetVideoProtection(VCMVideoProtection videoProtection,
|
|||||||
// Enable hybrid NACK/FEC. Always wait for retransmissions
|
// Enable hybrid NACK/FEC. Always wait for retransmissions
|
||||||
// and don't add extra delay when RTT is above
|
// and don't add extra delay when RTT is above
|
||||||
// kLowRttNackMs.
|
// kLowRttNackMs.
|
||||||
_receiver.SetNackMode(kNackHybrid,
|
_receiver.SetNackMode(kNack,
|
||||||
media_optimization::kLowRttNackMs,
|
media_optimization::kLowRttNackMs,
|
||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
@ -1392,7 +1392,7 @@ int VideoCodingModuleImpl::SetReceiverRobustnessMode(
|
|||||||
return VCM_NOT_IMPLEMENTED;
|
return VCM_NOT_IMPLEMENTED;
|
||||||
// Enable hybrid NACK/FEC. Always wait for retransmissions and don't add
|
// Enable hybrid NACK/FEC. Always wait for retransmissions and don't add
|
||||||
// extra delay when RTT is above kLowRttNackMs.
|
// extra delay when RTT is above kLowRttNackMs.
|
||||||
_receiver.SetNackMode(kNackHybrid, media_optimization::kLowRttNackMs, -1);
|
_receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
|
||||||
_dualReceiver.SetNackMode(kNoNack, -1, -1);
|
_dualReceiver.SetNackMode(kNoNack, -1, -1);
|
||||||
_keyRequestMode = kKeyOnError;
|
_keyRequestMode = kKeyOnError;
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user