blob: 577408fee1e82696bdadeac99493a3e6a64a5bf4 [file] [log] [blame]
/*
* Copyright (c) 2012 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 "../source/event.h"
#include "../source/internal_defines.h"
#include "test_macros.h"
#include "rtp_player.h"
#include "modules/video_coding/main/source/mock/fake_tick_time.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((test::OutputPath() + "renderTiming.txt").c_str(),
"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 events.
#if !defined(EVENT_DEBUG)
return -1;
#endif
// BEGIN Settings
bool protectionEnabled = false;
VCMVideoProtection protectionMethod = kProtectionNack;
WebRtc_UWord32 rttMS = 0;
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 = test::OutputPath() + "RtpPlay_decoded.yuv";
FrameReceiveCallback receiveCallback(outFile);
FakeTickTime clock(0);
VideoCodingModule* vcm = VideoCodingModule::Create(1, &clock);
RtpDataCallback dataCallback(vcm);
RTPPlayer rtpStream(args.inputFile.c_str(), &dataCallback, &clock);
PayloadTypeList payloadTypes;
payloadTypes.push_front(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, "VP8",
kVideoCodecVP8));
Trace::CreateTrace();
Trace::SetTraceFile((test::OutputPath() + "receiverTestTrace.txt").c_str());
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
for (PayloadTypeList::iterator it = payloadTypes.begin();
it != payloadTypes.end(); ++it) {
PayloadCodecTuple* payloadType = *it;
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;
}
}
}
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(clock.MillisecondTimestamp())) == 0)
{
if (clock.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 && clock.MillisecondTimestamp() >=
MAX_RUNTIME_MS)
{
break;
}
clock.IncrementDebugClock(1);
}
switch (ret)
{
case 1:
printf("Success\n");
break;
case -1:
printf("Failed\n");
break;
case 0:
printf("Timeout\n");
break;
}
rtpStream.Print();
// Tear down
while (!payloadTypes.empty())
{
delete payloadTypes.front();
payloadTypes.pop_front();
}
delete vcm;
vcm = NULL;
Trace::ReturnTrace();
return 0;
}