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)
{
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,7 +1724,6 @@ VCMJitterBuffer::InsertPacket(VCMEncodedFrame* buffer, const VCMPacket& packet)
assert(!"JitterBuffer::InsertPacket: Undefined value");
}
}
return ret;
}

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,7 +112,8 @@ 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),
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
VCMId(_vcmId, _receiverId),
"Packet seqNo %u of frame %u at %u",
packet.seqNum, packet.timestamp,
MaskWord64ToUWord32(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,13 +172,15 @@ 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;

View File

@ -1409,15 +1409,19 @@ VideoCodingModuleImpl::IncomingPacket(const WebRtc_UWord8* incomingPayload,
ret = _dualReceiver.InsertPacket(packet,
rtpInfo.type.Video.width,
rtpInfo.type.Video.height);
if (ret < 0)
{
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)
{
if (ret == VCM_FLUSH_INDICATOR) {
RequestKeyFrame();
ResetDecoder();
} else if (ret < 0) {
return ret;
}
return VCM_OK;

View File

@ -24,9 +24,12 @@
using namespace webrtc;
void CheckOutFrame(VCMEncodedFrame* frameOut, unsigned int size, bool startCode)
int CheckOutFrame(VCMEncodedFrame* frameOut, unsigned int size, bool startCode)
{
TEST(frameOut != 0);
if (frameOut == 0)
{
return -1;
}
const WebRtc_UWord8* outData = frameOut->Buffer();
@ -71,6 +74,7 @@ void CheckOutFrame(VCMEncodedFrame* frameOut, unsigned int size, bool startCode)
}
}
}
return 0;
}
@ -200,7 +204,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -258,7 +262,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
TEST(CheckOutFrame(frameOut, size*2, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -335,7 +339,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
TEST(CheckOutFrame(frameOut, size*100, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameKey);
@ -411,7 +415,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
TEST(CheckOutFrame(frameOut, size*100, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -488,7 +492,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
TEST(CheckOutFrame(frameOut, size*100, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -588,7 +592,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
TEST(CheckOutFrame(frameOut, size*2, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -599,7 +603,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
TEST(CheckOutFrame(frameOut, size*2, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -664,7 +668,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, (size*2)-1, false);
TEST(CheckOutFrame(frameOut, (size*2)-1, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -729,7 +733,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
TEST(CheckOutFrame(frameOut, size*2, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -788,7 +792,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2+4*2, true);
TEST(CheckOutFrame(frameOut, size*2+4*2, true) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -825,7 +829,7 @@ int JitterBufferTest(CmdArgs& args)
// TEST packet loss. Verify missing packets statistics and not decodable
// packets statistics.
// Insert 10 frames consisting of 4 packets and remove one from all of them.
// The last packet is a empty (non-media) packet
// The last packet is an empty (non-media) packet
//
// Select a start seqNum which triggers a difficult wrap situation
@ -851,16 +855,16 @@ int JitterBufferTest(CmdArgs& args)
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
// Get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
// Check incoming frame type
TEST(incomingFrameType == frametype);
// get the frame
// Get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
// Should not be complete
TEST(frameOut == 0);
seqNum += 2;
@ -890,11 +894,11 @@ int JitterBufferTest(CmdArgs& args)
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// get the frame
// Get the frame
frameOut = jb.GetFrameForDecoding();
// One of the packets has been discarded by the jitter buffer
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == frametype);
@ -1017,7 +1021,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
TEST(CheckOutFrame(frameOut, size*100, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1110,7 +1114,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
TEST(CheckOutFrame(frameOut, size*100, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1195,7 +1199,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*3, false);
TEST(CheckOutFrame(frameOut, size*3, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1238,7 +1242,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(3000 == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1290,7 +1294,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(timeStamp == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1356,7 +1360,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
TEST(CheckOutFrame(frameOut, size*2, false) == 0);
seqNum++;
timeStamp += 33*90;
@ -1398,7 +1402,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
TEST(CheckOutFrame(frameOut, size*2, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1459,7 +1463,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(0xffffff00 == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1472,7 +1476,7 @@ int JitterBufferTest(CmdArgs& args)
VCMEncodedFrame* frameOut2 = jb.GetCompleteFrameForDecoding(10);
TEST(2700 == frameOut2->TimeStamp());
CheckOutFrame(frameOut2, size, false);
TEST(CheckOutFrame(frameOut2, size, false) == 0);
// check the frame type
TEST(frameOut2->FrameType() == kVideoFrameDelta);
@ -1534,7 +1538,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(0xffffff00 == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
@ -1547,7 +1551,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut2 = jb.GetCompleteFrameForDecoding(10);
TEST(2700 == frameOut2->TimeStamp());
CheckOutFrame(frameOut2, size, false);
TEST(CheckOutFrame(frameOut2, size, false) == 0);
// check the frame type
TEST(frameOut2->FrameType() == kVideoFrameDelta);
@ -1684,7 +1688,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameKey);
@ -1971,7 +1975,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(ptrFirstKeyFrame == frameOut);
CheckOutFrame(frameOut, size, false);
TEST(CheckOutFrame(frameOut, size, false) == 0);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameKey);
@ -2149,7 +2153,7 @@ int JitterBufferTest(CmdArgs& args)
// We can decode everything from a NALU until a packet has been lost.
// Thus we can decode the first packet of the first NALU and the second NALU
// which consists of one packet.
CheckOutFrame(frameOut, packet.sizeBytes * 2, false);
TEST(CheckOutFrame(frameOut, packet.sizeBytes * 2, false) == 0);
jb.ReleaseFrame(frameOut);
// Test reordered start frame + 1 lost
@ -2213,7 +2217,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetFrameForDecoding();
// Only last NALU is complete
CheckOutFrame(frameOut, insertedLength, false);
TEST(CheckOutFrame(frameOut, insertedLength, false) == 0);
jb.ReleaseFrame(frameOut);
@ -2262,7 +2266,7 @@ int JitterBufferTest(CmdArgs& args)
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// Only last NALU is complete
CheckOutFrame(frameOut, packet.sizeBytes, false);
TEST(CheckOutFrame(frameOut, packet.sizeBytes, false) == 0);
jb.Flush();
// Three reordered H263 packets with bits.
@ -2352,7 +2356,7 @@ int JitterBufferTest(CmdArgs& args)
frameOut = jb.GetFrameForDecoding();
TEST(frameOut != NULL);
CheckOutFrame(frameOut, packet.sizeBytes, false);
TEST(CheckOutFrame(frameOut, packet.sizeBytes, false) == 0);
jb.Flush();