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

#include "mediastreamer2_tester_windows.h"
5
#include "mswinrtvid.h"
6

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

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

static OutputTraceListener^ sTraceListener;

23
NativeTester^ NativeTester::_instance = ref new NativeTester();
24

25 26
static void nativeOutputTraceHandler(int lev, const char *fmt, va_list args)
{
27 28 29 30 31
	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);
32 33
	if (sTraceListener) {
		String^ msg = ref new String(wstr);
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
		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);
51
	}
52 53
	OutputDebugStringW(wstr);
	OutputDebugStringW(L"\n");
54 55
}

56
static void ms2NativeOutputTraceHandler(const char *domain, OrtpLogLevel lev, const char *fmt, va_list args)
57 58 59 60 61
{
	nativeOutputTraceHandler((int)lev, fmt, args);
}


62
NativeTester::NativeTester()
63
	: _deviceRotation(0)
64 65 66
{
}

67
NativeTester::~NativeTester()
68
{
69
	uninitMS2();
70 71 72
	mediastreamer2_tester_uninit();
}

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

78
void NativeTester::initialize(StorageFolder^ writableDirectory, Platform::Boolean ui)
79
{
80 81
	if (ui) {
		mediastreamer2_tester_init(nativeOutputTraceHandler);
82 83
	}
	else {
84
		mediastreamer2_tester_init(NULL);
85
		ortp_set_log_level_mask(NULL, (OrtpLogLevel)(ORTP_MESSAGE | ORTP_WARNING | ORTP_ERROR | ORTP_FATAL));
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
	}

	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);
102 103 104
	}
}

105
bool NativeTester::run(Platform::String^ suiteName, Platform::String^ caseName, Platform::Boolean verbose)
106 107 108 109 110 111 112 113 114
{
	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 };
	wcstombs(csuitename, wssuitename.c_str(), sizeof(csuitename));
	wcstombs(ccasename, wscasename.c_str(), sizeof(ccasename));

115
	if (verbose) {
116
		ortp_set_log_level_mask(NULL, ORTP_MESSAGE | ORTP_WARNING | ORTP_ERROR | ORTP_FATAL);
117 118
	}
	else {
119
		ortp_set_log_level_mask(NULL, ORTP_ERROR | ORTP_FATAL);
120
	}
121
	ortp_set_log_handler(ms2NativeOutputTraceHandler);
122
	return bc_tester_run_tests(wssuitename == all ? 0 : csuitename, wscasename == all ? 0 : ccasename, NULL) != 0;
123
}
124

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

134
unsigned int NativeTester::nbTestSuites()
135 136 137 138
{
	return bc_tester_nb_suites();
}

139
unsigned int NativeTester::nbTests(Platform::String^ suiteName)
140 141 142 143 144 145 146
{
	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);
}

147
Platform::String^ NativeTester::testSuiteName(int index)
148 149 150 151 152 153 154
{
	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);
}

155
Platform::String^ NativeTester::testName(Platform::String^ suiteName, int testIndex)
156 157 158 159 160 161 162 163 164
{
	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);
}
165

166
Windows::Foundation::Collections::IVector<Platform::String^>^ NativeTester::VideoDevices::get()
167
{
168 169 170
	if (_factory == nullptr) {
		initMS2();
	}
171 172
	wchar_t wcname[MAX_DEVICE_NAME_SIZE];
	Vector<Platform::String^>^ devices = ref new Vector<Platform::String^>();
173
	const MSList *elem = ms_web_cam_manager_get_list(ms_factory_get_web_cam_manager(_factory));
174 175 176 177 178 179 180 181 182
	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;
}

183
void NativeTester::initVideo()
184
{
185 186 187
	if (_factory == nullptr) {
		initMS2();
	}
188 189
	rtp_profile_set_payload(&av_profile, 100, &payload_type_h263);
	rtp_profile_set_payload(&av_profile, 101, &payload_type_mp4v);
190
	rtp_profile_set_payload(&av_profile, 102, &payload_type_h264);
191 192 193 194 195 196 197 198 199
	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);
}

200
void NativeTester::uninitVideo()
201
{
202
	uninitMS2();
203 204 205 206 207 208 209 210
}

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


211
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)
212
{
213 214
	ms_factory_enable_statistics(_factory, TRUE);
	ms_factory_reset_statistics(_factory);
215

216
	MSVideoSize vsize = { MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H };
217
	int payload = 103;
218 219
	char cst[1024];
	std::wstring wst;
220
	MSWebCamManager *manager = ms_factory_get_web_cam_manager(_factory);
221 222 223
	PLATFORM_STRING_TO_C_STRING(camera);
	MSWebCam *cam = ms_web_cam_manager_get_cam(manager, cst);
	PLATFORM_STRING_TO_C_STRING(codec);
224 225 226 227
	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;
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
	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;
247 248 249 250 251
	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);
252
		video_preview_set_display_filter_name(_videoStream, "MSWinRTBackgroundDis");
253 254 255 256 257 258 259 260 261 262 263
		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);
264
		video_stream_set_display_filter_name(_videoStream, "MSWinRTBackgroundDis");
265 266 267 268 269 270
		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);
	}
271 272
}

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

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

292
void NativeTester::setOrientation(int degrees)
293 294 295
{
	_deviceRotation = degrees;
	if (_videoStream != NULL) {
296 297 298 299 300 301 302
		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);
		}
303 304
	}
}
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

void NativeTester::initMS2()
{
	if (_factory == nullptr) {
		ortp_init();
		ortp_set_log_level_mask(NULL, ORTP_MESSAGE | ORTP_WARNING | ORTP_ERROR | ORTP_FATAL);
		ortp_set_log_handler(ms2NativeOutputTraceHandler);
		_factory = ms_factory_new_with_voip();
	}
}

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