1 /* $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 <pjmedia/vid_codec.h>
21 #include <pjmedia/errno.h>
22 #include <pj/array.h>
23 #include <pj/assert.h>
24 #include <pj/log.h>
25 #include <pj/string.h>
26
27
28 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
29
30
31 #define THIS_FILE "vid_codec.c"
32
33 static pjmedia_vid_codec_mgr *def_vid_codec_mgr;
34
35
36 /* Definition of default codecs parameters */
37 typedef struct pjmedia_vid_codec_default_param
38 {
39 pj_pool_t *pool;
40 pjmedia_vid_codec_param *param;
41 } pjmedia_vid_codec_default_param;
42
43
44 /*
45 * Codec manager maintains array of these structs for each supported
46 * codec.
47 */
48 typedef struct pjmedia_vid_codec_desc
49 {
50 pjmedia_vid_codec_info info; /**< Codec info. */
51 pjmedia_codec_id id; /**< Fully qualified name */
52 pjmedia_codec_priority prio; /**< Priority. */
53 pjmedia_vid_codec_factory *factory; /**< The factory. */
54 pjmedia_vid_codec_default_param *def_param; /**< Default codecs
55 parameters. */
56 } pjmedia_vid_codec_desc;
57
58
59 /* The declaration of video codec manager */
60 struct pjmedia_vid_codec_mgr
61 {
62 /** Pool factory instance. */
63 pj_pool_factory *pf;
64
65 /** Codec manager mutex. */
66 pj_mutex_t *mutex;
67
68 /** List of codec factories registered to codec manager. */
69 pjmedia_vid_codec_factory factory_list;
70
71 /** Number of supported codecs. */
72 unsigned codec_cnt;
73
74 /** Array of codec descriptor. */
75 pjmedia_vid_codec_desc codec_desc[PJMEDIA_CODEC_MGR_MAX_CODECS];
76
77 };
78
79
80
81 /* Sort codecs in codec manager based on priorities */
82 static void sort_codecs(pjmedia_vid_codec_mgr *mgr);
83
84
85 /*
86 * Duplicate video codec parameter.
87 */
pjmedia_vid_codec_param_clone(pj_pool_t * pool,const pjmedia_vid_codec_param * src)88 PJ_DEF(pjmedia_vid_codec_param*) pjmedia_vid_codec_param_clone(
89 pj_pool_t *pool,
90 const pjmedia_vid_codec_param *src)
91 {
92 pjmedia_vid_codec_param *p;
93 unsigned i;
94
95 PJ_ASSERT_RETURN(pool && src, NULL);
96
97 p = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec_param);
98
99 /* Update codec param */
100 pj_memcpy(p, src, sizeof(pjmedia_vid_codec_param));
101 for (i = 0; i < src->dec_fmtp.cnt; ++i) {
102 pj_strdup(pool, &p->dec_fmtp.param[i].name,
103 &src->dec_fmtp.param[i].name);
104 pj_strdup(pool, &p->dec_fmtp.param[i].val,
105 &src->dec_fmtp.param[i].val);
106 }
107 for (i = 0; i < src->enc_fmtp.cnt; ++i) {
108 pj_strdup(pool, &p->enc_fmtp.param[i].name,
109 &src->enc_fmtp.param[i].name);
110 pj_strdup(pool, &p->enc_fmtp.param[i].val,
111 &src->enc_fmtp.param[i].val);
112 }
113
114 return p;
115 }
116
117 /*
118 * Initialize codec manager.
119 */
pjmedia_vid_codec_mgr_create(pj_pool_t * pool,pjmedia_vid_codec_mgr ** p_mgr)120 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_create(
121 pj_pool_t *pool,
122 pjmedia_vid_codec_mgr **p_mgr)
123 {
124 pjmedia_vid_codec_mgr *mgr;
125 pj_status_t status;
126
127 PJ_ASSERT_RETURN(pool, PJ_EINVAL);
128
129 mgr = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec_mgr);
130 mgr->pf = pool->factory;
131 pj_list_init (&mgr->factory_list);
132 mgr->codec_cnt = 0;
133
134 /* Create mutex */
135 status = pj_mutex_create_recursive(pool, "vid-codec-mgr", &mgr->mutex);
136 if (status != PJ_SUCCESS)
137 return status;
138
139 if (!def_vid_codec_mgr)
140 def_vid_codec_mgr = mgr;
141
142 if (p_mgr)
143 *p_mgr = mgr;
144
145 return PJ_SUCCESS;
146 }
147
148 /*
149 * Initialize codec manager.
150 */
pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr * mgr)151 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_destroy (pjmedia_vid_codec_mgr *mgr)
152 {
153 if (!mgr) mgr = def_vid_codec_mgr;
154 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
155
156 /* Destroy mutex */
157 if (mgr->mutex)
158 pj_mutex_destroy(mgr->mutex);
159
160 /* Just for safety, set codec manager states to zero */
161 pj_bzero(mgr, sizeof(pjmedia_vid_codec_mgr));
162
163 if (mgr == def_vid_codec_mgr)
164 def_vid_codec_mgr = NULL;
165
166 return PJ_SUCCESS;
167 }
168
169
pjmedia_vid_codec_mgr_instance(void)170 PJ_DEF(pjmedia_vid_codec_mgr*) pjmedia_vid_codec_mgr_instance(void)
171 {
172 //pj_assert(def_vid_codec_mgr);
173 return def_vid_codec_mgr;
174 }
175
pjmedia_vid_codec_mgr_set_instance(pjmedia_vid_codec_mgr * mgr)176 PJ_DEF(void) pjmedia_vid_codec_mgr_set_instance(pjmedia_vid_codec_mgr* mgr)
177 {
178 def_vid_codec_mgr = mgr;
179 }
180
181
182 /*
183 * Register a codec factory.
184 */
pjmedia_vid_codec_mgr_register_factory(pjmedia_vid_codec_mgr * mgr,pjmedia_vid_codec_factory * factory)185 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_register_factory(
186 pjmedia_vid_codec_mgr *mgr,
187 pjmedia_vid_codec_factory *factory)
188 {
189 pjmedia_vid_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS];
190 unsigned i, count;
191 pj_status_t status;
192
193 PJ_ASSERT_RETURN(factory, PJ_EINVAL);
194
195 if (!mgr) mgr = def_vid_codec_mgr;
196 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
197
198 /* Enum codecs */
199 count = PJ_ARRAY_SIZE(info);
200 status = factory->op->enum_info(factory, &count, info);
201 if (status != PJ_SUCCESS)
202 return status;
203
204 pj_mutex_lock(mgr->mutex);
205
206 /* Check codec count */
207 if (count + mgr->codec_cnt > PJ_ARRAY_SIZE(mgr->codec_desc)) {
208 pj_mutex_unlock(mgr->mutex);
209 return PJ_ETOOMANY;
210 }
211
212
213 /* Save the codecs */
214 for (i=0; i<count; ++i) {
215 pj_memcpy( &mgr->codec_desc[mgr->codec_cnt+i],
216 &info[i], sizeof(pjmedia_vid_codec_info));
217 mgr->codec_desc[mgr->codec_cnt+i].prio = PJMEDIA_CODEC_PRIO_NORMAL;
218 mgr->codec_desc[mgr->codec_cnt+i].factory = factory;
219 pjmedia_vid_codec_info_to_id( &info[i],
220 mgr->codec_desc[mgr->codec_cnt+i].id,
221 sizeof(pjmedia_codec_id));
222 }
223
224 /* Update count */
225 mgr->codec_cnt += count;
226
227 /* Re-sort codec based on priorities */
228 sort_codecs(mgr);
229
230 /* Add factory to the list */
231 pj_list_push_back(&mgr->factory_list, factory);
232
233 pj_mutex_unlock(mgr->mutex);
234
235 return PJ_SUCCESS;
236 }
237
238
239 /*
240 * Unregister a codec factory.
241 */
pjmedia_vid_codec_mgr_unregister_factory(pjmedia_vid_codec_mgr * mgr,pjmedia_vid_codec_factory * factory)242 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_unregister_factory(
243 pjmedia_vid_codec_mgr *mgr,
244 pjmedia_vid_codec_factory *factory)
245 {
246 unsigned i;
247 PJ_ASSERT_RETURN(factory, PJ_EINVAL);
248
249 if (!mgr) mgr = def_vid_codec_mgr;
250 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
251
252 pj_mutex_lock(mgr->mutex);
253
254 /* Factory must be registered. */
255 if (pj_list_find_node(&mgr->factory_list, factory) != factory) {
256 pj_mutex_unlock(mgr->mutex);
257 return PJ_ENOTFOUND;
258 }
259
260 /* Erase factory from the factory list */
261 pj_list_erase(factory);
262
263
264 /* Remove all supported codecs from the codec manager that were created
265 * by the specified factory.
266 */
267 for (i=0; i<mgr->codec_cnt; ) {
268
269 if (mgr->codec_desc[i].factory == factory) {
270 /* Remove the codec from array of codec descriptions */
271 pj_array_erase(mgr->codec_desc, sizeof(mgr->codec_desc[0]),
272 mgr->codec_cnt, i);
273 --mgr->codec_cnt;
274
275 } else {
276 ++i;
277 }
278 }
279
280 pj_mutex_unlock(mgr->mutex);
281
282 return PJ_SUCCESS;
283 }
284
285
286 /*
287 * Enum all codecs.
288 */
pjmedia_vid_codec_mgr_enum_codecs(pjmedia_vid_codec_mgr * mgr,unsigned * count,pjmedia_vid_codec_info codecs[],unsigned * prio)289 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_enum_codecs(
290 pjmedia_vid_codec_mgr *mgr,
291 unsigned *count,
292 pjmedia_vid_codec_info codecs[],
293 unsigned *prio)
294 {
295 unsigned i;
296
297 PJ_ASSERT_RETURN(count && codecs, PJ_EINVAL);
298
299 if (!mgr) mgr = def_vid_codec_mgr;
300 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
301
302 pj_mutex_lock(mgr->mutex);
303
304 if (*count > mgr->codec_cnt)
305 *count = mgr->codec_cnt;
306
307 for (i=0; i<*count; ++i) {
308 pj_memcpy(&codecs[i],
309 &mgr->codec_desc[i].info,
310 sizeof(pjmedia_vid_codec_info));
311 }
312
313 if (prio) {
314 for (i=0; i < *count; ++i)
315 prio[i] = mgr->codec_desc[i].prio;
316 }
317
318 pj_mutex_unlock(mgr->mutex);
319
320 return PJ_SUCCESS;
321 }
322
323
324 /*
325 * Get codec info for the specified payload type.
326 */
pjmedia_vid_codec_mgr_get_codec_info(pjmedia_vid_codec_mgr * mgr,unsigned pt,const pjmedia_vid_codec_info ** p_info)327 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_get_codec_info(
328 pjmedia_vid_codec_mgr *mgr,
329 unsigned pt,
330 const pjmedia_vid_codec_info **p_info)
331 {
332 unsigned i;
333
334 PJ_ASSERT_RETURN(p_info, PJ_EINVAL);
335
336 if (!mgr) mgr = def_vid_codec_mgr;
337 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
338
339 pj_mutex_lock(mgr->mutex);
340
341 for (i=0; i<mgr->codec_cnt; ++i) {
342 if (mgr->codec_desc[i].info.pt == pt) {
343 *p_info = &mgr->codec_desc[i].info;
344
345 pj_mutex_unlock(mgr->mutex);
346 return PJ_SUCCESS;
347 }
348 }
349
350 pj_mutex_unlock(mgr->mutex);
351
352 return PJMEDIA_CODEC_EUNSUP;
353 }
354
355
pjmedia_vid_codec_mgr_get_codec_info2(pjmedia_vid_codec_mgr * mgr,pjmedia_format_id fmt_id,const pjmedia_vid_codec_info ** p_info)356 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_get_codec_info2(
357 pjmedia_vid_codec_mgr *mgr,
358 pjmedia_format_id fmt_id,
359 const pjmedia_vid_codec_info **p_info)
360 {
361 unsigned i;
362
363 PJ_ASSERT_RETURN(p_info, PJ_EINVAL);
364
365 if (!mgr) mgr = def_vid_codec_mgr;
366 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
367
368 pj_mutex_lock(mgr->mutex);
369
370 for (i=0; i<mgr->codec_cnt; ++i) {
371 if (mgr->codec_desc[i].info.fmt_id == fmt_id) {
372 *p_info = &mgr->codec_desc[i].info;
373
374 pj_mutex_unlock(mgr->mutex);
375 return PJ_SUCCESS;
376 }
377 }
378
379 pj_mutex_unlock(mgr->mutex);
380
381 return PJMEDIA_CODEC_EUNSUP;
382 }
383
384
385 /*
386 * Convert codec info struct into a unique codec identifier.
387 * A codec identifier looks something like "H263/34".
388 */
pjmedia_vid_codec_info_to_id(const pjmedia_vid_codec_info * info,char * id,unsigned max_len)389 PJ_DEF(char*) pjmedia_vid_codec_info_to_id(
390 const pjmedia_vid_codec_info *info,
391 char *id, unsigned max_len )
392 {
393 int len;
394
395 PJ_ASSERT_RETURN(info && id && max_len, NULL);
396
397 len = pj_ansi_snprintf(id, max_len, "%.*s/%u",
398 (int)info->encoding_name.slen,
399 info->encoding_name.ptr,
400 info->pt);
401
402 if (len < 1 || len >= (int)max_len) {
403 id[0] = '\0';
404 return NULL;
405 }
406
407 return id;
408 }
409
410
411 /*
412 * Find codecs by the unique codec identifier.
413 */
pjmedia_vid_codec_mgr_find_codecs_by_id(pjmedia_vid_codec_mgr * mgr,const pj_str_t * codec_id,unsigned * count,const pjmedia_vid_codec_info * p_info[],unsigned prio[])414 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_find_codecs_by_id(
415 pjmedia_vid_codec_mgr *mgr,
416 const pj_str_t *codec_id,
417 unsigned *count,
418 const pjmedia_vid_codec_info *p_info[],
419 unsigned prio[])
420 {
421 unsigned i, found = 0;
422
423 PJ_ASSERT_RETURN(codec_id && count && *count, PJ_EINVAL);
424
425 if (!mgr) mgr = def_vid_codec_mgr;
426 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
427
428 pj_mutex_lock(mgr->mutex);
429
430 for (i=0; i<mgr->codec_cnt; ++i) {
431
432 if (codec_id->slen == 0 ||
433 pj_strnicmp2(codec_id, mgr->codec_desc[i].id,
434 codec_id->slen) == 0)
435 {
436
437 if (p_info)
438 p_info[found] = &mgr->codec_desc[i].info;
439 if (prio)
440 prio[found] = mgr->codec_desc[i].prio;
441
442 ++found;
443
444 if (found >= *count)
445 break;
446 }
447
448 }
449
450 pj_mutex_unlock(mgr->mutex);
451
452 *count = found;
453
454 return found ? PJ_SUCCESS : PJ_ENOTFOUND;
455 }
456
457
458 /* Swap two codecs positions in codec manager */
swap_codec(pjmedia_vid_codec_mgr * mgr,unsigned i,unsigned j)459 static void swap_codec(pjmedia_vid_codec_mgr *mgr, unsigned i, unsigned j)
460 {
461 pjmedia_vid_codec_desc tmp;
462
463 pj_memcpy(&tmp, &mgr->codec_desc[i], sizeof(pjmedia_vid_codec_desc));
464
465 pj_memcpy(&mgr->codec_desc[i], &mgr->codec_desc[j],
466 sizeof(pjmedia_vid_codec_desc));
467
468 pj_memcpy(&mgr->codec_desc[j], &tmp, sizeof(pjmedia_vid_codec_desc));
469 }
470
471
472 /* Sort codecs in codec manager based on priorities */
sort_codecs(pjmedia_vid_codec_mgr * mgr)473 static void sort_codecs(pjmedia_vid_codec_mgr *mgr)
474 {
475 unsigned i;
476
477 /* Re-sort */
478 for (i=0; i<mgr->codec_cnt; ++i) {
479 unsigned j, max;
480
481 for (max=i, j=i+1; j<mgr->codec_cnt; ++j) {
482 if (mgr->codec_desc[j].prio > mgr->codec_desc[max].prio)
483 max = j;
484 }
485
486 if (max != i)
487 swap_codec(mgr, i, max);
488 }
489
490 /* Change PJMEDIA_CODEC_PRIO_HIGHEST codecs to NEXT_HIGHER */
491 for (i=0; i<mgr->codec_cnt; ++i) {
492 if (mgr->codec_desc[i].prio == PJMEDIA_CODEC_PRIO_HIGHEST)
493 mgr->codec_desc[i].prio = PJMEDIA_CODEC_PRIO_NEXT_HIGHER;
494 else
495 break;
496 }
497 }
498
499
500 /**
501 * Set codec priority. The codec priority determines the order of
502 * the codec in the SDP created by the endpoint. If more than one codecs
503 * are found with the same codec_id prefix, then the function sets the
504 * priorities of all those codecs.
505 */
pjmedia_vid_codec_mgr_set_codec_priority(pjmedia_vid_codec_mgr * mgr,const pj_str_t * codec_id,pj_uint8_t prio)506 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_set_codec_priority(
507 pjmedia_vid_codec_mgr *mgr,
508 const pj_str_t *codec_id,
509 pj_uint8_t prio)
510 {
511 unsigned i, found = 0;
512
513 PJ_ASSERT_RETURN(codec_id, PJ_EINVAL);
514
515 if (!mgr) mgr = def_vid_codec_mgr;
516 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
517
518 pj_mutex_lock(mgr->mutex);
519
520 /* Update the priorities of affected codecs */
521 for (i=0; i<mgr->codec_cnt; ++i)
522 {
523 if (codec_id->slen == 0 ||
524 pj_strnicmp2(codec_id, mgr->codec_desc[i].id,
525 codec_id->slen) == 0)
526 {
527 mgr->codec_desc[i].prio = (pjmedia_codec_priority) prio;
528 ++found;
529 }
530 }
531
532 if (!found) {
533 pj_mutex_unlock(mgr->mutex);
534 return PJ_ENOTFOUND;
535 }
536
537 /* Re-sort codecs */
538 sort_codecs(mgr);
539
540 pj_mutex_unlock(mgr->mutex);
541
542 return PJ_SUCCESS;
543 }
544
545
546 /*
547 * Allocate one codec.
548 */
pjmedia_vid_codec_mgr_alloc_codec(pjmedia_vid_codec_mgr * mgr,const pjmedia_vid_codec_info * info,pjmedia_vid_codec ** p_codec)549 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_alloc_codec(
550 pjmedia_vid_codec_mgr *mgr,
551 const pjmedia_vid_codec_info *info,
552 pjmedia_vid_codec **p_codec)
553 {
554 pjmedia_vid_codec_factory *factory;
555 pj_status_t status;
556
557 PJ_ASSERT_RETURN(info && p_codec, PJ_EINVAL);
558
559 if (!mgr) mgr = def_vid_codec_mgr;
560 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
561
562 *p_codec = NULL;
563
564 pj_mutex_lock(mgr->mutex);
565
566 factory = mgr->factory_list.next;
567 while (factory != &mgr->factory_list) {
568
569 if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
570
571 status = (*factory->op->alloc_codec)(factory, info, p_codec);
572 if (status == PJ_SUCCESS) {
573 pj_mutex_unlock(mgr->mutex);
574 return PJ_SUCCESS;
575 }
576
577 }
578
579 factory = factory->next;
580 }
581
582 pj_mutex_unlock(mgr->mutex);
583
584 return PJMEDIA_CODEC_EUNSUP;
585 }
586
587
588 /*
589 * Get default codec parameter.
590 */
pjmedia_vid_codec_mgr_get_default_param(pjmedia_vid_codec_mgr * mgr,const pjmedia_vid_codec_info * info,pjmedia_vid_codec_param * param)591 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_get_default_param(
592 pjmedia_vid_codec_mgr *mgr,
593 const pjmedia_vid_codec_info *info,
594 pjmedia_vid_codec_param *param )
595 {
596 pjmedia_vid_codec_factory *factory;
597 pj_status_t status;
598 pjmedia_codec_id codec_id;
599 pjmedia_vid_codec_desc *codec_desc = NULL;
600 unsigned i;
601
602 PJ_ASSERT_RETURN(info && param, PJ_EINVAL);
603
604 if (!mgr) mgr = def_vid_codec_mgr;
605 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
606
607 if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id,
608 sizeof(codec_id)))
609 return PJ_EINVAL;
610
611 pj_mutex_lock(mgr->mutex);
612
613 /* First, lookup default param in codec desc */
614 for (i=0; i < mgr->codec_cnt; ++i) {
615 if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) {
616 codec_desc = &mgr->codec_desc[i];
617 break;
618 }
619 }
620
621 /* If we found the codec and its default param is set, return it */
622 if (codec_desc && codec_desc->def_param) {
623 pj_memcpy(param, codec_desc->def_param->param,
624 sizeof(pjmedia_vid_codec_param));
625
626 pj_mutex_unlock(mgr->mutex);
627 return PJ_SUCCESS;
628 }
629
630 /* Otherwise query the default param from codec factory */
631 factory = mgr->factory_list.next;
632 while (factory != &mgr->factory_list) {
633
634 if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
635
636 status = (*factory->op->default_attr)(factory, info, param);
637 if (status == PJ_SUCCESS) {
638 /* Check for invalid max_bps. */
639 //if (param->info.max_bps < param->info.avg_bps)
640 // param->info.max_bps = param->info.avg_bps;
641
642 pj_mutex_unlock(mgr->mutex);
643 return PJ_SUCCESS;
644 }
645
646 }
647
648 factory = factory->next;
649 }
650
651 pj_mutex_unlock(mgr->mutex);
652
653
654 return PJMEDIA_CODEC_EUNSUP;
655 }
656
657
658 /*
659 * Set default codec parameter.
660 */
pjmedia_vid_codec_mgr_set_default_param(pjmedia_vid_codec_mgr * mgr,const pjmedia_vid_codec_info * info,const pjmedia_vid_codec_param * param)661 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_set_default_param(
662 pjmedia_vid_codec_mgr *mgr,
663 const pjmedia_vid_codec_info *info,
664 const pjmedia_vid_codec_param *param )
665 {
666 unsigned i;
667 pjmedia_codec_id codec_id;
668 pjmedia_vid_codec_desc *codec_desc = NULL;
669 pj_pool_t *pool, *old_pool = NULL;
670 pjmedia_vid_codec_default_param *p;
671
672 PJ_ASSERT_RETURN(info, PJ_EINVAL);
673
674 if (!mgr) mgr = def_vid_codec_mgr;
675 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
676
677 if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id)))
678 return PJ_EINVAL;
679
680 pj_mutex_lock(mgr->mutex);
681
682 /* Lookup codec desc */
683 for (i=0; i < mgr->codec_cnt; ++i) {
684 if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) {
685 codec_desc = &mgr->codec_desc[i];
686 break;
687 }
688 }
689
690 /* Codec not found */
691 if (!codec_desc) {
692 pj_mutex_unlock(mgr->mutex);
693 return PJMEDIA_CODEC_EUNSUP;
694 }
695
696 /* If codec param is previously set */
697 if (codec_desc->def_param) {
698 pj_assert(codec_desc->def_param->pool);
699 old_pool = codec_desc->def_param->pool;
700 codec_desc->def_param = NULL;
701 }
702
703 /* When param is set to NULL, i.e: setting default codec param to library
704 * default setting, just return PJ_SUCCESS.
705 */
706 if (NULL == param) {
707 pj_mutex_unlock(mgr->mutex);
708 if (old_pool)
709 pj_pool_release(old_pool);
710 return PJ_SUCCESS;
711 }
712
713 /* Create new default codec param instance */
714 pool = pj_pool_create(mgr->pf, (char*)codec_id, 256, 256, NULL);
715 codec_desc->def_param = PJ_POOL_ZALLOC_T(pool,
716 pjmedia_vid_codec_default_param);
717 p = codec_desc->def_param;
718 p->pool = pool;
719
720 /* Update codec default param */
721 p->param = pjmedia_vid_codec_param_clone(pool, param);
722 if (!p->param) {
723 pj_mutex_unlock(mgr->mutex);
724 return PJ_EINVAL;
725 }
726
727 codec_desc->def_param = p;
728
729 pj_mutex_unlock(mgr->mutex);
730
731 /* Release old pool at the very end, as application tends to apply changes
732 * to the existing/old codec param fetched using
733 * pjmedia_vid_codec_mgr_get_default_param() which doesn't do deep clone.
734 */
735 if (old_pool)
736 pj_pool_release(old_pool);
737
738 return PJ_SUCCESS;
739 }
740
741
742 /*
743 * Dealloc codec.
744 */
745 PJ_DEF(pj_status_t)
pjmedia_vid_codec_mgr_dealloc_codec(pjmedia_vid_codec_mgr * mgr,pjmedia_vid_codec * codec)746 pjmedia_vid_codec_mgr_dealloc_codec(pjmedia_vid_codec_mgr *mgr,
747 pjmedia_vid_codec *codec)
748 {
749 PJ_ASSERT_RETURN(codec, PJ_EINVAL);
750
751 if (!mgr) mgr = def_vid_codec_mgr;
752 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
753
754 return (*codec->factory->op->dealloc_codec)(codec->factory, codec);
755 }
756
757
758 #endif /* PJMEDIA_HAS_VIDEO */
759