Don't force cont' when enabling kWithErrors
BUG= R=pbos@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2047004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4669 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -603,6 +603,7 @@ VCMFrameBufferEnum VCMJitterBuffer::GetFrame(const VCMPacket& packet,
|
||||
*frame = decodable_frames_.FindFrame(packet.timestamp);
|
||||
if (*frame)
|
||||
return kNoError;
|
||||
|
||||
// No match, return empty frame.
|
||||
*frame = GetEmptyFrame();
|
||||
VCMFrameBufferEnum ret = kNoError;
|
||||
@ -633,9 +634,6 @@ int64_t VCMJitterBuffer::LastPacketTime(const VCMEncodedFrame* frame,
|
||||
VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
||||
bool* retransmitted) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||
VCMFrameBufferEnum buffer_return = kSizeError;
|
||||
VCMFrameBufferEnum ret = kSizeError;
|
||||
|
||||
VCMFrameBuffer* frame = NULL;
|
||||
const VCMFrameBufferEnum error = GetFrame(packet, &frame);
|
||||
@ -643,19 +641,20 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
||||
return error;
|
||||
}
|
||||
|
||||
// We are keeping track of the first seq num, the latest seq num and
|
||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||
// We are keeping track of the first and latest seq numbers, and
|
||||
// the number of wraps to be able to calculate how many packets we expect.
|
||||
if (first_packet_since_reset_) {
|
||||
// Now it's time to start estimating jitter
|
||||
// reset the delay estimate.
|
||||
inter_frame_delay_.Reset(clock_->TimeInMilliseconds());
|
||||
inter_frame_delay_.Reset(now_ms);
|
||||
}
|
||||
if (last_decoded_state_.IsOldPacket(&packet)) {
|
||||
// This packet belongs to an old, already decoded frame, we want to update
|
||||
// the last decoded sequence number.
|
||||
last_decoded_state_.UpdateOldPacket(&packet);
|
||||
drop_count_++;
|
||||
// Flush() if this happens consistently.
|
||||
// Flush if this happens consistently.
|
||||
num_consecutive_old_frames_++;
|
||||
if (num_consecutive_old_frames_ > kMaxConsecutiveOldFrames) {
|
||||
Flush();
|
||||
@ -663,6 +662,7 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
||||
}
|
||||
return kNoError;
|
||||
}
|
||||
|
||||
num_consecutive_old_frames_ = 0;
|
||||
|
||||
// Empty packets may bias the jitter estimate (lacking size component),
|
||||
@ -688,22 +688,18 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
||||
// Check for first packet. High sequence number will be -1 if neither an empty
|
||||
// packet nor a media packet has been inserted.
|
||||
bool first = (frame->GetHighSeqNum() == -1);
|
||||
// When in Hybrid mode, we allow for a decodable state
|
||||
// Note: Under current version, a decodable frame will never be
|
||||
// triggered, as the body of the function is empty.
|
||||
// TODO(mikhal): Update when decodable is enabled.
|
||||
FrameData frame_data;
|
||||
frame_data.rtt_ms = rtt_ms_;
|
||||
frame_data.rolling_average_packets_per_frame = average_packets_per_frame_;
|
||||
buffer_return = frame->InsertPacket(packet,
|
||||
now_ms,
|
||||
decode_error_mode_,
|
||||
frame_data);
|
||||
VCMFrameBufferEnum buffer_return = frame->InsertPacket(packet,
|
||||
now_ms,
|
||||
decode_error_mode_,
|
||||
frame_data);
|
||||
if (!frame->GetCountedFrame()) {
|
||||
TRACE_EVENT_ASYNC_BEGIN1("webrtc", "Video", frame->TimeStamp(),
|
||||
"timestamp", frame->TimeStamp());
|
||||
}
|
||||
ret = buffer_return;
|
||||
|
||||
if (buffer_return > 0) {
|
||||
incoming_bit_count_ += packet.sizeBytes << 3;
|
||||
if (first_packet_since_reset_) {
|
||||
@ -721,51 +717,55 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
||||
latest_received_sequence_number_, packet.seqNum);
|
||||
}
|
||||
}
|
||||
|
||||
// Is the frame already in the decodable list?
|
||||
bool update_decodable_list = (previous_state != kStateDecodable &&
|
||||
previous_state != kStateComplete);
|
||||
bool continuous = IsContinuous(*frame);
|
||||
switch (buffer_return) {
|
||||
case kGeneralError:
|
||||
case kTimeStampError:
|
||||
case kSizeError: {
|
||||
// This frame will be cleaned up later from the frame lists.
|
||||
// This frame will be cleaned up later from the frame list.
|
||||
frame->Reset();
|
||||
break;
|
||||
}
|
||||
case kCompleteSession: {
|
||||
if (master_) {
|
||||
// Only trace the primary jitter buffer to make it possible to parse
|
||||
// and plot the trace file.
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
|
||||
VCMId(vcm_id_, receiver_id_),
|
||||
"JB(0x%x) FB(0x%x): Complete frame added to jitter buffer,"
|
||||
" size:%d type %d",
|
||||
this, frame, frame->Length(), frame->FrameType());
|
||||
}
|
||||
CountFrame(*frame);
|
||||
frame->SetCountedFrame(true);
|
||||
if (previous_state == kStateComplete) {
|
||||
*retransmitted = (frame->GetNackCount() > 0);
|
||||
packet_event_->Set();
|
||||
break;
|
||||
}
|
||||
}
|
||||
case kDecodableSession: {
|
||||
*retransmitted = (frame->GetNackCount() > 0);
|
||||
if (previous_state != kStateDecodable) {
|
||||
if (IsContinuous(*frame) || decode_error_mode_ == kWithErrors) {
|
||||
if (!first) {
|
||||
incomplete_frames_.PopFrame(packet.timestamp);
|
||||
}
|
||||
decodable_frames_.InsertFrame(frame);
|
||||
FindAndInsertContinuousFrames(*frame);
|
||||
if (buffer_return == kCompleteSession) {
|
||||
// Signal that we have a complete session
|
||||
frame_event_->Set();
|
||||
}
|
||||
} else if (first) {
|
||||
incomplete_frames_.InsertFrame(frame);
|
||||
if (update_decodable_list) {
|
||||
if (master_) {
|
||||
// Only trace the primary jitter buffer to make it possible to parse
|
||||
// and plot the trace file.
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
|
||||
VCMId(vcm_id_, receiver_id_),
|
||||
"JB(0x%x) FB(0x%x): Complete frame added to jitter"
|
||||
"buffer, size:%d type %d",
|
||||
this, frame, frame->Length(), frame->FrameType());
|
||||
}
|
||||
CountFrame(*frame);
|
||||
frame->SetCountedFrame(true);
|
||||
if (continuous) {
|
||||
// Signal that we have a complete session.
|
||||
frame_event_->Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: There is no break here - continuing to kDecodableSession.
|
||||
case kDecodableSession: {
|
||||
*retransmitted = (frame->GetNackCount() > 0);
|
||||
// Signal that we have a received packet.
|
||||
packet_event_->Set();
|
||||
if (!update_decodable_list) {
|
||||
break;
|
||||
}
|
||||
if (continuous) {
|
||||
if (!first) {
|
||||
incomplete_frames_.PopFrame(packet.timestamp);
|
||||
}
|
||||
decodable_frames_.InsertFrame(frame);
|
||||
FindAndInsertContinuousFrames(*frame);
|
||||
} else if (first) {
|
||||
incomplete_frames_.InsertFrame(frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kIncomplete: {
|
||||
@ -775,10 +775,7 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
||||
free_frames_.push_back(frame);
|
||||
frame->Reset();
|
||||
frame = NULL;
|
||||
ret = kNoError;
|
||||
} else if (previous_state == kStateDecodable) {
|
||||
decodable_frames_.PopFrame(packet.timestamp);
|
||||
incomplete_frames_.InsertFrame(frame);
|
||||
return kNoError;
|
||||
} else if (first) {
|
||||
incomplete_frames_.InsertFrame(frame);
|
||||
}
|
||||
@ -792,17 +789,18 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
||||
break;
|
||||
}
|
||||
case kFlushIndicator:
|
||||
ret = kFlushIndicator;
|
||||
break;
|
||||
return kFlushIndicator;
|
||||
default: {
|
||||
assert(false && "JitterBuffer::InsertPacket: Undefined value");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return buffer_return;
|
||||
}
|
||||
|
||||
bool VCMJitterBuffer::IsContinuousInState(const VCMFrameBuffer& frame,
|
||||
const VCMDecodingState& decoding_state) const {
|
||||
if (decode_error_mode_ == kWithErrors)
|
||||
return true;
|
||||
// Is this frame (complete or decodable) and continuous?
|
||||
// kStateDecodable will never be set when decode_error_mode_ is false
|
||||
// as SessionInfo determines this state based on the error mode (and frame
|
||||
@ -1017,36 +1015,7 @@ uint16_t* VCMJitterBuffer::GetNackList(uint16_t* nack_list_size,
|
||||
|
||||
void VCMJitterBuffer::SetDecodeErrorMode(VCMDecodeErrorMode error_mode) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
// If we are not moving from kWithErrors or KSelectiveErrors to kNoErrors,
|
||||
// set decode_error_mode_ and apply new error mode only to new packets.
|
||||
// Also no need for further processing if we have no old, previously
|
||||
// decodable (and potentially incomplete) frames.
|
||||
if (decode_error_mode_ == kNoErrors || error_mode != kNoErrors ||
|
||||
decodable_frames_.empty()) {
|
||||
decode_error_mode_ = error_mode;
|
||||
return;
|
||||
} else {
|
||||
// We just went from kWithErrors or kSelectiveErrors to kNoErrors. Make
|
||||
// sure no incomplete frames are marked decodable.
|
||||
// Begin by skipping over all complete frames.
|
||||
FrameList::const_iterator it = decodable_frames_.begin();
|
||||
VCMFrameBuffer* frame;
|
||||
for (; it != decodable_frames_.end(); ++it) {
|
||||
if (it->second->GetState() != kStateComplete) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Continue from first incomplete and previously decodable frame and move
|
||||
// subsequent frames to incomplete_frames_.
|
||||
while (it != decodable_frames_.end()) {
|
||||
frame = it->second;
|
||||
++it;
|
||||
frame = decodable_frames_.PopFrame(frame->TimeStamp());
|
||||
frame->SetNotDecodableIfIncomplete();
|
||||
incomplete_frames_.InsertFrame(frame);
|
||||
}
|
||||
decode_error_mode_ = error_mode;
|
||||
}
|
||||
decode_error_mode_ = error_mode;
|
||||
}
|
||||
|
||||
VCMFrameBuffer* VCMJitterBuffer::NextFrame() const {
|
||||
|
||||
Reference in New Issue
Block a user