VCM/JB: Setting only non-empty frames for decoding (when not waiting for NACK).

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@117 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mikhal@google.com 2011-06-22 17:25:06 +00:00
parent 5b95bcd22c
commit 2b83acef3e
2 changed files with 106 additions and 67 deletions

View File

@ -58,7 +58,8 @@ VCMJitterBuffer::CompleteDecodableKeyFrameCriteria(VCMFrameBuffer* frame,
} }
// Constructor // Constructor
VCMJitterBuffer::VCMJitterBuffer(WebRtc_Word32 vcmId, WebRtc_Word32 receiverId, bool master) : VCMJitterBuffer::VCMJitterBuffer(WebRtc_Word32 vcmId, WebRtc_Word32 receiverId,
bool master) :
_vcmId(vcmId), _vcmId(vcmId),
_receiverId(receiverId), _receiverId(receiverId),
_running(false), _running(false),
@ -216,7 +217,8 @@ VCMJitterBuffer::Start()
_NACKSeqNumLength = 0; _NACKSeqNumLength = 0;
_rttMs = 0; _rttMs = 0;
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId), "JB(0x%x): Jitter buffer: start", this); WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId,
_receiverId), "JB(0x%x): Jitter buffer: start", this);
} }
@ -240,7 +242,8 @@ VCMJitterBuffer::Stop()
_critSect.Leave(); _critSect.Leave();
_frameEvent.Set(); // Make sure we exit from trying to get a frame to decoder _frameEvent.Set(); // Make sure we exit from trying to get a frame to decoder
_packetEvent.Set(); // Make sure we exit from trying to get a sequence number _packetEvent.Set(); // Make sure we exit from trying to get a sequence number
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId), "JB(0x%x): Jitter buffer: stop", this); WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId,
_receiverId), "JB(0x%x): Jitter buffer: stop", this);
} }
bool bool
@ -290,8 +293,8 @@ VCMJitterBuffer::FlushInternal()
_NACKSeqNumLength = 0; _NACKSeqNumLength = 0;
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId), WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId,
"JB(0x%x): Jitter buffer: flush", this); _receiverId), "JB(0x%x): Jitter buffer: flush", this);
} }
// Set the frame state to free and remove it from the sorted // Set the frame state to free and remove it from the sorted
@ -314,8 +317,9 @@ VCMJitterBuffer::UpdateFrameState(VCMFrameBuffer* frame)
{ {
if (frame == NULL) if (frame == NULL)
{ {
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId), WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
"JB(0x%x) FB(0x%x): UpdateFrameState NULL frame pointer", this, frame); VCMId(_vcmId, _receiverId), "JB(0x%x) FB(0x%x): "
"UpdateFrameState NULL frame pointer", this, frame);
return; return;
} }
@ -518,8 +522,9 @@ VCMJitterBuffer::GetEmptyFrame()
_maxNumberOfFrames++; _maxNumberOfFrames++;
_critSect.Leave(); _critSect.Leave();
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId), "JB(0x%x) FB(0x%x): Jitter buffer increased to:%d frames", WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
this, ptrNewBuffer, _maxNumberOfFrames); VCMId(_vcmId, _receiverId), "JB(0x%x) FB(0x%x): Jitter buffer "
"increased to:%d frames", this, ptrNewBuffer, _maxNumberOfFrames);
return ptrNewBuffer; return ptrNewBuffer;
} }
_critSect.Leave(); _critSect.Leave();
@ -1084,9 +1089,8 @@ VCMJitterBuffer::GetFrameForDecoding()
_waitingForCompletion.frameSize = oldestFrame->Length(); _waitingForCompletion.frameSize = oldestFrame->Length();
_waitingForCompletion.latestPacketTime = oldestFrame->LatestPacketTimeMs(); _waitingForCompletion.latestPacketTime = oldestFrame->LatestPacketTimeMs();
_waitingForCompletion.timestamp = oldestFrame->TimeStamp(); _waitingForCompletion.timestamp = oldestFrame->TimeStamp();
oldestFrame->SetState(kStateDecoding);
} }
oldestFrame->SetState(kStateDecoding);
_frameBuffersTSOrder.Erase(oldestFrameListItem); _frameBuffersTSOrder.Erase(oldestFrameListItem);
oldestFrameListItem = NULL; oldestFrameListItem = NULL;
@ -1098,7 +1102,7 @@ VCMJitterBuffer::GetFrameForDecoding()
// store current time // store current time
_lastDecodedTimeStamp = oldestFrame->TimeStamp(); _lastDecodedTimeStamp = oldestFrame->TimeStamp();
// store seqnum // store seqnum
_lastDecodedSeqNum = oldestFrame->GetHighSeqNum(); _lastDecodedSeqNum = oldestFrame->GetHighSeqNum();
return oldestFrame; return oldestFrame;
@ -1282,9 +1286,9 @@ VCMJitterBuffer::GetLowHighSequenceNumbers(WebRtc_Word32& lowSeqNum, WebRtc_Word
VCMFrameBufferStateEnum state = _frameBuffers[i]->GetState(); VCMFrameBufferStateEnum state = _frameBuffers[i]->GetState();
if ((kStateFree != state) && if ((kStateFree != state) &&
(kStateEmpty != state) && (kStateEmpty != state) &&
(kStateDecoding != state) && (kStateDecoding != state) &&
seqNum != -1) seqNum != -1)
{ {
if (highSeqNum == -1) if (highSeqNum == -1)
{ {

View File

@ -38,17 +38,20 @@ VCMSessionInfo::~VCMSessionInfo()
{ {
} }
WebRtc_Word32 VCMSessionInfo::GetLowSeqNum() const WebRtc_Word32
VCMSessionInfo::GetLowSeqNum() const
{ {
return _lowSeqNum; return _lowSeqNum;
} }
WebRtc_Word32 VCMSessionInfo::GetHighSeqNum() const WebRtc_Word32
VCMSessionInfo::GetHighSeqNum() const
{ {
return _highSeqNum; return _highSeqNum;
} }
void VCMSessionInfo::Reset() void
VCMSessionInfo::Reset()
{ {
_lowSeqNum = -1; _lowSeqNum = -1;
_highSeqNum = -1; _highSeqNum = -1;
@ -93,9 +96,10 @@ VCMSessionInfo::HaveStartSeqNumber()
return true; return true;
} }
WebRtc_UWord32 VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer, WebRtc_UWord32
WebRtc_Word32 packetIndex, VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer,
const VCMPacket& packet) WebRtc_Word32 packetIndex,
const VCMPacket& packet)
{ {
WebRtc_UWord32 moveLength = 0; WebRtc_UWord32 moveLength = 0;
WebRtc_UWord32 returnLength = 0; WebRtc_UWord32 returnLength = 0;
@ -184,7 +188,8 @@ WebRtc_UWord32 VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer,
return returnLength; return returnLength;
} }
void VCMSessionInfo::UpdateCompleteSession() void
VCMSessionInfo::UpdateCompleteSession()
{ {
if (_haveFirstPacket && _markerBit) if (_haveFirstPacket && _markerBit)
{ {
@ -209,19 +214,20 @@ bool VCMSessionInfo::IsSessionComplete()
// Find the start and end index of packetIndex packet. // Find the start and end index of packetIndex packet.
// startIndex -1 if start not found endIndex=-1 if end index not found // startIndex -1 if start not found endIndex=-1 if end index not found
void VCMSessionInfo::FindNaluBorder(WebRtc_Word32 packetIndex, void
WebRtc_Word32& startIndex, VCMSessionInfo::FindNaluBorder(WebRtc_Word32 packetIndex,
WebRtc_Word32& endIndex) WebRtc_Word32& startIndex,
WebRtc_Word32& endIndex)
{ {
if(_naluCompleteness[packetIndex]==kNaluStart || if (_naluCompleteness[packetIndex] == kNaluStart ||
_naluCompleteness[packetIndex]==kNaluComplete) _naluCompleteness[packetIndex] == kNaluComplete)
{ {
startIndex = packetIndex; startIndex = packetIndex;
} }
else // Need to find the start else // Need to find the start
{ {
for(startIndex = packetIndex - 1; startIndex >= 0; --startIndex) for (startIndex = packetIndex - 1; startIndex >= 0; --startIndex)
{ {
if( (_naluCompleteness[startIndex] == kNaluComplete && if( (_naluCompleteness[startIndex] == kNaluComplete &&
@ -233,7 +239,7 @@ void VCMSessionInfo::FindNaluBorder(WebRtc_Word32 packetIndex,
break; break;
} }
// This is where the NALU start. // This is where the NALU start.
if( _naluCompleteness[startIndex] == kNaluStart) if (_naluCompleteness[startIndex] == kNaluStart)
{ {
break; break;
} }
@ -248,38 +254,40 @@ void VCMSessionInfo::FindNaluBorder(WebRtc_Word32 packetIndex,
else else
{ {
// Find the next NALU // Find the next NALU
for(endIndex=packetIndex+1;endIndex<=_highestPacketIndex;++endIndex) for (endIndex=packetIndex+1;endIndex<=_highestPacketIndex;++endIndex)
{ {
if((_naluCompleteness[endIndex]==kNaluComplete && if ((_naluCompleteness[endIndex]==kNaluComplete &&
_packetSizeBytes[endIndex]>0) || _packetSizeBytes[endIndex]>0) ||
_naluCompleteness[endIndex]==kNaluStart) // Found next NALU. _naluCompleteness[endIndex]==kNaluStart) // Found next NALU.
{ {
endIndex--; endIndex--;
break; break;
} }
if( _naluCompleteness[endIndex]==kNaluEnd) // This is where the NALU end. if ( _naluCompleteness[endIndex]==kNaluEnd)
{ {
// This is where the NALU end.
break; break;
} }
} }
if(endIndex > _highestPacketIndex) if (endIndex > _highestPacketIndex)
endIndex = -1; endIndex = -1;
} }
} }
// Deletes all packets between startIndex and endIndex // Deletes all packets between startIndex and endIndex
WebRtc_UWord32 VCMSessionInfo::DeletePackets(WebRtc_UWord8* ptrStartOfLayer, WebRtc_UWord32
WebRtc_Word32 startIndex, VCMSessionInfo::DeletePackets(WebRtc_UWord8* ptrStartOfLayer,
WebRtc_Word32 endIndex) WebRtc_Word32 startIndex,
WebRtc_Word32 endIndex)
{ {
//Get the number of bytes to delete. //Get the number of bytes to delete.
//Clear the size of these packets. //Clear the size of these packets.
WebRtc_UWord32 bytesToDelete = 0; /// The number of bytes to delete. WebRtc_UWord32 bytesToDelete = 0; /// The number of bytes to delete.
for(int j = startIndex;j <= endIndex; ++j) for (int j = startIndex;j <= endIndex; ++j)
{ {
bytesToDelete += _packetSizeBytes[j]; bytesToDelete += _packetSizeBytes[j];
_packetSizeBytes[j]=0; _packetSizeBytes[j] = 0;
} }
if (bytesToDelete > 0) if (bytesToDelete > 0)
{ {
@ -291,7 +299,7 @@ WebRtc_UWord32 VCMSessionInfo::DeletePackets(WebRtc_UWord8* ptrStartOfLayer,
} }
//Get the number of bytes to move //Get the number of bytes to move
WebRtc_UWord32 numberOfBytesToMove=0; WebRtc_UWord32 numberOfBytesToMove = 0;
for (int j = endIndex + 1; j <= _highestPacketIndex; ++j) for (int j = endIndex + 1; j <= _highestPacketIndex; ++j)
{ {
numberOfBytesToMove += _packetSizeBytes[j]; numberOfBytesToMove += _packetSizeBytes[j];
@ -307,10 +315,18 @@ WebRtc_UWord32 VCMSessionInfo::DeletePackets(WebRtc_UWord8* ptrStartOfLayer,
// Makes the layer decodable. Ie only contain decodable NALU // Makes the layer decodable. Ie only contain decodable NALU
// return the number of bytes deleted from the session. -1 if an error occurs // return the number of bytes deleted from the session. -1 if an error occurs
WebRtc_UWord32 VCMSessionInfo::MakeSessionDecodable(WebRtc_UWord8* ptrStartOfLayer) WebRtc_UWord32
VCMSessionInfo::MakeSessionDecodable(WebRtc_UWord8* ptrStartOfLayer)
{ {
if(_lowSeqNum < 0) // No packets in this session if(_lowSeqNum < 0) // No packets in this session
{
return 0; return 0;
}
else if (_lowSeqNum == _emptySeqNumLow)
{
// no data packets in this session
return 0;
}
WebRtc_Word32 startIndex = 0; WebRtc_Word32 startIndex = 0;
WebRtc_Word32 endIndex = 0; WebRtc_Word32 endIndex = 0;
@ -321,10 +337,14 @@ WebRtc_UWord32 VCMSessionInfo::MakeSessionDecodable(WebRtc_UWord8* ptrStartOfLay
if (_naluCompleteness[packetIndex] == kNaluUnset) // Found a lost packet if (_naluCompleteness[packetIndex] == kNaluUnset) // Found a lost packet
{ {
FindNaluBorder(packetIndex,startIndex,endIndex); FindNaluBorder(packetIndex,startIndex,endIndex);
if(startIndex == -1) if (startIndex == -1)
{
startIndex = 0; startIndex = 0;
if(endIndex == -1) }
if (endIndex == -1)
{
endIndex = _highestPacketIndex; endIndex = _highestPacketIndex;
}
returnLength += DeletePackets(ptrStartOfLayer,packetIndex,endIndex); returnLength += DeletePackets(ptrStartOfLayer,packetIndex,endIndex);
packetIndex = endIndex; packetIndex = endIndex;
@ -332,9 +352,9 @@ WebRtc_UWord32 VCMSessionInfo::MakeSessionDecodable(WebRtc_UWord8* ptrStartOfLay
} }
//Make sure the first packet is decodable (Either complete nalu or start of NALU) //Make sure the first packet is decodable (Either complete nalu or start of NALU)
if(_packetSizeBytes[0] > 0) if (_packetSizeBytes[0] > 0)
{ {
switch(_naluCompleteness[0]) switch (_naluCompleteness[0])
{ {
case kNaluComplete: //Packet can be decoded as is. case kNaluComplete: //Packet can be decoded as is.
break; break;
@ -363,8 +383,9 @@ WebRtc_UWord32 VCMSessionInfo::MakeSessionDecodable(WebRtc_UWord8* ptrStartOfLay
return returnLength; return returnLength;
} }
WebRtc_Word32 VCMSessionInfo::ZeroOutSeqNum(WebRtc_Word32* list, WebRtc_Word32
WebRtc_Word32 numberOfSeqNum) VCMSessionInfo::ZeroOutSeqNum(WebRtc_Word32* list,
WebRtc_Word32 numberOfSeqNum)
{ {
if ((NULL == list) || (numberOfSeqNum < 1)) if ((NULL == list) || (numberOfSeqNum < 1))
{ {
@ -402,16 +423,17 @@ WebRtc_Word32 VCMSessionInfo::ZeroOutSeqNum(WebRtc_Word32* list,
i++; i++;
index++; index++;
} }
if(!_haveFirstPacket) if (!_haveFirstPacket)
{ {
_sessionNACK = true; _sessionNACK = true;
} }
return 0; return 0;
} }
WebRtc_Word32 VCMSessionInfo::ZeroOutSeqNumHybrid(WebRtc_Word32* list, WebRtc_Word32
WebRtc_Word32 numberOfSeqNum, VCMSessionInfo::ZeroOutSeqNumHybrid(WebRtc_Word32* list,
float rttScore) WebRtc_Word32 numberOfSeqNum,
float rttScore)
{ {
if ((NULL == list) || (numberOfSeqNum < 1)) if ((NULL == list) || (numberOfSeqNum < 1))
{ {
@ -508,31 +530,37 @@ WebRtc_Word32 VCMSessionInfo::ZeroOutSeqNumHybrid(WebRtc_Word32* list,
return 0; return 0;
} }
WebRtc_Word32 VCMSessionInfo::GetHighestPacketIndex() WebRtc_Word32
VCMSessionInfo::GetHighestPacketIndex()
{ {
return _highestPacketIndex; return _highestPacketIndex;
} }
bool VCMSessionInfo::HaveLastPacket() bool
VCMSessionInfo::HaveLastPacket()
{ {
return _markerBit; return _markerBit;
} }
void VCMSessionInfo::ForceSetHaveLastPacket() void
VCMSessionInfo::ForceSetHaveLastPacket()
{ {
_markerBit = true; _markerBit = true;
UpdateCompleteSession(); UpdateCompleteSession();
} }
bool VCMSessionInfo::IsRetransmitted() bool
VCMSessionInfo::IsRetransmitted()
{ {
return _sessionNACK; return _sessionNACK;
} }
void VCMSessionInfo::UpdatePacketSize(WebRtc_Word32 packetIndex, WebRtc_UWord32 length) void
VCMSessionInfo::UpdatePacketSize(WebRtc_Word32 packetIndex,
WebRtc_UWord32 length)
{ {
// sanity // sanity
if(packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0) if (packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0)
{ {
// not allowed // not allowed
assert(!"SessionInfo::UpdatePacketSize Error: invalid packetIndex"); assert(!"SessionInfo::UpdatePacketSize Error: invalid packetIndex");
@ -541,11 +569,13 @@ void VCMSessionInfo::UpdatePacketSize(WebRtc_Word32 packetIndex, WebRtc_UWord32
_packetSizeBytes[packetIndex] = length; _packetSizeBytes[packetIndex] = length;
} }
void VCMSessionInfo::PrependPacketIndices(WebRtc_Word32 numberOfPacketIndices) void
VCMSessionInfo::PrependPacketIndices(WebRtc_Word32 numberOfPacketIndices)
{ {
// sanity // sanity
if((numberOfPacketIndices + GetHighestPacketIndex() >= kMaxPacketsInJitterBuffer) if ((numberOfPacketIndices +
|| numberOfPacketIndices < 0) GetHighestPacketIndex() >= kMaxPacketsInJitterBuffer)
|| numberOfPacketIndices < 0)
{ {
// not allowed // not allowed
assert(!"SessionInfo::PrependPacketIndexes Error: invalid packetIndex"); assert(!"SessionInfo::PrependPacketIndexes Error: invalid packetIndex");
@ -560,10 +590,11 @@ void VCMSessionInfo::PrependPacketIndices(WebRtc_Word32 numberOfPacketIndices)
_highestPacketIndex += (WebRtc_UWord16)numberOfPacketIndices; _highestPacketIndex += (WebRtc_UWord16)numberOfPacketIndices;
} }
void VCMSessionInfo::ClearPacketSize(WebRtc_Word32 packetIndex) void
VCMSessionInfo::ClearPacketSize(WebRtc_Word32 packetIndex)
{ {
// sanity // sanity
if(packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0) if (packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0)
{ {
// not allowed // not allowed
assert(!"SessionInfo::ClearPacketSize Error: invalid packetIndex"); assert(!"SessionInfo::ClearPacketSize Error: invalid packetIndex");
@ -572,10 +603,11 @@ void VCMSessionInfo::ClearPacketSize(WebRtc_Word32 packetIndex)
_packetSizeBytes[packetIndex] = 0; _packetSizeBytes[packetIndex] = 0;
} }
WebRtc_UWord32 VCMSessionInfo::GetPacketSize(WebRtc_Word32 packetIndex) WebRtc_UWord32
VCMSessionInfo::GetPacketSize(WebRtc_Word32 packetIndex)
{ {
// sanity // sanity
if(packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0) if (packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0)
{ {
//not allowed //not allowed
assert(!"SessionInfo::GetPacketSize Error: invalid packetIndex"); assert(!"SessionInfo::GetPacketSize Error: invalid packetIndex");
@ -585,9 +617,10 @@ WebRtc_UWord32 VCMSessionInfo::GetPacketSize(WebRtc_Word32 packetIndex)
} }
WebRtc_Word64 WebRtc_Word64
VCMSessionInfo::InsertPacket(const VCMPacket& packet, WebRtc_UWord8* ptrStartOfLayer) VCMSessionInfo::InsertPacket(const VCMPacket& packet,
WebRtc_UWord8* ptrStartOfLayer)
{ {
//not allowed // not allowed
assert(!packet.insertStartCode || !packet.bits); assert(!packet.insertStartCode || !packet.bits);
if (packet.frameType == kFrameEmpty) if (packet.frameType == kFrameEmpty)
@ -695,7 +728,8 @@ VCMSessionInfo::InsertPacket(const VCMPacket& packet, WebRtc_UWord8* ptrStartOfL
} }
// update highest packet index // update highest packet index
_highestPacketIndex = packetIndex > _highestPacketIndex ? packetIndex :_highestPacketIndex; _highestPacketIndex = packetIndex > _highestPacketIndex ?
packetIndex :_highestPacketIndex;
return InsertBuffer(ptrStartOfLayer, packetIndex, packet); return InsertBuffer(ptrStartOfLayer, packetIndex, packet);
} }
@ -743,7 +777,8 @@ VCMSessionInfo::InformOfEmptyPacket(const WebRtc_UWord16 seqNum)
} }
WebRtc_UWord32 WebRtc_UWord32
VCMSessionInfo::PrepareForDecode(WebRtc_UWord8* ptrStartOfLayer, VideoCodecType codec) VCMSessionInfo::PrepareForDecode(WebRtc_UWord8* ptrStartOfLayer,
VideoCodecType codec)
{ {
WebRtc_UWord32 currentPacketOffset = 0; WebRtc_UWord32 currentPacketOffset = 0;
WebRtc_UWord32 length = GetSessionLength(); WebRtc_UWord32 length = GetSessionLength();