blob: 542d2663eb4a8fc17334410d21e3740111cfdb26 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include "test.h"
21#include <pjmedia-audiodev/audiodev.h>
22#include <pjmedia-codec/ffmpeg_vid_codecs.h>
23#include <pjmedia/vid_codec.h>
24#include <pjmedia_videodev.h>
25
26
27#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
28
29
30#define THIS_FILE "vid_dev_test.c"
31#define LOOP_DURATION 6
32
33static pj_bool_t is_quitting = PJ_FALSE;
34
35static pj_status_t vid_event_cb(pjmedia_event *event,
36 void *user_data)
37{
38 PJ_UNUSED_ARG(user_data);
39
40 if (event->type == PJMEDIA_EVENT_WND_CLOSED)
41 is_quitting = PJ_TRUE;
42
43 return PJ_SUCCESS;
44}
45
46static int capture_render_loopback(pj_bool_t active,
47 int cap_dev_id, int rend_dev_id,
48 const pjmedia_format *fmt)
49{
50 pj_pool_t *pool;
51 pjmedia_vid_port *capture=NULL, *renderer=NULL;
52 pjmedia_vid_dev_info cdi, rdi;
53 pjmedia_vid_port_param param;
54 pjmedia_video_format_detail *vfd;
55 pj_status_t status;
56 int rc = 0, i;
57
58 pool = pj_pool_create(mem, "vidportloop", 1000, 1000, NULL);
59
60 status = pjmedia_vid_dev_get_info(cap_dev_id, &cdi);
61 if (status != PJ_SUCCESS)
62 goto on_return;
63
64 status = pjmedia_vid_dev_get_info(rend_dev_id, &rdi);
65 if (status != PJ_SUCCESS)
66 goto on_return;
67
68 PJ_LOG(3,(THIS_FILE,
69 " %s (%s) ===> %s (%s)\t%s\t%dx%d\t@%d:%d fps",
70 cdi.name, cdi.driver, rdi.name, rdi.driver,
71 pjmedia_get_video_format_info(NULL, fmt->id)->name,
72 fmt->det.vid.size.w, fmt->det.vid.size.h,
73 fmt->det.vid.fps.num, fmt->det.vid.fps.denum));
74
75 pjmedia_vid_port_param_default(&param);
76
77 /* Create capture, set it to active (master) */
78 status = pjmedia_vid_dev_default_param(pool, cap_dev_id,
79 &param.vidparam);
80 if (status != PJ_SUCCESS) {
81 rc = 100; goto on_return;
82 }
83 param.vidparam.dir = PJMEDIA_DIR_CAPTURE;
84 param.vidparam.fmt = *fmt;
85 param.active = (active? PJ_TRUE: PJ_FALSE);
86
87 if (param.vidparam.fmt.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO) {
88 rc = 103; goto on_return;
89 }
90
91 vfd = pjmedia_format_get_video_format_detail(&param.vidparam.fmt, PJ_TRUE);
92 if (vfd == NULL) {
93 rc = 105; goto on_return;
94 }
95
96 status = pjmedia_vid_port_create(pool, &param, &capture);
97 if (status != PJ_SUCCESS) {
98 rc = 110; goto on_return;
99 }
100
101 /* Create renderer, set it to passive (slave) */
102 status = pjmedia_vid_dev_default_param(pool, rend_dev_id,
103 &param.vidparam);
104 if (status != PJ_SUCCESS) {
105 rc = 120; goto on_return;
106 }
107
108 param.active = (active? PJ_FALSE: PJ_TRUE);
109 param.vidparam.dir = PJMEDIA_DIR_RENDER;
110 param.vidparam.rend_id = rend_dev_id;
111 param.vidparam.fmt = *fmt;
112 param.vidparam.disp_size = vfd->size;
113
114 status = pjmedia_vid_port_create(pool, &param, &renderer);
115 if (status != PJ_SUCCESS) {
116 rc = 130; goto on_return;
117 }
118
119 /* Set event handler */
120 pjmedia_event_subscribe(NULL, &vid_event_cb, NULL, renderer);
121
122 /* Connect capture to renderer */
123 status = pjmedia_vid_port_connect(
124 (active? capture: renderer),
125 pjmedia_vid_port_get_passive_port(active? renderer: capture),
126 PJ_FALSE);
127 if (status != PJ_SUCCESS) {
128 rc = 140; goto on_return;
129 }
130
131 /* Start streaming.. */
132 status = pjmedia_vid_port_start(renderer);
133 if (status != PJ_SUCCESS) {
134 rc = 150; goto on_return;
135 }
136 status = pjmedia_vid_port_start(capture);
137 if (status != PJ_SUCCESS) {
138 rc = 160; goto on_return;
139 }
140
141 /* Sleep while the webcam is being displayed... */
142 for (i = 0; i < LOOP_DURATION*10 && (!is_quitting); i++) {
143 pj_thread_sleep(100);
144 }
145
146on_return:
147 if (status != PJ_SUCCESS)
148 PJ_PERROR(3, (THIS_FILE, status, " error"));
149
150 if (capture)
151 pjmedia_vid_port_stop(capture);
152 if (renderer)
153 pjmedia_vid_port_stop(renderer);
154 if (capture)
155 pjmedia_vid_port_destroy(capture);
156 if (renderer) {
157 pjmedia_event_unsubscribe(NULL, &vid_event_cb, NULL, renderer);
158 pjmedia_vid_port_destroy(renderer);
159 }
160
161 pj_pool_release(pool);
162 return rc;
163}
164
165static int find_device(pjmedia_dir dir,
166 pj_bool_t has_callback)
167{
168 unsigned i, count = pjmedia_vid_dev_count();
169
170 for (i = 0; i < count; ++i) {
171 pjmedia_vid_dev_info cdi;
172
173 if (pjmedia_vid_dev_get_info(i, &cdi) != PJ_SUCCESS)
174 continue;
175 if ((cdi.dir & dir) != 0 && cdi.has_callback == has_callback)
176 return i;
177 }
178
179 return -999;
180}
181
182static int vidport_test(void)
183{
184 int i, j, k, l;
185 int cap_id, rend_id;
186 pjmedia_format_id test_fmts[] = {
187 PJMEDIA_FORMAT_RGBA,
188 PJMEDIA_FORMAT_I420
189 };
190
191 PJ_LOG(3, (THIS_FILE, " Video port tests:"));
192
193 /* Capturer's role: active/passive. */
194 for (i = 1; i >= 0; i--) {
195 /* Capturer's device has_callback: TRUE/FALSE. */
196 for (j = 1; j >= 0; j--) {
197 cap_id = find_device(PJMEDIA_DIR_CAPTURE, j);
198 if (cap_id < 0)
199 continue;
200
201 /* Renderer's device has callback: TRUE/FALSE. */
202 for (k = 1; k >= 0; k--) {
203 rend_id = find_device(PJMEDIA_DIR_RENDER, k);
204 if (rend_id < 0)
205 continue;
206
207 /* Check various formats to test format conversion. */
208 for (l = 0; l < PJ_ARRAY_SIZE(test_fmts); ++l) {
209 pjmedia_format fmt;
210
211 PJ_LOG(3,(THIS_FILE,
212 "capturer %s (stream: %s) ===> "
213 "renderer %s (stream: %s)",
214 (i? "active": "passive"),
215 (j? "active": "passive"),
216 (i? "passive": "active"),
217 (k? "active": "passive")));
218
219 pjmedia_format_init_video(&fmt, test_fmts[l],
220 640, 480, 25, 1);
221 capture_render_loopback(i, cap_id, rend_id, &fmt);
222 }
223 }
224 }
225 }
226
227 return 0;
228}
229
230int vid_port_test(void)
231{
232 int rc = 0;
233 pj_status_t status;
234
235 status = pjmedia_vid_dev_subsys_init(mem);
236 if (status != PJ_SUCCESS)
237 return -10;
238
239 rc = vidport_test();
240 if (rc != 0)
241 goto on_return;
242
243on_return:
244 pjmedia_vid_dev_subsys_shutdown();
245
246 return rc;
247}
248
249
250#endif /* PJMEDIA_HAS_VIDEO */