1
/* $Id: vid_codec.c 4008 2012-04-03 04:03:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
20
#include <pjmedia/vid_codec.h>
21
#include <pjmedia/errno.h>
23
#include <pj/assert.h>
25
#include <pj/string.h>
28
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
31
#define THIS_FILE "vid_codec.c"
33
static pjmedia_vid_codec_mgr *def_vid_codec_mgr;
36
/* Definition of default codecs parameters */
37
typedef struct pjmedia_vid_codec_default_param
40
pjmedia_vid_codec_param *param;
41
} pjmedia_vid_codec_default_param;
45
* Codec manager maintains array of these structs for each supported
48
typedef struct pjmedia_vid_codec_desc
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
56
} pjmedia_vid_codec_desc;
59
/* The declaration of video codec manager */
60
struct pjmedia_vid_codec_mgr
62
/** Pool factory instance. */
65
/** Codec manager mutex. */
68
/** List of codec factories registered to codec manager. */
69
pjmedia_vid_codec_factory factory_list;
71
/** Number of supported codecs. */
74
/** Array of codec descriptor. */
75
pjmedia_vid_codec_desc codec_desc[PJMEDIA_CODEC_MGR_MAX_CODECS];
81
/* Sort codecs in codec manager based on priorities */
82
static void sort_codecs(pjmedia_vid_codec_mgr *mgr);
86
* Duplicate video codec parameter.
88
PJ_DEF(pjmedia_vid_codec_param*) pjmedia_vid_codec_param_clone(
90
const pjmedia_vid_codec_param *src)
92
pjmedia_vid_codec_param *p;
95
PJ_ASSERT_RETURN(pool && src, NULL);
97
p = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec_param);
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);
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);
118
* Initialize codec manager.
120
PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_create(
122
pjmedia_vid_codec_mgr **p_mgr)
124
pjmedia_vid_codec_mgr *mgr;
127
PJ_ASSERT_RETURN(pool, PJ_EINVAL);
129
mgr = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec_mgr);
130
mgr->pf = pool->factory;
131
pj_list_init (&mgr->factory_list);
135
status = pj_mutex_create_recursive(pool, "vid-codec-mgr", &mgr->mutex);
136
if (status != PJ_SUCCESS)
139
if (!def_vid_codec_mgr)
140
def_vid_codec_mgr = mgr;
149
* Initialize codec manager.
151
PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_destroy (pjmedia_vid_codec_mgr *mgr)
153
if (!mgr) mgr = def_vid_codec_mgr;
154
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
158
pj_mutex_destroy(mgr->mutex);
160
/* Just for safety, set codec manager states to zero */
161
pj_bzero(mgr, sizeof(pjmedia_vid_codec_mgr));
163
if (mgr == def_vid_codec_mgr)
164
def_vid_codec_mgr = NULL;
170
PJ_DEF(pjmedia_vid_codec_mgr*) pjmedia_vid_codec_mgr_instance(void)
172
//pj_assert(def_vid_codec_mgr);
173
return def_vid_codec_mgr;
176
PJ_DEF(void) pjmedia_vid_codec_mgr_set_instance(pjmedia_vid_codec_mgr* mgr)
178
def_vid_codec_mgr = mgr;
183
* Register a codec 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)
189
pjmedia_vid_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS];
193
PJ_ASSERT_RETURN(factory, PJ_EINVAL);
195
if (!mgr) mgr = def_vid_codec_mgr;
196
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
199
count = PJ_ARRAY_SIZE(info);
200
status = factory->op->enum_info(factory, &count, info);
201
if (status != PJ_SUCCESS)
204
pj_mutex_lock(mgr->mutex);
206
/* Check codec count */
207
if (count + mgr->codec_cnt > PJ_ARRAY_SIZE(mgr->codec_desc)) {
208
pj_mutex_unlock(mgr->mutex);
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));
225
mgr->codec_cnt += count;
227
/* Re-sort codec based on priorities */
230
/* Add factory to the list */
231
pj_list_push_back(&mgr->factory_list, factory);
233
pj_mutex_unlock(mgr->mutex);
240
* Unregister a codec 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)
247
PJ_ASSERT_RETURN(factory, PJ_EINVAL);
249
if (!mgr) mgr = def_vid_codec_mgr;
250
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
252
pj_mutex_lock(mgr->mutex);
254
/* Factory must be registered. */
255
if (pj_list_find_node(&mgr->factory_list, factory) != factory) {
256
pj_mutex_unlock(mgr->mutex);
260
/* Erase factory from the factory list */
261
pj_list_erase(factory);
264
/* Remove all supported codecs from the codec manager that were created
265
* by the specified factory.
267
for (i=0; i<mgr->codec_cnt; ) {
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]),
280
pj_mutex_unlock(mgr->mutex);
289
PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_enum_codecs(
290
pjmedia_vid_codec_mgr *mgr,
292
pjmedia_vid_codec_info codecs[],
297
PJ_ASSERT_RETURN(count && codecs, PJ_EINVAL);
299
if (!mgr) mgr = def_vid_codec_mgr;
300
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
302
pj_mutex_lock(mgr->mutex);
304
if (*count > mgr->codec_cnt)
305
*count = mgr->codec_cnt;
307
for (i=0; i<*count; ++i) {
308
pj_memcpy(&codecs[i],
309
&mgr->codec_desc[i].info,
310
sizeof(pjmedia_vid_codec_info));
314
for (i=0; i < *count; ++i)
315
prio[i] = mgr->codec_desc[i].prio;
318
pj_mutex_unlock(mgr->mutex);
325
* Get codec info for the specified payload type.
327
PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_get_codec_info(
328
pjmedia_vid_codec_mgr *mgr,
330
const pjmedia_vid_codec_info **p_info)
334
PJ_ASSERT_RETURN(p_info, PJ_EINVAL);
336
if (!mgr) mgr = def_vid_codec_mgr;
337
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
339
pj_mutex_lock(mgr->mutex);
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;
345
pj_mutex_unlock(mgr->mutex);
350
pj_mutex_unlock(mgr->mutex);
352
return PJMEDIA_CODEC_EUNSUP;
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)
363
PJ_ASSERT_RETURN(p_info, PJ_EINVAL);
365
if (!mgr) mgr = def_vid_codec_mgr;
366
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
368
pj_mutex_lock(mgr->mutex);
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;
374
pj_mutex_unlock(mgr->mutex);
379
pj_mutex_unlock(mgr->mutex);
381
return PJMEDIA_CODEC_EUNSUP;
386
* Convert codec info struct into a unique codec identifier.
387
* A codec identifier looks something like "H263/34".
389
PJ_DEF(char*) pjmedia_vid_codec_info_to_id(
390
const pjmedia_vid_codec_info *info,
391
char *id, unsigned max_len )
395
PJ_ASSERT_RETURN(info && id && max_len, NULL);
397
len = pj_ansi_snprintf(id, max_len, "%.*s/%u",
398
(int)info->encoding_name.slen,
399
info->encoding_name.ptr,
402
if (len < 1 || len >= (int)max_len) {
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.
417
PJ_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,
421
const pjmedia_vid_codec_info *p_info[],
424
unsigned i, found = 0;
426
PJ_ASSERT_RETURN(codec_id && count && *count, PJ_EINVAL);
428
if (!mgr) mgr = def_vid_codec_mgr;
429
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
431
pj_mutex_lock(mgr->mutex);
433
for (i=0; i<mgr->codec_cnt; ++i) {
435
if (codec_id->slen == 0 ||
436
pj_strnicmp2(codec_id, mgr->codec_desc[i].id,
437
codec_id->slen) == 0)
441
p_info[found] = &mgr->codec_desc[i].info;
443
prio[found] = mgr->codec_desc[i].prio;
453
pj_mutex_unlock(mgr->mutex);
457
return found ? PJ_SUCCESS : PJ_ENOTFOUND;
461
/* Swap two codecs positions in codec manager */
462
static void swap_codec(pjmedia_vid_codec_mgr *mgr, unsigned i, unsigned j)
464
pjmedia_vid_codec_desc tmp;
466
pj_memcpy(&tmp, &mgr->codec_desc[i], sizeof(pjmedia_vid_codec_desc));
468
pj_memcpy(&mgr->codec_desc[i], &mgr->codec_desc[j],
469
sizeof(pjmedia_vid_codec_desc));
471
pj_memcpy(&mgr->codec_desc[j], &tmp, sizeof(pjmedia_vid_codec_desc));
475
/* Sort codecs in codec manager based on priorities */
476
static void sort_codecs(pjmedia_vid_codec_mgr *mgr)
481
for (i=0; i<mgr->codec_cnt; ++i) {
484
for (max=i, j=i+1; j<mgr->codec_cnt; ++j) {
485
if (mgr->codec_desc[j].prio > mgr->codec_desc[max].prio)
490
swap_codec(mgr, i, max);
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;
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.
509
PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_set_codec_priority(
510
pjmedia_vid_codec_mgr *mgr,
511
const pj_str_t *codec_id,
514
unsigned i, found = 0;
516
PJ_ASSERT_RETURN(codec_id, PJ_EINVAL);
518
if (!mgr) mgr = def_vid_codec_mgr;
519
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
521
pj_mutex_lock(mgr->mutex);
523
/* Update the priorities of affected codecs */
524
for (i=0; i<mgr->codec_cnt; ++i)
526
if (codec_id->slen == 0 ||
527
pj_strnicmp2(codec_id, mgr->codec_desc[i].id,
528
codec_id->slen) == 0)
530
mgr->codec_desc[i].prio = (pjmedia_codec_priority) prio;
536
pj_mutex_unlock(mgr->mutex);
543
pj_mutex_unlock(mgr->mutex);
550
* Allocate one codec.
552
PJ_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)
557
pjmedia_vid_codec_factory *factory;
560
PJ_ASSERT_RETURN(info && p_codec, PJ_EINVAL);
562
if (!mgr) mgr = def_vid_codec_mgr;
563
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
567
pj_mutex_lock(mgr->mutex);
569
factory = mgr->factory_list.next;
570
while (factory != &mgr->factory_list) {
572
if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
574
status = (*factory->op->alloc_codec)(factory, info, p_codec);
575
if (status == PJ_SUCCESS) {
576
pj_mutex_unlock(mgr->mutex);
582
factory = factory->next;
585
pj_mutex_unlock(mgr->mutex);
587
return PJMEDIA_CODEC_EUNSUP;
592
* Get default codec parameter.
594
PJ_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 )
599
pjmedia_vid_codec_factory *factory;
601
pjmedia_codec_id codec_id;
602
pjmedia_vid_codec_desc *codec_desc = NULL;
605
PJ_ASSERT_RETURN(info && param, PJ_EINVAL);
607
if (!mgr) mgr = def_vid_codec_mgr;
608
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
610
if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id,
614
pj_mutex_lock(mgr->mutex);
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];
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));
629
pj_mutex_unlock(mgr->mutex);
633
/* Otherwise query the default param from codec factory */
634
factory = mgr->factory_list.next;
635
while (factory != &mgr->factory_list) {
637
if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
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;
645
pj_mutex_unlock(mgr->mutex);
651
factory = factory->next;
654
pj_mutex_unlock(mgr->mutex);
657
return PJMEDIA_CODEC_EUNSUP;
662
* Set default codec parameter.
664
PJ_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 )
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;
675
PJ_ASSERT_RETURN(info, PJ_EINVAL);
677
if (!mgr) mgr = def_vid_codec_mgr;
678
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
680
if (!pjmedia_vid_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id)))
683
pj_mutex_lock(mgr->mutex);
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];
693
/* Codec not found */
695
pj_mutex_unlock(mgr->mutex);
696
return PJMEDIA_CODEC_EUNSUP;
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;
706
/* When param is set to NULL, i.e: setting default codec param to library
707
* default setting, just return PJ_SUCCESS.
710
pj_mutex_unlock(mgr->mutex);
712
pj_pool_release(old_pool);
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;
723
/* Update codec default param */
724
p->param = pjmedia_vid_codec_param_clone(pool, param);
728
codec_desc->def_param = p;
730
pj_mutex_unlock(mgr->mutex);
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.
737
pj_pool_release(old_pool);
747
pjmedia_vid_codec_mgr_dealloc_codec(pjmedia_vid_codec_mgr *mgr,
748
pjmedia_vid_codec *codec)
750
PJ_ASSERT_RETURN(codec, PJ_EINVAL);
752
if (!mgr) mgr = def_vid_codec_mgr;
753
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
755
return (*codec->factory->op->dealloc_codec)(codec->factory, codec);
759
#endif /* PJMEDIA_HAS_VIDEO */