/* * 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 #include 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(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(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; }