git-svn-id: http://webrtc.googlecode.com/svn/trunk@4 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
337
modules/video_coding/main/test/mt_rx_tx_test.cc
Normal file
337
modules/video_coding/main/test/mt_rx_tx_test.cc
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
*
|
||||
* Testing multi thread - receive and send sides
|
||||
*
|
||||
**************************************************/
|
||||
|
||||
#include "receiver_tests.h" // shared RTP state and receive side threads
|
||||
#include "video_coding.h"
|
||||
#include "rtp_rtcp.h"
|
||||
#include "thread_wrapper.h"
|
||||
#include "../source/event.h"
|
||||
#include "test_util.h" // send side callback
|
||||
#include "media_opt_test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
using namespace webrtc;
|
||||
|
||||
bool
|
||||
MainSenderThread(void* obj)
|
||||
{
|
||||
SendSharedState* state = static_cast<SendSharedState*>(obj);
|
||||
EventWrapper& waitEvent = *EventWrapper::Create();
|
||||
// preparing a frame for encoding
|
||||
VideoFrame sourceFrame;
|
||||
WebRtc_Word32 width = state->_args.width;
|
||||
WebRtc_Word32 height = state->_args.height;
|
||||
float frameRate = state->_args.frameRate;
|
||||
WebRtc_Word32 lengthSourceFrame = 3*width*height/2;
|
||||
sourceFrame.VerifyAndAllocate(lengthSourceFrame);
|
||||
WebRtc_UWord8* tmpBuffer = new WebRtc_UWord8[lengthSourceFrame];
|
||||
|
||||
if (state->_sourceFile == NULL)
|
||||
{
|
||||
state->_sourceFile = fopen(state->_args.inputFile.c_str(), "rb");
|
||||
if (state->_sourceFile == NULL)
|
||||
{
|
||||
printf ("Error when opening file \n");
|
||||
delete &waitEvent;
|
||||
delete tmpBuffer;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (feof(state->_sourceFile) == 0)
|
||||
{
|
||||
fread(tmpBuffer, 1, lengthSourceFrame,state->_sourceFile);
|
||||
state->_frameCnt++;
|
||||
sourceFrame.CopyFrame(lengthSourceFrame, tmpBuffer);
|
||||
sourceFrame.SetHeight(height);
|
||||
sourceFrame.SetWidth(width);
|
||||
state->_timestamp += (WebRtc_UWord32)(9e4 / frameRate);
|
||||
sourceFrame.SetTimeStamp(state->_timestamp);
|
||||
|
||||
WebRtc_Word32 ret = state->_vcm.AddVideoFrame(sourceFrame);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("Add Frame error: %d\n", ret);
|
||||
delete &waitEvent;
|
||||
delete tmpBuffer;
|
||||
return false;
|
||||
}
|
||||
waitEvent.Wait(33);
|
||||
}
|
||||
|
||||
delete &waitEvent;
|
||||
delete tmpBuffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IntSenderThread(void* obj)
|
||||
{
|
||||
SendSharedState* state = static_cast<SendSharedState*>(obj);
|
||||
state->_vcm.SetChannelParameters(1000,30,0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int MTRxTxTest(CmdArgs& args)
|
||||
{
|
||||
/* TEST SETTINGS */
|
||||
std::string inname = args.inputFile;
|
||||
std::string outname;
|
||||
if (args.outputFile == "")
|
||||
outname = "../MTRxTxTest_decoded.yuv";
|
||||
else
|
||||
outname = args.outputFile;
|
||||
|
||||
WebRtc_UWord16 width = args.width;
|
||||
WebRtc_UWord16 height = args.height;
|
||||
WebRtc_UWord32 lengthSourceFrame = 3*width*height/2;
|
||||
|
||||
float frameRate = args.frameRate;
|
||||
float bitRate = args.bitRate;
|
||||
WebRtc_Word32 numberOfCores = 1;
|
||||
|
||||
// error resilience/network
|
||||
bool nackEnabled = false;
|
||||
bool fecEnabled = false;
|
||||
WebRtc_UWord8 rttMS = 20;
|
||||
float lossRate = 0.0*255; // no packet loss
|
||||
WebRtc_UWord32 renderDelayMs = 0;
|
||||
WebRtc_UWord32 minPlayoutDelayMs = 0;
|
||||
WebRtc_UWord8 deltaFECRate = 0;
|
||||
WebRtc_UWord8 keyFECRate = 0;
|
||||
|
||||
/* TEST SET-UP */
|
||||
|
||||
// Set up trace
|
||||
Trace::CreateTrace();
|
||||
Trace::SetTraceFile("MTRxTxTestTrace.txt");
|
||||
Trace::SetLevelFilter(webrtc::kTraceAll);
|
||||
|
||||
FILE* sourceFile;
|
||||
FILE* decodedFile;
|
||||
|
||||
if ((sourceFile = fopen(inname.c_str(), "rb")) == NULL)
|
||||
{
|
||||
printf("Cannot read file %s.\n", inname.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((decodedFile = fopen(outname.c_str(), "wb")) == NULL)
|
||||
{
|
||||
printf("Cannot read file %s.\n", outname.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
//RTP
|
||||
RtpRtcp* rtp = RtpRtcp::CreateRtpRtcp(1, false);
|
||||
if (rtp->InitReceiver() < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (rtp->InitSender() < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// registering codecs for the RTP module
|
||||
TEST(rtp->RegisterReceivePayload("ULPFEC", VCM_ULPFEC_PAYLOAD_TYPE) == 0);
|
||||
TEST(rtp->RegisterReceivePayload("RED", VCM_RED_PAYLOAD_TYPE) == 0);
|
||||
TEST(rtp->RegisterReceivePayload(args.codecName.c_str(), VCM_VP8_PAYLOAD_TYPE) == 0);
|
||||
|
||||
// inform RTP Module of error resilience features
|
||||
TEST(rtp->SetGenericFECStatus(fecEnabled, VCM_RED_PAYLOAD_TYPE, VCM_ULPFEC_PAYLOAD_TYPE) == 0);
|
||||
|
||||
TEST(rtp->RegisterSendPayload(args.codecName.c_str(), VCM_VP8_PAYLOAD_TYPE, 90000, 1, 10000) == 0);
|
||||
|
||||
//VCM
|
||||
VideoCodingModule* vcm = VideoCodingModule::Create(1);
|
||||
if (vcm->InitializeReceiver() < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (vcm->InitializeSender())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// registering codecs for the VCM module
|
||||
VideoCodec sendCodec;
|
||||
vcm->InitializeSender();
|
||||
WebRtc_Word32 numberOfCodecs = vcm->NumberOfCodecs();
|
||||
if (numberOfCodecs < 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vcm->Codec(args.codecType, &sendCodec) != 0)
|
||||
{
|
||||
// desired codec unavailable
|
||||
printf("Codec not registered\n");
|
||||
return -1;
|
||||
}
|
||||
// register codec
|
||||
sendCodec.startBitrate = (int) bitRate;
|
||||
sendCodec.height = height;
|
||||
sendCodec.width = width;
|
||||
sendCodec.maxFramerate = (WebRtc_UWord8)frameRate;
|
||||
vcm->RegisterSendCodec(&sendCodec, numberOfCores, 1440);
|
||||
vcm->RegisterReceiveCodec(&sendCodec, numberOfCores); // same settings for encode and decode
|
||||
|
||||
vcm->SetRenderDelay(renderDelayMs);
|
||||
vcm->SetMinimumPlayoutDelay(minPlayoutDelayMs);
|
||||
|
||||
// Callback Settings
|
||||
|
||||
PacketRequester packetRequester(*rtp);
|
||||
vcm->RegisterPacketRequestCallback(&packetRequester);
|
||||
|
||||
VCMRTPEncodeCompleteCallback* encodeCompleteCallback = new VCMRTPEncodeCompleteCallback(rtp);
|
||||
vcm->RegisterTransportCallback(encodeCompleteCallback);
|
||||
encodeCompleteCallback->SetCodecType(ConvertCodecType(args.codecName.c_str()));
|
||||
encodeCompleteCallback->SetFrameDimensions(width, height);
|
||||
// frame ready to be sent to network
|
||||
RTPSendCompleteCallback* outgoingTransport = new RTPSendCompleteCallback(rtp, "dump.rtp");
|
||||
rtp->RegisterSendTransport(outgoingTransport);
|
||||
// FrameReceiveCallback
|
||||
VCMDecodeCompleteCallback receiveCallback(decodedFile);
|
||||
RtpDataCallback dataCallback(vcm);
|
||||
rtp->RegisterIncomingDataCallback(&dataCallback);
|
||||
vcm->RegisterReceiveCallback(&receiveCallback);
|
||||
|
||||
VCMTestProtectionCallback protectionCallback;
|
||||
vcm->RegisterProtectionCallback(&protectionCallback);
|
||||
|
||||
outgoingTransport->SetLossPct(lossRate);
|
||||
vcm->SetVideoProtection(kProtectionNack, nackEnabled);
|
||||
vcm->SetVideoProtection(kProtectionFEC, fecEnabled);
|
||||
|
||||
// inform RTP Module of error resilience features
|
||||
rtp->SetFECCodeRate(protectionCallback.FECKeyRate(),
|
||||
protectionCallback.FECDeltaRate());
|
||||
rtp->SetNACKStatus(protectionCallback.NACKMethod());
|
||||
|
||||
vcm->SetChannelParameters((WebRtc_UWord32) bitRate,
|
||||
(WebRtc_UWord8) lossRate, rttMS);
|
||||
|
||||
SharedRTPState mtState(*vcm, *rtp); // receive side
|
||||
SendSharedState mtSendState(*vcm, *rtp, args); // send side
|
||||
|
||||
/*START TEST*/
|
||||
|
||||
// Create and start all threads
|
||||
// send side threads
|
||||
ThreadWrapper* mainSenderThread = ThreadWrapper::CreateThread(MainSenderThread,
|
||||
&mtSendState, kNormalPriority, "MainSenderThread");
|
||||
ThreadWrapper* intSenderThread = ThreadWrapper::CreateThread(IntSenderThread,
|
||||
&mtSendState, kNormalPriority, "IntThread");
|
||||
|
||||
if (MainSenderThread != NULL)
|
||||
{
|
||||
unsigned int tid;
|
||||
mainSenderThread->Start(tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unable to start main sender thread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IntSenderThread != NULL)
|
||||
{
|
||||
unsigned int tid;
|
||||
intSenderThread->Start(tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unable to start sender interference thread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Receive side threads
|
||||
ThreadWrapper* processingThread = ThreadWrapper::CreateThread(ProcessingThread,
|
||||
&mtState, kNormalPriority, "ProcessingThread");
|
||||
ThreadWrapper* decodeThread = ThreadWrapper::CreateThread(DecodeThread,
|
||||
&mtState, kNormalPriority, "DecodeThread");
|
||||
|
||||
if (processingThread != NULL)
|
||||
{
|
||||
unsigned int tid;
|
||||
processingThread->Start(tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unable to start processing thread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (decodeThread != NULL)
|
||||
{
|
||||
unsigned int tid;
|
||||
decodeThread->Start(tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unable to start decode thread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EventWrapper& waitEvent = *EventWrapper::Create();
|
||||
|
||||
// Decode for 10 seconds and then tear down and exit.
|
||||
waitEvent.Wait(30000);
|
||||
|
||||
// Tear down
|
||||
|
||||
while (!mainSenderThread->Stop())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
while (!intSenderThread->Stop())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
while (!processingThread->Stop())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
while (!decodeThread->Stop())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
delete &waitEvent;
|
||||
delete mainSenderThread;
|
||||
delete intSenderThread;
|
||||
delete processingThread;
|
||||
delete decodeThread;
|
||||
delete encodeCompleteCallback;
|
||||
delete outgoingTransport;
|
||||
VideoCodingModule::Destroy(vcm);
|
||||
RtpRtcp::DestroyRtpRtcp(rtp);
|
||||
rtp = NULL;
|
||||
vcm = NULL;
|
||||
Trace::ReturnTrace();
|
||||
fclose(decodedFile);
|
||||
printf("Multi-Thread test Done: View output file \n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user