VCM: 1. Updating handling of empty packets. 2. Updating JB test. 3. Removing un-used code.
Review URL: http://webrtc-codereview.appspot.com/59001 git-svn-id: http://webrtc.googlecode.com/svn/trunk@142 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
c13708271a
commit
cdc943e2d5
@ -113,8 +113,9 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet, WebRtc_Word64 timeInMs)
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
if (_size + packet.sizeBytes + (packet.insertStartCode?kH264StartCodeLengthBytes:0) >
|
||||
kMaxJBFrameSizeBytes)
|
||||
if (_size + packet.sizeBytes +
|
||||
(packet.insertStartCode ? kH264StartCodeLengthBytes : 0 )
|
||||
> kMaxJBFrameSizeBytes)
|
||||
{
|
||||
return kSizeError;
|
||||
}
|
||||
@ -122,7 +123,8 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet, WebRtc_Word64 timeInMs)
|
||||
{
|
||||
return kSizeError;
|
||||
}
|
||||
if(!_sessionInfo.HaveStartSeqNumber())
|
||||
if ((packet.frameType != kFrameEmpty) &&
|
||||
(!_sessionInfo.HaveStartSeqNumber()))
|
||||
{
|
||||
_sessionInfo.SetStartSeqNumber(packet.seqNum);
|
||||
}
|
||||
@ -133,13 +135,13 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet, WebRtc_Word64 timeInMs)
|
||||
|
||||
if (kStateEmpty == _state)
|
||||
{
|
||||
// This is the first packet (empty and/or data) inserted into this frame.
|
||||
// First packet (empty and/or media) inserted into this frame.
|
||||
// store some info and set some initial values.
|
||||
_timeStamp = packet.timestamp;
|
||||
_codec = packet.codec;
|
||||
// for the first media packet
|
||||
if (packet.frameType != kFrameEmpty)
|
||||
{
|
||||
// first media packet
|
||||
SetState(kStateIncomplete);
|
||||
}
|
||||
}
|
||||
@ -148,9 +150,12 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet, WebRtc_Word64 timeInMs)
|
||||
(packet.insertStartCode ? kH264StartCodeLengthBytes : 0);
|
||||
if (requiredSizeBytes >= _size)
|
||||
{
|
||||
const WebRtc_UWord32 increments = requiredSizeBytes / kBufferIncStepSizeBytes +
|
||||
(requiredSizeBytes % kBufferIncStepSizeBytes > 0);
|
||||
const WebRtc_UWord32 newSize = _size + increments * kBufferIncStepSizeBytes;
|
||||
const WebRtc_UWord32 increments = requiredSizeBytes /
|
||||
kBufferIncStepSizeBytes +
|
||||
(requiredSizeBytes %
|
||||
kBufferIncStepSizeBytes > 0);
|
||||
const WebRtc_UWord32 newSize = _size +
|
||||
increments * kBufferIncStepSizeBytes;
|
||||
if (newSize > kMaxJBFrameSizeBytes)
|
||||
{
|
||||
return kSizeError;
|
||||
|
@ -666,7 +666,7 @@ VCMJitterBuffer::CheckForCompleteFrame(VCMFrameListItem* oldestFrameItem)
|
||||
// Verify that we have received the first packet of the next frame.
|
||||
// This is the only way we can be sure we're not missing the last packet.
|
||||
if (nextFrame != NULL && nextFrame->GetLowSeqNum() ==
|
||||
static_cast<WebRtc_UWord16>(oldestFrame->GetHighSeqNum()+1)) // Sequence number is only 16 bit
|
||||
static_cast<WebRtc_UWord16>(oldestFrame->GetHighSeqNum() + 1))
|
||||
{
|
||||
_missingMarkerBits = true;
|
||||
bool completeSession = oldestFrame->ForceSetHaveLastPacket();
|
||||
@ -800,7 +800,8 @@ VCMJitterBuffer::GetCompleteFrameForDecoding(WebRtc_UWord32 maxWaitTimeMS)
|
||||
_critSect.Leave();
|
||||
return NULL;
|
||||
}
|
||||
const WebRtc_Word64 endWaitTimeMs = VCMTickTime::MillisecondTimestamp() + maxWaitTimeMS;
|
||||
const WebRtc_Word64 endWaitTimeMs = VCMTickTime::MillisecondTimestamp()
|
||||
+ maxWaitTimeMS;
|
||||
WebRtc_Word64 waitTimeMs = maxWaitTimeMS;
|
||||
while (waitTimeMs > 0)
|
||||
{
|
||||
@ -849,7 +850,7 @@ VCMJitterBuffer::GetCompleteFrameForDecoding(WebRtc_UWord32 maxWaitTimeMS)
|
||||
|
||||
if (oldestFrame == NULL)
|
||||
{
|
||||
// Even after signalling we're still missing a complete _continuous_ frame
|
||||
// Even after signaling we're still missing a complete _continuous_ frame
|
||||
_critSect.Leave();
|
||||
return NULL;
|
||||
}
|
||||
@ -1269,7 +1270,8 @@ VCMJitterBuffer::GetNackList(WebRtc_UWord16& nackSize,bool& listExtended)
|
||||
|
||||
// Assume called internally with critsect
|
||||
WebRtc_Word32
|
||||
VCMJitterBuffer::GetLowHighSequenceNumbers(WebRtc_Word32& lowSeqNum, WebRtc_Word32& highSeqNum) const
|
||||
VCMJitterBuffer::GetLowHighSequenceNumbers(WebRtc_Word32& lowSeqNum,
|
||||
WebRtc_Word32& highSeqNum) const
|
||||
{
|
||||
int i = 0;
|
||||
int seqNum = -1;
|
||||
@ -1277,7 +1279,7 @@ VCMJitterBuffer::GetLowHighSequenceNumbers(WebRtc_Word32& lowSeqNum, WebRtc_Word
|
||||
highSeqNum = -1;
|
||||
lowSeqNum = _lastDecodedSeqNum;
|
||||
|
||||
// find highest seqnumbers
|
||||
// find highest seq numbers
|
||||
for (i = 0; i < _maxNumberOfFrames; ++i)
|
||||
{
|
||||
seqNum = _frameBuffers[i]->GetHighSeqNum();
|
||||
@ -1342,11 +1344,13 @@ VCMJitterBuffer::CreateNackList(WebRtc_UWord16& nackSize, bool& listExtended)
|
||||
//This happens if we lose the first packet, nothing is popped
|
||||
if (highSeqNum == -1)
|
||||
{
|
||||
nackSize = 0;// we have not received any packets yet
|
||||
// we have not received any packets yet
|
||||
nackSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nackSize = 0xffff; // signal that we want a key frame request to be sent
|
||||
// signal that we want a key frame request to be sent
|
||||
nackSize = 0xffff;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -1368,9 +1372,10 @@ VCMJitterBuffer::CreateNackList(WebRtc_UWord16& nackSize, bool& listExtended)
|
||||
if (numberOfSeqNum > kNackHistoryLength)
|
||||
{
|
||||
// Nack list is too big, flush and try to restart.
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
|
||||
"Nack list too large, try to find a key frame and restart from seq: %d."
|
||||
" Lowest seq in jb %d", highSeqNum,lowSeqNum);
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
|
||||
VCMId(_vcmId, _receiverId),
|
||||
"Nack list too large, try to find a key frame and restart "
|
||||
"from seq: %d. Lowest seq in jb %d", highSeqNum,lowSeqNum);
|
||||
|
||||
// This nack size will trigger a key request...
|
||||
bool foundIFrame = false;
|
||||
@ -1463,8 +1468,8 @@ VCMJitterBuffer::CreateNackList(WebRtc_UWord16& nackSize, bool& listExtended)
|
||||
(kStateDecoding != state))
|
||||
{
|
||||
// Reaching thus far means we are going to update the nack list
|
||||
// When in hybrid mode, we also need to check empty frames, so as not
|
||||
// to add empty packets to the nack list
|
||||
// When in hybrid mode, we also need to check empty frames, so as
|
||||
// not to add empty packets to the nack list
|
||||
if (_nackMode == kNackHybrid)
|
||||
{
|
||||
// build external rttScore based on RTT value
|
||||
@ -1534,7 +1539,7 @@ VCMJitterBuffer::CreateNackList(WebRtc_UWord16& nackSize, bool& listExtended)
|
||||
listExtended = true;
|
||||
}
|
||||
|
||||
for(WebRtc_UWord32 j = 0; j < nackSize; j++)
|
||||
for (WebRtc_UWord32 j = 0; j < nackSize; j++)
|
||||
{
|
||||
// Check if the list has been extended since it was last created. I.e,
|
||||
// new items have been added
|
||||
@ -1543,7 +1548,7 @@ VCMJitterBuffer::CreateNackList(WebRtc_UWord16& nackSize, bool& listExtended)
|
||||
WebRtc_UWord32 k = 0;
|
||||
for (k = j; k < _NACKSeqNumLength; k++)
|
||||
{
|
||||
// Found the item in the last list. I.e, no new items found yet.
|
||||
// Found the item in the last list, i.e, no new items found yet.
|
||||
if (_NACKSeqNum[k] == (WebRtc_UWord16)_NACKSeqNumInternal[j])
|
||||
{
|
||||
break;
|
||||
@ -1727,7 +1732,8 @@ void
|
||||
VCMJitterBuffer::UpdateOldJitterSample(const VCMPacket& packet)
|
||||
{
|
||||
if (_waitingForCompletion.timestamp != packet.timestamp &&
|
||||
LatestTimestamp(_waitingForCompletion.timestamp, packet.timestamp) == packet.timestamp)
|
||||
LatestTimestamp(_waitingForCompletion.timestamp, packet.timestamp) ==
|
||||
packet.timestamp)
|
||||
{
|
||||
// This is a newer frame than the one waiting for completion.
|
||||
_waitingForCompletion.frameSize = packet.sizeBytes;
|
||||
@ -1798,7 +1804,10 @@ VCMJitterBuffer::RecycleFramesUntilKeyFrame()
|
||||
{
|
||||
// Throw at least one frame.
|
||||
_dropCount++;
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId), "Jitter buffer drop count:%d, lowSeq %d", _dropCount, oldestFrame->GetLowSeqNum());
|
||||
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
|
||||
VCMId(_vcmId, _receiverId),
|
||||
"Jitter buffer drop count:%d, lowSeq %d", _dropCount,
|
||||
oldestFrame->GetLowSeqNum());
|
||||
_frameBuffersTSOrder.Erase(oldestFrameListItem);
|
||||
RecycleFrame(oldestFrame);
|
||||
|
||||
@ -1810,12 +1819,15 @@ VCMJitterBuffer::RecycleFramesUntilKeyFrame()
|
||||
|
||||
if(oldestFrame != NULL)
|
||||
{
|
||||
foundIFrame = foundIFrame || (oldestFrame->FrameType() != kVideoFrameDelta);
|
||||
foundIFrame = foundIFrame ||
|
||||
(oldestFrame->FrameType() != kVideoFrameDelta);
|
||||
if (foundIFrame)
|
||||
{
|
||||
// fake the last played out to match the start of this key frame
|
||||
_lastDecodedSeqNum = (WebRtc_UWord16)((WebRtc_UWord16)(oldestFrame->GetLowSeqNum()) - 1);
|
||||
_lastDecodedTimeStamp = (WebRtc_UWord32)(oldestFrame->TimeStamp() - 1);
|
||||
_lastDecodedSeqNum = (WebRtc_UWord16)((WebRtc_UWord16)
|
||||
(oldestFrame->GetLowSeqNum()) - 1);
|
||||
_lastDecodedTimeStamp = (WebRtc_UWord32)
|
||||
(oldestFrame->TimeStamp() - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1843,7 +1855,8 @@ VCMJitterBuffer::CleanUpOldFrames()
|
||||
|
||||
// Release the frame if it's older than the last decoded frame.
|
||||
if (_lastDecodedTimeStamp > -1 &&
|
||||
LatestTimestamp(static_cast<WebRtc_UWord32>(_lastDecodedTimeStamp), frameTimeStamp)
|
||||
LatestTimestamp(static_cast<WebRtc_UWord32>(_lastDecodedTimeStamp),
|
||||
frameTimeStamp)
|
||||
== static_cast<WebRtc_UWord32>(_lastDecodedTimeStamp))
|
||||
{
|
||||
const WebRtc_Word32 frameLowSeqNum = oldestFrame->GetLowSeqNum();
|
||||
@ -1855,7 +1868,8 @@ VCMJitterBuffer::CleanUpOldFrames()
|
||||
{
|
||||
// Could happen when sending filler data.
|
||||
// Filler packet (size = 0) belonging to last decoded frame.
|
||||
// Frame: | packet | packet | packet M=1 | filler data (size = 0) | filler data (size = 0)| ...
|
||||
// Frame: | packet | packet | packet M=1 |
|
||||
// filler data (size = 0) | filler data (size = 0)| ...
|
||||
|
||||
// This frame follows the last decoded frame
|
||||
_lastDecodedSeqNum = frameHighSeqNum;
|
||||
@ -1966,7 +1980,8 @@ VCMJitterBuffer::VerifyAndSetPreviousFrameLost(VCMFrameBuffer& frame)
|
||||
// First frame
|
||||
frame.SetPreviousFrameLoss();
|
||||
}
|
||||
else if (frame.GetLowSeqNum() != ((WebRtc_UWord16)_lastDecodedSeqNum + (WebRtc_UWord16)1))
|
||||
else if (frame.GetLowSeqNum() != ((WebRtc_UWord16)_lastDecodedSeqNum +
|
||||
(WebRtc_UWord16)1))
|
||||
{
|
||||
// Frame loss
|
||||
frame.SetPreviousFrameLoss();
|
||||
@ -1992,12 +2007,7 @@ VCMJitterBuffer::WaitForNack()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// RTT low, we can afford the wait
|
||||
else if (_rttMs <= kLowRttNackMs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// interim values - hybrid mode
|
||||
// Either NACK only or hybrid
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -55,11 +55,11 @@ enum { kH264StartCodeLengthBytes = 4};
|
||||
// Used to indicate if a received packet contain a complete NALU (or equivalent)
|
||||
enum VCMNaluCompleteness
|
||||
{
|
||||
kNaluUnset=0, //Packet has not been filled.
|
||||
kNaluComplete=1, //Packet can be decoded as is.
|
||||
kNaluStart, // Packet contain beginning of NALU
|
||||
kNaluIncomplete, //Packet is not beginning or end of NALU
|
||||
kNaluEnd // Packet is the end of a NALU
|
||||
kNaluUnset = 0, //Packet has not been filled.
|
||||
kNaluComplete = 1, //Packet can be decoded as is.
|
||||
kNaluStart, // Packet contain beginning of NALU
|
||||
kNaluIncomplete, //Packet is not beginning or end of NALU
|
||||
kNaluEnd, // Packet is the end of a NALU
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -113,7 +113,7 @@ VCMReceiver::InsertPacket(const VCMPacket& packet,
|
||||
|
||||
WebRtc_Word64 renderTimeMs = _timing.RenderTimeMs(packet.timestamp, nowMs);
|
||||
|
||||
if(renderTimeMs < 0)
|
||||
if (renderTimeMs < 0)
|
||||
{
|
||||
// Render time error. Assume that this is due to some change in
|
||||
// the incoming video stream and reset the JB and the timing.
|
||||
@ -163,7 +163,7 @@ VCMReceiver::InsertPacket(const VCMPacket& packet,
|
||||
}
|
||||
|
||||
// Insert packet into jitter buffer
|
||||
// both data and empty packets
|
||||
// both media and empty packets
|
||||
const VCMFrameBufferEnum ret = _jitterBuffer.InsertPacket(buffer, packet);
|
||||
|
||||
if (ret < 0)
|
||||
|
@ -27,7 +27,8 @@ VCMSessionInfo::VCMSessionInfo():
|
||||
_highSeqNum(-1),
|
||||
_highestPacketIndex(0),
|
||||
_emptySeqNumLow(-1),
|
||||
_emptySeqNumHigh(-1)
|
||||
_emptySeqNumHigh(-1),
|
||||
_markerSeqNum(-1)
|
||||
{
|
||||
memset(_packetSizeBytes, 0, sizeof(_packetSizeBytes));
|
||||
memset(_naluCompleteness, kNaluUnset, sizeof(_naluCompleteness));
|
||||
@ -47,6 +48,10 @@ VCMSessionInfo::GetLowSeqNum() const
|
||||
WebRtc_Word32
|
||||
VCMSessionInfo::GetHighSeqNum() const
|
||||
{
|
||||
if (_emptySeqNumHigh != -1)
|
||||
{
|
||||
return _emptySeqNumHigh;
|
||||
}
|
||||
return _highSeqNum;
|
||||
}
|
||||
|
||||
@ -64,6 +69,7 @@ VCMSessionInfo::Reset()
|
||||
_previousFrameLoss = false;
|
||||
_sessionNACK = false;
|
||||
_highestPacketIndex = 0;
|
||||
_markerSeqNum = -1;
|
||||
memset(_packetSizeBytes, 0, sizeof(_packetSizeBytes));
|
||||
memset(_naluCompleteness, kNaluUnset, sizeof(_naluCompleteness));
|
||||
memset(_ORwithPrevByte, 0, sizeof(_ORwithPrevByte));
|
||||
@ -89,7 +95,7 @@ VCMSessionInfo::SetStartSeqNumber(WebRtc_UWord16 seqNumber)
|
||||
bool
|
||||
VCMSessionInfo::HaveStartSeqNumber()
|
||||
{
|
||||
if(_lowSeqNum == -1 || _highSeqNum == -1)
|
||||
if (_lowSeqNum == -1 || _highSeqNum == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -118,7 +124,7 @@ VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer,
|
||||
else
|
||||
{
|
||||
packetSize = packet.sizeBytes +
|
||||
(packet.insertStartCode?kH264StartCodeLengthBytes:0);
|
||||
(packet.insertStartCode ? kH264StartCodeLengthBytes : 0);
|
||||
}
|
||||
|
||||
_packetSizeBytes[packetIndex] += packetSize;
|
||||
@ -146,7 +152,8 @@ VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer,
|
||||
_ORwithPrevByte[packetIndex] = true;
|
||||
if (packet.dataPtr != NULL)
|
||||
{
|
||||
memcpy((void*)(ptrStartOfLayer + offset), packet.dataPtr, packetSize);
|
||||
memcpy((void*)(ptrStartOfLayer + offset), packet.dataPtr,
|
||||
packetSize);
|
||||
}
|
||||
returnLength = packetSize;
|
||||
}
|
||||
@ -155,14 +162,14 @@ VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer,
|
||||
_ORwithPrevByte[packetIndex] = false;
|
||||
if (packet.dataPtr != NULL)
|
||||
{
|
||||
const unsigned char startCode[] = {0, 0, 0, 1};
|
||||
const unsigned char startCode[] = {0, 0, 0, 1};
|
||||
if(packet.insertStartCode)
|
||||
{
|
||||
memcpy((void*)(ptrStartOfLayer + offset), startCode,
|
||||
kH264StartCodeLengthBytes);
|
||||
}
|
||||
memcpy((void*)(ptrStartOfLayer + offset
|
||||
+ (packet.insertStartCode?kH264StartCodeLengthBytes:0)),
|
||||
+ (packet.insertStartCode ? kH264StartCodeLengthBytes : 0)),
|
||||
packet.dataPtr,
|
||||
packet.sizeBytes);
|
||||
}
|
||||
@ -172,16 +179,14 @@ VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer,
|
||||
if (packet.isFirstPacket)
|
||||
{
|
||||
_haveFirstPacket = true;
|
||||
//initializing FEC sequence numbers
|
||||
_emptySeqNumHigh = -1;
|
||||
_emptySeqNumLow = -1;
|
||||
}
|
||||
if (packet.markerBit)
|
||||
{
|
||||
_markerBit = true;
|
||||
_markerSeqNum = packet.seqNum;
|
||||
}
|
||||
// Store information about if the packet is decodable as is or not.
|
||||
_naluCompleteness[packetIndex]=packet.completeNALU;
|
||||
_naluCompleteness[packetIndex] = packet.completeNALU;
|
||||
|
||||
UpdateCompleteSession();
|
||||
|
||||
@ -193,9 +198,10 @@ VCMSessionInfo::UpdateCompleteSession()
|
||||
{
|
||||
if (_haveFirstPacket && _markerBit)
|
||||
{
|
||||
// do we have all packets in this session?
|
||||
// Do we have all the packets in this session?
|
||||
bool completeSession = true;
|
||||
for (int i = 0; i<= _highestPacketIndex; ++i)
|
||||
|
||||
for (int i = 0; i <= _highestPacketIndex; ++i)
|
||||
{
|
||||
if (_naluCompleteness[i] == kNaluUnset)
|
||||
{
|
||||
@ -213,13 +219,12 @@ bool VCMSessionInfo::IsSessionComplete()
|
||||
}
|
||||
|
||||
// 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,
|
||||
WebRtc_Word32& startIndex,
|
||||
WebRtc_Word32& endIndex)
|
||||
{
|
||||
|
||||
if (_naluCompleteness[packetIndex] == kNaluStart ||
|
||||
_naluCompleteness[packetIndex] == kNaluComplete)
|
||||
{
|
||||
@ -230,10 +235,11 @@ VCMSessionInfo::FindNaluBorder(WebRtc_Word32 packetIndex,
|
||||
for (startIndex = packetIndex - 1; startIndex >= 0; --startIndex)
|
||||
{
|
||||
|
||||
if( (_naluCompleteness[startIndex] == kNaluComplete &&
|
||||
_packetSizeBytes[startIndex] > 0) ||
|
||||
// Found previous NALU.
|
||||
(_naluCompleteness[startIndex] == kNaluEnd && startIndex>0))
|
||||
if ((_naluCompleteness[startIndex] == kNaluComplete &&
|
||||
_packetSizeBytes[startIndex] > 0) ||
|
||||
// Found previous NALU.
|
||||
(_naluCompleteness[startIndex] == kNaluEnd &&
|
||||
startIndex > 0))
|
||||
{
|
||||
startIndex++;
|
||||
break;
|
||||
@ -246,31 +252,35 @@ VCMSessionInfo::FindNaluBorder(WebRtc_Word32 packetIndex,
|
||||
}
|
||||
}
|
||||
|
||||
if(_naluCompleteness[packetIndex] == kNaluEnd ||
|
||||
if (_naluCompleteness[packetIndex] == kNaluEnd ||
|
||||
_naluCompleteness[packetIndex] == kNaluComplete)
|
||||
{
|
||||
endIndex=packetIndex;
|
||||
endIndex = packetIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the next NALU
|
||||
for (endIndex=packetIndex+1;endIndex<=_highestPacketIndex;++endIndex)
|
||||
for (endIndex = packetIndex + 1; endIndex <= _highestPacketIndex;
|
||||
++endIndex)
|
||||
{
|
||||
if ((_naluCompleteness[endIndex]==kNaluComplete &&
|
||||
_packetSizeBytes[endIndex]>0) ||
|
||||
_naluCompleteness[endIndex]==kNaluStart) // Found next NALU.
|
||||
if ((_naluCompleteness[endIndex] == kNaluComplete &&
|
||||
_packetSizeBytes[endIndex] > 0) ||
|
||||
// Found next NALU.
|
||||
_naluCompleteness[endIndex] == kNaluStart)
|
||||
{
|
||||
endIndex--;
|
||||
break;
|
||||
}
|
||||
if ( _naluCompleteness[endIndex]==kNaluEnd)
|
||||
if ( _naluCompleteness[endIndex] == kNaluEnd)
|
||||
{
|
||||
// This is where the NALU end.
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (endIndex > _highestPacketIndex)
|
||||
{
|
||||
endIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,7 +303,7 @@ VCMSessionInfo::DeletePackets(WebRtc_UWord8* ptrStartOfLayer,
|
||||
{
|
||||
// Get the offset we want to move to.
|
||||
int destOffset = 0;
|
||||
for(int j = 0;j < startIndex;j++)
|
||||
for (int j = 0;j < startIndex;j++)
|
||||
{
|
||||
destOffset += _packetSizeBytes[j];
|
||||
}
|
||||
@ -318,15 +328,10 @@ VCMSessionInfo::DeletePackets(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;
|
||||
}
|
||||
else if (_lowSeqNum == _emptySeqNumLow)
|
||||
{
|
||||
// no data packets in this session
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 startIndex = 0;
|
||||
WebRtc_Word32 endIndex = 0;
|
||||
@ -336,7 +341,7 @@ VCMSessionInfo::MakeSessionDecodable(WebRtc_UWord8* ptrStartOfLayer)
|
||||
{
|
||||
if (_naluCompleteness[packetIndex] == kNaluUnset) // Found a lost packet
|
||||
{
|
||||
FindNaluBorder(packetIndex,startIndex,endIndex);
|
||||
FindNaluBorder(packetIndex, startIndex, endIndex);
|
||||
if (startIndex == -1)
|
||||
{
|
||||
startIndex = 0;
|
||||
@ -346,34 +351,37 @@ VCMSessionInfo::MakeSessionDecodable(WebRtc_UWord8* ptrStartOfLayer)
|
||||
endIndex = _highestPacketIndex;
|
||||
}
|
||||
|
||||
returnLength += DeletePackets(ptrStartOfLayer,packetIndex,endIndex);
|
||||
returnLength += DeletePackets(ptrStartOfLayer,
|
||||
packetIndex, endIndex);
|
||||
packetIndex = endIndex;
|
||||
}// end lost packet
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
switch (_naluCompleteness[0])
|
||||
{
|
||||
case kNaluComplete: //Packet can be decoded as is.
|
||||
case kNaluComplete: // Packet can be decoded as is.
|
||||
break;
|
||||
|
||||
case kNaluStart: // Packet contain beginning of NALU- No need to do anything.
|
||||
case kNaluStart:
|
||||
// Packet contain beginning of NALU- No need to do anything.
|
||||
break;
|
||||
case kNaluIncomplete: //Packet is not beginning or end of NALU
|
||||
//Need to find the end of this fua NALU and delete all packets.
|
||||
// Need to find the end of this NALU and delete all packets.
|
||||
FindNaluBorder(0,startIndex,endIndex);
|
||||
if(endIndex == -1) // No end found. Delete
|
||||
if (endIndex == -1) // No end found. Delete
|
||||
{
|
||||
endIndex = _highestPacketIndex;
|
||||
}
|
||||
//Delete this NALU.
|
||||
returnLength += DeletePackets(ptrStartOfLayer,0,endIndex);
|
||||
// Delete this NALU.
|
||||
returnLength += DeletePackets(ptrStartOfLayer, 0, endIndex);
|
||||
break;
|
||||
case kNaluEnd: // Packet is the end of a NALU
|
||||
//Delete this NALU
|
||||
returnLength += DeletePackets(ptrStartOfLayer,0,0);
|
||||
// Delete this NALU
|
||||
returnLength += DeletePackets(ptrStartOfLayer, 0, 0);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
@ -441,7 +449,7 @@ VCMSessionInfo::ZeroOutSeqNumHybrid(WebRtc_Word32* list,
|
||||
}
|
||||
if (_lowSeqNum == -1)
|
||||
{
|
||||
// no packets in this frame
|
||||
// no media packets in this frame
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -478,8 +486,17 @@ VCMSessionInfo::ZeroOutSeqNumHybrid(WebRtc_Word32* list,
|
||||
int i = 0;
|
||||
// Score place holder - based on RTT and partition (when available).
|
||||
const float nackScoreTh = 0.25f;
|
||||
WebRtc_Word32 highMediaPacket = _emptySeqNumLow > _lowSeqNum ?
|
||||
_emptySeqNumLow - 1: _highSeqNum;
|
||||
|
||||
WebRtc_Word32 highMediaPacket;
|
||||
if (_markerSeqNum != -1)
|
||||
{
|
||||
highMediaPacket = _markerSeqNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
highMediaPacket = _emptySeqNumLow - 1 > _highSeqNum ?
|
||||
_emptySeqNumLow - 1: _highSeqNum;
|
||||
}
|
||||
|
||||
while (list[index] <= highMediaPacket && index < numberOfSeqNum)
|
||||
{
|
||||
@ -569,66 +586,12 @@ VCMSessionInfo::UpdatePacketSize(WebRtc_Word32 packetIndex,
|
||||
_packetSizeBytes[packetIndex] = length;
|
||||
}
|
||||
|
||||
void
|
||||
VCMSessionInfo::PrependPacketIndices(WebRtc_Word32 numberOfPacketIndices)
|
||||
{
|
||||
// sanity
|
||||
if ((numberOfPacketIndices +
|
||||
GetHighestPacketIndex() >= kMaxPacketsInJitterBuffer)
|
||||
|| numberOfPacketIndices < 0)
|
||||
{
|
||||
// not allowed
|
||||
assert(!"SessionInfo::PrependPacketIndexes Error: invalid packetIndex");
|
||||
return;
|
||||
}
|
||||
// Works if we have new packets before packetIndex = 0
|
||||
int numOfPacketsToMove = GetHighestPacketIndex()+1;
|
||||
memmove(&_packetSizeBytes[numberOfPacketIndices], &_packetSizeBytes[0],
|
||||
(numOfPacketsToMove)*sizeof(WebRtc_UWord16));
|
||||
memset(&_packetSizeBytes[0], 0, numberOfPacketIndices*sizeof(WebRtc_UWord16));
|
||||
|
||||
_highestPacketIndex += (WebRtc_UWord16)numberOfPacketIndices;
|
||||
}
|
||||
|
||||
void
|
||||
VCMSessionInfo::ClearPacketSize(WebRtc_Word32 packetIndex)
|
||||
{
|
||||
// sanity
|
||||
if (packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0)
|
||||
{
|
||||
// not allowed
|
||||
assert(!"SessionInfo::ClearPacketSize Error: invalid packetIndex");
|
||||
return;
|
||||
}
|
||||
_packetSizeBytes[packetIndex] = 0;
|
||||
}
|
||||
|
||||
WebRtc_UWord32
|
||||
VCMSessionInfo::GetPacketSize(WebRtc_Word32 packetIndex)
|
||||
{
|
||||
// sanity
|
||||
if (packetIndex >= kMaxPacketsInJitterBuffer || packetIndex < 0)
|
||||
{
|
||||
//not allowed
|
||||
assert(!"SessionInfo::GetPacketSize Error: invalid packetIndex");
|
||||
return 0;
|
||||
}
|
||||
return _packetSizeBytes[packetIndex];
|
||||
}
|
||||
|
||||
WebRtc_Word64
|
||||
VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
||||
WebRtc_UWord8* ptrStartOfLayer)
|
||||
{
|
||||
// not allowed
|
||||
assert(!packet.insertStartCode || !packet.bits);
|
||||
|
||||
if (packet.frameType == kFrameEmpty)
|
||||
{
|
||||
// update seq number as an empty packet
|
||||
// empty packets will be counted twice: both empty and standard packets.
|
||||
InformOfEmptyPacket(packet.seqNum);
|
||||
}
|
||||
// Check if this is first packet (only valid for some codecs)
|
||||
if (packet.isFirstPacket)
|
||||
{
|
||||
@ -637,12 +600,18 @@ VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
||||
}
|
||||
else if (_frameType == kFrameEmpty && packet.frameType != kFrameEmpty)
|
||||
{
|
||||
// in case an empty packet came in first, update the frame type
|
||||
// Update the frame type with the first media packet
|
||||
_frameType = packet.frameType;
|
||||
}
|
||||
if (packet.frameType == kFrameEmpty)
|
||||
{
|
||||
// update seq number as an empty packet
|
||||
InformOfEmptyPacket(packet.seqNum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check sequence number and update highest and lowest sequence numbers received.
|
||||
// Move data if this seq num is lower than previously lowest.
|
||||
// Check sequence number and update highest and lowest sequence numbers
|
||||
// received. Move data if this seq num is lower than previously lowest.
|
||||
|
||||
if (packet.seqNum > _highSeqNum)
|
||||
{
|
||||
@ -672,19 +641,22 @@ VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
||||
+ (WebRtc_UWord16)1;
|
||||
} else
|
||||
{
|
||||
// This packet's seq num is lower than previously lowest seq num, but no wrap
|
||||
// We need to move the data in all arrays indexed by packetIndex and insert the new
|
||||
// packet's info
|
||||
// This packet's seq num is lower than previously lowest seq num,
|
||||
// but no wrap We need to move the data in all arrays indexed by
|
||||
// packetIndex and insert the new packet's info
|
||||
// How many packets should we leave room for (positions to shift)?
|
||||
// Example - this seq num is 3 lower than previously lowest seq num
|
||||
// Before: |--prev packet with lowest seq num--|--|...|
|
||||
// After: |--new lowest seq num--|--|--|--prev packet with lowest seq num--|--|...|
|
||||
// After: |--new lowest seq num--|--|--|--prev packet with
|
||||
// lowest seq num--|--|...|
|
||||
|
||||
WebRtc_UWord16 positionsToShift = (WebRtc_UWord16)_lowSeqNum - packet.seqNum;
|
||||
WebRtc_UWord16 positionsToShift = (WebRtc_UWord16)_lowSeqNum -
|
||||
packet.seqNum;
|
||||
WebRtc_UWord16 numOfPacketsToMove = _highestPacketIndex + 1;
|
||||
|
||||
// sanity, do we have room for the shift?
|
||||
if ((positionsToShift + numOfPacketsToMove) > kMaxPacketsInJitterBuffer)
|
||||
if ((positionsToShift + numOfPacketsToMove) >
|
||||
kMaxPacketsInJitterBuffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ -696,13 +668,17 @@ VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
||||
|
||||
// Shift _packetSizeBytes array
|
||||
memmove(&_packetSizeBytes[positionsToShift],
|
||||
&_packetSizeBytes[0], numOfPacketsToMove*sizeof(WebRtc_UWord32));
|
||||
memset(&_packetSizeBytes[0], 0, positionsToShift*sizeof(WebRtc_UWord32));
|
||||
&_packetSizeBytes[0],
|
||||
numOfPacketsToMove * sizeof(WebRtc_UWord32));
|
||||
memset(&_packetSizeBytes[0], 0,
|
||||
positionsToShift * sizeof(WebRtc_UWord32));
|
||||
|
||||
//Shift _naluCompleteness
|
||||
// Shift _naluCompleteness
|
||||
memmove(&_naluCompleteness[positionsToShift],
|
||||
&_naluCompleteness[0], numOfPacketsToMove*sizeof(WebRtc_UWord8));
|
||||
memset(&_naluCompleteness[0], kNaluUnset, positionsToShift*sizeof(WebRtc_UWord8));
|
||||
&_naluCompleteness[0],
|
||||
numOfPacketsToMove * sizeof(WebRtc_UWord8));
|
||||
memset(&_naluCompleteness[0], kNaluUnset,
|
||||
positionsToShift * sizeof(WebRtc_UWord8));
|
||||
|
||||
_highestPacketIndex += positionsToShift;
|
||||
_lowSeqNum = packet.seqNum;
|
||||
@ -723,7 +699,7 @@ VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
||||
// Check for duplicate packets
|
||||
if (_packetSizeBytes[packetIndex] != 0)
|
||||
{
|
||||
// We have already received a packet with this sequence number, ignore it.
|
||||
// We have already received a packet with this seq number, ignore it.
|
||||
return -2;
|
||||
}
|
||||
|
||||
@ -743,7 +719,7 @@ VCMSessionInfo::InformOfEmptyPacket(const WebRtc_UWord16 seqNum)
|
||||
// and low sequence numbers and may assume that the packets in between are
|
||||
// empty packets belonging to the same frame (timestamp).
|
||||
|
||||
if (_emptySeqNumLow == -1 && _emptySeqNumHigh == -1)
|
||||
if (_emptySeqNumLow == -1 && _emptySeqNumHigh == -1)
|
||||
{
|
||||
_emptySeqNumLow = seqNum;
|
||||
_emptySeqNumHigh = seqNum;
|
||||
@ -795,23 +771,27 @@ VCMSessionInfo::PrepareForDecode(WebRtc_UWord8* ptrStartOfLayer,
|
||||
{
|
||||
if (currentPacketOffset > 0)
|
||||
{
|
||||
WebRtc_UWord8* ptrFirstByte = ptrStartOfLayer + currentPacketOffset;
|
||||
WebRtc_UWord8* ptrFirstByte = ptrStartOfLayer +
|
||||
currentPacketOffset;
|
||||
|
||||
if (_packetSizeBytes[i-1] == 0 || previousLost)
|
||||
{
|
||||
// It is be better to throw away this packet if we are missing the
|
||||
// previous packet.
|
||||
// It is be better to throw away this packet if we are
|
||||
// missing the previous packet.
|
||||
memset(ptrFirstByte, 0, _packetSizeBytes[i]);
|
||||
previousLost = true;
|
||||
}
|
||||
else if (_packetSizeBytes[i] > 0) // Ignore if empty packet
|
||||
{
|
||||
// Glue with previous byte
|
||||
// Move everything from [this packet start + 1, end of buffer] one byte to the left
|
||||
// Move everything from [this packet start + 1,
|
||||
// end of buffer] one byte to the left
|
||||
WebRtc_UWord8* ptrPrevByte = ptrFirstByte - 1;
|
||||
*ptrPrevByte = (*ptrPrevByte) | (*ptrFirstByte);
|
||||
WebRtc_UWord32 lengthToEnd = length - (currentPacketOffset + 1);
|
||||
memmove((void*)ptrFirstByte, (void*)(ptrFirstByte + 1), lengthToEnd);
|
||||
WebRtc_UWord32 lengthToEnd = length -
|
||||
(currentPacketOffset + 1);
|
||||
memmove((void*)ptrFirstByte, (void*)(ptrFirstByte + 1),
|
||||
lengthToEnd);
|
||||
_packetSizeBytes[i]--;
|
||||
length--;
|
||||
previousLost = false;
|
||||
@ -827,7 +807,8 @@ VCMSessionInfo::PrepareForDecode(WebRtc_UWord8* ptrStartOfLayer,
|
||||
else if (_packetSizeBytes[i] == 0 && codec == kVideoCodecH263)
|
||||
{
|
||||
WebRtc_UWord8* ptrFirstByte = ptrStartOfLayer + currentPacketOffset;
|
||||
memmove(ptrFirstByte + 10, ptrFirstByte, length - currentPacketOffset);
|
||||
memmove(ptrFirstByte + 10, ptrFirstByte,
|
||||
length - currentPacketOffset);
|
||||
memset(ptrFirstByte, 0, 10);
|
||||
_packetSizeBytes[i] = 10;
|
||||
length += _packetSizeBytes[i];
|
||||
|
@ -47,16 +47,14 @@ public:
|
||||
webrtc::FrameType FrameType() const { return _frameType; }
|
||||
|
||||
virtual WebRtc_Word32 GetHighestPacketIndex();
|
||||
virtual WebRtc_UWord32 GetPacketSize(WebRtc_Word32 packetIndex);
|
||||
virtual void ClearPacketSize(WebRtc_Word32 packetIndex);
|
||||
virtual void UpdatePacketSize(WebRtc_Word32 packetIndex, WebRtc_UWord32 length);
|
||||
virtual void PrependPacketIndices(WebRtc_Word32 numberOfPacketIndexes);
|
||||
|
||||
void SetStartSeqNumber(WebRtc_UWord16 seqNumber);
|
||||
|
||||
bool HaveStartSeqNumber();
|
||||
|
||||
WebRtc_Word32 GetLowSeqNum() const;
|
||||
// returns highest seqNum, media or empty
|
||||
WebRtc_Word32 GetHighSeqNum() const;
|
||||
|
||||
WebRtc_UWord32 PrepareForDecode(WebRtc_UWord8* ptrStartOfLayer, VideoCodecType codec);
|
||||
@ -94,6 +92,8 @@ protected:
|
||||
WebRtc_UWord8 _naluCompleteness[kMaxPacketsInJitterBuffer];
|
||||
WebRtc_Word32 _emptySeqNumLow;
|
||||
WebRtc_Word32 _emptySeqNumHigh;
|
||||
// Store the sequence number that marks the last media packet
|
||||
WebRtc_Word32 _markerSeqNum;
|
||||
bool _ORwithPrevByte[kMaxPacketsInJitterBuffer];
|
||||
};
|
||||
|
||||
|
@ -1786,7 +1786,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
//printf("DONE fill JB - number of delta frames > max number of frames\n");
|
||||
|
||||
//
|
||||
// TEST fill JB with more than max number of frame (50 delta frames + 51 key frames) with wrap in seqNum
|
||||
// TEST fill JB with more than max number of frame (50 delta frames +
|
||||
// 51 key frames) with wrap in seqNum
|
||||
//
|
||||
// --------------------------------------------------------------
|
||||
// | 65485 | 65486 | 65487 | .... | 65535 | 0 | 1 | 2 | .....| 50 |
|
||||
@ -1829,7 +1830,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// Get packet notification, should be first inserted frame
|
||||
TEST(timeStampStart == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
|
||||
TEST(timeStampStart == jb.GetNextTimeStamp(10, incomingFrameType,
|
||||
renderTimeMs));
|
||||
|
||||
// check incoming frame type
|
||||
TEST(incomingFrameType == kVideoFrameDelta);
|
||||
@ -1849,13 +1851,15 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
// Now, no free frame - frames will be recycled until first key frame
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0 && frameIn && ptrLastDeltaFrame); // ptr to last inserted delta frame should be returned
|
||||
// ptr to last inserted delta frame should be returned
|
||||
TEST(frameIn != 0 && frameIn && ptrLastDeltaFrame);
|
||||
|
||||
// Insert frame
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// First inserted key frame should be oldest in buffer
|
||||
TEST(timeStampFirstKey == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
|
||||
TEST(timeStampFirstKey == jb.GetNextTimeStamp(10, incomingFrameType,
|
||||
renderTimeMs));
|
||||
|
||||
// check incoming frame type
|
||||
TEST(incomingFrameType == kVideoFrameKey);
|
||||
@ -1874,7 +1878,93 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
jb.Flush();
|
||||
|
||||
//printf("DONE fill JB - nr of delta + key frames (w/ wrap in seqNum) > max nr of frames\n");
|
||||
// printf("DONE fill JB - nr of delta + key frames (w/ wrap in seqNum) >
|
||||
// max nr of frames\n");
|
||||
|
||||
// Test handling empty packets
|
||||
// first insert 2 empty packets
|
||||
jb.ReleaseFrame(frameIn);
|
||||
timeStamp = 33 * 90;
|
||||
seqNum = 5;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
frameIn = jb.GetFrame(packet);
|
||||
TEST(frameIn);
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
seqNum = 6;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
// now insert the first data packet
|
||||
seqNum = 1;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
|
||||
// insert an additional data packet
|
||||
seqNum = 2;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
|
||||
// insert the last packet and verify frame completness
|
||||
// (even though packet 4 (empty) is missing)
|
||||
seqNum = 3;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = true;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kVideoFrameDelta;
|
||||
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
|
||||
jb.Flush();
|
||||
|
||||
// testing that empty packets do not clog the jitter buffer
|
||||
// Set hybrid mode
|
||||
jb.SetNackMode(kNackHybrid);
|
||||
TEST(jb.GetNackMode() == kNackHybrid);
|
||||
|
||||
int maxSize = 100;
|
||||
seqNum = 3;
|
||||
VCMEncodedFrame* testFrame;
|
||||
for (int i = 0; i < maxSize + 10; i++)
|
||||
{
|
||||
timeStamp += 33 * 90;
|
||||
packet.isFirstPacket = false;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
testFrame = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
TEST(kFirstPacket == jb.InsertPacket(testFrame, packet));
|
||||
}
|
||||
// verify insertion of a data packet (old empty frames will be flushed)
|
||||
timeStamp += 33 * 90;
|
||||
packet.isFirstPacket = true;
|
||||
packet.markerBit = false;
|
||||
packet.seqNum = seqNum;
|
||||
packet.timestamp = timeStamp;
|
||||
packet.frameType = kFrameEmpty;
|
||||
testFrame = jb.GetFrame(packet);
|
||||
TEST(frameIn != 0);
|
||||
|
||||
jb.SetNackMode(kNoNack);
|
||||
|
||||
|
||||
// printf(DONE testing inserting empty packets to the JB)
|
||||
|
||||
|
||||
// H.264 tests
|
||||
//Test incomplete NALU frames
|
||||
@ -1977,7 +2067,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
packet.completeNALU=kNaluStart;
|
||||
packet.markerBit=false;
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
insertedLength+=packet.sizeBytes; // This packet should be decoded since it's the beginning of a NAL
|
||||
// This packet should be decoded since it's the beginning of a NAL
|
||||
insertedLength+=packet.sizeBytes;
|
||||
|
||||
seqNum+=2;
|
||||
packet.seqNum=seqNum;
|
||||
@ -1987,10 +2078,13 @@ int JitterBufferTest(CmdArgs& args)
|
||||
packet.completeNALU=kNaluEnd;
|
||||
packet.markerBit=true;
|
||||
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
|
||||
insertedLength+=0; // This packet should not be decoded because it is an incomplete NAL if it is the last
|
||||
// This packet should not be decoded because it is an incomplete NAL if it
|
||||
// is the last
|
||||
insertedLength+=0;
|
||||
|
||||
frameOut = jb.GetFrameForDecoding();
|
||||
CheckOutFrame(frameOut, insertedLength, false); // Only last NALU is complete
|
||||
// Only last NALU is complete
|
||||
CheckOutFrame(frameOut, insertedLength, false);
|
||||
jb.ReleaseFrame(frameOut);
|
||||
|
||||
|
||||
@ -2006,7 +2100,9 @@ int JitterBufferTest(CmdArgs& args)
|
||||
emptypacket.markerBit=true;
|
||||
TEST(frameIn=jb.GetFrame(emptypacket));
|
||||
TEST(kFirstPacket == jb.InsertPacket(frameIn, emptypacket));
|
||||
insertedLength+=0; // This packet should not be decoded because it is an incomplete NAL if it is the last
|
||||
// This packet should not be decoded because it is an incomplete NAL if it
|
||||
// is the last
|
||||
insertedLength+=0;
|
||||
|
||||
TEST(-1 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
|
||||
TEST(NULL==jb.GetFrameForDecoding());
|
||||
@ -2036,8 +2132,8 @@ int JitterBufferTest(CmdArgs& args)
|
||||
|
||||
// get the frame
|
||||
frameOut = jb.GetCompleteFrameForDecoding(10);
|
||||
CheckOutFrame(frameOut, packet.sizeBytes, false); // Only last NALU is complete
|
||||
|
||||
// Only last NALU is complete
|
||||
CheckOutFrame(frameOut, packet.sizeBytes, false);
|
||||
jb.Flush();
|
||||
|
||||
// Three reordered H263 packets with bits.
|
||||
|
Loading…
x
Reference in New Issue
Block a user