webrtc/modules/video_coding/main/test/jitter_buffer_test.cc

2253 lines
59 KiB
C++

/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "common_types.h"
#include "jitter_buffer.h"
#include "jitter_estimator.h"
#include "inter_frame_delay.h"
#include "packet.h"
#include "tick_time.h"
#include "../source/event.h"
#include "frame_buffer.h"
#include "jitter_estimate_test.h"
#include "test_macros.h"
#include "test_util.h"
#include <stdio.h>
#include <math.h>
using namespace webrtc;
void CheckOutFrame(VCMEncodedFrame* frameOut, int size, bool startCode)
{
TEST(frameOut != 0);
const WebRtc_UWord8* outData = frameOut->Buffer();
int i = 0;
if(startCode)
{
TEST(outData[0] == 0);
TEST(outData[1] == 0);
TEST(outData[2] == 0);
TEST(outData[3] == 1);
i+= 4;
}
// check the frame data
int count = 3;
int layer = 0;
// check the frame length
TEST(frameOut->Length() == size);
for(; i < size; i++)
{
if (outData[i] == 0 && outData[i+1] == 0 && outData[i+2] == 0x80)
{
i += 2;
}
else if(startCode && outData[i] == 0 && outData[i+1] == 0)
{
TEST(outData[i] == 0);
TEST(outData[i+1] == 0);
TEST(outData[i+2] == 0);
TEST(outData[i+3] == 1);
i += 3;
}
else
{
if (outData[i] != count)
{
int a=0;
}
TEST(outData[i] == count);
count++;
if(count == 10)
{
count = 3;
}
}
}
}
int JitterBufferTest(CmdArgs& args)
{
// Don't run these tests with debug time
#if defined(TICK_TIME_DEBUG) || defined(EVENT_DEBUG)
return -1;
#endif
// Start test
WebRtc_UWord16 seqNum = 1234;
WebRtc_UWord32 timeStamp = 0;
int size = 1400;
WebRtc_UWord8 data[1500];
VCMPacket packet(data, size, seqNum, timeStamp, true);
VCMFrameListTimestampOrderAsc frameList;
VCMFrameBuffer* fb = NULL;
for (int i=0; i < 100; i++)
{
fb = new VCMFrameBuffer();
fb->SetState(kStateEmpty);
packet.timestamp = 0xfffffff0 + i;
packet.seqNum = seqNum;
packet.payloadType = 126;
seqNum++;
fb->InsertPacket(packet, VCMTickTime::MillisecondTimestamp());
TEST(frameList.Insert(fb) == 0);
}
VCMFrameListItem* item = NULL;
WebRtc_UWord32 prevTimestamp = 0;
int i = 0;
for (i=0; !frameList.Empty(); i++)
{
item = frameList.First();
fb = static_cast<VCMFrameBuffer*>(item->GetItem());
TEST(i > 0 || fb->TimeStamp() == 0xfffffff0); // Frame 0 has no prev
TEST(prevTimestamp - fb->TimeStamp() == -1 || i == 0);
prevTimestamp = fb->TimeStamp();
frameList.Erase(item);
delete fb;
}
TEST(i == 100);
//printf("DONE timestamp ordered frame list\n");
VCMJitterBuffer jb;
seqNum = 1234;
timeStamp = 123*90;
VCMFrameBufferEnum retVal(kNoError);
FrameType incomingFrameType(kVideoFrameKey);
VCMEncodedFrame* frameOut=NULL;
WebRtc_Word64 renderTimeMs = 0;
WebRtc_UWord8 payloadType = 0;
packet.timestamp = timeStamp;
packet.seqNum = seqNum;
// build a data vector with 0, 0, 0x80, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0x80, 3....
data[0] = 0;
data[1] = 0;
data[2] = 0x80;
int count = 3;
for(int i = 3; i < sizeof(data) - 3; ++i )
{
data[i] = count;
count++;
if(count == 10)
{
data[i+1] = 0;
data[i+2] = 0;
data[i+3] = 0x80;
count = 3;
i += 3;
}
}
// Test out of range inputs
TEST(kSizeError == jb.InsertPacket(0, packet));
jb.ReleaseFrame(0);
// Not started
TEST(0 == jb.GetFrame(packet));
TEST(-1 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(0 == jb.GetCompleteFrameForDecoding(10));
TEST(0 == jb.GetFrameForDecoding());
// Start
jb.Start();
// Get frame to use for this timestamp
VCMEncodedFrame* frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// No packets inserted
TEST(0 == jb.GetCompleteFrameForDecoding(10));
//
// TEST single packet frame
//
// --------
// | 1234 |
// --------
// packet.frameType;
// packet.dataPtr;
// packet.sizeBytes;
// packet.timestamp;
// packet.seqNum;
// packet.isFirstPacket;
// packet.markerBit;
//
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE delta frame 1 packet\n");
//
// TEST dual packet frame
//
// -----------------
// | 1235 | 1236 |
// -----------------
//
seqNum++;
timeStamp += 33*90;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE delta frame 2 packets\n");
//
// TEST 100 packets frame Key frame
//
// ----------------------------------
// | 1237 | 1238 | .... | 1336 |
// ----------------------------------
// insert first packet
timeStamp += 33*90;
seqNum++;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameKey);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert 98 frames
int loop = 0;
do
{
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
loop++;
} while (loop < 98);
// insert last packet
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameKey);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE key frame 100 packets\n");
//
// TEST 100 packets frame Delta frame
//
// ----------------------------------
// | 1337 | 1238 | .... | 1436 |
// ----------------------------------
// insert first packet
timeStamp += 33*90;
seqNum++;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert 98 frames
loop = 0;
do
{
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
loop++;
} while (loop < 98);
// insert last packet
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE delta frame 100 packets\n");
//
// TEST packet re-ordering reverse order
//
// ----------------------------------
// | 1437 | 1238 | .... | 1536 |
// ----------------------------------
// <----------
// insert "first" packet last seqnum
timeStamp += 33*90;
seqNum += 100;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert 98 packets
loop = 0;
do
{
seqNum--;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
loop++;
} while (loop < 98);
// insert last packet
seqNum--;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE delta frame 100 packets reverse order\n");
seqNum+= 100;
//
// TEST frame re-ordering 2 frames 2 packets each
//
// ----------------- -----------------
// | 1539 | 1540 | | 1537 | 1538 |
// ----------------- -----------------
seqNum += 2;
timeStamp += 2* 33 * 90;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// check that we fail to get frame since seqnum is not continuous
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(frameOut == 0);
seqNum -= 3;
timeStamp -= 33*90;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
seqNum += 2;
//printf("DONE frame re-ordering 2 frames 2 packets\n");
//
// TEST H.263 bits
//
// -----------------
// | 1541 | 1542 |
// -----------------
// sBits
seqNum++;
timeStamp += 2*33*90;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
packet.bits = false;
packet.codec = kVideoCodecH263;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.bits = true;
packet.dataPtr = &(data[9]);
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, (size*2)-1, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
// restore
packet.dataPtr = data;
packet.bits = false;
packet.codec = kVideoCodecUnknown;
//printf("DONE H.263 frame 2 packets with bits\n");
//
// TEST duplicate packets
//
// -----------------
// | 1543 | 1543 |
// -----------------
//
seqNum++;
timeStamp += 33*90;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
packet.isFirstPacket = false;
packet.markerBit = true;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kDuplicatePacket == jb.InsertPacket(frameIn, packet));
seqNum++;
packet.seqNum = seqNum;
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE test duplicate packets\n");
//
// TEST H.264 insert start code
//
// -----------------
// | 1544 | 1545 |
// -----------------
// insert start code, both packets
seqNum++;
timeStamp += 33*90;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
packet.insertStartCode = true;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2+4*2, true);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
// reset
packet.insertStartCode = false;
//printf("DONE H.264 insert start code test 2 packets\n");
// Temporarily do this to make the rest of the test work:
timeStamp += 33*90;
seqNum += 4;
//
// TEST statistics
//
WebRtc_UWord32 numDeltaFrames = 0;
WebRtc_UWord32 numKeyFrames = 0;
TEST(jb.GetFrameStatistics(numDeltaFrames, numKeyFrames) == 0);
TEST(numDeltaFrames == 9);
TEST(numKeyFrames == 1);
WebRtc_UWord32 frameRate;
WebRtc_UWord32 bitRate;
TEST(jb.GetUpdate(frameRate, bitRate) == 0);
// these depend on CPU speed works on a T61
TEST(frameRate > 30);
TEST(bitRate > 10000000);
//printf("DONE Statistics\n");
//
// TEST delta frame 100 packets with seqNum wrap
//
// ---------------------------------------
// | 65520 | 65521 | ... | 82 | 83 |
// ---------------------------------------
//
// test flush
jb.Flush();
// insert first packet
timeStamp += 33*90;
seqNum = 0xfff0;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert 98 packets
loop = 0;
do
{
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(2, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(2);
// it should not be complete
TEST(frameOut == 0);
loop++;
} while (loop < 98);
// insert last packet
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE delta frame 100 packets with wrap in seqNum\n");
//
// TEST packet re-ordering reverse order with neg seqNum warp
//
// ----------------------------------------
// | 65447 | 65448 | ... | 9 | 10 |
// ----------------------------------------
// <-------------
// test flush
jb.Flush();
// insert "first" packet last seqnum
timeStamp += 33*90;
seqNum = 10;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert 98 frames
loop = 0;
do
{
seqNum--;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(2, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(2);
// it should not be complete
TEST(frameOut == 0);
loop++;
} while (loop < 98);
// insert last packet
seqNum--;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*100, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE delta frame 100 packets reverse order with wrap in seqNum \n");
// test flush
jb.Flush();
//
// TEST packet re-ordering with seqNum wrap
//
// -----------------------
// | 1 | 65535 | 0 |
// -----------------------
// insert "first" packet last seqnum
timeStamp += 33*90;
seqNum = 1;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert last packet
seqNum -= 2;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*3, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE delta frame 3 packets re-ordering with wrap in seqNum \n");
// test flush
jb.Flush();
//
// TEST insert old frame
//
// ------- -------
// | 2 | | 1 |
// ------- -------
// t = 3000 t = 2000
seqNum = 2;
timeStamp = 3000;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(3000 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(3000 == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
seqNum--;
timeStamp = 2000;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
// Changed behavior, never insert packets into frames older than the
// last decoded frame.
TEST(frameIn == 0);
//printf("DONE insert old frame\n");
jb.Flush();
//
// TEST insert old frame with wrap in timestamp
//
// ------- -------
// | 2 | | 1 |
// ------- -------
// t = 3000 t = 0xffffff00
seqNum = 2;
timeStamp = 3000;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(timeStamp == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
seqNum--;
timeStamp = 0xffffff00;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
// This timestamp is old
TEST(frameIn == 0);
jb.Flush();
//
// TEST wrap in timeStamp
//
// --------------- ---------------
// | 1 | 2 | | 3 | 4 |
// --------------- ---------------
// t = 0xffffff00 t = 33*90
seqNum = 1;
timeStamp = 0xffffff00;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
seqNum++;
timeStamp += 33*90;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size*2, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
//printf("DONE time stamp wrap 2 frames 2 packets\n");
jb.Flush();
//
// TEST insert 2 frames with wrap in timeStamp
//
// ------- -------
// | 1 | | 2 |
// ------- -------
// t = 0xffffff00 t = 2700
seqNum = 1;
timeStamp = 0xffffff00;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert first frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// Get packet notification
TEST(0xffffff00 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Insert next frame
seqNum++;
timeStamp = 2700;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// Get packet notification
TEST(0xffffff00 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Get frame
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(0xffffff00 == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// Get packet notification
TEST(2700 == jb.GetNextTimeStamp(0, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Get frame
VCMEncodedFrame* frameOut2 = jb.GetCompleteFrameForDecoding(10);
TEST(2700 == frameOut2->TimeStamp());
CheckOutFrame(frameOut2, size, false);
// check the frame type
TEST(frameOut2->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
jb.ReleaseFrame(frameOut2);
//printf("DONE insert 2 frames (1 packet) with wrap in timestamp\n");
jb.Flush();
//
// TEST insert 2 frames re-ordered with wrap in timeStamp
//
// ------- -------
// | 2 | | 1 |
// ------- -------
// t = 2700 t = 0xffffff00
seqNum = 2;
timeStamp = 2700;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert first frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// Get packet notification
TEST(2700 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Insert second frame
seqNum--;
timeStamp = 0xffffff00;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// Get packet notification
TEST(0xffffff00 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Get frame
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(0xffffff00 == frameOut->TimeStamp());
CheckOutFrame(frameOut, size, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameDelta);
// get packet notification
TEST(2700 == jb.GetNextTimeStamp(0, incomingFrameType, renderTimeMs));
TEST(kVideoFrameDelta == incomingFrameType);
// Get frame
frameOut2 = jb.GetCompleteFrameForDecoding(10);
TEST(2700 == frameOut2->TimeStamp());
CheckOutFrame(frameOut2, size, false);
// check the frame type
TEST(frameOut2->FrameType() == kVideoFrameDelta);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
jb.ReleaseFrame(frameOut2);
//printf("DONE insert 2 frames (1 packet) re-ordered with wrap in timestamp\n");
//
// TEST NACK
//
// ---------------------------------------------------------------------------------------------
// | 3 | 4 | 5 | 6 | 7 | 9 | x | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | x | 21 |.....| 102 |
// ---------------------------------------------------------------------------------------------
jb.SetNackMode(kNackInfinite);
TEST(jb.GetNackMode() == kNackInfinite);
// insert first packet
timeStamp += 33*90;
seqNum += 2;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameKey);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert 98 packets
loop = 0;
do
{
seqNum++;
if(seqNum % 10 != 0)
{
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
}
loop++;
} while (loop < 98);
// insert last packet
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// try to get the frame, should fail
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(frameOut == 0);
// try to get the frame, should fail
frameOut = jb.GetFrameForDecoding();
TEST(frameOut == 0);
WebRtc_UWord16 nackSize = 0;
bool extended = false;
WebRtc_UWord16* list = jb.GetNackList(nackSize, extended);
TEST(nackSize == 10);
for(int i = 0; i < nackSize; i++)
{
TEST(list[i] == (1+i)*10);
}
jb.Stop();
//printf("DONE NACK\n");
//
// TEST NACK with wrap in seqNum
//
// ------- -----------------------------------------------------------------------------------
// | 65532 | | 65533 | 65534 | 65535 | x | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | x | 11 |.....| 96 |
// ------- -----------------------------------------------------------------------------------
jb.Flush();
jb.Start();
// insert first frame
timeStamp = 33*90;
seqNum = 65532;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameKey);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
CheckOutFrame(frameOut, size, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameKey);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
// insert first packet
timeStamp += 33*90;
seqNum++;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = true;
packet.markerBit = false;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// it should not be complete
TEST(frameOut == 0);
// insert 98 packets
loop = 0;
do
{
seqNum++;
if (seqNum % 10 != 0)
{
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// try to get the frame, should fail
frameOut = jb.GetCompleteFrameForDecoding(1);
TEST(frameOut == 0);
// try to get the frame, should fail
frameOut = jb.GetFrameForDecoding();
TEST(frameOut == 0);
}
loop++;
} while (loop < 98);
// insert last packet
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// try to get the frame, should fail
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(frameOut == 0);
// try to get the frame, should fail
frameOut = jb.GetFrameForDecoding();
TEST(frameOut == 0);
nackSize = 0;
list = jb.GetNackList(nackSize, extended);
TEST(nackSize == 10);
for(int i = 0; i < nackSize; i++)
{
TEST(list[i] == i*10);
}
jb.Stop();
//printf("DONE NACK with wrap in seqNum\n");
//
// TEST delta frame with more than max number of packets
//
jb.Start();
loop = 0;
packet.timestamp += 33*90;
bool firstPacket = true;
// insert kMaxPacketsInJitterBuffer into frame
do
{
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert frame
if (firstPacket)
{
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
firstPacket = false;
}
else
{
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
}
// get packet notification
TEST(packet.timestamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
loop++;
} while (loop < kMaxPacketsInJitterBuffer);
// Max number of packets inserted
// Insert one more packet
seqNum++;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.seqNum = seqNum;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert the packet -> frame recycled
TEST(kSizeError == jb.InsertPacket(frameIn, packet));
// should fail
TEST(-1 == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
TEST(0 == jb.GetCompleteFrameForDecoding(10));
//printf("DONE fill frame - packets > max number of packets\n");
//
// TEST fill JB with more than max number of delta frame
//
loop = 0;
WebRtc_UWord32 timeStampStart = timeStamp + 33*90;
// insert MAX_NUMBER_OF_FRAMES frames
do
{
timeStamp += 33*90;
seqNum++;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
// Insert frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStampStart == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
loop++;
} while (loop < kMaxNumberOfFrames);
// Max number of frames inserted
// Insert one more frame
timeStamp += 33*90;
seqNum++;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
// Now, no free frame - frames will be recycled until first key frame
frameIn = jb.GetFrame(packet);
TEST(frameIn); // no key, so we have recycled all frames
//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
//
// --------------------------------------------------------------
// | 65485 | 65486 | 65487 | .... | 65535 | 0 | 1 | 2 | .....| 50 |
// --------------------------------------------------------------
// |<-----------delta frames------------->|<------key frames----->|
jb.Flush();
loop = 0;
seqNum = 65485;
timeStampStart = timeStamp + 33*90;
WebRtc_UWord32 timeStampFirstKey = 0;
VCMEncodedFrame* ptrLastDeltaFrame;
VCMEncodedFrame* ptrFirstKeyFrame;
// insert MAX_NUMBER_OF_FRAMES frames
do
{
timeStamp += 33*90;
seqNum++;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
frameIn = jb.GetFrame(packet);
TEST(frameIn != 0);
if (loop == 49) // last delta
{
ptrLastDeltaFrame = frameIn;
}
if (loop == 50) // first key
{
ptrFirstKeyFrame = frameIn;
packet.frameType = kVideoFrameKey;
timeStampFirstKey = packet.timestamp;
}
// Insert frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
// Get packet notification, should be first inserted frame
TEST(timeStampStart == jb.GetNextTimeStamp(10, incomingFrameType,
renderTimeMs));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameDelta);
loop++;
} while (loop < kMaxNumberOfFrames);
// Max number of frames inserted
// Insert one more frame
timeStamp += 33*90;
seqNum++;
packet.isFirstPacket = true;
packet.markerBit = true;
packet.seqNum = seqNum;
packet.timestamp = timeStamp;
// Now, no free frame - frames will be recycled until first key frame
frameIn = jb.GetFrame(packet);
// 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));
// check incoming frame type
TEST(incomingFrameType == kVideoFrameKey);
// get the first key frame
frameOut = jb.GetCompleteFrameForDecoding(10);
TEST(ptrFirstKeyFrame == frameOut);
CheckOutFrame(frameOut, size, false);
// check the frame type
TEST(frameOut->FrameType() == kVideoFrameKey);
// Release frame (when done with decoding)
jb.ReleaseFrame(frameOut);
jb.Flush();
// 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
jb.Flush();
jb.SetNackMode(kNoNack);
seqNum ++;
timeStamp += 33*90;
int insertedLength=0;
packet.seqNum=seqNum;
packet.timestamp=timeStamp;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = true;
packet.completeNALU=kNaluStart;
packet.markerBit=false;
frameIn=jb.GetFrame(packet);
// Insert a packet into a frame
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
seqNum+=2; // Skip one packet
packet.seqNum=seqNum;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = false;
packet.completeNALU=kNaluIncomplete;
packet.markerBit=false;
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
seqNum++;
packet.seqNum=seqNum;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = false;
packet.completeNALU=kNaluEnd;
packet.markerBit=false;
// Insert a packet into a frame
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
seqNum++;
packet.seqNum=seqNum;
packet.completeNALU=kNaluComplete;
packet.markerBit=true; // Last packet
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// get packet notification
TEST(timeStamp == jb.GetNextTimeStamp(10, incomingFrameType, renderTimeMs));
frameOut = jb.GetFrameForDecoding();
// 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);
jb.ReleaseFrame(frameOut);
// Test reordered start frame + 1 lost
seqNum +=2; // Reoreder 1 frame
timeStamp += 33*90;
insertedLength=0;
packet.seqNum=seqNum;
packet.timestamp=timeStamp;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = false;
packet.completeNALU=kNaluEnd;
packet.markerBit=false;
TEST(frameIn=jb.GetFrame(packet));
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
insertedLength+=packet.sizeBytes; // This packet should be decoded
seqNum--;
packet.seqNum=seqNum;
packet.timestamp=timeStamp;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = true;
packet.completeNALU=kNaluStart;
packet.markerBit=false;
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
insertedLength+=packet.sizeBytes; // This packet should be decoded
seqNum+=3; // One packet drop
packet.seqNum=seqNum;
packet.timestamp=timeStamp;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = false;
packet.completeNALU=kNaluComplete;
packet.markerBit=false;
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
insertedLength+=packet.sizeBytes; // This packet should be decoded
seqNum+=1;
packet.seqNum=seqNum;
packet.timestamp=timeStamp;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = false;
packet.completeNALU=kNaluStart;
packet.markerBit=false;
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// This packet should be decoded since it's the beginning of a NAL
insertedLength+=packet.sizeBytes;
seqNum+=2;
packet.seqNum=seqNum;
packet.timestamp=timeStamp;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = false;
packet.completeNALU=kNaluEnd;
packet.markerBit=true;
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
// This packet should not be decoded because it is an incomplete NAL if it
// is the last
insertedLength+=0;
frameOut = jb.GetFrameForDecoding();
// Only last NALU is complete
CheckOutFrame(frameOut, insertedLength, false);
jb.ReleaseFrame(frameOut);
//Test to insert empty packet
seqNum+=1;
timeStamp += 33*90;
VCMPacket emptypacket(data, 0, seqNum, timeStamp, true);
emptypacket.seqNum=seqNum;
emptypacket.timestamp=timeStamp;
emptypacket.frameType = kVideoFrameKey;
emptypacket.isFirstPacket = true;
emptypacket.completeNALU=kNaluComplete;
emptypacket.markerBit=true;
TEST(frameIn=jb.GetFrame(emptypacket));
TEST(kFirstPacket == jb.InsertPacket(frameIn, emptypacket));
// 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());
// Test that a frame can include an empty packet.
seqNum+=1;
timeStamp += 33*90;
packet.seqNum=seqNum;
packet.timestamp=timeStamp;
packet.frameType = kVideoFrameKey;
packet.isFirstPacket = true;
packet.completeNALU=kNaluComplete;
packet.markerBit=false;
TEST(frameIn=jb.GetFrame(packet));
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
seqNum+=1;
emptypacket.seqNum=seqNum;
emptypacket.timestamp=timeStamp;
emptypacket.frameType = kVideoFrameKey;
emptypacket.isFirstPacket = true;
emptypacket.completeNALU=kNaluComplete;
emptypacket.markerBit=true;
TEST(kCompleteSession == jb.InsertPacket(frameIn, emptypacket));
// get the frame
frameOut = jb.GetCompleteFrameForDecoding(10);
// Only last NALU is complete
CheckOutFrame(frameOut, packet.sizeBytes, false);
jb.Flush();
// Three reordered H263 packets with bits.
packet.codec = kVideoCodecH263;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = false;
packet.markerBit = false;
packet.bits = true;
packet.seqNum += 1;
WebRtc_UWord8 oldData1 = data[0];
WebRtc_UWord8 oldData2 = data[packet.sizeBytes - 1];
unsigned char startByte = 0x07;
unsigned char endByte = 0xF8;
data[0] = startByte;
TEST(frameIn = jb.GetFrame(packet));
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetFrameForDecoding();
TEST(frameOut == NULL);
packet.seqNum -= 1;
packet.isFirstPacket = true;
packet.bits = false;
data[0] = oldData1;
data[packet.sizeBytes - 1] = endByte;
TEST(frameIn = jb.GetFrame(packet));
TEST(kIncomplete == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetFrameForDecoding();
TEST(frameOut == NULL);
packet.seqNum += 2;
packet.isFirstPacket = false;
packet.markerBit = true;
data[packet.sizeBytes - 1] = oldData2;
TEST(frameIn = jb.GetFrame(packet));
TEST(kCompleteSession == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetFrameForDecoding();
TEST(frameOut != NULL);
//CheckOutFrame(frameOut, packet.sizeBytes * 3 - 1, false);
const WebRtc_UWord8* buf = frameOut->Buffer();
TEST(buf[packet.sizeBytes - 1] == (startByte | endByte));
// First packet lost, second packet with bits.
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = false;
packet.markerBit = true;
packet.bits = true;
packet.seqNum += 2;
packet.timestamp += 33*90;
data[0] = 0x07;
data[packet.sizeBytes - 1] = 0xF8;
//unsigned char startByte = packet.dataPtr[0];
//unsigned char endByte = packet.dataPtr[packet.sizeBytes-1];
TEST(frameIn = jb.GetFrame(packet));
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetFrameForDecoding();
TEST(frameOut != NULL);
TEST(frameOut->Length() == 0);
data[0] = oldData1;
data[packet.sizeBytes - 1] = oldData2;
packet.codec = kVideoCodecUnknown;
jb.Flush();
// Test that a we cannot get incomplete frames from the JB if we haven't received
// the marker bit, unless we have received a packet from a later timestamp.
packet.seqNum +=2;
packet.bits = false;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = false;
packet.markerBit = false;
TEST(frameIn = jb.GetFrame(packet));
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetFrameForDecoding();
TEST(frameOut == NULL);
packet.seqNum += 2;
packet.timestamp += 33*90;
TEST(frameIn = jb.GetFrame(packet));
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetFrameForDecoding();
TEST(frameOut != NULL);
CheckOutFrame(frameOut, packet.sizeBytes, false);
jb.Flush();
// Test that a we can get incomplete frames from the JB if we have received
// the marker bit.
packet.seqNum +=2;
packet.frameType = kVideoFrameDelta;
packet.isFirstPacket = false;
packet.markerBit = true;
TEST(frameIn = jb.GetFrame(packet));
TEST(kFirstPacket == jb.InsertPacket(frameIn, packet));
frameOut = jb.GetFrameForDecoding();
TEST(frameOut != NULL);
// ---
jb.Stop();
printf("DONE !!!\n");
EventWrapper* waitEvent = EventWrapper::Create();
waitEvent->Wait(5000);
return 0;
}