Ignore:
Timestamp:
Apr 27, 2006 10:36:40 PM (18 years ago)
Author:
bennylp
Message:

Initial support for stereo codecs, and added L16 codecs. Also better handling for case remote media is restarted

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/codec.c

    r276 r411  
    1919#include <pjmedia/codec.h> 
    2020#include <pjmedia/errno.h> 
     21#include <pj/array.h> 
     22#include <pj/assert.h> 
     23#include <pj/log.h> 
    2124#include <pj/pool.h> 
    2225#include <pj/string.h> 
    23 #include <pj/assert.h> 
    24 #include <pj/log.h> 
    2526 
    2627#define THIS_FILE   "codec.c" 
    2728 
    28 /* 
    29  * Reinitialize array of supported codecs. 
    30  */ 
    31 static void enum_all_codecs (pjmedia_codec_mgr *mgr) 
    32 { 
    33     pjmedia_codec_factory *factory; 
    34  
    35     mgr->codec_cnt = 0; 
    36  
    37     factory = mgr->factory_list.next; 
    38     while (factory != &mgr->factory_list) { 
    39         unsigned count; 
    40         pj_status_t status; 
    41  
    42         count = PJ_ARRAY_SIZE(mgr->codecs) - mgr->codec_cnt; 
    43         status = factory->op->enum_info(factory, &count,  
    44                                         mgr->codecs+mgr->codec_cnt); 
    45         if (status == PJ_SUCCESS) 
    46             mgr->codec_cnt += count; 
    47  
    48         factory = factory->next; 
    49     } 
    50 } 
     29 
     30 
     31 
     32/* Sort codecs in codec manager based on priorities */ 
     33static void sort_codecs(pjmedia_codec_mgr *mgr); 
     34 
    5135 
    5236/* 
     
    6246    return PJ_SUCCESS; 
    6347} 
     48 
    6449 
    6550/* 
     
    7055                                    pjmedia_codec_factory *factory) 
    7156{ 
     57    pjmedia_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS]; 
     58    unsigned i, count; 
     59    pj_status_t status; 
     60 
    7261    PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL); 
    7362 
     63    /* Enum codecs */ 
     64    count = PJ_ARRAY_SIZE(info); 
     65    status = factory->op->enum_info(factory, &count, info); 
     66    if (status != PJ_SUCCESS) 
     67        return status; 
     68     
     69 
     70    /* Check codec count */ 
     71    if (count + mgr->codec_cnt > PJ_ARRAY_SIZE(mgr->codec_desc)) 
     72        return PJ_ETOOMANY; 
     73 
     74 
     75    /* Save the codecs */ 
     76    for (i=0; i<count; ++i) { 
     77        pj_memcpy( &mgr->codec_desc[mgr->codec_cnt+i], 
     78                   &info[i], sizeof(pjmedia_codec_info)); 
     79        mgr->codec_desc[mgr->codec_cnt+i].prio = PJMEDIA_CODEC_PRIO_NORMAL; 
     80        mgr->codec_desc[mgr->codec_cnt+i].factory = factory; 
     81        pjmedia_codec_info_to_id( &info[i], 
     82                                  mgr->codec_desc[mgr->codec_cnt+i].id, 
     83                                  sizeof(pjmedia_codec_id)); 
     84    } 
     85 
     86    /* Update count */ 
     87    mgr->codec_cnt += count; 
     88 
     89    /* Re-sort codec based on priorities */ 
     90    sort_codecs(mgr); 
     91 
     92    /* Add factory to the list */ 
    7493    pj_list_push_back(&mgr->factory_list, factory); 
    75     enum_all_codecs (mgr); 
     94 
    7695 
    7796    return PJ_SUCCESS; 
    7897} 
     98 
    7999 
    80100/* 
     
    85105                                     pjmedia_codec_factory *factory) 
    86106{ 
    87  
     107    unsigned i; 
    88108    PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL); 
    89109 
     
    92112                     PJ_ENOTFOUND); 
    93113 
    94  
     114    /* Erase factory from the factory list */ 
    95115    pj_list_erase(factory); 
    96     enum_all_codecs (mgr); 
     116 
     117 
     118    /* Remove all supported codecs from the codec manager that were created  
     119     * by the specified factory. 
     120     */ 
     121    for (i=0; i<mgr->codec_cnt; ) { 
     122 
     123        if (mgr->codec_desc[i].factory == factory) { 
     124 
     125            pj_array_erase(mgr->codec_desc, sizeof(mgr->codec_desc[0]),  
     126                           mgr->codec_cnt, i); 
     127            --mgr->codec_cnt; 
     128 
     129        } else { 
     130            ++i; 
     131        } 
     132    } 
     133 
    97134 
    98135    return PJ_SUCCESS; 
    99136} 
     137 
    100138 
    101139/* 
     
    105143pjmedia_codec_mgr_enum_codecs(pjmedia_codec_mgr *mgr,  
    106144                              unsigned *count,  
    107                               pjmedia_codec_info codecs[]) 
    108 { 
     145                              pjmedia_codec_info codecs[], 
     146                              unsigned *prio) 
     147{ 
     148    unsigned i; 
     149 
    109150    PJ_ASSERT_RETURN(mgr && count && codecs, PJ_EINVAL); 
    110151 
     
    112153        *count = mgr->codec_cnt; 
    113154     
    114     pj_memcpy(codecs, mgr->codecs, *count * sizeof(pjmedia_codec_info)); 
     155    for (i=0; i<*count; ++i) { 
     156        pj_memcpy(&codecs[i],  
     157                  &mgr->codec_desc[i].info,  
     158                  sizeof(pjmedia_codec_info)); 
     159    } 
     160 
     161    if (prio) { 
     162        for (i=0; i < *count; ++i) 
     163            prio[i] = mgr->codec_desc[i].prio; 
     164    } 
    115165 
    116166    return PJ_SUCCESS; 
    117167} 
    118168 
     169 
    119170/* 
    120171 * Get codec info for static payload type. 
    121172 */ 
    122 PJ_DEF(pj_status_t) pjmedia_codec_mgr_get_codec_info(pjmedia_codec_mgr *mgr, 
    123                                                      unsigned pt, 
    124                                                      pjmedia_codec_info *inf) 
     173PJ_DEF(pj_status_t)  
     174pjmedia_codec_mgr_get_codec_info( pjmedia_codec_mgr *mgr, 
     175                                  unsigned pt, 
     176                                  const pjmedia_codec_info **p_info) 
    125177{ 
    126178    unsigned i; 
    127179 
    128     PJ_ASSERT_RETURN(mgr && inf && pt>=0 && pt < 96, PJ_EINVAL); 
     180    PJ_ASSERT_RETURN(mgr && p_info && pt>=0 && pt < 96, PJ_EINVAL); 
    129181 
    130182    for (i=0; i<mgr->codec_cnt; ++i) { 
    131         if (mgr->codecs[i].pt == pt) { 
    132             pj_memcpy(inf, &mgr->codecs[i], sizeof(pjmedia_codec_info)); 
     183        if (mgr->codec_desc[i].info.pt == pt) { 
     184            *p_info = &mgr->codec_desc[i].info; 
    133185            return PJ_SUCCESS; 
    134186        } 
     
    137189    return PJMEDIA_CODEC_EUNSUP; 
    138190} 
     191 
     192 
     193/* 
     194 * Convert codec info struct into a unique codec identifier. 
     195 * A codec identifier looks something like "L16/44100/2". 
     196 */ 
     197PJ_DEF(char*) pjmedia_codec_info_to_id( const pjmedia_codec_info *info, 
     198                                        char *id, unsigned max_len ) 
     199{ 
     200    int len; 
     201 
     202    PJ_ASSERT_RETURN(info && id && max_len, NULL); 
     203 
     204    len = pj_ansi_snprintf(id, max_len, "%.*s/%u/%u",  
     205                           (int)info->encoding_name.slen, 
     206                           info->encoding_name.ptr, 
     207                           info->clock_rate, 
     208                           info->channel_cnt); 
     209 
     210    if (len < 1 || len >= (int)max_len) { 
     211        id[0] = '\0'; 
     212        return NULL; 
     213    } 
     214 
     215    return id; 
     216} 
     217 
     218 
     219/* 
     220 * Find codecs by the unique codec identifier. This function will find 
     221 * all codecs that match the codec identifier prefix. For example, if 
     222 * "L16" is specified, then it will find "L16/8000/1", "L16/16000/1", 
     223 * and so on, up to the maximum count specified in the argument. 
     224 */ 
     225PJ_DEF(pj_status_t)  
     226pjmedia_codec_mgr_find_codecs_by_id( pjmedia_codec_mgr *mgr, 
     227                                     const pj_str_t *codec_id, 
     228                                     unsigned *count, 
     229                                     const pjmedia_codec_info *p_info[], 
     230                                     unsigned prio[]) 
     231{ 
     232    unsigned i, found = 0; 
     233 
     234    PJ_ASSERT_RETURN(mgr && codec_id && count && *count, PJ_EINVAL); 
     235 
     236    for (i=0; i<mgr->codec_cnt; ++i) { 
     237 
     238        if (pj_strnicmp2(codec_id, mgr->codec_desc[i].id,  
     239                         codec_id->slen) == 0)  
     240        { 
     241 
     242            if (p_info) 
     243                p_info[found] = &mgr->codec_desc[i].info; 
     244            if (prio) 
     245                prio[found] = mgr->codec_desc[i].prio; 
     246 
     247            ++found; 
     248 
     249            if (found >= *count) 
     250                break; 
     251        } 
     252 
     253    } 
     254 
     255    *count = found; 
     256 
     257    return found ? PJ_SUCCESS : PJ_ENOTFOUND; 
     258} 
     259 
     260 
     261/* Swap two codecs positions in codec manager */ 
     262static void swap_codec(pjmedia_codec_mgr *mgr, unsigned i, unsigned j) 
     263{ 
     264    struct pjmedia_codec_desc tmp; 
     265 
     266    pj_memcpy(&tmp, &mgr->codec_desc[i], sizeof(struct pjmedia_codec_desc)); 
     267 
     268    pj_memcpy(&mgr->codec_desc[i], &mgr->codec_desc[j],  
     269               sizeof(struct pjmedia_codec_desc)); 
     270 
     271    pj_memcpy(&mgr->codec_desc[j], &tmp, sizeof(struct pjmedia_codec_desc)); 
     272} 
     273 
     274 
     275/* Sort codecs in codec manager based on priorities */ 
     276static void sort_codecs(pjmedia_codec_mgr *mgr) 
     277{ 
     278    unsigned i; 
     279 
     280   /* Re-sort */ 
     281    for (i=0; i<mgr->codec_cnt; ++i) { 
     282        unsigned j, max; 
     283 
     284        for (max=i, j=i+1; j<mgr->codec_cnt; ++j) { 
     285            if (mgr->codec_desc[j].prio > mgr->codec_desc[max].prio) 
     286                max = j; 
     287        } 
     288 
     289        if (max != i) 
     290            swap_codec(mgr, i, max); 
     291    } 
     292 
     293    /* Change PJMEDIA_CODEC_PRIO_HIGHEST codecs to NEXT_HIGHER */ 
     294    for (i=0; i<mgr->codec_cnt; ++i) { 
     295        if (mgr->codec_desc[i].prio == PJMEDIA_CODEC_PRIO_HIGHEST) 
     296            mgr->codec_desc[i].prio = PJMEDIA_CODEC_PRIO_NEXT_HIGHER; 
     297        else 
     298            break; 
     299    } 
     300} 
     301 
     302 
     303/** 
     304 * Set codec priority. The codec priority determines the order of 
     305 * the codec in the SDP created by the endpoint. If more than one codecs 
     306 * are found with the same codec_id prefix, then the function sets the 
     307 * priorities of all those codecs. 
     308 */ 
     309PJ_DEF(pj_status_t) 
     310pjmedia_codec_mgr_set_codec_priority(pjmedia_codec_mgr *mgr,  
     311                                     const pj_str_t *codec_id, 
     312                                     pjmedia_codec_priority prio) 
     313{ 
     314    unsigned i, found = 0; 
     315 
     316    PJ_ASSERT_RETURN(mgr && codec_id, PJ_EINVAL); 
     317 
     318    /* Update the priorities of affected codecs */ 
     319    for (i=0; i<mgr->codec_cnt; ++i)  
     320    { 
     321        if (codec_id->slen == 0 || 
     322            pj_strnicmp2(codec_id, mgr->codec_desc[i].id,  
     323                         codec_id->slen) == 0)  
     324        { 
     325            mgr->codec_desc[i].prio = prio; 
     326            ++found; 
     327        } 
     328    } 
     329 
     330    if (!found) 
     331        return PJ_ENOTFOUND; 
     332 
     333    /* Re-sort codecs */ 
     334    sort_codecs(mgr); 
     335  
     336 
     337    return PJ_SUCCESS; 
     338} 
     339 
    139340 
    140341/* 
Note: See TracChangeset for help on using the changeset viewer.