blob: 93690a2925f23b1cd28d27b97e46a5294139ddbe [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 <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
33static pjmedia_vid_codec_mgr *def_vid_codec_mgr;
34
35
36/* Definition of default codecs parameters */
37typedef 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 */
48typedef 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 */
60struct 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 */
82static void sort_codecs(pjmedia_vid_codec_mgr *mgr);
83
84
85/*
86 * Duplicate video codec parameter.
87 */
88PJ_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 */
120PJ_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 */
151PJ_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
170PJ_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
176PJ_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 */
185PJ_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 */
242PJ_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 */
289PJ_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 */
327PJ_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
356PJ_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 */
389PJ_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. This function will find
413 * all codecs that match the codec identifier prefix. For example, if
414 * "L16" is specified, then it will find "L16/8000/1", "L16/16000/1",
415 * and so on, up to the maximum count specified in the argument.
416 */
417PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_find_codecs_by_id(
418 pjmedia_vid_codec_mgr *mgr,
419 const pj_str_t *codec_id,
420 unsigned *count,
421 const pjmedia_vid_codec_info *p_info[],
422 unsigned prio[])
423{
424 unsigned i, found = 0;
425
426 PJ_ASSERT_RETURN(codec_id && count && *count, PJ_EINVAL);
427
428 if (!mgr) mgr = def_vid_codec_mgr;
429 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
430
431 pj_mutex_lock(mgr->mutex);
432
433 for (i=0; i<mgr->codec_cnt; ++i) {
434
435 if (codec_id->slen == 0 ||
436 pj_strnicmp2(codec_id, mgr->codec_desc[i].id,
437 codec_id->slen) == 0)
438 {
439
440 if (p_info)
441 p_info[found] = &mgr->codec_desc[i].info;
442 if (prio)
443 prio[found] = mgr->codec_desc[i].prio;
444
445 ++found;
446
447 if (found >= *count)
448 break;
449 }
450
451 }
452
453 pj_mutex_unlock(mgr->mutex);
454
455 *count = found;
456
457 return found ? PJ_SUCCESS : PJ_ENOTFOUND;
458}
459
460
461/* Swap two codecs positions in codec manager */
462static void swap_codec(pjmedia_vid_codec_mgr *mgr, unsigned i, unsigned j)
463{
464 pjmedia_vid_codec_desc tmp;
465
466 pj_memcpy(&tmp, &mgr->codec_desc[i], sizeof(pjmedia_vid_codec_desc));
467
468 pj_memcpy(&mgr->codec_desc[i], &mgr->codec_desc[j],
469 sizeof(pjmedia_vid_codec_desc));
470
471 pj_memcpy(&mgr->codec_desc[j], &tmp, sizeof(pjmedia_vid_codec_desc));
472}
473
474
475/* Sort codecs in codec manager based on priorities */
476static void sort_codecs(pjmedia_vid_codec_mgr *mgr)
477{
478 unsigned i;
479
480 /* Re-sort */
481 for (i=0; i<mgr->codec_cnt; ++i) {
482 unsigned j, max;
483
484 for (max=i, j=i+1; j<mgr->codec_cnt; ++j) {
485 if (mgr->codec_desc[j].prio > mgr->codec_desc[max].prio)
486 max = j;
487 }
488
489 if (max != i)
490 swap_codec(mgr, i, max);
491 }
492
493 /* Change PJMEDIA_CODEC_PRIO_HIGHEST codecs to NEXT_HIGHER */
494 for (i=0; i<mgr->codec_cnt; ++i) {
495 if (mgr->codec_desc[i].prio == PJMEDIA_CODEC_PRIO_HIGHEST)
496 mgr->codec_desc[i].prio = PJMEDIA_CODEC_PRIO_NEXT_HIGHER;
497 else
498 break;
499 }
500}
501
502
503/**
504 * Set codec priority. The codec priority determines the order of
505 * the codec in the SDP created by the endpoint. If more than one codecs
506 * are found with the same codec_id prefix, then the function sets the
507 * priorities of all those codecs.
508 */
509PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_set_codec_priority(
510 pjmedia_vid_codec_mgr *mgr,
511 const pj_str_t *codec_id,
512 pj_uint8_t prio)
513{
514 unsigned i, found = 0;
515
516 PJ_ASSERT_RETURN(codec_id, PJ_EINVAL);
517
518 if (!mgr) mgr = def_vid_codec_mgr;
519 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
520
521 pj_mutex_lock(mgr->mutex);
522
523 /* Update the priorities of affected codecs */
524 for (i=0; i<mgr->codec_cnt; ++i)
525 {
526 if (codec_id->slen == 0 ||
527 pj_strnicmp2(codec_id, mgr->codec_desc[i].id,
528 codec_id->slen) == 0)
529 {
530 mgr->codec_desc[i].prio = (pjmedia_codec_priority) prio;
531 ++found;
532 }
533 }
534
535 if (!found) {
536 pj_mutex_unlock(mgr->mutex);
537 return PJ_ENOTFOUND;
538 }
539
540 /* Re-sort codecs */
541 sort_codecs(mgr);
542
543 pj_mutex_unlock(mgr->mutex);
544
545 return PJ_SUCCESS;
546}
547
548
549/*
550 * Allocate one codec.
551 */
552PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_alloc_codec(
553 pjmedia_vid_codec_mgr *mgr,
554 const pjmedia_vid_codec_info *info,
555 pjmedia_vid_codec **p_codec)
556{
557 pjmedia_vid_codec_factory *factory;
558 pj_status_t status;
559
560 PJ_ASSERT_RETURN(info && p_codec, PJ_EINVAL);
561
562 if (!mgr) mgr = def_vid_codec_mgr;
563 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
564
565 *p_codec = NULL;
566
567 pj_mutex_lock(mgr->mutex);
568
569 factory = mgr->factory_list.next;
570 while (factory != &mgr->factory_list) {
571
572 if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
573
574 status = (*factory->op->alloc_codec)(factory, info, p_codec);
575 if (status == PJ_SUCCESS) {
576 pj_mutex_unlock(mgr->mutex);
577 return PJ_SUCCESS;
578 }
579
580 }
581
582 factory = factory->next;
583 }
584
585 pj_mutex_unlock(mgr->mutex);
586
587 return PJMEDIA_CODEC_EUNSUP;
588}
589
590
591/*
592 * Get default codec parameter.
593 */
594PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_get_default_param(
595 pjmedia_vid_codec_mgr *mgr,
596 const pjmedia_vid_codec_info *info,
597 pjmedia_vid_codec_param *param )
598{
599 pjmedia_vid_codec_factory *factory;
600 pj_status_t status;
601 pjmedia_codec_id codec_id;
602 pjmedia_vid_codec_desc *codec_desc = NULL;
603 unsigned i;
604
605 PJ_ASSERT_RETURN(info && param, PJ_EINVAL);
606
607 if (!mgr) mgr = def_vid_codec_mgr;
608 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
609
610 if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id,
611 sizeof(codec_id)))
612 return PJ_EINVAL;
613
614 pj_mutex_lock(mgr->mutex);
615
616 /* First, lookup default param in codec desc */
617 for (i=0; i < mgr->codec_cnt; ++i) {
618 if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) {
619 codec_desc = &mgr->codec_desc[i];
620 break;
621 }
622 }
623
624 /* If we found the codec and its default param is set, return it */
625 if (codec_desc && codec_desc->def_param) {
626 pj_memcpy(param, codec_desc->def_param->param,
627 sizeof(pjmedia_vid_codec_param));
628
629 pj_mutex_unlock(mgr->mutex);
630 return PJ_SUCCESS;
631 }
632
633 /* Otherwise query the default param from codec factory */
634 factory = mgr->factory_list.next;
635 while (factory != &mgr->factory_list) {
636
637 if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
638
639 status = (*factory->op->default_attr)(factory, info, param);
640 if (status == PJ_SUCCESS) {
641 /* Check for invalid max_bps. */
642 //if (param->info.max_bps < param->info.avg_bps)
643 // param->info.max_bps = param->info.avg_bps;
644
645 pj_mutex_unlock(mgr->mutex);
646 return PJ_SUCCESS;
647 }
648
649 }
650
651 factory = factory->next;
652 }
653
654 pj_mutex_unlock(mgr->mutex);
655
656
657 return PJMEDIA_CODEC_EUNSUP;
658}
659
660
661/*
662 * Set default codec parameter.
663 */
664PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_set_default_param(
665 pjmedia_vid_codec_mgr *mgr,
666 const pjmedia_vid_codec_info *info,
667 const pjmedia_vid_codec_param *param )
668{
669 unsigned i;
670 pjmedia_codec_id codec_id;
671 pjmedia_vid_codec_desc *codec_desc = NULL;
672 pj_pool_t *pool, *old_pool = NULL;
673 pjmedia_vid_codec_default_param *p;
674
675 PJ_ASSERT_RETURN(info, PJ_EINVAL);
676
677 if (!mgr) mgr = def_vid_codec_mgr;
678 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
679
680 if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id)))
681 return PJ_EINVAL;
682
683 pj_mutex_lock(mgr->mutex);
684
685 /* Lookup codec desc */
686 for (i=0; i < mgr->codec_cnt; ++i) {
687 if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) {
688 codec_desc = &mgr->codec_desc[i];
689 break;
690 }
691 }
692
693 /* Codec not found */
694 if (!codec_desc) {
695 pj_mutex_unlock(mgr->mutex);
696 return PJMEDIA_CODEC_EUNSUP;
697 }
698
699 /* If codec param is previously set */
700 if (codec_desc->def_param) {
701 pj_assert(codec_desc->def_param->pool);
702 old_pool = codec_desc->def_param->pool;
703 codec_desc->def_param = NULL;
704 }
705
706 /* When param is set to NULL, i.e: setting default codec param to library
707 * default setting, just return PJ_SUCCESS.
708 */
709 if (NULL == param) {
710 pj_mutex_unlock(mgr->mutex);
711 if (old_pool)
712 pj_pool_release(old_pool);
713 return PJ_SUCCESS;
714 }
715
716 /* Create new default codec param instance */
717 pool = pj_pool_create(mgr->pf, (char*)codec_id, 256, 256, NULL);
718 codec_desc->def_param = PJ_POOL_ZALLOC_T(pool,
719 pjmedia_vid_codec_default_param);
720 p = codec_desc->def_param;
721 p->pool = pool;
722
723 /* Update codec default param */
724 p->param = pjmedia_vid_codec_param_clone(pool, param);
725 if (!p->param)
726 return PJ_EINVAL;
727
728 codec_desc->def_param = p;
729
730 pj_mutex_unlock(mgr->mutex);
731
732 /* Release old pool at the very end, as application tends to apply changes
733 * to the existing/old codec param fetched using
734 * pjmedia_vid_codec_mgr_get_default_param() which doesn't do deep clone.
735 */
736 if (old_pool)
737 pj_pool_release(old_pool);
738
739 return PJ_SUCCESS;
740}
741
742
743/*
744 * Dealloc codec.
745 */
746PJ_DEF(pj_status_t)
747pjmedia_vid_codec_mgr_dealloc_codec(pjmedia_vid_codec_mgr *mgr,
748 pjmedia_vid_codec *codec)
749{
750 PJ_ASSERT_RETURN(codec, PJ_EINVAL);
751
752 if (!mgr) mgr = def_vid_codec_mgr;
753 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
754
755 return (*codec->factory->op->dealloc_codec)(codec->factory, codec);
756}
757
758
759#endif /* PJMEDIA_HAS_VIDEO */