blob: d32e1769baed564611dcfeeec8f827ac8111c0e4 [file] [log] [blame]
Benny Prijonoc45d9512010-12-10 11:04:30 +00001#include "test.h"
2#include <pjmedia-codec/ffmpeg_codecs.h>
3#include <pjmedia-videodev/videodev.h>
4#include <pjmedia/vid_codec.h>
5#include <pjmedia/port.h>
6
7#define THIS_FILE "vid_codec.c"
8
9#define BYPASS_CODEC 0
10
11typedef struct codec_port_data_t
12{
13 pjmedia_vid_codec *codec;
14 pjmedia_port *dn_port;
15 pj_uint8_t *enc_buf;
16 pj_size_t enc_buf_size;
17} codec_port_data_t;
18
19static pj_status_t codec_put_frame(pjmedia_port *port,
20 pjmedia_frame *frame)
21{
22 codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata;
23 pjmedia_vid_codec *codec = port_data->codec;
24 pjmedia_frame enc_frame;
25 pj_status_t status;
26
27 enc_frame.buf = port_data->enc_buf;
28 enc_frame.size = port_data->enc_buf_size;
29
30#if !BYPASS_CODEC
31 status = codec->op->encode(codec, frame, enc_frame.size, &enc_frame);
32 if (status != PJ_SUCCESS) goto on_error;
33 status = codec->op->decode(codec, &enc_frame, frame->size, frame);
34 if (status != PJ_SUCCESS) goto on_error;
35#endif
36
37 status = pjmedia_port_put_frame(port_data->dn_port, frame);
38 if (status != PJ_SUCCESS) goto on_error;
39
40 return PJ_SUCCESS;
41
42on_error:
43 pj_perror(3, THIS_FILE, status, "codec_put_frame() error");
44 return status;
45}
46
47static const char* dump_codec_info(const pjmedia_vid_codec_info *info)
48{
49 static char str[80];
50 unsigned i;
51 char *p = str;
52
53 /* Raw format ids */
54 for (i=0; (i<info->dec_fmt_id_cnt) && (p-str+5<sizeof(str)); ++i) {
55 pj_memcpy(p, &info->dec_fmt_id[i], 4);
56 p += 4;
57 *p++ = ' ';
58 }
59 *p = '\0';
60
61 return str;
62}
63
64static int enum_codecs()
65{
66 unsigned i, cnt;
67 pjmedia_vid_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS];
68 pj_status_t status;
69
70 PJ_LOG(3, (THIS_FILE, " codec enums"));
71 cnt = PJ_ARRAY_SIZE(info);
72 status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &cnt, info, NULL);
73 if (status != PJ_SUCCESS)
74 return 100;
75
76 for (i = 0; i < cnt; ++i) {
77 PJ_LOG(3, (THIS_FILE, " %16.*s %c%c %s",
78 info[i].encoding_name.slen, info[i].encoding_name.ptr,
79 (info[i].dir & PJMEDIA_DIR_ENCODING? 'E' : ' '),
80 (info[i].dir & PJMEDIA_DIR_DECODING? 'D' : ' '),
81 dump_codec_info(&info[i])));
82 }
83
84 return PJ_SUCCESS;
85}
86
87static int encode_decode_test(pj_pool_t *pool, const char *codec_id,
88 pjmedia_format_id raw_fmt_id)
89{
90
91 pjmedia_vid_codec *codec=NULL;
92 pjmedia_port codec_port;
93 codec_port_data_t codec_port_data;
94 pjmedia_vid_codec_param codec_param;
95 const pjmedia_vid_codec_info *codec_info;
96
97 pjmedia_vid_dev_index cap_idx, rdr_idx;
98 pjmedia_vid_port *capture=NULL, *renderer=NULL;
99 pjmedia_vid_port_param vport_param;
100 pjmedia_video_format_detail *vfd;
101 pj_status_t status;
102 int rc = 0;
103
104 PJ_LOG(3, (THIS_FILE, " encode decode test"));
105
106 /* Lookup codec */
107 {
108 pj_str_t codec_id_st;
109 unsigned info_cnt = 1;
110
111 /* Lookup codec */
112 pj_cstr(&codec_id_st, codec_id);
113 status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, &codec_id_st,
114 &info_cnt,
115 &codec_info, NULL);
116 if (status != PJ_SUCCESS) {
117 rc = 205; goto on_return;
118 }
119 }
120
121 /* Lookup colorbar source */
122 status = pjmedia_vid_dev_lookup("Colorbar", "Colorbar generator", &cap_idx);
123 if (status != PJ_SUCCESS) {
124 rc = 206; goto on_return;
125 }
126
127 /* Lookup SDL renderer */
128 status = pjmedia_vid_dev_lookup("SDL", "SDL renderer", &rdr_idx);
129 if (status != PJ_SUCCESS) {
130 rc = 207; goto on_return;
131 }
132
133 /* Raw format ID "not specified", lets find common format among the codec
134 * and the video devices
135 */
136 if (raw_fmt_id == 0) {
137 pjmedia_vid_dev_info cap_info, rdr_info;
138 unsigned i, j, k;
139
140 pjmedia_vid_dev_get_info(cap_idx, &cap_info);
141 pjmedia_vid_dev_get_info(rdr_idx, &rdr_info);
142
143 for (i=0; i<codec_info->dec_fmt_id_cnt && !raw_fmt_id; ++i) {
144 for (j=0; j<cap_info.fmt_cnt && !raw_fmt_id; ++j) {
145 if (codec_info->dec_fmt_id[i]==(int)cap_info.fmt[j].id) {
146 for (k=0; k<rdr_info.fmt_cnt && !raw_fmt_id; ++k) {
147 if (codec_info->dec_fmt_id[i]==(int)rdr_info.fmt[k].id)
148 {
149 raw_fmt_id = codec_info->dec_fmt_id[i];
150 }
151 }
152 }
153 }
154 }
155
156 if (raw_fmt_id == 0) {
157 PJ_LOG(3, (THIS_FILE, " No common format ID among the codec "
158 "and the video devices"));
159 status = PJ_ENOTFOUND;
160 rc = 210;
161 goto on_return;
162 }
163 }
164
165 pjmedia_vid_port_param_default(&vport_param);
166
167 /* Create capture, set it to active (master) */
168 status = pjmedia_vid_dev_default_param(pool, cap_idx,
169 &vport_param.vidparam);
170 if (status != PJ_SUCCESS) {
171 rc = 220; goto on_return;
172 }
173 vport_param.vidparam.fmt.id = raw_fmt_id;
174 vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE;
175 vport_param.active = PJ_TRUE;
176
177 if (vport_param.vidparam.fmt.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO) {
178 rc = 221; goto on_return;
179 }
180
181 vfd = pjmedia_format_get_video_format_detail(&vport_param.vidparam.fmt,
182 PJ_TRUE);
183 if (vfd == NULL) {
184 rc = 225; goto on_return;
185 }
186
187 status = pjmedia_vid_port_create(pool, &vport_param, &capture);
188 if (status != PJ_SUCCESS) {
189 rc = 226; goto on_return;
190 }
191
192 /* Create renderer, set it to passive (slave) */
193 vport_param.active = PJ_FALSE;
194 vport_param.vidparam.dir = PJMEDIA_DIR_RENDER;
195 vport_param.vidparam.rend_id = rdr_idx;
196 vport_param.vidparam.disp_size = vfd->size;
197
198 status = pjmedia_vid_port_create(pool, &vport_param, &renderer);
199 if (status != PJ_SUCCESS) {
200 rc = 230; goto on_return;
201 }
202
203 /* Prepare codec */
204 {
205 pj_str_t codec_id_st;
206 unsigned info_cnt = 1;
207 const pjmedia_vid_codec_info *codec_info;
208 pj_str_t port_name = {"codec", 5};
209 pj_uint8_t *enc_buf = NULL;
210 pj_size_t enc_buf_size = 0;
211
212
213 /* Lookup codec */
214 pj_cstr(&codec_id_st, codec_id);
215 status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, &codec_id_st,
216 &info_cnt,
217 &codec_info, NULL);
218 if (status != PJ_SUCCESS) {
219 rc = 245; goto on_return;
220 }
221 status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info,
222 &codec_param);
223 if (status != PJ_SUCCESS) {
224 rc = 246; goto on_return;
225 }
226
227 pjmedia_format_copy(&codec_param.dec_fmt, &vport_param.vidparam.fmt);
228
229#if !BYPASS_CODEC
230
231 /* Open codec */
232 status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info,
233 &codec);
234 if (status != PJ_SUCCESS) {
235 rc = 250; goto on_return;
236 }
237
238 status = codec->op->init(codec, pool);
239 if (status != PJ_SUCCESS) {
240 rc = 251; goto on_return;
241 }
242
243 status = codec->op->open(codec, &codec_param);
244 if (status != PJ_SUCCESS) {
245 rc = 252; goto on_return;
246 }
247
248 /* Alloc encoding buffer */
249 enc_buf_size = codec_param.dec_fmt.det.vid.size.w *
250 codec_param.dec_fmt.det.vid.size.h * 4
251 + 16; /*< padding, just in case */
252 enc_buf = pj_pool_alloc(pool,enc_buf_size);
253
254#endif /* !BYPASS_CODEC */
255
256 /* Init codec port */
257 pj_bzero(&codec_port, sizeof(codec_port));
258 status = pjmedia_port_info_init2(&codec_port.info, &port_name, 0x1234,
259 PJMEDIA_DIR_ENCODING,
260 &codec_param.dec_fmt);
261 if (status != PJ_SUCCESS) {
262 rc = 260; goto on_return;
263 }
264 codec_port_data.codec = codec;
265 codec_port_data.dn_port = pjmedia_vid_port_get_passive_port(renderer);
266 codec_port_data.enc_buf = enc_buf;
267 codec_port_data.enc_buf_size = enc_buf_size;
268
269 codec_port.put_frame = &codec_put_frame;
270 codec_port.port_data.pdata = &codec_port_data;
271 }
272
273
274 /* Connect capture to codec port */
275 status = pjmedia_vid_port_connect(capture,
276 &codec_port,
277 PJ_FALSE);
278 if (status != PJ_SUCCESS) {
279 rc = 270; goto on_return;
280 }
281
282 PJ_LOG(3, (THIS_FILE, " starting codec test: %c%c%c%c<->%s %dx%d",
283 ((codec_param.dec_fmt.id & 0x000000FF) >> 0),
284 ((codec_param.dec_fmt.id & 0x0000FF00) >> 8),
285 ((codec_param.dec_fmt.id & 0x00FF0000) >> 16),
286 ((codec_param.dec_fmt.id & 0xFF000000) >> 24),
287 codec_id,
288 codec_param.dec_fmt.det.vid.size.w,
289 codec_param.dec_fmt.det.vid.size.h
290 ));
291
292 /* Start streaming.. */
293 status = pjmedia_vid_port_start(renderer);
294 if (status != PJ_SUCCESS) {
295 rc = 275; goto on_return;
296 }
297 status = pjmedia_vid_port_start(capture);
298 if (status != PJ_SUCCESS) {
299 rc = 280; goto on_return;
300 }
301
302 /* Sleep while the video is being displayed... */
303 pj_thread_sleep(10000);
304
305on_return:
306 if (status != PJ_SUCCESS) {
307 PJ_PERROR(3, (THIS_FILE, status, " error"));
308 }
309 if (capture) {
310 pjmedia_vid_port_stop(capture);
311 pjmedia_vid_port_destroy(capture);
312 }
313 if (renderer) {
314 pjmedia_vid_port_stop(renderer);
315 pjmedia_vid_port_destroy(renderer);
316 }
317 if (codec) {
318 codec->op->close(codec);
319 pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec);
320 }
321
322 return rc;
323}
324
325int vid_codec_test(void)
326{
327 pj_pool_t *pool;
328 int rc = 0;
329 pj_status_t status;
330
331 PJ_LOG(3, (THIS_FILE, "Performing video codec tests.."));
332
333 pool = pj_pool_create(mem, "Vid codec test", 256, 256, 0);
334
335 status = pjmedia_vid_subsys_init(mem);
336 if (status != PJ_SUCCESS)
337 return -10;
338
339 status = pjmedia_codec_ffmpeg_init(NULL, mem);
340 if (status != PJ_SUCCESS)
341 return -20;
342
343 rc = enum_codecs();
344 if (rc != 0)
345 goto on_return;
346
347 rc = encode_decode_test(pool, "mjpeg", 0);
348 if (rc != 0)
349 goto on_return;
350
351on_return:
352 pjmedia_codec_ffmpeg_deinit();
353 pjmedia_vid_subsys_shutdown();
354 pj_pool_release(pool);
355
356 return rc;
357}
358
359