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.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 */ 
Note: See TracChangeset for help on using the changeset viewer.