Changeset 3819


Ignore:
Timestamp:
Oct 18, 2011 1:51:01 AM (8 years ago)
Author:
nanang
Message:

Reenable ffmpeg H264 (re #1390):

  • Review H264 codec settings such as profile, level, NAL unit size, bitrate, quality, latency.
  • Added new format PJMEDIA_FORMAT_GBRP, 24 bits planar RGB, one of the formats outputted by the latest ffmpeg H264 decoder.
  • Fixed format change detection bug in ffmpeg wrapper, decoder didn't update its internal state with the new format so format change event was generated in every decoding operation.
  • Added compile time configurations for enabling/disabling ffmpeg codec H263+ & H264.
  • Updated pjsua app to adjust window size to original video size. With H264, default window size will be too big as it is init'd with default H264 video size, e.g: 720x480 for profile level 30.
Location:
pjproject/trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia-codec/config.h

    r3664 r3819  
    355355 
    356356/** 
     357 * Enable FFMPEG H263+/H263-1998 codec. 
     358 * 
     359 * Default: 1 
     360 */ 
     361#ifndef PJMEDIA_HAS_FFMPEG_CODEC_H263P 
     362#   define PJMEDIA_HAS_FFMPEG_CODEC_H263P       1 
     363#endif 
     364 
     365/** 
     366 * Enable FFMPEG H264 codec (requires libx264). 
     367 * 
     368 * Default: 0 
     369 */ 
     370#ifndef PJMEDIA_HAS_FFMPEG_CODEC_H264 
     371#   define PJMEDIA_HAS_FFMPEG_CODEC_H264        0 
     372#endif 
     373 
     374/** 
    357375 * @} 
    358376 */ 
  • pjproject/trunk/pjmedia/include/pjmedia/format.h

    r3715 r3819  
    110110     */ 
    111111    PJMEDIA_FORMAT_DIB      = PJMEDIA_FORMAT_PACK('D', 'I', 'B', ' '), 
     112 
     113    /** 
     114     * This is planar 4:4:4/24bpp RGB format, the data can be treated as 
     115     * three planes of color components, where the first plane contains 
     116     * only the G samples, the second plane contains only the B samples, 
     117     * and the third plane contains only the R samples. 
     118     */ 
     119    PJMEDIA_FORMAT_GBRP    = PJMEDIA_FORMAT_PACK('G', 'B', 'R', 'P'), 
    112120 
    113121    /** 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c

    r3805 r3819  
    4343#include <libavcodec/avcodec.h> 
    4444#include <libavformat/avformat.h> 
    45  
    46 #define ENABLE_H264     0 
     45#include <libavutil/opt.h> 
     46 
    4747 
    4848/* Prototypes for FFMPEG codecs factory */ 
     
    220220 
    221221 
    222 #if ENABLE_H264 
     222#if PJMEDIA_HAS_FFMPEG_CODEC_H264 && \ 
     223    (LIBAVCODEC_VERSION_MAJOR < 53 || LIBAVCODEC_VERSION_MINOR < 20) 
     224#   error "Must use libavcodec version 53.20 or later to enable FFMPEG H264" 
     225#endif 
     226 
    223227/* H264 constants */ 
    224228#define PROFILE_H264_BASELINE           66 
     
    230234static FUNC_PACKETIZE(h264_packetize); 
    231235static FUNC_UNPACKETIZE(h264_unpacketize); 
    232 #endif  /* ENABLE_H264 */ 
    233236 
    234237static pj_status_t h263_preopen(ffmpeg_private *ff); 
     
    240243static ffmpeg_codec_desc codec_desc[] = 
    241244{ 
    242 #if ENABLE_H264 
     245#if PJMEDIA_HAS_FFMPEG_CODEC_H264 
    243246    { 
    244247        {PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264, {"H264",4}, 
     
    251254              {{" packetization-mode",19},  {"1",1}}, } }, 
    252255    }, 
    253     { 
    254         {PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264_RSV1, {"H264",4}, 
    255          {"Baseline (level=30, pack=1)", 27}}, 
    256         PJMEDIA_FORMAT_H264,    128000,    1000000, 
    257         &h264_packetize, &h264_unpacketize, &h264_preopen, &h264_postopen, 
    258         &pjmedia_vid_codec_h264_match_sdp, 
    259         {2, { {{"profile-level-id",16},    {"42001e",6}},  
    260               {{" packetization-mode",19},  {"1",1}}, } }, 
    261     }, 
    262256#endif 
     257 
     258#if PJMEDIA_HAS_FFMPEG_CODEC_H263P 
    263259    { 
    264260        {PJMEDIA_FORMAT_H263P, PJMEDIA_RTP_PT_H263P, {"H263-1998",9}}, 
     
    268264              {{"QCIF",4},  {"1",1}}, } }, 
    269265    }, 
    270 #if 0 
    271     /* Force plain H263 to use H263-1998 RTP packetization */ 
    272     { 
    273         {PJMEDIA_FORMAT_H263, PJMEDIA_RTP_PT_H263, {"H263",4}}, 
    274         PJMEDIA_FORMAT_H263,    1000000,    2000000, 
    275         &h263_packetize, &h263_unpacketize, &h263_preopen, NULL, NULL, 
    276         {2, { {{"CIF",3},   {"1",1}},  
    277               {{"QCIF",4},  {"1",1}}, } }, 
    278     }, 
    279 #else 
     266#endif 
     267 
    280268    { 
    281269        {PJMEDIA_FORMAT_H263,   PJMEDIA_RTP_PT_H263,    {"H263",4}}, 
    282270    }, 
    283 #endif 
    284271    { 
    285272        {PJMEDIA_FORMAT_H261,   PJMEDIA_RTP_PT_H261,    {"H261",4}}, 
     
    297284}; 
    298285 
    299 #if ENABLE_H264 
     286#if PJMEDIA_HAS_FFMPEG_CODEC_H264 
     287 
    300288typedef struct h264_data 
    301289{ 
     
    354342    if (ff->param.dir & PJMEDIA_DIR_ENCODING) { 
    355343        AVCodecContext *ctx = ff->enc_ctx; 
    356  
    357         /* Apply profile. Note that, for x264 backend, ffmpeg doesn't seem to 
    358          * use this profile param field, so let's try to apply it "manually". 
    359          */ 
     344        const char *profile = NULL; 
     345 
     346        /* Apply profile. */ 
    360347        ctx->profile  = data->fmtp.profile_idc; 
    361         if (ctx->profile == PROFILE_H264_BASELINE) { 
    362             /* Baseline profile settings (the most used profile in 
    363              * conversational/real-time communications). 
    364              */ 
    365             ctx->coder_type = FF_CODER_TYPE_VLC; 
    366             ctx->max_b_frames = 0; 
    367             ctx->flags2 &= ~(CODEC_FLAG2_WPRED | CODEC_FLAG2_8X8DCT); 
    368             ctx->weighted_p_pred = 0; 
    369         } else if (ctx->profile == PROFILE_H264_MAIN) { 
    370             ctx->flags2 &= ~CODEC_FLAG2_8X8DCT; 
     348        switch (ctx->profile) { 
     349        case PROFILE_H264_BASELINE: 
     350            profile = "baseline"; 
     351            break; 
     352        case PROFILE_H264_MAIN: 
     353            profile = "main"; 
     354            break; 
     355        default: 
     356            break; 
     357        } 
     358        if (profile && 
     359            av_set_string3(ctx->priv_data, "profile", profile, 0, NULL)) 
     360        { 
     361            PJ_LOG(3, (THIS_FILE, "Failed to set H264 profile")); 
    371362        } 
    372363 
    373364        /* Apply profile constraint bits. */ 
    374         // The x264 doesn't seem to support non-constrained (baseline) profile 
    375         // so this shouldn't be a problem (for now). 
    376365        //PJ_TODO(set_h264_constraint_bits_properly_in_ffmpeg); 
    377366        if (data->fmtp.profile_iop) { 
     
    384373        ctx->level    = data->fmtp.level; 
    385374 
    386         /* Libx264 rejects the "broken" ffmpeg defaults, so just change some */ 
    387         ctx->me_range = 16; 
    388         ctx->max_qdiff = 4; 
    389         ctx->qmin = 20; 
    390         ctx->qmax = 32; 
    391         ctx->qcompress = 0.6f; 
    392  
    393         ctx->rtp_payload_size = ff->param.enc_mtu; 
     375        /* Limit NAL unit size as we prefer single NAL unit packetization */ 
     376        if (!av_set_int(ctx->priv_data, "slice-max-size", ff->param.enc_mtu)) 
     377        { 
     378            PJ_LOG(3, (THIS_FILE, "Failed to set H264 max NAL size to %d", 
     379                       ff->param.enc_mtu)); 
     380        } 
     381 
     382        /* Apply intra-refresh */ 
     383        if (!av_set_int(ctx->priv_data, "intra-refresh", 1)) 
     384        { 
     385            PJ_LOG(3, (THIS_FILE, "Failed to set x264 intra-refresh")); 
     386        } 
     387 
     388        /* Misc x264 settings (performance, quality, latency, etc). 
     389         * Let's just use the x264 predefined preset & tune. 
     390         */ 
     391        if (av_set_string3(ctx->priv_data, "preset", "veryslow", 0, NULL)) 
     392        { 
     393            PJ_LOG(3, (THIS_FILE, "Failed to set x264 preset 'veryfast'")); 
     394        } 
     395        if (av_set_string3(ctx->priv_data, "tune", "animation+zerolatency", 
     396                           0, NULL)) 
     397        { 
     398            PJ_LOG(3, (THIS_FILE, "Failed to set x264 tune 'zerolatency'")); 
     399        } 
    394400    } 
    395401 
     
    416422} 
    417423 
    418  
    419424static FUNC_PACKETIZE(h264_packetize) 
    420425{ 
     
    430435                                    bits, bits_len, bits_pos); 
    431436} 
    432 #endif  /* ENABLE_H264 */ 
     437 
     438#endif /* PJMEDIA_HAS_FFMPEG_CODEC_H264 */ 
     439 
     440 
     441#if PJMEDIA_HAS_FFMPEG_CODEC_H263P 
    433442 
    434443typedef struct h263_data 
     
    475484                                    bits, bits_len, bits_pos); 
    476485} 
     486 
     487#endif /* PJMEDIA_HAS_FFMPEG_CODEC_H263P */ 
    477488 
    478489 
     
    9901001} 
    9911002 
    992 static enum PixelFormat dec_get_format(struct AVCodecContext *s,  
    993                                        const enum PixelFormat * fmt) 
    994 { 
    995     ffmpeg_private *ff = (ffmpeg_private*)s->opaque; 
    996     enum PixelFormat def_fmt = *fmt; 
    997  
    998     while (*fmt != -1) { 
    999         if (*fmt == ff->expected_dec_fmt) 
    1000             return *fmt; 
    1001         ++fmt; 
    1002     } 
    1003  
    1004     pj_assert(!"Inconsistency in supported formats"); 
    1005     return def_fmt; 
    1006 } 
    1007  
    1008  
    10091003static pj_status_t open_ffmpeg_codec(ffmpeg_private *ff, 
    10101004                                     pj_mutex_t *ff_mutex) 
     
    10281022    /* Allocate ffmpeg codec context */ 
    10291023    if (ff->param.dir & PJMEDIA_DIR_ENCODING) { 
    1030         ff->enc_ctx = avcodec_alloc_context(); 
     1024        ff->enc_ctx = avcodec_alloc_context3(ff->enc); 
    10311025        if (ff->enc_ctx == NULL) 
    10321026            goto on_error; 
    10331027    } 
    10341028    if (ff->param.dir & PJMEDIA_DIR_DECODING) { 
    1035         ff->dec_ctx = avcodec_alloc_context(); 
     1029        ff->dec_ctx = avcodec_alloc_context3(ff->dec); 
    10361030        if (ff->dec_ctx == NULL) 
    10371031            goto on_error; 
    10381032    } 
    10391033 
    1040     /* Let the codec apply specific settings before the codec opened */ 
    1041     if (ff->desc->preopen) { 
    1042         status = (*ff->desc->preopen)(ff); 
    1043         if (status != PJ_SUCCESS) 
    1044             goto on_error; 
    1045     } 
    1046  
     1034    /* Init generic encoder params */ 
    10471035    if (ff->param.dir & PJMEDIA_DIR_ENCODING) { 
    10481036        AVCodecContext *ctx = ff->enc_ctx; 
    1049         int err; 
    1050  
    1051         /* Init common settings */ 
     1037 
    10521038        ctx->pix_fmt = pix_fmt; 
    10531039        ctx->width = vfd->size.w; 
     
    10711057        ctx->rc_lookahead = 0; 
    10721058#endif 
    1073  
    1074         /* Open ffmpeg codec */ 
    1075         pj_mutex_lock(ff_mutex); 
    1076         err = avcodec_open(ctx, ff->enc); 
     1059    } 
     1060 
     1061    /* Init generic decoder params */ 
     1062    if (ff->param.dir & PJMEDIA_DIR_DECODING) { 
     1063        AVCodecContext *ctx = ff->dec_ctx; 
     1064 
     1065        /* Width/height may be overriden by ffmpeg after first decoding. */ 
     1066        ctx->width  = ctx->coded_width  = ff->param.dec_fmt.det.vid.size.w; 
     1067        ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h; 
     1068        ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; 
     1069        ctx->workaround_bugs = FF_BUG_AUTODETECT; 
     1070        ctx->opaque = ff; 
     1071    } 
     1072 
     1073    /* Init codec override generic params or apply specific params before 
     1074     * the codec opened. 
     1075     */ 
     1076    if (ff->desc->preopen) { 
     1077        status = (*ff->desc->preopen)(ff); 
     1078        if (status != PJ_SUCCESS) 
     1079            goto on_error; 
     1080    } 
     1081 
     1082    /* Open encoder */ 
     1083    if (ff->param.dir & PJMEDIA_DIR_ENCODING) { 
     1084        int err; 
     1085 
     1086        pj_mutex_lock(ff_mutex); 
     1087        err = avcodec_open(ff->enc_ctx, ff->enc); 
    10771088        pj_mutex_unlock(ff_mutex); 
    10781089        if (err < 0) { 
     
    10841095    } 
    10851096 
     1097    /* Open decoder */ 
    10861098    if (ff->param.dir & PJMEDIA_DIR_DECODING) { 
    1087         AVCodecContext *ctx = ff->dec_ctx; 
    10881099        int err; 
    10891100 
    1090         /* Init common settings */ 
    1091         /* Width/height may be overriden by ffmpeg after first decoding. */ 
    1092         ctx->width  = ctx->coded_width  = ff->param.dec_fmt.det.vid.size.w; 
    1093         ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h; 
    1094         ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; 
    1095         ctx->workaround_bugs = FF_BUG_AUTODETECT; 
    1096         ctx->opaque = ff; 
    1097         ctx->get_format = &dec_get_format; 
    1098  
    1099         /* Open ffmpeg codec */ 
    1100         pj_mutex_lock(ff_mutex); 
    1101         err = avcodec_open(ctx, ff->dec); 
     1101        pj_mutex_lock(ff_mutex); 
     1102        err = avcodec_open(ff->dec_ctx, ff->dec); 
    11021103        pj_mutex_unlock(ff_mutex); 
    11031104        if (err < 0) { 
     
    11091110    } 
    11101111 
    1111     /* Let the codec apply specific settings after the codec opened */ 
     1112    /* Let the codec apply specific params after the codec opened */ 
    11121113    if (ff->desc->postopen) { 
    11131114        status = (*ff->desc->postopen)(ff); 
     
    15281529            ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->width; 
    15291530            ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->height; 
     1531            ff->expected_dec_fmt = ff->dec_ctx->pix_fmt; 
    15301532 
    15311533            /* Re-init format info and apply-param of decoder */ 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/h264_packetizer.c

    r3667 r3819  
    320320 
    321321    /* Single NAL unit packet */ 
    322     pj_assert(nal_octet); 
    323  
    324322    *payload = nal_start; 
    325323    *payload_len = nal_end - nal_start; 
  • pjproject/trunk/pjmedia/src/pjmedia/ffmpeg_util.c

    r3664 r3819  
    3333{ 
    3434    { PJMEDIA_FORMAT_RGBA, PIX_FMT_RGBA}, 
    35     { PJMEDIA_FORMAT_RGB24,PIX_FMT_RGB24}, 
     35    { PJMEDIA_FORMAT_RGB24,PIX_FMT_BGR24}, 
    3636    { PJMEDIA_FORMAT_BGRA, PIX_FMT_BGRA}, 
     37    { PJMEDIA_FORMAT_GBRP, PIX_FMT_GBR24P}, 
    3738 
    3839    { PJMEDIA_FORMAT_AYUV, PIX_FMT_NONE}, 
  • pjproject/trunk/pjmedia/src/pjmedia/format.c

    r3715 r3819  
    7979                                    pjmedia_video_apply_fmt_param *aparam); 
    8080 
     81static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi, 
     82                                    pjmedia_video_apply_fmt_param *aparam); 
     83 
    8184struct pjmedia_video_format_mgr 
    8285{ 
     
    9396    {PJMEDIA_FORMAT_BGRA,  "BGRA", PJMEDIA_COLOR_MODEL_RGB, 32, 1, &apply_packed_fmt}, 
    9497    {PJMEDIA_FORMAT_DIB ,  "DIB ", PJMEDIA_COLOR_MODEL_RGB, 24, 1, &apply_packed_fmt}, 
     98    {PJMEDIA_FORMAT_GBRP,  "GBRP", PJMEDIA_COLOR_MODEL_RGB, 24, 3, &apply_planar_444}, 
    9599    {PJMEDIA_FORMAT_AYUV,  "AYUV", PJMEDIA_COLOR_MODEL_YUV, 32, 1, &apply_packed_fmt}, 
    96100    {PJMEDIA_FORMAT_YUY2,  "YUY2", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt}, 
     
    241245} 
    242246 
     247static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi, 
     248                                    pjmedia_video_apply_fmt_param *aparam) 
     249{ 
     250    unsigned i; 
     251    pj_size_t Y_bytes; 
     252 
     253    PJ_UNUSED_ARG(fi); 
     254 
     255    /* Calculate memsize */ 
     256    Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h); 
     257    aparam->framebytes = (Y_bytes * 3); 
     258 
     259    /* Planar formats use 3 plane */ 
     260    aparam->strides[0] = aparam->strides[1] =  
     261                         aparam->strides[2] = aparam->size.w; 
     262 
     263    aparam->planes[0] = aparam->buffer; 
     264    aparam->planes[1] = aparam->planes[0] + Y_bytes; 
     265    aparam->planes[2] = aparam->planes[1] + Y_bytes; 
     266 
     267    aparam->plane_bytes[0] = aparam->plane_bytes[1] = 
     268                             aparam->plane_bytes[2] = Y_bytes; 
     269 
     270    /* Zero unused planes */ 
     271    for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) { 
     272        aparam->strides[i] = 0; 
     273        aparam->planes[i] = NULL; 
     274        aparam->plane_bytes[i] = 0; 
     275    } 
     276 
     277    return PJ_SUCCESS; 
     278} 
     279 
    243280PJ_DEF(pj_status_t) 
    244281pjmedia_video_format_mgr_create(pj_pool_t *pool, 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r3800 r3819  
    31953195{ 
    31963196    char event_name[5]; 
    3197     PJ_UNUSED_ARG(call_id); 
    3198     PJ_UNUSED_ARG(med_idx); 
    3199     PJ_LOG(4,(THIS_FILE, "Event %s", 
     3197 
     3198    PJ_LOG(5,(THIS_FILE, "Event %s", 
    32003199              pjmedia_fourcc_name(event->type, event_name))); 
     3200 
     3201    if (event->type == PJMEDIA_EVENT_FMT_CHANGED) { 
     3202        /* Adjust renderer window size to original video size */ 
     3203        pjsua_call_info ci; 
     3204        pjsua_vid_win_id wid; 
     3205        pjmedia_rect_size size; 
     3206 
     3207        pjsua_call_get_info(call_id, &ci); 
     3208 
     3209        if ((ci.media[med_idx].type == PJMEDIA_TYPE_VIDEO) && 
     3210            (ci.media[med_idx].dir & PJMEDIA_DIR_DECODING)) 
     3211        { 
     3212            wid = ci.media[med_idx].stream.vid.win_in; 
     3213            size = event->data.fmt_changed.new_fmt.det.vid.size; 
     3214            pjsua_vid_win_set_size(wid, &size); 
     3215        } 
     3216    } 
    32013217} 
    32023218 
Note: See TracChangeset for help on using the changeset viewer.