Ignore:
Timestamp:
Dec 7, 2011 10:43:28 AM (13 years ago)
Author:
nanang
Message:

Re #1234: Initial version of keyframe request/response via SIP INFO.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c

    r3893 r3901  
    7878static pj_status_t  ffmpeg_codec_get_param(pjmedia_vid_codec *codec, 
    7979                                           pjmedia_vid_codec_param *param); 
    80 static pj_status_t ffmpeg_codec_encode_begin( pjmedia_vid_codec *codec, 
    81                                               const pjmedia_frame *input, 
    82                                               unsigned out_size, 
    83                                               pjmedia_frame *output, 
    84                                               pj_bool_t *has_more); 
     80static pj_status_t ffmpeg_codec_encode_begin(pjmedia_vid_codec *codec, 
     81                                             const pjmedia_vid_encode_opt *opt, 
     82                                             const pjmedia_frame *input, 
     83                                             unsigned out_size, 
     84                                             pjmedia_frame *output, 
     85                                             pj_bool_t *has_more); 
    8586static pj_status_t ffmpeg_codec_encode_more(pjmedia_vid_codec *codec, 
    8687                                            unsigned out_size, 
     
    137138    pjmedia_vid_codec_param          param;     /**< Codec param            */ 
    138139    pj_pool_t                       *pool;      /**< Pool for each instance */ 
    139     pj_timestamp                     last_tx;   /**< Timestamp of last  
    140                                                      transmit               */ 
    141140 
    142141    /* Format info and apply format param */ 
     
    150149    void                            *enc_buf; 
    151150    unsigned                         enc_buf_size; 
     151    pj_bool_t                        enc_buf_is_keyframe; 
    152152    unsigned                         enc_frame_len; 
    153153    unsigned                         enc_processed; 
    154154    void                            *dec_buf; 
    155155    unsigned                         dec_buf_size; 
     156    pj_timestamp                     last_dec_keyframe_ts;  
    156157 
    157158    /* The ffmpeg codec states. */ 
     
    982983    /* Create pool for codec instance */ 
    983984    pool = pj_pool_create(ffmpeg_factory.pf, "ffmpeg codec", 512, 512, NULL); 
    984     codec = PJ_POOL_ALLOC_T(pool, pjmedia_vid_codec); 
     985    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec); 
    985986    if (!codec) { 
    986987        status = PJ_ENOMEM; 
    987988        goto on_error; 
    988989    } 
    989     pjmedia_vid_codec_reset(codec, PJMEDIA_SIG_VID_CODEC_FFMPEG); 
    990990    codec->op = &ffmpeg_op; 
    991991    codec->factory = factory; 
     
    13621362 */ 
    13631363static pj_status_t ffmpeg_codec_encode_whole(pjmedia_vid_codec *codec, 
     1364                                             const pjmedia_vid_encode_opt *opt, 
    13641365                                             const pjmedia_frame *input, 
    13651366                                             unsigned output_buf_len, 
     
    14021403    } 
    14031404 
     1405    /* Force keyframe */ 
     1406    if (opt && opt->force_keyframe) 
     1407        avframe.pict_type = AV_PICTURE_TYPE_I; 
     1408 
    14041409    err = avcodec_encode_video(ff->enc_ctx, out_buf, out_buf_len, &avframe); 
    14051410    if (err < 0) { 
     
    14081413    } else { 
    14091414        output->size = err; 
     1415        output->bit_info = 0; 
     1416        if (ff->enc_ctx->coded_frame->key_frame) 
     1417            output->bit_info |= PJMEDIA_VID_FRM_KEYFRAME; 
    14101418    } 
    14111419 
     
    14131421} 
    14141422 
    1415 static pj_status_t ffmpeg_codec_encode_begin( pjmedia_vid_codec *codec, 
    1416                                               const pjmedia_frame *input, 
    1417                                               unsigned out_size, 
    1418                                               pjmedia_frame *output, 
    1419                                               pj_bool_t *has_more) 
     1423static pj_status_t ffmpeg_codec_encode_begin(pjmedia_vid_codec *codec, 
     1424                                             const pjmedia_vid_encode_opt *opt, 
     1425                                             const pjmedia_frame *input, 
     1426                                             unsigned out_size, 
     1427                                             pjmedia_frame *output, 
     1428                                             pj_bool_t *has_more) 
    14201429{ 
    14211430    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     
    14251434 
    14261435    if (ff->whole) { 
    1427         status = ffmpeg_codec_encode_whole(codec, input, out_size, output); 
     1436        status = ffmpeg_codec_encode_whole(codec, opt, input, out_size, 
     1437                                           output); 
    14281438    } else { 
    14291439        pjmedia_frame whole_frm; 
     
    14341444        whole_frm.buf = ff->enc_buf; 
    14351445        whole_frm.size = ff->enc_buf_size; 
    1436         status = ffmpeg_codec_encode_whole(codec, input, 
     1446        status = ffmpeg_codec_encode_whole(codec, opt, input, 
    14371447                                           whole_frm.size, &whole_frm); 
    14381448        if (status != PJ_SUCCESS) 
    14391449            return status; 
    14401450 
     1451        ff->enc_buf_is_keyframe = (whole_frm.bit_info &  
     1452                                   PJMEDIA_VID_FRM_KEYFRAME); 
    14411453        ff->enc_frame_len = (unsigned)whole_frm.size; 
    14421454        ff->enc_processed = 0; 
     
    14541466        output->size = payload_len; 
    14551467 
     1468        if (ff->enc_buf_is_keyframe) 
     1469            output->bit_info |= PJMEDIA_VID_FRM_KEYFRAME; 
     1470 
    14561471        *has_more = (ff->enc_processed < ff->enc_frame_len); 
    14571472    } 
     
    14901505    output->size = payload_len; 
    14911506 
     1507    if (ff->enc_buf_is_keyframe) 
     1508        output->bit_info |= PJMEDIA_VID_FRM_KEYFRAME; 
     1509 
    14921510    *has_more = (ff->enc_processed < ff->enc_frame_len); 
    14931511 
     
    14951513} 
    14961514 
     1515 
     1516static pj_status_t check_decode_result(pjmedia_vid_codec *codec, 
     1517                                       const pj_timestamp *ts, 
     1518                                       pj_bool_t got_keyframe) 
     1519{ 
     1520    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; 
     1521    pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp; 
     1522    pjmedia_event event; 
     1523 
     1524    /* Check for format change. 
     1525     * Decoder output format is set by libavcodec, in case it is different 
     1526     * to the configured param. 
     1527     */ 
     1528    if (ff->dec_ctx->pix_fmt != ff->expected_dec_fmt || 
     1529        ff->dec_ctx->width != (int)vafp->size.w || 
     1530        ff->dec_ctx->height != (int)vafp->size.h) 
     1531    { 
     1532        pjmedia_format_id new_fmt_id; 
     1533        pj_status_t status; 
     1534 
     1535        /* Get current raw format id from ffmpeg decoder context */ 
     1536        status = PixelFormat_to_pjmedia_format_id(ff->dec_ctx->pix_fmt,  
     1537                                                  &new_fmt_id); 
     1538        if (status != PJ_SUCCESS) 
     1539            return status; 
     1540 
     1541        /* Update decoder format in param */ 
     1542                ff->param.dec_fmt.id = new_fmt_id; 
     1543        ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->width; 
     1544        ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->height; 
     1545        ff->expected_dec_fmt = ff->dec_ctx->pix_fmt; 
     1546 
     1547        /* Re-init format info and apply-param of decoder */ 
     1548        ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id); 
     1549        if (!ff->dec_vfi) 
     1550            return PJ_ENOTSUP; 
     1551        pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp)); 
     1552        ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size; 
     1553        ff->dec_vafp.buffer = NULL; 
     1554        status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp); 
     1555        if (status != PJ_SUCCESS) 
     1556            return status; 
     1557 
     1558        /* Realloc buffer if necessary */ 
     1559        if (ff->dec_vafp.framebytes > ff->dec_buf_size) { 
     1560            PJ_LOG(5,(THIS_FILE, "Reallocating decoding buffer %u --> %u", 
     1561                       (unsigned)ff->dec_buf_size, 
     1562                       (unsigned)ff->dec_vafp.framebytes)); 
     1563            ff->dec_buf_size = ff->dec_vafp.framebytes; 
     1564            ff->dec_buf = pj_pool_alloc(ff->pool, ff->dec_buf_size); 
     1565        } 
     1566 
     1567        /* Broadcast format changed event */ 
     1568        pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED, ts, codec); 
     1569        event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING; 
     1570        pj_memcpy(&event.data.fmt_changed.new_fmt, &ff->param.dec_fmt, 
     1571                  sizeof(ff->param.dec_fmt)); 
     1572        pjmedia_event_publish(NULL, codec, &event, 0); 
     1573    } 
     1574 
     1575    /* Check for missing/found keyframe */ 
     1576    if (got_keyframe) { 
     1577        pj_get_timestamp(&ff->last_dec_keyframe_ts); 
     1578 
     1579        /* Broadcast keyframe event */ 
     1580        pjmedia_event_init(&event, PJMEDIA_EVENT_KEYFRAME_FOUND, ts, codec); 
     1581        pjmedia_event_publish(NULL, codec, &event, 0); 
     1582    } else if (ff->last_dec_keyframe_ts.u64 == 0) { 
     1583        /* Broadcast missing keyframe event */ 
     1584        pjmedia_event_init(&event, PJMEDIA_EVENT_KEYFRAME_MISSING, ts, codec); 
     1585        pjmedia_event_publish(NULL, codec, &event, 0); 
     1586    } 
     1587 
     1588    return PJ_SUCCESS; 
     1589} 
    14971590 
    14981591/* 
     
    15581651#endif 
    15591652    if (err < 0) { 
     1653        pjmedia_event event; 
     1654 
    15601655        output->type = PJMEDIA_FRAME_TYPE_NONE; 
    15611656        output->size = 0; 
    15621657        print_ffmpeg_err(err); 
    1563         return PJMEDIA_CODEC_EFAILED; 
     1658 
     1659        /* Broadcast missing keyframe event */ 
     1660        pjmedia_event_init(&event, PJMEDIA_EVENT_KEYFRAME_MISSING, 
     1661                           &input->timestamp, codec); 
     1662        pjmedia_event_publish(NULL, codec, &event, 0); 
     1663 
     1664        return PJMEDIA_CODEC_EBADBITSTREAM; 
    15641665    } else if (got_picture) { 
    15651666        pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp; 
    15661667        pj_uint8_t *q = (pj_uint8_t*)output->buf; 
    15671668        unsigned i; 
    1568  
    1569         /* Decoder output format is set by libavcodec, in case it is different 
    1570          * to the configured param. 
     1669        pj_status_t status; 
     1670 
     1671        /* Check decoding result, e.g: see if the format got changed, 
     1672         * keyframe found/missing. 
    15711673         */ 
    1572         if (ff->dec_ctx->pix_fmt != ff->expected_dec_fmt || 
    1573             ff->dec_ctx->width != (int)vafp->size.w || 
    1574             ff->dec_ctx->height != (int)vafp->size.h) 
    1575         { 
    1576             pjmedia_format_id new_fmt_id; 
    1577             pj_status_t status; 
    1578  
    1579             /* Get current raw format id from ffmpeg decoder context */ 
    1580             status = PixelFormat_to_pjmedia_format_id(ff->dec_ctx->pix_fmt,  
    1581                                                       &new_fmt_id); 
    1582             if (status != PJ_SUCCESS) 
    1583                 return status; 
    1584  
    1585             /* Update decoder format in param */ 
    1586             ff->param.dec_fmt.id = new_fmt_id; 
    1587             ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->width; 
    1588             ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->height; 
    1589             ff->expected_dec_fmt = ff->dec_ctx->pix_fmt; 
    1590  
    1591             /* Re-init format info and apply-param of decoder */ 
    1592             ff->dec_vfi = pjmedia_get_video_format_info(NULL, ff->param.dec_fmt.id); 
    1593             if (!ff->dec_vfi) 
    1594                 return PJ_ENOTSUP; 
    1595             pj_bzero(&ff->dec_vafp, sizeof(ff->dec_vafp)); 
    1596             ff->dec_vafp.size = ff->param.dec_fmt.det.vid.size; 
    1597             ff->dec_vafp.buffer = NULL; 
    1598             status = (*ff->dec_vfi->apply_fmt)(ff->dec_vfi, &ff->dec_vafp); 
    1599             if (status != PJ_SUCCESS) 
    1600                 return status; 
    1601  
    1602             /* Realloc buffer if necessary */ 
    1603             if (ff->dec_vafp.framebytes > ff->dec_buf_size) { 
    1604                 PJ_LOG(5,(THIS_FILE, "Reallocating decoding buffer %u --> %u", 
    1605                            (unsigned)ff->dec_buf_size, 
    1606                            (unsigned)ff->dec_vafp.framebytes)); 
    1607                 ff->dec_buf_size = ff->dec_vafp.framebytes; 
    1608                 ff->dec_buf = pj_pool_alloc(ff->pool, ff->dec_buf_size); 
    1609             } 
    1610  
    1611             /* Broadcast event */ 
    1612             { 
    1613                 pjmedia_event event; 
    1614  
    1615                 pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED, 
    1616                                    &input->timestamp, codec); 
    1617                 event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING; 
    1618                 pj_memcpy(&event.data.fmt_changed.new_fmt, &ff->param.dec_fmt, 
    1619                           sizeof(ff->param.dec_fmt)); 
    1620                 pjmedia_event_publish(NULL, codec, &event, 0); 
    1621             } 
    1622         } 
     1674        status = check_decode_result(codec, &input->timestamp, 
     1675                                     avframe.key_frame); 
     1676        if (status != PJ_SUCCESS) 
     1677            return status; 
    16231678 
    16241679        /* Check provided buffer size */ 
     
    16501705        output->type = PJMEDIA_FRAME_TYPE_VIDEO; 
    16511706        output->size = vafp->framebytes; 
    1652  
    1653         /* Check if we got key frame */ 
    1654         if (avframe.key_frame) 
    1655         { 
    1656             pjmedia_event event; 
    1657  
    1658             pjmedia_event_init(&event, PJMEDIA_EVENT_KEY_FRAME_FOUND, 
    1659                                &output->timestamp, codec); 
    1660             pjmedia_event_publish(NULL, codec, &event, 0); 
    1661         } 
    16621707    } else { 
    16631708        output->type = PJMEDIA_FRAME_TYPE_NONE; 
Note: See TracChangeset for help on using the changeset viewer.