Ignore:
Timestamp:
Feb 24, 2011 7:47:55 AM (10 years ago)
Author:
nanang
Message:

Re #1182:

  • Added video stream interface in vid_stream.h, the video stream will be able to handle different video formats in encoding and decoding direction.
  • Renamed video device stream class identifiers from 'pjmedia_vid_stream*' to 'pjmedia_vid_dev_stream*' as 'pjmedia_vid_stream' is used by video stream interface.
  • Added ffmpeg video capability to be able to parse SDP format param for H263 and also decide video format for encoding direction based on remote preference and local format-capability setting.
  • Added some new APIs in jitter buffer for handling video stream: pjmedia_jbuf_put_frame3(), pjmedia_jbuf_get_frame3(), pjmedia_jbuf_peek_frame(), and pjmedia_jbuf_remove_frame().
  • Moved pjmedia_stream_info_from_sdp() from session to stream
File:
1 edited

Legend:

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

    r3392 r3420  
    2828#include <pj/os.h> 
    2929 
     30 
    3031/* 
    3132 * Only build this file if PJMEDIA_HAS_FFMPEG_CODEC != 0 
     
    3839#include <libavcodec/avcodec.h> 
    3940#include <libavformat/avformat.h> 
     41#include <libswscale/swscale.h> 
    4042 
    4143 
     
    6668static pj_status_t  ffmpeg_codec_modify(pjmedia_vid_codec *codec,  
    6769                                        const pjmedia_vid_codec_param *attr ); 
     70static pj_status_t  ffmpeg_codec_get_param(pjmedia_vid_codec *codec, 
     71                                           pjmedia_vid_codec_param *param); 
    6872static pj_status_t  ffmpeg_packetize ( pjmedia_vid_codec *codec, 
    6973                                       pj_uint8_t *buf, 
     
    96100    &ffmpeg_codec_close, 
    97101    &ffmpeg_codec_modify, 
     102    &ffmpeg_codec_get_param, 
    98103    &ffmpeg_packetize, 
    99104    &ffmpeg_unpacketize, 
     
    112117    &ffmpeg_dealloc_codec 
    113118}; 
    114  
    115  
    116 typedef struct ffmpeg_codec_info { 
    117     PJ_DECL_LIST_MEMBER(struct ffmpeg_codec_info); 
    118     pjmedia_vid_codec_info       info; 
    119     AVCodec                     *enc; 
    120     AVCodec                     *dec; 
    121 } ffmpeg_codec_info; 
    122119 
    123120 
     
    129126    pj_pool_t                   *pool; 
    130127    pj_mutex_t                  *mutex; 
    131     ffmpeg_codec_info            codecs; 
    132128} ffmpeg_factory; 
    133129 
     130 
     131typedef struct ffmpeg_codec_desc ffmpeg_codec_desc; 
     132 
     133/* ITU resolution ID */ 
     134typedef enum itu_res_id { 
     135    ITU_RES_SQCIF, 
     136    ITU_RES_QCIF, 
     137    ITU_RES_CIF, 
     138    ITU_RES_4CIF, 
     139    ITU_RES_16CIF, 
     140    ITU_RES_CUSTOM, 
     141} itu_res_id; 
     142 
     143/* ITU resolution definition */ 
     144struct itu_res { 
     145    itu_res_id          id; 
     146    pj_str_t            name;     
     147    pjmedia_rect_size   size; 
     148} itu_res_def [] = 
     149{ 
     150    {ITU_RES_16CIF,     {"16CIF",5},    {1408,1142}}, 
     151    {ITU_RES_4CIF,      {"4CIF",4},     {704,576}}, 
     152    {ITU_RES_CIF,       {"CIF",3},      {352,288}}, 
     153    {ITU_RES_QCIF,      {"QCIF",4},     {176,144}}, 
     154    {ITU_RES_SQCIF,     {"SQCIF",5},    {88,72}}, 
     155    {ITU_RES_CUSTOM,    {"CUSTOM",6},   {0,0}}, 
     156}; 
    134157 
    135158/* FFMPEG codecs private data. */ 
    136159typedef struct ffmpeg_private { 
     160    const ffmpeg_codec_desc         *desc; 
     161    pjmedia_vid_codec_param          param;     /**< Codec param            */ 
     162    pj_pool_t                       *pool;      /**< Pool for each instance */ 
     163    pj_timestamp                     last_tx;   /**< Timestamp of last  
     164                                                     transmit               */ 
     165 
     166    /* Format info and apply format param */ 
     167    const pjmedia_video_format_info *enc_vfi; 
     168    pjmedia_video_apply_fmt_param    enc_vafp; 
     169    const pjmedia_video_format_info *dec_vfi; 
     170    pjmedia_video_apply_fmt_param    dec_vafp; 
     171 
     172    /* The ffmpeg codec states. */ 
     173    AVCodec                         *enc; 
     174    AVCodec                         *dec; 
     175    AVCodecContext                  *enc_ctx; 
     176    AVCodecContext                  *dec_ctx; 
     177 
     178    /* The ffmpeg decoder cannot set the output format, so format conversion 
     179     * may be needed for post-decoding. 
     180     */ 
     181    enum PixelFormat                 expected_dec_fmt; 
     182                                                /**< expected output format of  
     183                                                     ffmpeg decoder         */ 
     184    struct SwsContext               *sws_ctx;   /**< the format converter for  
     185                                                     post decoding          */ 
     186 
     187} ffmpeg_private; 
     188 
     189 
     190typedef pj_status_t (*func_packetize)   (pj_uint8_t *buf, 
     191                                         pj_size_t buf_len, 
     192                                         unsigned *pos, 
     193                                         int max_payload_len, 
     194                                         const pj_uint8_t **payload, 
     195                                         pj_size_t *payload_len); 
     196 
     197typedef pj_status_t (*func_unpacketize) (const pj_uint8_t *payload, 
     198                                         pj_size_t   payload_len, 
     199                                         pj_uint8_t *bits, 
     200                                         pj_size_t  *bits_len); 
     201 
     202typedef pj_status_t (*func_parse_fmtp)  (ffmpeg_private *ff); 
     203 
     204/* FFMPEG codec info */ 
     205struct ffmpeg_codec_desc { 
     206    /* Predefined info */ 
     207    pjmedia_vid_codec_info       info; 
     208    func_packetize               packetize; 
     209    func_unpacketize             unpacketize; 
     210    func_parse_fmtp              parse_fmtp; 
     211    pjmedia_codec_fmtp           dec_fmtp; 
     212 
     213    /* Init time defined info */ 
     214    pj_bool_t                    enabled; 
    137215    AVCodec                     *enc; 
    138216    AVCodec                     *dec; 
    139     AVCodecContext              *enc_ctx; 
    140     AVCodecContext              *dec_ctx; 
    141     AVCodecParserContext        *dec_parser_ctx; 
    142  
    143     /* 
    144     pjmedia_frame               *pack_frms; 
    145     unsigned                     pack_frm_cnt; 
    146     unsigned                     pack_frm_max_cnt; 
    147     */ 
    148  
    149     pjmedia_vid_codec_param      param;     /**< Codec param.               */ 
    150     pj_pool_t                   *pool;      /**< Pool for each instance.    */ 
    151     pj_timestamp                 last_tx;   /**< Timestamp of last transmit.*/ 
    152     const pjmedia_video_format_info *vfi; 
    153     pjmedia_video_apply_fmt_param    vafp; 
    154 } ffmpeg_private; 
     217}; 
     218 
     219/* H263 packetizer */ 
     220static pj_status_t h263_packetize(pj_uint8_t *buf, 
     221                                  pj_size_t buf_len, 
     222                                  unsigned *pos, 
     223                                  int max_payload_len, 
     224                                  const pj_uint8_t **payload, 
     225                                  pj_size_t *payload_len) 
     226{ 
     227    return pjmedia_h263_packetize(buf, buf_len, pos, max_payload_len,  
     228                                  payload, payload_len); 
     229} 
     230 
     231/* H263 unpacketizer */ 
     232static pj_status_t h263_unpacketize(const pj_uint8_t *payload, 
     233                                    pj_size_t   payload_len, 
     234                                    pj_uint8_t *bits, 
     235                                    pj_size_t  *bits_len) 
     236{ 
     237    return pjmedia_h263_unpacketize(payload, payload_len, bits, bits_len); 
     238} 
     239 
     240/* H263 fmtp parser */ 
     241static pj_status_t h263_parse_fmtp(ffmpeg_private *ff); 
     242 
     243 
     244/* Internal codec info */ 
     245ffmpeg_codec_desc codec_desc[] = 
     246{ 
     247    { 
     248        {PJMEDIA_FORMAT_H263,   {"H263",4},     PJMEDIA_RTP_PT_H263}, 
     249        &h263_packetize, &h263_unpacketize, &h263_parse_fmtp, 
     250        {2, { {{"CIF",3}, {"2",1}}, {{"QCIF",4}, {"1",1}}, } }, 
     251    }, 
     252    { 
     253        {PJMEDIA_FORMAT_H261,   {"H261",4},     PJMEDIA_RTP_PT_H261}, 
     254    }, 
     255    { 
     256        {PJMEDIA_FORMAT_MJPEG,  {"JPEG",4},     PJMEDIA_RTP_PT_JPEG}, 
     257    }, 
     258}; 
     259 
     260/* Parse fmtp value for custom resolution, e.g: "CUSTOM=800,600,2" */ 
     261static pj_status_t parse_fmtp_itu_custom_res(const pj_str_t *fmtp_val, 
     262                                             pjmedia_rect_size *size, 
     263                                             unsigned *mpi) 
     264{ 
     265    const char *p, *p_end; 
     266    pj_str_t token; 
     267    unsigned long val[3] = {0}; 
     268    unsigned i = 0; 
     269 
     270    p = token.ptr = fmtp_val->ptr; 
     271    p_end = p + fmtp_val->slen; 
     272 
     273    while (p<=p_end && i<PJ_ARRAY_SIZE(val)) { 
     274        if (*p==',' || p==p_end) { 
     275            token.slen = (char*)p - token.ptr; 
     276            val[i++] = pj_strtoul(&token); 
     277            token.ptr = (char*)p+1; 
     278        } 
     279        ++p; 
     280    } 
     281 
     282    if (!val[0] || !val[1]) 
     283        return PJ_ETOOSMALL; 
     284 
     285    if (val[2]<1 || val[2]>32) 
     286        return PJ_EINVAL; 
     287 
     288    size->w = val[0]; 
     289    size->h = val[1]; 
     290    *mpi = val[2]; 
     291    return PJ_SUCCESS; 
     292} 
     293 
     294#define CALC_ITU_CUSTOM_RES_SCORE(size, mpi) ((size)->w * (size)->h / mpi) 
     295 
     296/* ITU codec capabilities */ 
     297typedef struct itu_cap 
     298{ 
     299    /* Lowest MPI for each non-custom resolution */ 
     300    unsigned            lowest_mpi[PJ_ARRAY_SIZE(itu_res_def)]; 
     301    /* For custom resolution, we use maximum processing score */ 
     302    unsigned            custom_res_max_score; 
     303} itu_cap; 
     304 
     305 
     306static pj_status_t load_itu_cap(const pjmedia_codec_fmtp *fmtp, 
     307                                itu_cap *cap) 
     308{ 
     309    unsigned i, j; 
     310    unsigned min_mpi = 0; 
     311 
     312    /* Get Minimum Picture Interval (MPI) for each resolution. If a resolution 
     313     * has no MPI setting in fmtp, the MPI setting is derived from the higher 
     314     * resolution. 
     315     */ 
     316    for (i=0; i<PJ_ARRAY_SIZE(itu_res_def); ++i) { 
     317 
     318        /* Init lowest MPI */ 
     319        cap->lowest_mpi[i] = min_mpi? min_mpi:1; 
     320 
     321        for (j=0; j<fmtp->cnt; ++j) { 
     322            if (pj_stricmp(&fmtp->param[j].name, &itu_res_def[i].name)==0) { 
     323                pjmedia_rect_size size; 
     324                unsigned mpi; 
     325                unsigned score; 
     326 
     327                if (i != ITU_RES_CUSTOM) { 
     328                    size = itu_res_def[i].size; 
     329                    mpi = pj_strtoul(&fmtp->param[j].val); 
     330                    if (min_mpi) 
     331                        min_mpi = PJ_MIN(mpi, min_mpi); 
     332                    else 
     333                        min_mpi = mpi; 
     334 
     335                    /* Update the lowest MPI for this resolution */ 
     336                    cap->lowest_mpi[i] = min_mpi; 
     337 
     338                    /* Also update the processing score for the custom  
     339                     * resolution. 
     340                     */ 
     341                    score = CALC_ITU_CUSTOM_RES_SCORE(&size, mpi); 
     342                    cap->custom_res_max_score =  
     343                                    PJ_MAX(score, cap->custom_res_max_score); 
     344                } else { 
     345                     
     346 
     347                    if (parse_fmtp_itu_custom_res(&fmtp->param[j].val,  
     348                                                  &size, &mpi) == PJ_SUCCESS) 
     349                    { 
     350                        score = CALC_ITU_CUSTOM_RES_SCORE(&size, mpi); 
     351                        cap->custom_res_max_score =  
     352                                    PJ_MAX(score, cap->custom_res_max_score); 
     353                    } 
     354                } 
     355            } 
     356        } 
     357    } 
     358 
     359    return PJ_SUCCESS; 
     360} 
     361 
     362/* H263 fmtp parser */ 
     363static pj_status_t h263_parse_fmtp(ffmpeg_private *ff) 
     364{ 
     365    pjmedia_dir dir; 
     366    pj_status_t status; 
     367 
     368    dir = ff->param.dir; 
     369 
     370    if (ff->param.dir & PJMEDIA_DIR_ENCODING) { 
     371        pjmedia_vid_codec_param param_ref; 
     372        pjmedia_codec_fmtp *fmtp_rem, *fmtp_ref; 
     373        itu_cap local_cap; 
     374        pjmedia_rect_size size = {0}; 
     375        unsigned mpi = 0; 
     376        pj_bool_t got_good_res = PJ_FALSE; 
     377        pj_bool_t has_prefered_res = PJ_FALSE; 
     378        unsigned i, j; 
     379 
     380        fmtp_rem = &ff->param.enc_fmtp; 
     381        dir &= ~PJMEDIA_DIR_ENCODING; 
     382 
     383        /* Get default fmtp setting as the reference for local capabilities */ 
     384        status = pjmedia_vid_codec_mgr_get_default_param( 
     385                        ffmpeg_factory.mgr, &ff->desc->info, &param_ref); 
     386        fmtp_ref = (status==PJ_SUCCESS)? &param_ref.enc_fmtp : fmtp_rem; 
     387 
     388        /* Load default local capabilities */ 
     389        status = load_itu_cap(fmtp_ref, &local_cap); 
     390        pj_assert(status == PJ_SUCCESS); 
     391 
     392        /* Negotiate resolution and MPI */ 
     393        for (i=0; i<fmtp_rem->cnt && !got_good_res; ++i) 
     394        { 
     395            for (j=0; j<PJ_ARRAY_SIZE(itu_res_def) && !got_good_res; ++j) 
     396            { 
     397                if (pj_stricmp(&fmtp_rem->param[i].name, &itu_res_def[j].name)) 
     398                    continue; 
     399 
     400                has_prefered_res = PJ_TRUE; 
     401                if (j == ITU_RES_CUSTOM) { 
     402                    unsigned score; 
     403 
     404                    if (parse_fmtp_itu_custom_res(&fmtp_rem->param[i].val,  
     405                                                  &size, &mpi) != PJ_SUCCESS) 
     406                    { 
     407                        /* Invalid custom resolution format, skip this  
     408                         * custom resolution 
     409                         */ 
     410                        break; 
     411                    } 
     412 
     413                    score = CALC_ITU_CUSTOM_RES_SCORE(&size, mpi); 
     414                    if (score <= local_cap.custom_res_max_score) 
     415                        got_good_res = PJ_TRUE; 
     416                } else { 
     417                    mpi = pj_strtoul(&fmtp_rem->param[i].val); 
     418                    if (mpi>=1 && mpi<=32 && mpi>=local_cap.lowest_mpi[j]) { 
     419                        got_good_res = PJ_TRUE; 
     420                        size = itu_res_def[j].size; 
     421                    } 
     422                } 
     423            } 
     424        } 
     425 
     426        if (has_prefered_res) { 
     427            if (got_good_res) { 
     428                pjmedia_video_format_detail *vfd; 
     429 
     430                /* Apply this size & MPI */ 
     431                vfd = pjmedia_format_get_video_format_detail(&ff->param.enc_fmt, 
     432                                                             PJ_TRUE); 
     433                vfd->size = size; 
     434                vfd->fps.num = 30000; 
     435                vfd->fps.denum = 1001 * mpi; 
     436                got_good_res = PJ_TRUE; 
     437 
     438                PJ_TODO(NOTIFY_APP_ABOUT_THIS_NEW_ENCODING_FORMAT); 
     439            } else { 
     440                return PJ_EUNKNOWN; 
     441            } 
     442        } 
     443    } 
     444 
     445    return PJ_SUCCESS; 
     446} 
     447 
     448 
     449 
     450static const ffmpeg_codec_desc* find_codec_info( 
     451                        const pjmedia_vid_codec_info *info) 
     452{ 
     453    int i; 
     454 
     455    for (i=0; i<PJ_ARRAY_SIZE(codec_desc); ++i) { 
     456        ffmpeg_codec_desc *desc = &codec_desc[i]; 
     457 
     458        if (desc->enabled && 
     459            (desc->info.fmt_id == info->fmt_id) && 
     460            ((desc->info.dir & info->dir) == info->dir) && 
     461            pj_stricmp(&desc->info.encoding_name, &info->encoding_name)==0) 
     462        { 
     463            return desc; 
     464        } 
     465    } 
     466 
     467    return NULL; 
     468} 
     469 
     470 
     471static int find_codec_info_idx_by_fmt_id(pjmedia_format_id fmt_id) 
     472{ 
     473    int i; 
     474    for (i=0; i<PJ_ARRAY_SIZE(codec_desc); ++i) { 
     475        if (codec_desc[i].info.fmt_id == fmt_id) 
     476            return i; 
     477    } 
     478 
     479    return -1; 
     480} 
    155481 
    156482 
     
    163489    pj_pool_t *pool; 
    164490    AVCodec *c; 
    165     enum CodecID last_codec_id = CODEC_ID_NONE; 
    166491    pj_status_t status; 
    167492 
     
    179504    ffmpeg_factory.mgr = mgr; 
    180505    ffmpeg_factory.pf = pf; 
    181     pj_list_init(&ffmpeg_factory.codecs); 
    182506 
    183507    pool = pj_pool_create(pf, "ffmpeg codec factory", 256, 256, NULL); 
     
    197521    for (c=av_codec_next(NULL); c; c=av_codec_next(c))  
    198522    { 
    199         ffmpeg_codec_info *ci; 
     523        ffmpeg_codec_desc *desc; 
     524        pjmedia_format_id fmt_id; 
     525        int codec_info_idx; 
    200526         
    201527        if (c->type != CODEC_TYPE_VIDEO) 
     
    203529 
    204530        /* Video encoder and decoder are usually implemented in separate 
    205          * AVCodec instances. 
     531         * AVCodec instances. While the codec attributes (e.g: raw formats, 
     532         * supported fps) are in the encoder. 
    206533         */ 
    207534 
    208         if (c->id == last_codec_id) { 
    209             /* This codec usually be the decoder, and not as much info as in 
    210              * encoder can be fetched here. 
    211              */ 
    212             pj_assert(!pj_list_empty(&ffmpeg_factory.codecs)); 
    213             ci = ffmpeg_factory.codecs.prev; 
    214             pj_assert(ci->info.dir != PJMEDIA_DIR_ENCODING_DECODING); 
    215             pj_assert(!ci->dec || !ci->enc); 
    216         } else { 
    217             pjmedia_format_id enc_fmt_id; 
    218             pjmedia_format_id raw_fmt[PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT]; 
    219             unsigned raw_fmt_cnt = 0; 
    220             unsigned raw_fmt_cnt_should_be = 0; 
    221  
    222             /* Get encoded format id */ 
    223             status = CodecID_to_pjmedia_format_id(c->id, &enc_fmt_id); 
    224             if (status != PJ_SUCCESS) { 
    225                 //PJ_LOG(5, (THIS_FILE, "Unrecognized ffmpeg codec id %d, " 
    226                 //                      "codec [%s/%s] ignored", 
    227                 //                      c->id, c->name, c->long_name)); 
    228                 //enc_fmt_id = PJMEDIA_FORMAT_FFMPEG_UNKNOWN; 
    229  
    230                 /* Skip unrecognized encoding format ID */ 
    231                 continue; 
    232             } 
    233  
    234             /* Get raw/decoded format ids */ 
    235             if (c->pix_fmts) { 
    236                 const enum PixelFormat *p = c->pix_fmts; 
    237                 for(;(p && *p != -1) && 
    238                      (raw_fmt_cnt < PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT); 
    239                      ++p) 
    240                 { 
    241                     pjmedia_format_id fmt_id; 
    242  
    243                     raw_fmt_cnt_should_be++; 
    244                     status = PixelFormat_to_pjmedia_format_id(*p, &fmt_id); 
    245                     if (status != PJ_SUCCESS) { 
    246                         PJ_LOG(6, (THIS_FILE, "Unrecognized ffmpeg pixel " 
    247                                    "format %d", *p)); 
    248                         continue; 
    249                     } 
    250                     raw_fmt[raw_fmt_cnt++] = fmt_id; 
    251                 } 
    252             } else { 
    253                 /* Unknown raw format, ignore this codec? */ 
    254                 continue; 
    255             } 
    256  
    257             if (raw_fmt_cnt < raw_fmt_cnt_should_be) { 
    258                 PJ_LOG(6, (THIS_FILE, "Codec [%s/%s] have %d raw formats, " 
    259                                       "recognized only %d raw formats", 
    260                                       c->name, c->long_name, 
    261                                       raw_fmt_cnt_should_be, raw_fmt_cnt)); 
    262             } 
    263             if (raw_fmt_cnt == 0) { 
    264                 PJ_LOG(5, (THIS_FILE, "No recognized raw format " 
    265                                       "for codec [%s/%s], codec ignored", 
    266                                       c->name, c->long_name)); 
    267                 /* Comment this to see all ffmpeg codecs */ 
    268                 continue; 
    269             } 
    270  
    271             ci = PJ_POOL_ZALLOC_T(pool, ffmpeg_codec_info); 
    272             ci->info.fmt_id = enc_fmt_id; 
    273             pj_cstr(&ci->info.encoding_name, c->name); 
    274             ci->info.clock_rate = 90000; 
    275             ci->info.dec_fmt_id_cnt = raw_fmt_cnt; 
    276             pj_memcpy(ci->info.dec_fmt_id, raw_fmt,  
    277                       sizeof(raw_fmt[0])*raw_fmt_cnt); 
    278  
    279             switch (enc_fmt_id) { 
    280                 case PJMEDIA_FORMAT_H263: 
    281                     ci->info.pt = PJMEDIA_RTP_PT_H263; 
    282                     break; 
    283                 case PJMEDIA_FORMAT_H261: 
    284                     ci->info.pt = PJMEDIA_RTP_PT_H261; 
    285                     break; 
    286                 default: 
    287                     break; 
    288             } 
    289  
    290             if (c->supported_framerates) { 
    291                 const AVRational *fr = c->supported_framerates; 
    292                 while ((fr->num != 0 || fr->den != 0) &&  
    293                        ci->info.fps_cnt < PJMEDIA_VID_CODEC_MAX_FPS_CNT) 
    294                 { 
    295                     ci->info.fps[ci->info.fps_cnt].num = fr->num; 
    296                     ci->info.fps[ci->info.fps_cnt].denum = fr->den; 
    297                     ++ci->info.fps_cnt; 
    298                     ++fr; 
    299                 } 
    300             } 
    301  
    302             pj_list_push_back(&ffmpeg_factory.codecs, ci); 
     535        status = CodecID_to_pjmedia_format_id(c->id, &fmt_id); 
     536        /* Skip if format ID is unknown */ 
     537        if (status != PJ_SUCCESS) 
     538            continue; 
     539 
     540        codec_info_idx = find_codec_info_idx_by_fmt_id(fmt_id); 
     541        /* Skip if codec is unwanted by this wrapper (not listed in  
     542         * the codec info array) 
     543         */ 
     544        if (codec_info_idx < 0) 
     545            continue; 
     546 
     547        desc = &codec_desc[codec_info_idx]; 
     548 
     549        /* Skip duplicated codec implementation */ 
     550        if ((c->encode && (desc->info.dir & PJMEDIA_DIR_ENCODING)) || 
     551            (c->decode && (desc->info.dir & PJMEDIA_DIR_DECODING))) 
     552        { 
     553            continue; 
     554        } 
     555 
     556        /* Get raw/decoded format ids in the encoder */ 
     557        if (c->pix_fmts && c->encode) { 
     558            pjmedia_format_id raw_fmt[PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT]; 
     559            unsigned raw_fmt_cnt = 0; 
     560            unsigned raw_fmt_cnt_should_be = 0; 
     561            const enum PixelFormat *p = c->pix_fmts; 
     562 
     563            for(;(p && *p != -1) && 
     564                 (raw_fmt_cnt < PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT); 
     565                 ++p) 
     566            { 
     567                pjmedia_format_id fmt_id; 
     568 
     569                raw_fmt_cnt_should_be++; 
     570                status = PixelFormat_to_pjmedia_format_id(*p, &fmt_id); 
     571                if (status != PJ_SUCCESS) { 
     572                    PJ_LOG(6, (THIS_FILE, "Unrecognized ffmpeg pixel " 
     573                               "format %d", *p)); 
     574                    continue; 
     575                } 
     576                raw_fmt[raw_fmt_cnt++] = fmt_id; 
     577            } 
     578 
     579            if (raw_fmt_cnt == 0) { 
     580                PJ_LOG(5, (THIS_FILE, "No recognized raw format " 
     581                                      "for codec [%s/%s], codec ignored", 
     582                                      c->name, c->long_name)); 
     583                /* Skip this encoder */ 
     584                continue; 
     585            } 
     586 
     587            if (raw_fmt_cnt < raw_fmt_cnt_should_be) { 
     588                PJ_LOG(6, (THIS_FILE, "Codec [%s/%s] have %d raw formats, " 
     589                                      "recognized only %d raw formats", 
     590                                      c->name, c->long_name, 
     591                                      raw_fmt_cnt_should_be, raw_fmt_cnt)); 
     592            } 
     593 
     594            desc->info.dec_fmt_id_cnt = raw_fmt_cnt; 
     595            pj_memcpy(desc->info.dec_fmt_id, raw_fmt,  
     596                      sizeof(raw_fmt[0])*raw_fmt_cnt); 
     597        } 
     598 
     599        /* Get supported framerates */ 
     600        if (c->supported_framerates) { 
     601            const AVRational *fr = c->supported_framerates; 
     602            while ((fr->num != 0 || fr->den != 0) &&  
     603                   desc->info.fps_cnt < PJMEDIA_VID_CODEC_MAX_FPS_CNT) 
     604            { 
     605                desc->info.fps[desc->info.fps_cnt].num = fr->num; 
     606                desc->info.fps[desc->info.fps_cnt].denum = fr->den; 
     607                ++desc->info.fps_cnt; 
     608                ++fr; 
     609            } 
     610        } 
     611 
     612        /* Get ffmpeg encoder instance */ 
     613        if (c->encode && !desc->enc) { 
     614            desc->info.dir |= PJMEDIA_DIR_ENCODING; 
     615            desc->enc = c; 
    303616        } 
    304  
    305         if (c->encode) { 
    306             ci->info.dir |= PJMEDIA_DIR_ENCODING; 
    307             ci->enc = c; 
     617         
     618        /* Get ffmpeg decoder instance */ 
     619        if (c->decode && !desc->dec) { 
     620            desc->info.dir |= PJMEDIA_DIR_DECODING; 
     621            desc->dec = c; 
    308622        } 
    309         if (c->decode) { 
    310             ci->info.dir |= PJMEDIA_DIR_DECODING; 
    311             ci->dec = c; 
    312         } 
    313  
    314         last_codec_id = c->id; 
     623 
     624        /* Enable this codec when any ffmpeg codec instance are recognized 
     625         * and the supported raw formats info has been collected. 
     626         */ 
     627        if ((desc->dec || desc->enc) && desc->info.dec_fmt_id_cnt) 
     628        { 
     629            desc->enabled = PJ_TRUE; 
     630        } 
     631 
     632        /* Normalize default value of clock rate */ 
     633        if (desc->info.clock_rate == 0) 
     634            desc->info.clock_rate = 90000; 
    315635    } 
    316636 
     
    360680 
    361681 
    362 static ffmpeg_codec_info* find_codec(const pjmedia_vid_codec_info *info) 
    363 { 
    364     ffmpeg_codec_info *ci = ffmpeg_factory.codecs.next; 
    365  
    366     pj_mutex_lock(ffmpeg_factory.mutex); 
    367  
    368     while (ci != &ffmpeg_factory.codecs) { 
    369         if ((ci->info.fmt_id == info->fmt_id) && 
    370             ((ci->info.dir & info->dir) == info->dir) && 
    371             pj_stricmp(&ci->info.encoding_name, &info->encoding_name)==0) 
    372         { 
    373             pj_mutex_unlock(ffmpeg_factory.mutex); 
    374             return ci; 
    375         } 
    376         ci = ci->next; 
    377     } 
    378  
    379     pj_mutex_unlock(ffmpeg_factory.mutex); 
    380  
    381     return NULL; 
    382 } 
    383  
    384  
    385682/*  
    386683 * Check if factory can allocate the specified codec.  
     
    389686                                      const pjmedia_vid_codec_info *info ) 
    390687{ 
    391     ffmpeg_codec_info *ci; 
     688    const ffmpeg_codec_desc *desc; 
    392689 
    393690    PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL); 
    394691    PJ_ASSERT_RETURN(info, PJ_EINVAL); 
    395692 
    396     ci = find_codec(info); 
    397     if (!ci) { 
     693    desc = find_codec_info(info); 
     694    if (!desc) { 
    398695        return PJMEDIA_CODEC_EUNSUP; 
    399696    } 
     
    409706                                        pjmedia_vid_codec_param *attr ) 
    410707{ 
    411     ffmpeg_codec_info *ci; 
     708    const ffmpeg_codec_desc *desc; 
    412709 
    413710    PJ_ASSERT_RETURN(factory==&ffmpeg_factory.base, PJ_EINVAL); 
    414711    PJ_ASSERT_RETURN(info && attr, PJ_EINVAL); 
    415712 
    416     ci = find_codec(info); 
    417     if (!ci) { 
     713    desc = find_codec_info(info); 
     714    if (!desc) { 
    418715        return PJMEDIA_CODEC_EUNSUP; 
    419716    } 
    420717 
    421718    pj_bzero(attr, sizeof(pjmedia_vid_codec_param)); 
    422     attr->dir = ci->info.dir; 
    423     attr->pt = info->pt; 
    424     pjmedia_format_init_video(&attr->enc_fmt, ci->info.fmt_id, 
    425                               352, 288, 25, 1); 
    426     pjmedia_format_init_video(&attr->dec_fmt, ci->info.dec_fmt_id[0], 
    427                               352, 288, 25, 1); 
     719 
     720    /* Direction */ 
     721    attr->dir = desc->info.dir; 
     722 
     723    /* Encoded format */ 
     724    pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id, 
     725                              352, 288, 30000, 1001); 
     726 
     727    /* Decoded format */ 
     728    pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0], 
     729                              352, 288, 30000, 1001); 
     730 
     731    /* Decoding fmtp */ 
     732    attr->dec_fmtp = desc->dec_fmtp; 
    428733 
    429734    return PJ_SUCCESS; 
     
    437742                                       pjmedia_vid_codec_info codecs[]) 
    438743{ 
    439     ffmpeg_codec_info *ci; 
    440     unsigned max; 
     744    unsigned i; 
    441745 
    442746    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL); 
    443747    PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL); 
    444748 
    445     max = *count; 
    446     *count = 0; 
    447     ci = ffmpeg_factory.codecs.next; 
    448  
    449     pj_mutex_lock(ffmpeg_factory.mutex); 
    450     while (*count < max && ci != &ffmpeg_factory.codecs) { 
    451         pj_memcpy(&codecs[*count], &ci->info, sizeof(pjmedia_vid_codec_info)); 
    452         *count = *count + 1; 
    453         ci = ci->next; 
    454     } 
    455     pj_mutex_unlock(ffmpeg_factory.mutex); 
     749    *count = PJ_MIN(*count, PJ_ARRAY_SIZE(codec_desc)); 
     750 
     751    for (i=0; i<*count; ++i) { 
     752        pj_memcpy(&codecs[i], &codec_desc[i].info,  
     753                  sizeof(pjmedia_vid_codec_info)); 
     754    } 
    456755 
    457756    return PJ_SUCCESS; 
     
    466765{ 
    467766    ffmpeg_private *ff; 
    468     ffmpeg_codec_info *ci; 
     767    const ffmpeg_codec_desc *desc; 
    469768    pjmedia_vid_codec *codec; 
    470769    pj_pool_t *pool = NULL; 
     
    474773    PJ_ASSERT_RETURN(factory == &ffmpeg_factory.base, PJ_EINVAL); 
    475774 
    476     ci = find_codec(info); 
    477     if (!ci) { 
     775    desc = find_codec_info(info); 
     776    if (!desc) { 
    478777        return PJMEDIA_CODEC_EUNSUP; 
    479778    } 
     
    495794    codec->codec_data = ff; 
    496795    ff->pool = pool; 
    497     ff->enc = ci->enc; 
    498     ff->dec = ci->dec; 
     796    ff->enc = desc->enc; 
     797    ff->dec = desc->dec; 
     798    ff->desc = desc; 
    499799 
    500800    *p_codec = codec; 
     
    551851} 
    552852 
    553 /* 
    554 static enum PixelFormat ffdec_nego_format(struct AVCodecContext *s,  
     853static enum PixelFormat dec_get_format(struct AVCodecContext *s,  
    555854                                          const enum PixelFormat * fmt) 
    556855{ 
    557     enum PixelFormat pix_fmt; 
    558  
    559     PJ_UNUSED_ARG(s); 
    560     PJ_UNUSED_ARG(fmt); 
    561  
    562     pjmedia_format_id_to_PixelFormat(PJMEDIA_FORMAT_BGRA, &pix_fmt); 
    563     return pix_fmt; 
    564 } 
    565  
    566 static void enc_got_payload(struct AVCodecContext *avctx, 
    567                             void *data, int size, int mb_nb); 
    568 */ 
     856    ffmpeg_private *ff = (ffmpeg_private*)s->opaque; 
     857    enum PixelFormat def_fmt = *fmt; 
     858 
     859    while (*fmt != -1) { 
     860        if (*fmt == ff->expected_dec_fmt) 
     861            return *fmt; 
     862        ++fmt; 
     863    } 
     864 
     865    pj_assert(!"Inconsistency in supported formats"); 
     866    return def_fmt; 
     867} 
    569868 
    570869 
     
    574873    enum PixelFormat pix_fmt; 
    575874    pj_status_t status; 
     875    pjmedia_video_format_detail *vfd; 
    576876 
    577877    status = pjmedia_format_id_to_PixelFormat(ff->param.dec_fmt.id, 
     
    579879    if (status != PJ_SUCCESS) 
    580880        return status; 
     881 
     882    vfd = pjmedia_format_get_video_format_detail(&ff->param.enc_fmt,  
     883                                                 PJ_TRUE); 
     884    ff->expected_dec_fmt = pix_fmt; 
    581885 
    582886    while (((ff->param.dir & PJMEDIA_DIR_ENCODING) && ff->enc_ctx == NULL) || 
     
    595899        } 
    596900 
     901        /* Init ffmpeg codec context */ 
    597902        ctx = avcodec_alloc_context(); 
    598903 
    599904        /* Common attributes */ 
    600905        ctx->pix_fmt = pix_fmt; 
    601         ctx->width = ff->param.enc_fmt.det.vid.size.w; 
    602         ctx->height = ff->param.enc_fmt.det.vid.size.h; 
    603906        ctx->workaround_bugs = FF_BUG_AUTODETECT; 
    604907        ctx->opaque = ff; 
     
    608911 
    609912            /* Encoding only attributes */ 
    610             ctx->time_base.num = ff->param.enc_fmt.det.vid.fps.denum; 
    611             ctx->time_base.den = ff->param.enc_fmt.det.vid.fps.num; 
    612             if (ff->param.enc_fmt.det.vid.avg_bps) 
    613                 ctx->bit_rate = ff->param.enc_fmt.det.vid.avg_bps; 
    614             if (ff->param.enc_fmt.det.vid.max_bps) 
    615                 ctx->rc_max_rate = ff->param.enc_fmt.det.vid.max_bps; 
    616 #if 0 
    617             if (ff->param.enc_mtu) { 
    618                 //ctx->rtp_payload_size = ff->param.enc_mtu; 
    619                 //ctx->rtp_callback = &enc_got_payload; 
    620  
    621                 /* Allocate frame array for RTP payload packing */ 
    622                 if (ff->param.enc_fmt.det.vid.max_bps) 
    623                     ff->pack_frm_max_cnt = ff->param.enc_fmt.det.vid.max_bps / 
    624                                            ff->param.enc_mtu + 1; 
    625                 else 
    626                     ff->pack_frm_max_cnt = 32; 
    627  
    628                 ff->pack_frms = (pjmedia_frame*) 
    629                                 pj_pool_calloc(ff->pool, ff->pack_frm_max_cnt, 
    630                                                sizeof(ff->pack_frms[0])); 
    631             } 
    632 #endif 
    633  
    634             /* For encoder, should be better to be strict to the standards */ 
     913            ctx->width = vfd->size.w; 
     914            ctx->height = vfd->size.h; 
     915            ctx->time_base.num = vfd->fps.denum; 
     916            ctx->time_base.den = vfd->fps.num; 
     917            if (vfd->avg_bps) 
     918                ctx->bit_rate = vfd->avg_bps; 
     919            if (vfd->max_bps) 
     920                ctx->rc_max_rate = vfd->max_bps; 
     921 
     922            /* For encoder, should be better to be strict to the standards */ 
    635923            ctx->strict_std_compliance = FF_COMPLIANCE_STRICT; 
    636924        } 
     925 
    637926        if (dir & PJMEDIA_DIR_DECODING) { 
    638927            codec = ff->dec; 
    639928 
    640929            /* Decoding only attributes */ 
    641             ctx->coded_width = ctx->width; 
    642             ctx->coded_height = ctx->height; 
     930            // this setting will be automatically fetched from the bitstream. 
     931            //ctx->coded_width = ff->param.dec_fmt.det.vid.size.w; 
     932            //ctx->coded_height = ff->param.dec_fmt.det.vid.size.h; 
    643933 
    644934            /* For decoder, be more flexible */ 
    645             if (ff->param.dir!=PJMEDIA_DIR_ENCODING_DECODING || ff->enc!=ff->dec) 
     935            if (ff->param.dir!=PJMEDIA_DIR_ENCODING_DECODING ||  
     936                ff->enc!=ff->dec) 
     937            { 
    646938                ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; 
    647  
    648             //ctx->get_format = &ffdec_nego_format; 
     939            } 
     940 
     941            ctx->get_format = &dec_get_format; 
    649942        } 
    650943 
     
    680973    ff = (ffmpeg_private*)codec->codec_data; 
    681974 
    682     ff->vfi = pjmedia_get_video_format_info(NULL, attr->dec_fmt.id); 
    683     if (!ff->vfi) { 
    684         status = PJ_EINVAL; 
    685         goto on_error; 
    686     } 
    687  
    688     pj_bzero(&ff->vafp, sizeof(ff->vafp)); 
    689     ff->vafp.size = attr->dec_fmt.det.vid.size; 
    690     ff->vafp.buffer = 0; 
    691     status = (*ff->vfi->apply_fmt)(ff->vfi, &ff->vafp); 
    692     if (status != PJ_SUCCESS) { 
    693         goto on_error; 
    694     } 
    695  
    696975    pj_memcpy(&ff->param, attr, sizeof(*attr)); 
    697976 
     977    /* Apply SDP fmtp attribute */ 
     978    if (ff->desc->parse_fmtp) { 
     979        status = (*ff->desc->parse_fmtp)(ff); 
     980        if (status != PJ_SUCCESS) 
     981            goto on_error; 
     982    } 
     983 
     984    /* Open the codec */ 
    698985    ff_mutex = ((struct ffmpeg_factory*)codec->factory)->mutex; 
    699986    status = open_ffmpeg_codec(ff, ff_mutex); 
     
    701988        goto on_error; 
    702989 
     990    /* Init format info and apply-param of decoder */ 
     991    ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id); 
     992    if (!ff->dec_vfi) { 
     993        status = PJ_EINVAL; 
     994        goto on_error; 
     995    } 
     996    pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp)); 
     997    ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size; 
     998    ff->dec_vafp.buffer = NULL; 
     999    status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp); 
     1000    if (status != PJ_SUCCESS) { 
     1001        goto on_error; 
     1002    } 
     1003 
     1004    /* Init format info and apply-param of encoder */ 
     1005    ff->enc_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id); 
     1006    if (!ff->enc_vfi) { 
     1007        status = PJ_EINVAL; 
     1008        goto on_error; 
     1009    } 
     1010    pj_bzero(&ff->enc_vafp, sizeof(ff->enc_vafp)); 
     1011    ff->enc_vafp.size = ff->param.enc_fmt.det.vid.size; 
     1012    ff->enc_vafp.buffer = NULL; 
     1013    status = (*ff->enc_vfi->apply_fmt)(ff->enc_vfi, &ff->enc_vafp); 
     1014    if (status != PJ_SUCCESS) { 
     1015        goto on_error; 
     1016    } 
     1017 
     1018    /* Update codec attributes, e.g: encoding format may be changed by 
     1019     * SDP fmtp negotiation. 
     1020     */ 
     1021    pj_memcpy(attr, &ff->param, sizeof(*attr)); 
     1022 
    7031023    return PJ_SUCCESS; 
    7041024 
     
    7291049        av_free(ff->dec_ctx); 
    7301050    } 
    731     if (ff->dec_parser_ctx) { 
    732         av_parser_close(ff->dec_parser_ctx); 
    733  
     1051    if (ff->sws_ctx) { 
     1052        sws_freeContext(ff->sws_ctx); 
    7341053    } 
    7351054    ff->enc_ctx = NULL; 
    7361055    ff->dec_ctx = NULL; 
    737     ff->dec_parser_ctx = NULL; 
     1056    ff->sws_ctx = NULL; 
    7381057    pj_mutex_unlock(ff_mutex); 
    7391058 
     
    7461065 */ 
    7471066static pj_status_t  ffmpeg_codec_modify( pjmedia_vid_codec *codec,  
    748                                          const pjmedia_vid_codec_param *attr ) 
     1067                                         const pjmedia_vid_codec_param *attr) 
    7491068{ 
    7501069    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     
    7551074    return PJ_ENOTSUP; 
    7561075} 
     1076 
     1077static pj_status_t  ffmpeg_codec_get_param(pjmedia_vid_codec *codec, 
     1078                                           pjmedia_vid_codec_param *param) 
     1079{ 
     1080    ffmpeg_private *ff; 
     1081 
     1082    PJ_ASSERT_RETURN(codec && param, PJ_EINVAL); 
     1083 
     1084    ff = (ffmpeg_private*)codec->codec_data; 
     1085    pj_memcpy(param, &ff->param, sizeof(*param)); 
     1086 
     1087    return PJ_SUCCESS; 
     1088} 
     1089 
    7571090 
    7581091static pj_status_t  ffmpeg_packetize ( pjmedia_vid_codec *codec, 
     
    7651098    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
    7661099 
    767     switch (ff->param.enc_fmt.id) { 
    768         case PJMEDIA_FORMAT_H263: 
    769             return pjmedia_h263_packetize(buf, buf_len, pos, 
    770                                           ff->param.enc_mtu, payload, 
    771                                           payload_len); 
    772             break; 
    773         default: 
    774             return PJ_ENOTSUP; 
    775     } 
     1100    if (ff->desc->packetize) { 
     1101        return (*ff->desc->packetize)(buf, buf_len, pos, 
     1102                                      ff->param.enc_mtu, payload, 
     1103                                      payload_len); 
     1104    } 
     1105 
     1106    return PJ_ENOTSUP; 
    7761107} 
    7771108 
     
    7841115    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
    7851116 
    786     switch (ff->param.enc_fmt.id) { 
    787         case PJMEDIA_FORMAT_H263: 
    788             return pjmedia_h263_unpacketize(payload, payload_len, 
    789                                             buf, buf_len); 
    790             break; 
    791         default: 
    792             return PJ_ENOTSUP; 
    793     } 
    794 } 
    795  
    796 #if 0 
    797 /* 
    798  * Pack encoded frame to RTP payload frames. 
    799  */ 
    800 static pj_status_t  ffmpeg_codec_pack ( pjmedia_vid_codec *codec, 
    801                                         const pjmedia_frame *enc_frame, 
    802                                         unsigned *frame_cnt, 
    803                                         pjmedia_frame frames[]) 
    804 { 
    805     ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
    806     unsigned i; 
    807  
    808     /* Can only work when encoding MTU is set */ 
    809     PJ_ASSERT_RETURN(ff->param.enc_mtu, PJ_EINVALIDOP); 
    810  
    811     /* Validate available payload number */ 
    812     PJ_ASSERT_RETURN(ff->pack_frm_cnt <= *frame_cnt, PJ_EINVALIDOP); 
    813  
    814     /* Validate encoded bitstream */ 
    815     PJ_ASSERT_RETURN(ff->pack_frm_cnt==0 ||  
    816                      ff->pack_frms[0].buf == enc_frame->buf, 
    817                      PJ_EINVAL); 
    818  
    819     /* Return the payloads */ 
    820     *frame_cnt = ff->pack_frm_cnt; 
    821     for (i = 0; i < *frame_cnt; ++i) 
    822         frames[i] = ff->pack_frms[i]; 
    823  
    824     return PJ_SUCCESS; 
    825 } 
    826  
    827 /* 
    828  * Get frames in the packet. 
    829  */ 
    830 static pj_status_t  ffmpeg_codec_parse( pjmedia_vid_codec *codec, 
    831                                         void *pkt, 
    832                                         pj_size_t pkt_size, 
    833                                         const pj_timestamp *ts, 
    834                                         pjmedia_frame *frame) 
    835 { 
    836     ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
    837     pj_uint8_t *buf = frame->buf; 
    838     int buf_size = frame->size; 
    839     int processed; 
    840  
    841  
    842     if (!ff->dec_parser_ctx) { 
    843         ff->dec_parser_ctx = av_parser_init(ff->dec->id); 
    844         if (!ff->dec_parser_ctx) 
    845             return PJ_ENOTSUP; 
    846     } 
    847  
    848 #if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72 
    849     processed = av_parser_parse2(ff->dec_parser_ctx, ff->dec_ctx,  
    850                                  &buf, &buf_size, (uint8_t*)pkt, pkt_size, 
    851                                  ts->u64, ts->u64, AV_NOPTS_VALUE); 
    852 #else 
    853     processed = av_parser_parse (ff->dec_parser_ctx, ff->dec_ctx,  
    854                                  &buf, &buf_size, (uint8_t*)pkt, pkt_size, 
    855                                  ts->u64, ts->u64); 
    856 #endif 
    857  
    858     if (buf_size) { 
    859         frame->timestamp = *ts; 
    860         frame->size = buf_size; 
    861         return PJ_SUCCESS; 
    862     } 
    863  
    864     return PJ_EPENDING; 
    865 } 
    866  
    867 static void enc_got_payload(struct AVCodecContext *avctx, 
    868                             void *data, int size, int mb_nb) 
    869 { 
    870     ffmpeg_private *ff = (ffmpeg_private*) avctx->opaque; 
    871     pjmedia_frame *payload; 
    872  
    873     pj_assert(ff->pack_frm_cnt < ff->pack_frm_max_cnt); 
    874     payload = &ff->pack_frms[ff->pack_frm_cnt++]; 
    875     payload->buf = data; 
    876     payload->size = size; 
    877     payload->bit_info = mb_nb; 
    878 } 
    879  
    880 #endif 
     1117    if (ff->desc->unpacketize) { 
     1118        return (*ff->desc->unpacketize)(payload, payload_len, 
     1119                                        buf, buf_len); 
     1120    } 
     1121     
     1122    return PJ_ENOTSUP; 
     1123} 
    8811124 
    8821125 
     
    8851128 */ 
    8861129static pj_status_t ffmpeg_codec_encode( pjmedia_vid_codec *codec,  
    887                                         const struct pjmedia_frame *input, 
     1130                                        const pjmedia_frame *input, 
    8881131                                        unsigned output_buf_len,  
    889                                         struct pjmedia_frame *output) 
     1132                                        pjmedia_frame *output) 
    8901133{ 
    8911134    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     
    9001143    PJ_ASSERT_RETURN(ff->enc_ctx, PJ_EINVALIDOP); 
    9011144 
    902     /* 
    903     ff->pack_frm_cnt = 0; 
    904     */ 
    9051145    avcodec_get_frame_defaults(&avframe); 
    9061146     
    907     for (i = 0; i < ff->vfi->plane_cnt; ++i) { 
     1147    for (i = 0; i < ff->enc_vfi->plane_cnt; ++i) { 
    9081148        avframe.data[i] = p; 
    909         avframe.linesize[i] = ff->vafp.strides[i]; 
    910         p += ff->vafp.plane_bytes[i]; 
     1149        avframe.linesize[i] = ff->enc_vafp.strides[i]; 
     1150        p += ff->enc_vafp.plane_bytes[i]; 
    9111151    } 
    9121152 
     
    9461186 */ 
    9471187static pj_status_t ffmpeg_codec_decode( pjmedia_vid_codec *codec,  
    948                                         const struct pjmedia_frame *input, 
     1188                                        const pjmedia_frame *input, 
    9491189                                        unsigned output_buf_len,  
    950                                         struct pjmedia_frame *output) 
     1190                                        pjmedia_frame *output) 
    9511191{ 
    9521192    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     
    9581198    PJ_ASSERT_RETURN(ff->dec_ctx, PJ_EINVALIDOP); 
    9591199 
    960     PJ_UNUSED_ARG(output_buf_len); 
     1200    /* Validate output buffer size */ 
     1201    PJ_ASSERT_RETURN(ff->dec_vafp.framebytes <= output_buf_len, PJ_ETOOSMALL); 
    9611202 
    9621203    /* Init frame to receive the decoded data, the ffmpeg codec context will 
     
    9791220     */ 
    9801221    pj_bzero(avpacket.data+avpacket.size, FF_INPUT_BUFFER_PADDING_SIZE); 
     1222 
     1223    output->bit_info = 0; 
    9811224 
    9821225#if LIBAVCODEC_VERSION_MAJOR >= 52 && LIBAVCODEC_VERSION_MINOR >= 72 
     
    9971240        return PJ_EUNKNOWN; 
    9981241    } else if (got_picture) { 
    999         pjmedia_video_apply_fmt_param *vafp = (pjmedia_video_apply_fmt_param*) 
    1000                                               &ff->vafp; 
     1242        pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp; 
    10011243        pj_uint8_t *q = (pj_uint8_t*)output->buf; 
    1002         unsigned i; 
    1003  
    1004         /* Get the decoded data */ 
    1005         for (i = 0; i < ff->vfi->plane_cnt; ++i) { 
    1006             pj_uint8_t *p = avframe.data[i]; 
    1007  
    1008             /* The decoded data may contain padding */ 
    1009             if (avframe.linesize[i]==vafp->strides[i]) { 
    1010                 /* No padding, copy the whole plane */ 
    1011                 pj_memcpy(q, p, vafp->plane_bytes[i]); 
    1012                 q += vafp->plane_bytes[i]; 
    1013             } else { 
    1014                 /* Padding exists, copy line by line */ 
    1015                 pj_uint8_t *q_end; 
    1016                  
    1017                 q_end = q+vafp->plane_bytes[i]; 
    1018                 while(q < q_end) { 
    1019                     pj_memcpy(q, p, vafp->strides[i]); 
    1020                     q += vafp->strides[i]; 
    1021                     p += avframe.linesize[i]; 
    1022                 } 
    1023             } 
    1024         } 
     1244        unsigned i; 
     1245 
     1246        /* Decoder output format is set by libavcodec, in case it is different 
     1247         * to the configured param. 
     1248         */ 
     1249        if (ff->dec_ctx->pix_fmt != ff->expected_dec_fmt || 
     1250            ff->dec_ctx->coded_width != (int)vafp->size.w || 
     1251            ff->dec_ctx->coded_height != (int)vafp->size.h) 
     1252        { 
     1253#if 0        
     1254            // it should not be the codec responsibility to do resizing 
     1255            pj_uint8_t *data[PJMEDIA_MAX_VIDEO_PLANES] = {0}; 
     1256            unsigned i; 
     1257            int h; 
     1258 
     1259            if (!ff->sws_ctx) { 
     1260                pj_assert(sws_isSupportedInput(ff->dec_ctx->pix_fmt) > 0); 
     1261                pj_assert(sws_isSupportedOutput(ff->expected_dec_fmt) > 0); 
     1262                ff->sws_ctx = sws_getContext(ff->dec_ctx->coded_width, 
     1263                                             ff->dec_ctx->coded_height, 
     1264                                             ff->dec_ctx->pix_fmt, 
     1265                                             vafp->size.w, vafp->size.h, 
     1266                                             ff->expected_dec_fmt, 
     1267                                             SWS_BILINEAR | SWS_PRINT_INFO, 
     1268                                             NULL, NULL, NULL); 
     1269                if (ff->sws_ctx == NULL) { 
     1270                    return PJ_EUNKNOWN; 
     1271                } 
     1272            } 
     1273 
     1274            for (i = 0; i < ff->vfi->plane_cnt; ++i) { 
     1275                data[i] = q; 
     1276                q += vafp->plane_bytes[i]; 
     1277            } 
     1278            h = sws_scale(ff->sws_ctx, avframe.data, avframe.linesize, 0,  
     1279                          ff->dec_ctx->coded_height, data, vafp->strides); 
     1280            pj_assert((int)vafp->size.h == h); 
     1281#endif 
     1282 
     1283            pjmedia_format_id new_fmt_id; 
     1284            pj_status_t status; 
     1285 
     1286            /* Get current raw format id from ffmpeg decoder context */ 
     1287            status = PixelFormat_to_pjmedia_format_id(ff->dec_ctx->pix_fmt,  
     1288                                                      &new_fmt_id); 
     1289            if (status != PJ_SUCCESS) 
     1290                return status; 
     1291 
     1292            /* Update decoder format in param */ 
     1293            ff->param.dec_fmt.id = new_fmt_id; 
     1294            ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->coded_width; 
     1295            ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->coded_height; 
     1296 
     1297            /* Re-init format info and apply-param of decoder */ 
     1298            ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id); 
     1299            if (!ff->dec_vfi) 
     1300                return PJ_EUNKNOWN; 
     1301            pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp)); 
     1302            ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size; 
     1303            ff->dec_vafp.buffer = NULL; 
     1304            status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp); 
     1305            if (status != PJ_SUCCESS) 
     1306                return status; 
     1307 
     1308            /* Notify application via the bit_info field of pjmedia_frame */ 
     1309            output->bit_info = PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED; 
     1310        } 
     1311 
     1312        /* Check provided buffer size after format changed */ 
     1313        if (vafp->framebytes > output_buf_len) 
     1314            return PJ_ETOOSMALL; 
     1315 
     1316        /* Get the decoded data */ 
     1317        for (i = 0; i < ff->dec_vfi->plane_cnt; ++i) { 
     1318            pj_uint8_t *p = avframe.data[i]; 
     1319 
     1320            /* The decoded data may contain padding */ 
     1321            if (avframe.linesize[i]!=vafp->strides[i]) { 
     1322                /* Padding exists, copy line by line */ 
     1323                pj_uint8_t *q_end; 
     1324                     
     1325                q_end = q+vafp->plane_bytes[i]; 
     1326                while(q < q_end) { 
     1327                    pj_memcpy(q, p, vafp->strides[i]); 
     1328                    q += vafp->strides[i]; 
     1329                    p += avframe.linesize[i]; 
     1330                } 
     1331            } else { 
     1332                /* No padding, copy the whole plane */ 
     1333                pj_memcpy(q, p, vafp->plane_bytes[i]); 
     1334                q += vafp->plane_bytes[i]; 
     1335            } 
     1336        } 
     1337 
    10251338        output->size = vafp->framebytes; 
    10261339    } else { 
     
    10361349static pj_status_t  ffmpeg_codec_recover( pjmedia_vid_codec *codec,  
    10371350                                          unsigned output_buf_len,  
    1038                                           struct pjmedia_frame *output) 
    1039 { 
    1040     ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
    1041  
     1351                                          pjmedia_frame *output) 
     1352{ 
     1353    PJ_UNUSED_ARG(codec); 
    10421354    PJ_UNUSED_ARG(output_buf_len); 
    10431355    PJ_UNUSED_ARG(output); 
    1044     PJ_UNUSED_ARG(ff); 
    1045  
    1046     return PJ_SUCCESS; 
     1356 
     1357    return PJ_ENOTSUP; 
    10471358} 
    10481359 
    10491360#ifdef _MSC_VER 
    10501361#   pragma comment( lib, "avcodec.lib") 
     1362#   pragma comment( lib, "swscale.lib") 
    10511363#endif 
    10521364 
Note: See TracChangeset for help on using the changeset viewer.