video_coding: Requesting a key frame after a JB flush

Review URL: http://webrtc-codereview.appspot.com/280006

git-svn-id: http://webrtc.googlecode.com/svn/trunk@994 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mikhal@webrtc.org
2011-11-22 22:57:51 +00:00
parent 6b9a7f8704
commit f13388f134
6 changed files with 83 additions and 67 deletions

View File

@@ -298,7 +298,7 @@ VCMJitterBuffer::ReleaseFrameInternal(VCMFrameBuffer* frame)
// Doing it here increases the degree of freedom for e.g. future
// reconstructability of separate layers. Must be called under the
// critical section _critSect.
void
VCMFrameBufferEnum
VCMJitterBuffer::UpdateFrameState(VCMFrameBuffer* frame)
{
if (frame == NULL)
@@ -306,7 +306,7 @@ VCMJitterBuffer::UpdateFrameState(VCMFrameBuffer* frame)
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
VCMId(_vcmId, _receiverId), "JB(0x%x) FB(0x%x): "
"UpdateFrameState NULL frame pointer", this, frame);
return;
return kNoError;
}
int length = frame->Length();
@@ -350,11 +350,11 @@ VCMJitterBuffer::UpdateFrameState(VCMFrameBuffer* frame)
_dropCount, _numConsecutiveOldFrames);
// Flush() if this happens consistently.
_numConsecutiveOldFrames++;
if (_numConsecutiveOldFrames > kMaxConsecutiveOldFrames)
{
FlushInternal();
if (_numConsecutiveOldFrames > kMaxConsecutiveOldFrames) {
FlushInternal();
return kFlushIndicator;
}
return;
return kNoError;
}
_numConsecutiveOldFrames = 0;
frame->SetState(kStateComplete);
@@ -405,6 +405,7 @@ VCMJitterBuffer::UpdateFrameState(VCMFrameBuffer* frame)
{
_frameEvent.Set();
}
return kNoError;
}
// Get received key and delta frames
@@ -451,6 +452,8 @@ VCMJitterBuffer::GetFrame(const VCMPacket& packet, VCMEncodedFrame*& frame)
if (_numConsecutiveOldPackets > kMaxConsecutiveOldPackets)
{
FlushInternal();
_critSect.Leave();
return VCM_FLUSH_INDICATOR;
}
_critSect.Leave();
return VCM_OLD_PACKET_ERROR;
@@ -1697,7 +1700,9 @@ VCMJitterBuffer::InsertPacket(VCMEncodedFrame* buffer, const VCMPacket& packet)
}
case kCompleteSession:
{
UpdateFrameState(frame);
// Only update return value for a JB flush indicator.
if (UpdateFrameState(frame) == kFlushIndicator)
ret = kFlushIndicator;
// Signal that we have a received packet
_packetEvent.Set();
break;
@@ -1719,8 +1724,7 @@ VCMJitterBuffer::InsertPacket(VCMEncodedFrame* buffer, const VCMPacket& packet)
assert(!"JitterBuffer::InsertPacket: Undefined value");
}
}
return ret;
return ret;
}
// Must be called from within _critSect

View File

@@ -145,7 +145,7 @@ private:
bool RecycleFramesUntilKeyFrame();
// Update frame state
// (set as complete or reconstructable if conditions are met)
void UpdateFrameState(VCMFrameBuffer* frameListItem);
VCMFrameBufferEnum UpdateFrameState(VCMFrameBuffer* frameListItem);
// Help functions for getting a frame
// Find oldest complete frame, used for getting next frame to decode

View File

@@ -33,12 +33,13 @@ enum VCMJitterBufferEnum
enum VCMFrameBufferEnum
{
kStateError = -4,
kFlushIndicator = -3, // Indicator that a flush has occurred.
kTimeStampError = -2,
kSizeError = -1,
kNoError = 0,
kIncomplete = 1, // Frame incomplete
kFirstPacket = 2,
kCompleteSession = 3, // at least one layer in the frame complete
kCompleteSession = 3, // at least one layer in the frame complete.
kDecodableSession = 4, // Frame incomplete, but ready to be decoded
kDuplicatePacket = 5 // We're receiving a duplicate packet.
};

View File

@@ -112,10 +112,11 @@ VCMReceiver::InsertPacket(const VCMPacket& packet,
{
// Only trace the primary receiver to make it possible
// to parse and plot the trace file.
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
"Packet seqNo %u of frame %u at %u",
packet.seqNum, packet.timestamp,
MaskWord64ToUWord32(VCMTickTime::MillisecondTimestamp()));
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
VCMId(_vcmId, _receiverId),
"Packet seqNo %u of frame %u at %u",
packet.seqNum, packet.timestamp,
MaskWord64ToUWord32(VCMTickTime::MillisecondTimestamp()));
}
const WebRtc_Word64 nowMs = VCMTickTime::MillisecondTimestamp();
@@ -128,7 +129,7 @@ VCMReceiver::InsertPacket(const VCMPacket& packet,
// the incoming video stream and reset the JB and the timing.
_jitterBuffer.Flush();
_timing.Reset();
return VCM_OK;
return VCM_FLUSH_INDICATOR;
}
else if (renderTimeMs < nowMs - kMaxVideoDelayMs)
{
@@ -137,7 +138,7 @@ VCMReceiver::InsertPacket(const VCMPacket& packet,
"Flushing jitter buffer and resetting timing.", kMaxVideoDelayMs);
_jitterBuffer.Flush();
_timing.Reset();
return VCM_OK;
return VCM_FLUSH_INDICATOR;
}
else if (_timing.TargetVideoDelay() > kMaxVideoDelayMs)
{
@@ -146,7 +147,7 @@ VCMReceiver::InsertPacket(const VCMPacket& packet,
kMaxVideoDelayMs);
_jitterBuffer.Flush();
_timing.Reset();
return VCM_OK;
return VCM_FLUSH_INDICATOR;
}
// First packet received belonging to this frame.
@@ -171,16 +172,18 @@ VCMReceiver::InsertPacket(const VCMPacket& packet,
}
}
// Insert packet into jitter buffer
// Insert packet into the jitter buffer
// both media and empty packets
const VCMFrameBufferEnum ret = _jitterBuffer.InsertPacket(buffer, packet);
if (ret < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
const VCMFrameBufferEnum
ret = _jitterBuffer.InsertPacket(buffer, packet);
if (ret == kFlushIndicator) {
return VCM_FLUSH_INDICATOR;
} else if (ret < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding,
VCMId(_vcmId, _receiverId),
"Error inserting packet seqNo=%u, timeStamp=%u",
packet.seqNum, packet.timestamp);
return VCM_JITTER_BUFFER_ERROR;
return VCM_JITTER_BUFFER_ERROR;
}
}
return VCM_OK;

View File

@@ -1409,16 +1409,20 @@ VideoCodingModuleImpl::IncomingPacket(const WebRtc_UWord8* incomingPayload,
ret = _dualReceiver.InsertPacket(packet,
rtpInfo.type.Video.width,
rtpInfo.type.Video.height);
if (ret < 0)
{
return ret;
if (ret == VCM_FLUSH_INDICATOR) {
RequestKeyFrame();
ResetDecoder();
} else if (ret < 0) {
return ret;
}
}
ret = _receiver.InsertPacket(packet, rtpInfo.type.Video.width,
rtpInfo.type.Video.height);
if (ret < 0)
{
return ret;
if (ret == VCM_FLUSH_INDICATOR) {
RequestKeyFrame();
ResetDecoder();
} else if (ret < 0) {
return ret;
}
return VCM_OK;
}