mediastreamer2_tester_windows.cpp 10.5 KB
Newer Older
1
#include <string>
2
#include <collection.h>
3

4 5
#include <bctoolbox/logging.h>

6
#include "mediastreamer2_tester_windows.h"
7
#include "mswinrtvid.h"
8

9
using namespace BelledonneCommunications::Mediastreamer2::Tester;
10
using namespace Platform;
11
using namespace Platform::Collections;
12
using namespace Windows::Foundation;
13
using namespace Windows::Storage;
14
using namespace Windows::System::Threading;
15
using namespace Windows::UI::ViewManagement;
16

17
#define MAX_TRACE_SIZE		2048
18 19
#define MAX_SUITE_NAME_SIZE	128
#define MAX_WRITABLE_DIR_SIZE 1024
20 21
#define MAX_FILEPATH_SIZE	2048
#define MAX_DEVICE_NAME_SIZE 256
22 23 24

static OutputTraceListener^ sTraceListener;

25
NativeTester^ NativeTester::_instance = ref new NativeTester();
26

27 28
static void nativeOutputTraceHandler(int lev, const char *fmt, va_list args)
{
29 30 31 32 33
	wchar_t wstr[MAX_TRACE_SIZE];
	std::string str;
	str.resize(MAX_TRACE_SIZE);
	vsnprintf((char *)str.c_str(), MAX_TRACE_SIZE, fmt, args);
	mbstowcs(wstr, str.c_str(), MAX_TRACE_SIZE - 1);
34 35
	if (sTraceListener) {
		String^ msg = ref new String(wstr);
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
		String^ l;
		switch (lev) {
		case ORTP_FATAL:
		case ORTP_ERROR:
			l = ref new String(L"Error");
			break;
		case ORTP_WARNING:
			l = ref new String(L"Warning");
			break;
		case ORTP_MESSAGE:
			l = ref new String(L"Message");
			break;
		default:
			l = ref new String(L"Debug");
			break;
		}
		sTraceListener->outputTrace(l, msg);
53
	}
54 55
	OutputDebugStringW(wstr);
	OutputDebugStringW(L"\n");
56 57
}

58
static void ms2NativeOutputTraceHandler(void *info, const char *domain, BctbxLogLevel lev, const char *fmt, va_list args)
59 60 61 62 63
{
	nativeOutputTraceHandler((int)lev, fmt, args);
}


64
NativeTester::NativeTester()
65
	: _deviceRotation(0)
66 67 68
{
}

69
NativeTester::~NativeTester()
70
{
71
	uninitMS2();
72 73 74
	mediastreamer2_tester_uninit();
}

75
void NativeTester::setOutputTraceListener(OutputTraceListener^ traceListener)
76 77 78 79
{
	sTraceListener = traceListener;
}

80
void NativeTester::initialize(StorageFolder^ writableDirectory, Platform::Boolean ui)
81
{
82 83
	if (ui) {
		mediastreamer2_tester_init(nativeOutputTraceHandler);
84 85
	}
	else {
86
		mediastreamer2_tester_init(NULL);
87
		bctbx_set_log_level(NULL, BCTBX_LOG_MESSAGE);
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
	}

	char writable_dir[MAX_WRITABLE_DIR_SIZE] = { 0 };
	const wchar_t *wwritable_dir = writableDirectory->Path->Data();
	wcstombs(writable_dir, wwritable_dir, sizeof(writable_dir));
	bc_tester_set_writable_dir_prefix(writable_dir);
	bc_tester_set_resource_dir_prefix("Assets");

	if (!ui) {
		char *xmlFile = bc_tester_file("MS2Windows10.xml");
		char *args[] = { "--xml-file", xmlFile };
		bc_tester_parse_args(2, args, 0);

		char *logFile = bc_tester_file("MS2Windows10.log");
		mediastreamer2_tester_set_log_file(logFile);
		free(logFile);
104 105 106
	}
}

107
bool NativeTester::run(Platform::String^ suiteName, Platform::String^ caseName, Platform::Boolean verbose)
108 109 110 111 112 113
{
	std::wstring all(L"ALL");
	std::wstring wssuitename = suiteName->Data();
	std::wstring wscasename = caseName->Data();
	char csuitename[MAX_SUITE_NAME_SIZE] = { 0 };
	char ccasename[MAX_SUITE_NAME_SIZE] = { 0 };
114
	bctbx_log_handler_t *log_handler = bctbx_create_log_handler(ms2NativeOutputTraceHandler, NULL, NULL);
115 116 117
	wcstombs(csuitename, wssuitename.c_str(), sizeof(csuitename));
	wcstombs(ccasename, wscasename.c_str(), sizeof(ccasename));

118
	if (verbose) {
119
		bctbx_set_log_level(NULL, BCTBX_LOG_MESSAGE);
120 121
	}
	else {
122
		bctbx_set_log_level(NULL, BCTBX_LOG_ERROR);
123
	}
124
	bctbx_add_log_handler(log_handler);
125
	return bc_tester_run_tests(wssuitename == all ? 0 : csuitename, wscasename == all ? 0 : ccasename, NULL) != 0;
126
}
127

128
void NativeTester::runAllToXml()
129 130
{
	auto workItem = ref new WorkItemHandler([this](IAsyncAction ^workItem) {
131
		bc_tester_start(NULL);
132 133 134
		bc_tester_uninit();
	});
	_asyncAction = ThreadPool::RunAsync(workItem);
135 136
}

137
unsigned int NativeTester::nbTestSuites()
138 139 140 141
{
	return bc_tester_nb_suites();
}

142
unsigned int NativeTester::nbTests(Platform::String^ suiteName)
143 144 145 146 147 148 149
{
	std::wstring suitename = suiteName->Data();
	char cname[MAX_SUITE_NAME_SIZE] = { 0 };
	wcstombs(cname, suitename.c_str(), sizeof(cname));
	return bc_tester_nb_tests(cname);
}

150
Platform::String^ NativeTester::testSuiteName(int index)
151 152 153 154 155 156 157
{
	const char *cname = bc_tester_suite_name(index);
	wchar_t wcname[MAX_SUITE_NAME_SIZE];
	mbstowcs(wcname, cname, sizeof(wcname));
	return ref new String(wcname);
}

158
Platform::String^ NativeTester::testName(Platform::String^ suiteName, int testIndex)
159 160 161 162 163 164 165 166 167
{
	std::wstring suitename = suiteName->Data();
	char csuitename[MAX_SUITE_NAME_SIZE] = { 0 };
	wcstombs(csuitename, suitename.c_str(), sizeof(csuitename));
	const char *cname = bc_tester_test_name(csuitename, testIndex);
	wchar_t wcname[MAX_SUITE_NAME_SIZE];
	mbstowcs(wcname, cname, sizeof(wcname));
	return ref new String(wcname);
}
168

169
Windows::Foundation::Collections::IVector<Platform::String^>^ NativeTester::VideoDevices::get()
170
{
171 172 173
	if (_factory == nullptr) {
		initMS2();
	}
174 175
	wchar_t wcname[MAX_DEVICE_NAME_SIZE];
	Vector<Platform::String^>^ devices = ref new Vector<Platform::String^>();
176
	const MSList *elem = ms_web_cam_manager_get_list(ms_factory_get_web_cam_manager(_factory));
177 178 179 180 181 182 183 184 185
	for (int i = 0; elem != NULL; elem = elem->next, i++) {
		const char *id = ms_web_cam_get_string_id((MSWebCam *)elem->data);
		memset(wcname, 0, sizeof(wcname));
		mbstowcs(wcname, id, sizeof(wcname));
		devices->Append(ref new String(wcname));
	}
	return devices;
}

186
void NativeTester::initVideo()
187
{
188 189 190
	if (_factory == nullptr) {
		initMS2();
	}
191 192
	rtp_profile_set_payload(&av_profile, 100, &payload_type_h263);
	rtp_profile_set_payload(&av_profile, 101, &payload_type_mp4v);
193
	rtp_profile_set_payload(&av_profile, 102, &payload_type_h264);
194 195 196 197 198 199 200 201 202
	rtp_profile_set_payload(&av_profile, 103, &payload_type_vp8);
	Platform::String^ appFolder = Windows::ApplicationModel::Package::Current->InstalledLocation->Path;
	Platform::String^ psPath = Platform::String::Concat(appFolder, ref new Platform::String(L"\\Assets\\Images\\nowebcamCIF.jpg"));
	std::wstring wsPath = psPath->Data();
	char cPath[MAX_FILEPATH_SIZE] = { 0 };
	wcstombs(cPath, wsPath.c_str(), sizeof(cPath));
	ms_static_image_set_default_image(cPath);
}

203
void NativeTester::uninitVideo()
204
{
205
	uninitMS2();
206 207 208 209 210 211 212 213
}

#define PLATFORM_STRING_TO_C_STRING(x) \
	memset(cst, 0, sizeof(cst)); \
	wst = x->Data(); \
	wcstombs(cst, wst.c_str(), sizeof(cst))


214
void NativeTester::startVideoStream(Platform::String^ videoSwapChainPanelName, Platform::String^ previewSwapChainPanelName, Platform::String^ camera, Platform::String^ codec, Platform::String^ videoSize, unsigned int frameRate, unsigned int bitRate, Platform::Boolean usePreviewStream)
215
{
216 217
	ms_factory_enable_statistics(_factory, TRUE);
	ms_factory_reset_statistics(_factory);
218

219
	MSVideoSize vsize = { MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H };
220
	int payload = 103;
221 222
	char cst[1024];
	std::wstring wst;
223
	MSWebCamManager *manager = ms_factory_get_web_cam_manager(_factory);
224 225 226
	PLATFORM_STRING_TO_C_STRING(camera);
	MSWebCam *cam = ms_web_cam_manager_get_cam(manager, cst);
	PLATFORM_STRING_TO_C_STRING(codec);
227 228 229 230
	if (strcmp(cst, "H263") == 0) payload = 100;
	else if (strcmp(cst, "H264") == 0) payload = 102;
	else if (strcmp(cst, "MPEG4") == 0) payload = 101;
	else if (strcmp(cst, "VP8") == 0) payload = 103;
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
	PLATFORM_STRING_TO_C_STRING(videoSize);
	if (strcmp(cst, "720P") == 0) {
		vsize.width = MS_VIDEO_SIZE_720P_W;
		vsize.height = MS_VIDEO_SIZE_720P_H;
	} else if (strcmp(cst, "VGA") == 0) {
		vsize.width = MS_VIDEO_SIZE_VGA_W;
		vsize.height = MS_VIDEO_SIZE_VGA_H;
	} else if (strcmp(cst, "CIF") == 0) {
		vsize.width = MS_VIDEO_SIZE_CIF_W;
		vsize.height = MS_VIDEO_SIZE_CIF_H;
	} else if (strcmp(cst, "QVGA") == 0) {
		vsize.width = MS_VIDEO_SIZE_QVGA_W;
		vsize.height = MS_VIDEO_SIZE_QVGA_H;
	} else if (strcmp(cst, "QCIF") == 0) {
		vsize.width = MS_VIDEO_SIZE_QCIF_W;
		vsize.height = MS_VIDEO_SIZE_QCIF_H;
	}
	PayloadType *pt = rtp_profile_get_payload(&av_profile, payload);
	pt->normal_bitrate = bitRate * 1000;
250 251 252 253 254
	if (usePreviewStream) {
		_usePreviewStream = usePreviewStream;
		_videoStream = video_preview_new(_factory);
		RefToPtrProxy<Platform::String^> *nativeWindowId = new RefToPtrProxy<Platform::String^>(videoSwapChainPanelName);
		video_preview_set_native_window_id(_videoStream, nativeWindowId);
255
		video_preview_set_display_filter_name(_videoStream, "MSWinRTBackgroundDis");
256 257 258 259 260 261 262 263 264 265 266
		video_preview_set_size(_videoStream, vsize);
		video_preview_set_fps(_videoStream, (float)frameRate);
		video_preview_set_device_rotation(_videoStream, _deviceRotation);
		video_preview_start(_videoStream, cam);
	} else {
		_videoStream = video_stream_new(_factory, 20000, 0, FALSE);
		RefToPtrProxy<Platform::String^> *nativeWindowId = new RefToPtrProxy<Platform::String^>(videoSwapChainPanelName);
		video_stream_set_native_window_id(_videoStream, nativeWindowId);
		RefToPtrProxy<Platform::String^> *nativePreviewWindowId = new RefToPtrProxy<Platform::String^>(previewSwapChainPanelName);
		video_stream_set_native_preview_window_id(_videoStream, nativePreviewWindowId);
		video_stream_use_preview_video_window(_videoStream, TRUE);
267
		video_stream_set_display_filter_name(_videoStream, "MSWinRTBackgroundDis");
268 269 270 271 272 273
		video_stream_use_video_preset(_videoStream, "custom");
		video_stream_set_sent_video_size(_videoStream, vsize);
		video_stream_set_fps(_videoStream, (float)frameRate);
		video_stream_set_device_rotation(_videoStream, _deviceRotation);
		video_stream_start(_videoStream, &av_profile, "127.0.0.1", 20000, NULL, 0, payload, 0, cam);
	}
274 275
}

276
void NativeTester::stopVideoStream()
277
{
278
	ms_factory_log_statistics(_factory);
279 280
	if (_usePreviewStream) video_preview_stop(_videoStream);
	else video_stream_stop(_videoStream);
281 282
	_videoStream = NULL;
}
283

284
void NativeTester::changeCamera(Platform::String^ camera)
285 286 287
{
	char cst[1024];
	std::wstring wst;
288
	MSWebCamManager *manager = ms_factory_get_web_cam_manager(_factory);
289 290
	PLATFORM_STRING_TO_C_STRING(camera);
	MSWebCam *cam = ms_web_cam_manager_get_cam(manager, cst);
291 292
	if (_usePreviewStream) video_preview_change_camera(_videoStream, cam);
	else video_stream_change_camera(_videoStream, cam);
293 294
}

295
void NativeTester::setOrientation(int degrees)
296 297 298
{
	_deviceRotation = degrees;
	if (_videoStream != NULL) {
299 300 301 302 303 304 305
		if (_usePreviewStream) {
			video_preview_set_device_rotation(_videoStream, _deviceRotation);
			video_preview_update_video_params(_videoStream);
		} else {
			video_stream_set_device_rotation(_videoStream, _deviceRotation);
			video_stream_update_video_params(_videoStream);
		}
306 307
	}
}
308 309 310 311 312

void NativeTester::initMS2()
{
	if (_factory == nullptr) {
		ortp_init();
313
		bctbx_set_log_level(NULL, BCTBX_LOG_MESSAGE);
314 315
		bctbx_log_handler_t *log_handler = bctbx_create_log_handler(ms2NativeOutputTraceHandler, NULL, NULL);
		bctbx_add_log_handler(log_handler);
316 317 318 319 320 321 322 323 324 325 326
		_factory = ms_factory_new_with_voip();
	}
}

void NativeTester::uninitMS2()
{
	if (_factory != nullptr) {
		ms_factory_destroy(_factory);
		_factory = nullptr;
	}
}