207 lines
5.5 KiB
C++
207 lines
5.5 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 "receiver_tests.h"
|
||
|
#include "video_coding.h"
|
||
|
#include "rtp_rtcp.h"
|
||
|
#include "trace.h"
|
||
|
#include "tick_time.h"
|
||
|
#include "../source/event.h"
|
||
|
#include "../source/internal_defines.h"
|
||
|
#include "test_macros.h"
|
||
|
#include "rtp_player.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
using namespace webrtc;
|
||
|
|
||
|
WebRtc_Word32
|
||
|
RtpDataCallback::OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
|
||
|
const WebRtc_UWord16 payloadSize,
|
||
|
const WebRtcRTPHeader* rtpHeader)
|
||
|
{
|
||
|
return _vcm->IncomingPacket(payloadData, payloadSize, *rtpHeader);
|
||
|
}
|
||
|
|
||
|
FrameReceiveCallback::~FrameReceiveCallback()
|
||
|
{
|
||
|
if (_timingFile != NULL)
|
||
|
{
|
||
|
fclose(_timingFile);
|
||
|
}
|
||
|
if (_outFile != NULL)
|
||
|
{
|
||
|
fclose(_outFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WebRtc_Word32
|
||
|
FrameReceiveCallback::FrameToRender(VideoFrame& videoFrame)
|
||
|
{
|
||
|
if (_timingFile == NULL)
|
||
|
{
|
||
|
_timingFile = fopen("renderTiming.txt", "w");
|
||
|
if (_timingFile == NULL)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
if (_outFile == NULL)
|
||
|
{
|
||
|
_outFile = fopen(_outFilename.c_str(), "wb");
|
||
|
if (_outFile == NULL)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
fprintf(_timingFile, "%u, %u\n",
|
||
|
videoFrame.TimeStamp(),
|
||
|
MaskWord64ToUWord32(videoFrame.RenderTimeMs()));
|
||
|
fwrite(videoFrame.Buffer(), 1, videoFrame.Length(), _outFile);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int RtpPlay(CmdArgs& args)
|
||
|
{
|
||
|
// Make sure this test isn't executed without simulated clocks
|
||
|
#if !defined(TICK_TIME_DEBUG) || !defined(EVENT_DEBUG)
|
||
|
return -1;
|
||
|
#endif
|
||
|
// BEGIN Settings
|
||
|
|
||
|
bool protectionEnabled = false;
|
||
|
VCMVideoProtection protectionMethod = kProtectionNack;
|
||
|
WebRtc_UWord32 rttMS = 10;
|
||
|
float lossRate = 0.0f;
|
||
|
bool reordering = false;
|
||
|
WebRtc_UWord32 renderDelayMs = 0;
|
||
|
WebRtc_UWord32 minPlayoutDelayMs = 0;
|
||
|
const WebRtc_Word64 MAX_RUNTIME_MS = -1;
|
||
|
std::string outFile = args.outputFile;
|
||
|
if (outFile == "")
|
||
|
outFile = "RtpPlay_decoded.yuv";
|
||
|
FrameReceiveCallback receiveCallback(outFile);
|
||
|
VideoCodingModule* vcm = VideoCodingModule::Create(1);
|
||
|
RtpDataCallback dataCallback(vcm);
|
||
|
RTPPlayer rtpStream(args.inputFile.c_str(), &dataCallback);
|
||
|
|
||
|
|
||
|
ListWrapper payloadTypes;
|
||
|
payloadTypes.PushFront(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, "VP8", kVideoCodecVP8));
|
||
|
|
||
|
Trace::CreateTrace();
|
||
|
Trace::SetTraceFile("receiverTestTrace.txt");
|
||
|
Trace::SetLevelFilter(webrtc::kTraceAll);
|
||
|
// END Settings
|
||
|
|
||
|
// Set up
|
||
|
|
||
|
WebRtc_Word32 ret = vcm->InitializeReceiver();
|
||
|
if (ret < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
vcm->RegisterReceiveCallback(&receiveCallback);
|
||
|
vcm->RegisterPacketRequestCallback(&rtpStream);
|
||
|
|
||
|
// Register receive codecs in VCM
|
||
|
ListItem* item = payloadTypes.First();
|
||
|
while (item != NULL)
|
||
|
{
|
||
|
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem());
|
||
|
if (payloadType != NULL)
|
||
|
{
|
||
|
VideoCodec codec;
|
||
|
if (VideoCodingModule::Codec(payloadType->codecType, &codec) < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
codec.plType = payloadType->payloadType;
|
||
|
if (vcm->RegisterReceiveCodec(&codec, 1) < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
item = payloadTypes.Next(item);
|
||
|
}
|
||
|
|
||
|
if (rtpStream.Initialize(payloadTypes) < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
bool nackEnabled = protectionEnabled && (protectionMethod == kProtectionNack ||
|
||
|
protectionMethod == kProtectionDualDecoder);
|
||
|
rtpStream.SimulatePacketLoss(lossRate, nackEnabled, rttMS);
|
||
|
rtpStream.SetReordering(reordering);
|
||
|
vcm->SetChannelParameters(0, 0, rttMS);
|
||
|
vcm->SetVideoProtection(protectionMethod, protectionEnabled);
|
||
|
vcm->SetRenderDelay(renderDelayMs);
|
||
|
vcm->SetMinimumPlayoutDelay(minPlayoutDelayMs);
|
||
|
|
||
|
ret = 0;
|
||
|
|
||
|
// RTP stream main loop
|
||
|
while ((ret = rtpStream.NextPacket(VCMTickTime::MillisecondTimestamp())) == 0)
|
||
|
{
|
||
|
if (VCMTickTime::MillisecondTimestamp() % 5 == 0)
|
||
|
{
|
||
|
ret = vcm->Decode();
|
||
|
if (ret < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
while (vcm->DecodeDualFrame(0) == 1);
|
||
|
if (vcm->TimeUntilNextProcess() <= 0)
|
||
|
{
|
||
|
vcm->Process();
|
||
|
}
|
||
|
if (MAX_RUNTIME_MS > -1 && VCMTickTime::MillisecondTimestamp() >= MAX_RUNTIME_MS)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
VCMTickTime::IncrementDebugClock();
|
||
|
}
|
||
|
|
||
|
switch (ret)
|
||
|
{
|
||
|
case 1:
|
||
|
printf("Success\n");
|
||
|
break;
|
||
|
case -1:
|
||
|
printf("Failed\n");
|
||
|
break;
|
||
|
case 0:
|
||
|
printf("Timeout\n");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
rtpStream.Print();
|
||
|
|
||
|
// Tear down
|
||
|
item = payloadTypes.First();
|
||
|
while (item != NULL)
|
||
|
{
|
||
|
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem());
|
||
|
if (payloadType != NULL)
|
||
|
{
|
||
|
delete payloadType;
|
||
|
}
|
||
|
ListItem* itemToRemove = item;
|
||
|
item = payloadTypes.Next(item);
|
||
|
payloadTypes.Erase(itemToRemove);
|
||
|
}
|
||
|
delete vcm;
|
||
|
vcm = NULL;
|
||
|
Trace::ReturnTrace();
|
||
|
return 0;
|
||
|
}
|