Ignore:
Timestamp:
Apr 6, 2011 1:55:01 PM (11 years ago)
Author:
nanang
Message:

Re #1186:

  • Added custom negotiation callback mechanism in SDP negotiator, mainly for specific formats that require SDP fmtp negotiation.
  • Modified video codec ID string to use encoding name+payload type (was encoding name+clock rate), also added encoding description in video codec info, so duplicated codecs (e.g: multiple H264 configurations) can be differentiated.
  • Few enhancements for H264 in ffmpeg wrapper (e.g: added proper profile-id & packetization-mode setup).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_codec_util.c

    r3493 r3500  
    2020#include <pjmedia/vid_codec_util.h> 
    2121#include <pjmedia/errno.h> 
     22#include <pjmedia/stream_common.h> 
    2223#include <pjlib-util/base64.h> 
     24#include <pj/ctype.h> 
    2325#include <pj/math.h> 
    2426 
     
    259261 
    260262/* H264 fmtp parser */ 
    261 PJ_DEF(pj_status_t) pjmedia_vid_codec_parse_h264_fmtp( 
     263PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_parse_fmtp( 
    262264                                    const pjmedia_codec_fmtp *fmtp, 
    263265                                    pjmedia_vid_codec_h264_fmtp *h264_fmtp) 
     
    289291            h264_fmtp->profile_idc = (pj_uint8_t)((tmp >> 16) & 0xFF); 
    290292            h264_fmtp->profile_iop = (pj_uint8_t)((tmp >> 8) & 0xFF); 
    291             h264_fmtp->profile_idc = (pj_uint8_t)(tmp & 0xFF); 
     293            h264_fmtp->level = (pj_uint8_t)(tmp & 0xFF); 
    292294        } else if (pj_stricmp(&fmtp->param[i].name, &PACKETIZATION_MODE)==0) { 
    293295            tmp = pj_strtoul(&fmtp->param[i].val); 
    294             if (tmp) h264_fmtp->max_br = tmp; 
     296            if (tmp >= 0 && tmp <= 2)  
     297                h264_fmtp->packetization_mode = (pj_uint8_t)tmp; 
     298            else 
     299                return PJMEDIA_SDP_EINFMTP; 
    295300        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_MBPS)==0) { 
    296301            tmp = pj_strtoul(&fmtp->param[i].val); 
    297             if (tmp) h264_fmtp->max_mbps = tmp; 
     302            h264_fmtp->max_mbps = tmp; 
    298303        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_FS)==0) { 
    299304            tmp = pj_strtoul(&fmtp->param[i].val); 
    300             if (tmp) h264_fmtp->max_fs = tmp; 
     305            h264_fmtp->max_fs = tmp; 
    301306        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_CPB)==0) { 
    302307            tmp = pj_strtoul(&fmtp->param[i].val); 
    303             if (tmp) h264_fmtp->max_cpb = tmp; 
     308            h264_fmtp->max_cpb = tmp; 
    304309        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_DPB)==0) { 
    305310            tmp = pj_strtoul(&fmtp->param[i].val); 
    306             if (tmp) h264_fmtp->max_dpb = tmp; 
     311            h264_fmtp->max_dpb = tmp; 
    307312        } else if (pj_stricmp(&fmtp->param[i].name, &MAX_BR)==0) { 
    308313            tmp = pj_strtoul(&fmtp->param[i].val); 
    309             if (tmp) h264_fmtp->max_br = tmp; 
     314            h264_fmtp->max_br = tmp; 
    310315        } else if (pj_stricmp(&fmtp->param[i].name, &SPROP_PARAMETER_SETS)==0) 
    311316        { 
     
    351356    } 
    352357 
     358    /* When profile-level-id is not specified, use default value "42000A" */ 
     359    if (h264_fmtp->profile_idc == 0) { 
     360        h264_fmtp->profile_idc = 0x42; 
     361        h264_fmtp->profile_iop = 0x00; 
     362        h264_fmtp->level = 0x0A; 
     363    } 
     364 
    353365    return PJ_SUCCESS; 
    354366} 
     367 
     368PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_match_sdp(pj_pool_t *pool, 
     369                                                     pjmedia_sdp_media *offer, 
     370                                                     unsigned o_fmt_idx, 
     371                                                     pjmedia_sdp_media *answer, 
     372                                                     unsigned a_fmt_idx, 
     373                                                     unsigned option) 
     374{ 
     375    const pj_str_t PROFILE_LEVEL_ID     = {"profile-level-id", 16}; 
     376    const pj_str_t PACKETIZATION_MODE   = {"packetization-mode", 18}; 
     377    pjmedia_codec_fmtp o_fmtp_raw, a_fmtp_raw; 
     378    pjmedia_vid_codec_h264_fmtp o_fmtp, a_fmtp; 
     379    pj_status_t status; 
     380 
     381    PJ_UNUSED_ARG(pool); 
     382 
     383    /* Parse offer */ 
     384    status = pjmedia_stream_info_parse_fmtp( 
     385                                    NULL, offer,  
     386                                    pj_strtoul(&offer->desc.fmt[o_fmt_idx]), 
     387                                    &o_fmtp_raw); 
     388    if (status != PJ_SUCCESS) 
     389        return status; 
     390 
     391    status = pjmedia_vid_codec_h264_parse_fmtp(&o_fmtp_raw, &o_fmtp); 
     392    if (status != PJ_SUCCESS) 
     393        return status; 
     394 
     395    /* Parse answer */ 
     396    status = pjmedia_stream_info_parse_fmtp( 
     397                                    NULL, answer,  
     398                                    pj_strtoul(&answer->desc.fmt[a_fmt_idx]), 
     399                                    &a_fmtp_raw); 
     400    if (status != PJ_SUCCESS) 
     401        return status; 
     402 
     403    status = pjmedia_vid_codec_h264_parse_fmtp(&a_fmtp_raw, &a_fmtp); 
     404    if (status != PJ_SUCCESS) 
     405        return status; 
     406 
     407    if (option & PJMEDIA_SDP_NEG_FMT_MATCH_ALLOW_MODIFY_ANSWER) { 
     408        unsigned i; 
     409 
     410        /* Flexible negotiation, if the answer has higher capability than 
     411         * the offer, adjust the answer capability to be match to the offer. 
     412         */ 
     413        if (a_fmtp.profile_idc >= o_fmtp.profile_idc) 
     414            a_fmtp.profile_idc = o_fmtp.profile_idc; 
     415        if (a_fmtp.profile_iop != o_fmtp.profile_iop) 
     416            a_fmtp.profile_iop = o_fmtp.profile_iop; 
     417        if (a_fmtp.level >= o_fmtp.level) 
     418            a_fmtp.level = o_fmtp.level; 
     419        if (a_fmtp.packetization_mode >= o_fmtp.packetization_mode) 
     420            a_fmtp.packetization_mode = o_fmtp.packetization_mode; 
     421 
     422        /* Match them now */ 
     423        if (a_fmtp.profile_idc != o_fmtp.profile_idc || 
     424            a_fmtp.profile_iop != o_fmtp.profile_iop || 
     425            a_fmtp.level != o_fmtp.level || 
     426            a_fmtp.packetization_mode != o_fmtp.packetization_mode) 
     427        { 
     428            return PJMEDIA_SDP_EFORMATNOTEQUAL; 
     429        } 
     430 
     431        /* Update the answer */ 
     432        for (i = 0; i < a_fmtp_raw.cnt; ++i) { 
     433            if (pj_stricmp(&a_fmtp_raw.param[i].name, &PROFILE_LEVEL_ID) == 0) 
     434            { 
     435                char *p = a_fmtp_raw.param[i].val.ptr; 
     436                pj_val_to_hex_digit(a_fmtp.profile_idc, p); 
     437                p += 2; 
     438                pj_val_to_hex_digit(a_fmtp.profile_iop, p); 
     439                p += 2; 
     440                pj_val_to_hex_digit(a_fmtp.level, p); 
     441            } 
     442            else if (pj_stricmp(&a_fmtp_raw.param[i].name, &PACKETIZATION_MODE) == 0) 
     443            { 
     444                char *p = a_fmtp_raw.param[i].val.ptr; 
     445                *p = '0' + a_fmtp.packetization_mode; 
     446            } 
     447        } 
     448    } else { 
     449        /* Strict negotiation */ 
     450        if (a_fmtp.profile_idc != o_fmtp.profile_idc || 
     451            a_fmtp.profile_iop != o_fmtp.profile_iop || 
     452            a_fmtp.level != o_fmtp.level || 
     453            a_fmtp.packetization_mode != o_fmtp.packetization_mode) 
     454        { 
     455            return PJMEDIA_SDP_EFORMATNOTEQUAL; 
     456        } 
     457    } 
     458 
     459    return PJ_SUCCESS; 
     460} 
Note: See TracChangeset for help on using the changeset viewer.