Ignore:
Timestamp:
Feb 21, 2013 2:48:53 PM (12 years ago)
Author:
nanang
Message:

Close #1622: Apply H264 SDP fmtp parameters: max-fs, max-mbps, max-br.

File:
1 edited

Legend:

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

    r3995 r4361  
    3939#define H264_STRICT_SDP_NEGO        0 
    4040 
     41/* Default frame rate, if not specified */ 
     42#define DEFAULT_H264_FPS_NUM        15 
     43#define DEFAULT_H264_FPS_DENUM      1 
     44 
     45/* Default aspect ratio, if not specified */ 
     46#define DEFAULT_H264_RATIO_NUM      15 
     47#define DEFAULT_H264_RATIO_DENUM    1 
     48 
    4149 
    4250/* ITU resolution definition */ 
     
    5462    {{"CIF16",5},   {1408,1142}}, 
    5563}; 
     64 
     65 
     66#define CALC_H264_MB_NUM(size) (((size.w+15)/16)*((size.h+15)/16)) 
     67#define CALC_H264_MBPS(size,fps) CALC_H264_MB_NUM(size)*fps.num/fps.denum 
    5668 
    5769 
     
    292304 
    293305 
     306/* Declaration of H.264 level info */ 
     307typedef struct h264_level_info_t 
     308{ 
     309    unsigned id;            /* Level id.                        */ 
     310    unsigned max_mbps;      /* Max macroblocks per second.      */ 
     311    unsigned max_mb;        /* Max macroblocks.                 */ 
     312    unsigned max_br;        /* Max bitrate (kbps).              */ 
     313} h264_level_info_t; 
     314 
     315 
     316/* Init H264 parameters based on profile-level-id */ 
     317static pj_status_t init_h264_profile(const pj_str_t *profile, 
     318                                     pjmedia_vid_codec_h264_fmtp *fmtp) 
     319{ 
     320    const h264_level_info_t level_info[] = 
     321    { 
     322        { 10,   1485,    99,     64 }, 
     323        { 9,    1485,    99,    128 }, /*< level 1b */ 
     324        { 11,   3000,   396,    192 }, 
     325        { 12,   6000,   396,    384 }, 
     326        { 13,  11880,   396,    768 }, 
     327        { 20,  11880,   396,   2000 }, 
     328        { 21,  19800,   792,   4000 }, 
     329        { 22,  20250,  1620,   4000 }, 
     330        { 30,  40500,  1620,  10000 }, 
     331        { 31, 108000,  3600,  14000 }, 
     332        { 32, 216000,  5120,  20000 }, 
     333        { 40, 245760,  8192,  20000 }, 
     334        { 41, 245760,  8192,  50000 }, 
     335        { 42, 522240,  8704,  50000 }, 
     336        { 50, 589824, 22080, 135000 }, 
     337        { 51, 983040, 36864, 240000 }, 
     338    }; 
     339    unsigned i, tmp; 
     340    pj_str_t endst; 
     341    const h264_level_info_t *li = NULL; 
     342 
     343    if (profile->slen != 6) 
     344        return PJMEDIA_SDP_EINFMTP; 
     345 
     346    tmp = pj_strtoul2(profile, &endst, 16); 
     347    if (endst.slen) 
     348        return PJMEDIA_SDP_EINFMTP; 
     349 
     350    fmtp->profile_idc = (pj_uint8_t)((tmp >> 16) & 0xFF); 
     351    fmtp->profile_iop = (pj_uint8_t)((tmp >> 8) & 0xFF); 
     352    fmtp->level = (pj_uint8_t)(tmp & 0xFF); 
     353 
     354    for (i = 0; i < PJ_ARRAY_SIZE(level_info); ++i) { 
     355        if (level_info[i].id == fmtp->level) { 
     356            li = &level_info[i]; 
     357            break; 
     358        } 
     359    } 
     360    if (li == NULL) 
     361        return PJMEDIA_SDP_EINFMTP; 
     362 
     363    /* Init profile level spec */ 
     364    if (fmtp->max_br == 0) 
     365        fmtp->max_br = li->max_br; 
     366    if (fmtp->max_mbps == 0) 
     367        fmtp->max_mbps = li->max_mbps; 
     368    if (fmtp->max_fs == 0) 
     369        fmtp->max_fs = li->max_mb; 
     370 
     371    return PJ_SUCCESS; 
     372} 
     373 
     374 
    294375/* H264 fmtp parser */ 
    295376PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_parse_fmtp( 
     
    306387    const pj_str_t SPROP_PARAMETER_SETS = {"sprop-parameter-sets", 20}; 
    307388    unsigned i; 
     389    pj_status_t status; 
    308390 
    309391    pj_bzero(h264_fmtp, sizeof(*h264_fmtp)); 
     
    312394        unsigned tmp; 
    313395        if (pj_stricmp(&fmtp->param[i].name, &PROFILE_LEVEL_ID)==0) { 
    314             pj_str_t endst; 
    315  
    316             if (fmtp->param[i].val.slen != 6) 
    317                 return PJMEDIA_SDP_EINFMTP; 
    318  
    319             tmp = pj_strtoul2(&fmtp->param[i].val, &endst, 16); 
    320             if (endst.slen) 
    321                 return PJMEDIA_SDP_EINFMTP; 
    322  
    323             h264_fmtp->profile_idc = (pj_uint8_t)((tmp >> 16) & 0xFF); 
    324             h264_fmtp->profile_iop = (pj_uint8_t)((tmp >> 8) & 0xFF); 
    325             h264_fmtp->level = (pj_uint8_t)(tmp & 0xFF); 
     396            /* Init H264 parameters based on level, if not set yet */ 
     397            status = init_h264_profile(&fmtp->param[i].val, h264_fmtp); 
     398            if (status != PJ_SUCCESS) 
     399                return status; 
    326400        } else if (pj_stricmp(&fmtp->param[i].name, &PACKETIZATION_MODE)==0) { 
    327401            tmp = pj_strtoul(&fmtp->param[i].val); 
     
    332406        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_MBPS)==0) { 
    333407            tmp = pj_strtoul(&fmtp->param[i].val); 
    334             h264_fmtp->max_mbps = tmp; 
     408            h264_fmtp->max_mbps = PJ_MAX(tmp, h264_fmtp->max_mbps); 
    335409        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_FS)==0) { 
    336410            tmp = pj_strtoul(&fmtp->param[i].val); 
    337             h264_fmtp->max_fs = tmp; 
     411            h264_fmtp->max_fs = PJ_MAX(tmp, h264_fmtp->max_fs); 
    338412        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_CPB)==0) { 
    339413            tmp = pj_strtoul(&fmtp->param[i].val); 
    340             h264_fmtp->max_cpb = tmp; 
     414            h264_fmtp->max_cpb = PJ_MAX(tmp, h264_fmtp->max_cpb); 
    341415        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_DPB)==0) { 
    342416            tmp = pj_strtoul(&fmtp->param[i].val); 
    343             h264_fmtp->max_dpb = tmp; 
     417            h264_fmtp->max_dpb = PJ_MAX(tmp, h264_fmtp->max_dpb); 
    344418        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_BR)==0) { 
    345419            tmp = pj_strtoul(&fmtp->param[i].val); 
    346             h264_fmtp->max_br = tmp; 
     420            h264_fmtp->max_br = PJ_MAX(tmp, h264_fmtp->max_br); 
    347421        } else if (pj_stricmp(&fmtp->param[i].name, &SPROP_PARAMETER_SETS)==0) 
    348422        { 
     
    508582 
    509583 
    510 /* Declaration of H.264 level info */ 
    511 typedef struct h264_level_info_t 
    512 { 
    513     unsigned id;            /* Level id.                        */ 
    514     unsigned max_mbps;      /* Max macroblocks per second.      */ 
    515     unsigned max_mb;        /* Max macroblocks.                 */ 
    516     unsigned bitrate;       /* Max bitrate (kbps).              */ 
    517     unsigned def_w;         /* Default width.                   */ 
    518     unsigned def_h;         /* Default height.                  */ 
    519     unsigned def_fps;       /* Default fps.                     */ 
    520 } h264_level_info_t; 
    521  
    522  
    523 /* Get H.264 level info from specified level ID */ 
    524 static pj_status_t get_h264_level_info(unsigned id, h264_level_info_t *level) 
    525 { 
    526     unsigned i; 
    527     const h264_level_info_t level_info[] = 
    528     { 
    529         { 10,   1485,    99,     64,  176,  144, 15 }, 
    530         { 9,    1485,    99,    128,  176,  144, 15 }, /*< level 1b */ 
    531         { 11,   3000,   396,    192,  320,  240, 10 }, 
    532         { 12,   6000,   396,    384,  352,  288, 15 }, 
    533         { 13,  11880,   396,    768,  352,  288, 15 }, 
    534         { 20,  11880,   396,   2000,  352,  288, 30 }, 
    535         { 21,  19800,   792,   4000,  352,  288, 30 }, 
    536         { 22,  20250,  1620,   4000,  352,  288, 30 }, 
    537         { 30,  40500,  1620,  10000,  720,  480, 30 }, 
    538         { 31, 108000,  3600,  14000, 1280,  720, 30 }, 
    539         { 32, 216000,  5120,  20000, 1280,  720, 30 }, 
    540         { 40, 245760,  8192,  20000, 1920, 1080, 30 }, 
    541         { 41, 245760,  8192,  50000, 1920, 1080, 30 }, 
    542         { 42, 522240,  8704,  50000, 1920, 1080, 30 }, 
    543         { 50, 589824, 22080, 135000, 1920, 1080, 30 }, 
    544         { 51, 983040, 36864, 240000, 1920, 1080, 30 }, 
    545     }; 
    546  
    547     for (i = 0; i < PJ_ARRAY_SIZE(level_info); ++i) { 
    548         if (level_info[i].id == id) { 
    549             *level = level_info[i]; 
    550             return PJ_SUCCESS; 
    551         } 
    552     } 
    553     return PJ_ENOTFOUND; 
    554 } 
    555  
    556  
    557 #define CALC_H264_MB_NUM(size) (((size.w+15)/16)*((size.h+15)/16)) 
    558 #define CALC_H264_MBPS(size,fps) CALC_H264_MB_NUM(size)*fps.num/fps.denum 
     584/* Find greatest common divisor (GCD) */ 
     585static unsigned gcd (unsigned a, unsigned b) { 
     586    unsigned c; 
     587    while (b) { 
     588        c = a % b; 
     589        a = b; 
     590        b = c; 
     591    } 
     592    return a; 
     593} 
     594 
     595/* Find highest resolution possible for the specified H264 fmtp and 
     596 * aspect ratio. 
     597 */ 
     598static pj_status_t find_highest_res(pjmedia_vid_codec_h264_fmtp *fmtp, 
     599                                    const pjmedia_ratio *fps, 
     600                                    const pjmedia_ratio *ratio, 
     601                                    pjmedia_rect_size *size) 
     602{ 
     603    pjmedia_ratio def_ratio = { DEFAULT_H264_RATIO_NUM, 
     604                                DEFAULT_H264_RATIO_DENUM }; 
     605    pjmedia_ratio def_fps   = { DEFAULT_H264_FPS_NUM, 
     606                                DEFAULT_H264_FPS_DENUM }; 
     607    pjmedia_ratio asp_ratio, the_fps; 
     608    unsigned max_fs, g, scale; 
     609 
     610    pj_assert(size); 
     611 
     612    /* Get the ratio, or just use default if not provided. */ 
     613    if (ratio && ratio->num && ratio->denum) { 
     614        asp_ratio = *ratio; 
     615    } else { 
     616        asp_ratio = def_ratio; 
     617    } 
     618 
     619    /* Normalize the aspect ratio */ 
     620    g = gcd(asp_ratio.num, asp_ratio.denum); 
     621    asp_ratio.num /= g; 
     622    asp_ratio.denum /= g; 
     623 
     624    /* Get the frame rate, or just use default if not provided. */ 
     625    if (fps && fps->num && fps->denum) { 
     626        the_fps = *fps; 
     627    } else { 
     628        the_fps = def_fps; 
     629    } 
     630 
     631    /* Calculate maximum size (in macroblocks) */ 
     632    max_fs = fmtp->max_mbps * fps->denum / fps->num; 
     633    max_fs = PJ_MIN(max_fs, fmtp->max_fs); 
     634 
     635    /* Check if the specified ratio is using big numbers 
     636     * (not normalizable), override it with default ratio! 
     637     */ 
     638    if ((int)max_fs < asp_ratio.num * asp_ratio.denum) 
     639        asp_ratio = def_ratio; 
     640 
     641    /* Calculate the scale factor for size */ 
     642    scale = pj_isqrt(max_fs / asp_ratio.denum / asp_ratio.num); 
     643 
     644    /* Calculate the size, note that the frame size is in macroblock units */ 
     645    size->w = asp_ratio.num   * scale * 16; 
     646    size->h = asp_ratio.denum * scale * 16; 
     647 
     648    return PJ_SUCCESS; 
     649} 
    559650 
    560651 
     
    562653                                pjmedia_vid_codec_param *param) 
    563654{ 
    564     const unsigned default_fps = 30; 
    565  
    566655    if (param->dir & PJMEDIA_DIR_ENCODING) { 
    567656        pjmedia_vid_codec_h264_fmtp fmtp; 
    568657        pjmedia_video_format_detail *vfd; 
    569         h264_level_info_t level_info; 
    570658        pj_status_t status; 
    571659 
     
    576664            return status; 
    577665 
    578         status = get_h264_level_info(fmtp.level, &level_info); 
    579         if (status != PJ_SUCCESS) 
    580             return status; 
    581  
    582         /* Size and fps for encoding direction must conform to H.264 level 
     666        /* Adjust fps, size, and bitrate to conform to H.264 level 
    583667         * specified by remote SDP fmtp. 
    584668         */ 
    585669        vfd = pjmedia_format_get_video_format_detail(&param->enc_fmt, 
    586670                                                     PJ_TRUE); 
     671 
     672        if (vfd->fps.num == 0 || vfd->fps.denum == 0) { 
     673            vfd->fps.num   = DEFAULT_H264_FPS_NUM; 
     674            vfd->fps.denum = DEFAULT_H264_FPS_DENUM; 
     675        } 
     676 
    587677        if (vfd->size.w && vfd->size.h) { 
    588678            unsigned mb, mbps; 
    589679             
    590             if (vfd->fps.num == 0 || vfd->fps.denum == 0) { 
    591                 vfd->fps.num = default_fps; 
    592                 vfd->fps.denum = 1; 
    593             } 
     680            /* Scale down the resolution if it exceeds profile spec */ 
    594681            mb = CALC_H264_MB_NUM(vfd->size); 
    595682            mbps = CALC_H264_MBPS(vfd->size, vfd->fps); 
    596             if (mb > level_info.max_mb || mbps > level_info.max_mbps) { 
    597                 vfd->size.w = level_info.def_w; 
    598                 vfd->size.h = level_info.def_h; 
    599                 vfd->fps.num = level_info.def_fps; 
    600                 vfd->fps.denum = 1; 
     683            if (mb > fmtp.max_fs || mbps > fmtp.max_mbps) { 
     684                pjmedia_ratio r; 
     685                r.num = vfd->size.w; 
     686                r.denum = vfd->size.h; 
     687                find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size); 
    601688            } 
    602689        } else { 
    603             vfd->size.w = level_info.def_w; 
    604             vfd->size.h = level_info.def_h; 
    605             vfd->fps.num = level_info.def_fps; 
    606             vfd->fps.denum = 1; 
    607         } 
     690            /* When not specified, just use the highest res possible*/ 
     691            pjmedia_ratio r; 
     692            r.num = vfd->size.w; 
     693            r.denum = vfd->size.h; 
     694            find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size); 
     695        } 
     696 
     697        /* Encoding bitrate must not be higher than H264 level spec */ 
     698        if (vfd->avg_bps > fmtp.max_br * 1000) 
     699            vfd->avg_bps = fmtp.max_br * 1000; 
     700        if (vfd->max_bps > fmtp.max_br * 1000) 
     701            vfd->max_bps = fmtp.max_br * 1000; 
    608702    } 
    609703 
     
    614708        pjmedia_vid_codec_h264_fmtp fmtp; 
    615709        pjmedia_video_format_detail *vfd; 
    616         h264_level_info_t level_info; 
     710        pjmedia_ratio r; 
     711        pjmedia_rect_size highest_size; 
    617712        pj_status_t status; 
    618713         
     
    622717            return status; 
    623718 
    624         status = get_h264_level_info(fmtp.level, &level_info); 
    625         if (status != PJ_SUCCESS) 
    626             return status; 
    627  
    628719        vfd = pjmedia_format_get_video_format_detail(&param->dec_fmt, 
    629720                                                     PJ_TRUE); 
    630721 
    631         if (vfd->size.w * vfd->size.h < level_info.def_w * level_info.def_h) { 
    632             vfd->size.w = level_info.def_w; 
    633             vfd->size.h = level_info.def_h; 
    634         } 
    635  
    636722        if (vfd->fps.num == 0 || vfd->fps.denum == 0) { 
    637             vfd->fps.num = default_fps; 
    638             vfd->fps.denum = 1; 
    639         } 
     723            vfd->fps.num   = DEFAULT_H264_FPS_NUM; 
     724            vfd->fps.denum = DEFAULT_H264_FPS_DENUM; 
     725        } 
     726 
     727        /* Normalize decoding resolution, i.e: it must not be lower than 
     728         * the H264 profile level setting used, as this may be used by 
     729         * app to allocate buffer. 
     730         */ 
     731        r.num = vfd->size.w; 
     732        r.denum = vfd->size.h; 
     733        find_highest_res(&fmtp, &vfd->fps, &r, &highest_size); 
     734        if (vfd->size.w * vfd->size.h < highest_size.w * highest_size.h) 
     735            vfd->size = highest_size; 
     736 
     737        /* Normalize decoding bitrate based on H264 level spec */ 
     738        if (vfd->avg_bps < fmtp.max_br * 1000) 
     739            vfd->avg_bps = fmtp.max_br * 1000; 
     740        if (vfd->max_bps < fmtp.max_br * 1000) 
     741            vfd->max_bps = fmtp.max_br * 1000; 
    640742    } 
    641743 
Note: See TracChangeset for help on using the changeset viewer.