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-codec/ffmpeg_codecs.c

    r3496 r3500  
    176176                      pj_size_t bits_len, unsigned *bits_pos) 
    177177 
     178#define FUNC_FMT_MATCH(name) \ 
     179    pj_status_t(name)(pj_pool_t *pool, \ 
     180                      pjmedia_sdp_media *offer, unsigned o_fmt_idx, \ 
     181                      pjmedia_sdp_media *answer, unsigned a_fmt_idx, \ 
     182                      unsigned option) 
     183 
     184 
     185/* Type definition of codec specific functions */ 
    178186typedef FUNC_PACKETIZE(*func_packetize); 
    179187typedef FUNC_UNPACKETIZE(*func_unpacketize); 
    180188typedef pj_status_t (*func_preopen)     (ffmpeg_private *ff); 
    181189typedef pj_status_t (*func_postopen)    (ffmpeg_private *ff); 
     190typedef FUNC_FMT_MATCH(*func_sdp_fmt_match); 
    182191 
    183192 
     
    187196    /* Predefined info */ 
    188197    pjmedia_vid_codec_info       info; 
    189     pjmedia_format_id            base_fmt_id; 
     198    pjmedia_format_id            base_fmt_id;   /**< Some codecs may be exactly 
     199                                                     same or compatible with 
     200                                                     another codec, base format 
     201                                                     will tell the initializer 
     202                                                     to copy this codec desc 
     203                                                     from its base format   */ 
    190204    pj_uint32_t                  avg_bps; 
    191205    pj_uint32_t                  max_bps; 
     
    194208    func_preopen                 preopen; 
    195209    func_preopen                 postopen; 
     210    func_sdp_fmt_match           sdp_fmt_match; 
    196211    pjmedia_codec_fmtp           dec_fmtp; 
    197212 
     
    217232{ 
    218233    { 
    219         {PJMEDIA_FORMAT_H264,   {"H264",4},         PJMEDIA_RTP_PT_H264}, 
    220         0,      500000,    1000000, 
     234        {PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264, {"H264",4}, 
     235         {"Constrained Baseline (level=30, pack=1)", 39}}, 
     236        0,      128000,    1000000, 
    221237        &h264_packetize, &h264_unpacketize, &h264_preopen, &h264_postopen, 
     238        &pjmedia_vid_codec_h264_match_sdp, 
    222239        /* Leading space for better compatibility (strange indeed!) */ 
    223         {2, { {{" profile-level-id",17},    {"42e01e",6}},  
     240        {2, { {{"profile-level-id",16},    {"42e01e",6}},  
    224241              {{" packetization-mode",19},  {"1",1}}, } }, 
    225242    }, 
    226243    { 
    227         {PJMEDIA_FORMAT_H263P,  {"H263-1998",9},    PJMEDIA_RTP_PT_H263P}, 
     244        {PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264_RSV1, {"H264",4}, 
     245         {"Baseline (level=30, pack=1)", 27}}, 
     246        PJMEDIA_FORMAT_H264,    128000,    1000000, 
     247        &h264_packetize, &h264_unpacketize, &h264_preopen, &h264_postopen, 
     248        &pjmedia_vid_codec_h264_match_sdp, 
     249        {2, { {{"profile-level-id",16},    {"42001e",6}},  
     250              {{" packetization-mode",19},  {"1",1}}, } }, 
     251    }, 
     252    { 
     253        {PJMEDIA_FORMAT_H263P, PJMEDIA_RTP_PT_H263P, {"H263-1998",9}}, 
    228254        PJMEDIA_FORMAT_H263,    1000000,    2000000, 
    229         &h263_packetize, &h263_unpacketize, &h263_preopen, NULL, 
     255        &h263_packetize, &h263_unpacketize, &h263_preopen, NULL, NULL, 
    230256        {2, { {{"CIF",3},   {"1",1}},  
    231257              {{"QCIF",4},  {"1",1}}, } }, 
    232258    }, 
    233259    { 
    234         {PJMEDIA_FORMAT_H263,   {"H263",4},         PJMEDIA_RTP_PT_H263}, 
     260        {PJMEDIA_FORMAT_H263,   PJMEDIA_RTP_PT_H263,    {"H263",4}}, 
    235261    }, 
    236262    { 
    237         {PJMEDIA_FORMAT_H261,   {"H261",4},         PJMEDIA_RTP_PT_H261}, 
     263        {PJMEDIA_FORMAT_H261,   PJMEDIA_RTP_PT_H261,    {"H261",4}}, 
    238264    }, 
    239265    { 
    240         {PJMEDIA_FORMAT_MJPEG,  {"JPEG",4},         PJMEDIA_RTP_PT_JPEG}, 
     266        {PJMEDIA_FORMAT_MJPEG,  PJMEDIA_RTP_PT_JPEG,    {"JPEG",4}}, 
    241267    }, 
    242268    { 
    243         {PJMEDIA_FORMAT_MPEG4,  {"MP4V",4}}, 
     269        {PJMEDIA_FORMAT_MPEG4,  0,                      {"MP4V",4}}, 
    244270    }, 
    245271    { 
    246         {PJMEDIA_FORMAT_XVID,   {"XVID",4}}, 
     272        {PJMEDIA_FORMAT_XVID,   0,                      {"XVID",4}}, 
    247273        PJMEDIA_FORMAT_MPEG4, 
    248274    }, 
     
    266292    ff->data = data; 
    267293 
     294    /* Parse remote fmtp */ 
     295    status = pjmedia_vid_codec_h264_parse_fmtp(&ff->param.enc_fmtp, 
     296                                               &data->fmtp); 
     297    if (status != PJ_SUCCESS) 
     298        return status; 
     299 
    268300    /* Create packetizer */ 
    269301    pktz_cfg.mtu = ff->param.enc_mtu; 
    270     pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED; 
     302    if (data->fmtp.packetization_mode == 0) 
     303        pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL; 
     304    else if (data->fmtp.packetization_mode == 1) 
     305        pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED; 
     306    else 
     307        return PJ_ENOTSUP; 
     308 
    271309    status = pjmedia_h264_packetizer_create(ff->pool, &pktz_cfg, &data->pktz); 
    272310    if (status != PJ_SUCCESS) 
     
    276314        AVCodecContext *ctx = ff->enc_ctx; 
    277315 
    278         status = pjmedia_vid_codec_parse_h264_fmtp(&ff->param.enc_fmtp, 
    279                                                    &data->fmtp); 
    280         if (status != PJ_SUCCESS) 
    281             return status; 
    282  
     316        /* Apply profile. Note that, for x264 backend, ffmpeg doesn't seem to 
     317         * use this profile param field, so let's try to apply it "manually". 
     318         */ 
    283319        ctx->profile  = data->fmtp.profile_idc; 
     320        if (ctx->profile == FF_PROFILE_H264_BASELINE) { 
     321            /* Baseline profile settings (the most used profile in 
     322             * conversational/real-time communications). 
     323             */ 
     324            ctx->coder_type = FF_CODER_TYPE_VLC; 
     325            ctx->max_b_frames = 0; 
     326            ctx->flags2 &= ~(CODEC_FLAG2_WPRED | CODEC_FLAG2_8X8DCT); 
     327            ctx->weighted_p_pred = 0; 
     328        } else if (ctx->profile == FF_PROFILE_H264_MAIN) { 
     329            ctx->flags2 &= ~CODEC_FLAG2_8X8DCT; 
     330        } 
     331 
     332        /* Apply profile constraint bits. */ 
     333        // The x264 doesn't seem to support non-constrained (baseline) profile 
     334        // so this shouldn't be a problem (for now). 
     335        //PJ_TODO(set_h264_constraint_bits_properly_in_ffmpeg); 
    284336        if (data->fmtp.profile_iop) { 
    285337#if defined(FF_PROFILE_H264_CONSTRAINED) 
     
    287339#endif 
    288340        } 
     341 
     342        /* Apply profile level. */ 
     343        PJ_TODO(apply_h264_profile_level_in_pjmedia_vid_codec_param); 
    289344        ctx->level    = data->fmtp.level; 
    290         PJ_TODO(set_h264_constrain_bits_properly_in_ffmpeg); 
    291345 
    292346        /* Libx264 rejects the "broken" ffmpeg defaults, so just change some */ 
     
    383437            (desc->info.fmt_id == info->fmt_id) && 
    384438            ((desc->info.dir & info->dir) == info->dir) && 
    385             pj_stricmp(&desc->info.encoding_name, &info->encoding_name)==0) 
     439            (desc->info.pt == info->pt)) 
    386440        { 
    387441            return desc; 
     
    566620    } 
    567621 
    568     /* Init unassigned encoder/decoder description from base codec */ 
     622    /* Review all codecs for applying base format, registering format match for 
     623     * SDP negotiation, etc. 
     624     */ 
    569625    for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) { 
    570626        ffmpeg_codec_desc *desc = &codec_desc[i]; 
    571627 
     628        /* Init encoder/decoder description from base format */ 
    572629        if (desc->base_fmt_id && (!desc->dec || !desc->enc)) { 
    573630            ffmpeg_codec_desc *base_desc = NULL; 
     
    606663            desc->info.dir |= copied_dir; 
    607664            desc->enabled = (desc->info.dir != PJMEDIA_DIR_NONE); 
     665            desc->info.has_rtp_pack = (desc->packetize != NULL) && 
     666                                      (desc->unpacketize != NULL); 
    608667 
    609668            if (copied_dir != PJMEDIA_DIR_NONE) { 
     
    617676            } 
    618677        } 
     678 
     679        /* Registering format match for SDP negotiation */ 
     680        if (desc->sdp_fmt_match) { 
     681            status = pjmedia_sdp_neg_register_fmt_match_cb( 
     682                                                &desc->info.encoding_name, 
     683                                                desc->sdp_fmt_match); 
     684            pj_assert(status == PJ_SUCCESS); 
     685        } 
    619686    } 
    620687 
Note: See TracChangeset for help on using the changeset viewer.