Changeset 3901


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.

Location:
pjproject/trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/errno.h

    r3664 r3901  
    347347 */ 
    348348#define PJMEDIA_CODEC_EINMODE       (PJMEDIA_ERRNO_START+86)    /* 220086 */ 
     349/** 
     350 * @hideinitializer 
     351 * Bad or corrupted bitstream. 
     352 */ 
     353#define PJMEDIA_CODEC_EBADBITSTREAM (PJMEDIA_ERRNO_START+87)    /* 220087 */ 
    349354 
    350355 
  • pjproject/trunk/pjmedia/include/pjmedia/event.h

    r3893 r3901  
    7171 
    7272    /** 
    73      * Video key frame has just been decoded event. 
    74      */ 
    75     PJMEDIA_EVENT_KEY_FRAME_FOUND = PJMEDIA_FOURCC('I', 'F', 'R', 'F'), 
    76  
    77     /** 
    78      * Video decoding error due to missing key frame event. 
    79      */ 
    80     PJMEDIA_EVENT_KEY_FRAME_MISSING = PJMEDIA_FOURCC('I', 'F', 'R', 'M'), 
     73     * Video keyframe has just been decoded event. 
     74     */ 
     75    PJMEDIA_EVENT_KEYFRAME_FOUND = PJMEDIA_FOURCC('I', 'F', 'R', 'F'), 
     76 
     77    /** 
     78     * Video decoding error due to missing keyframe event. 
     79     */ 
     80    PJMEDIA_EVENT_KEYFRAME_MISSING = PJMEDIA_FOURCC('I', 'F', 'R', 'M'), 
    8181 
    8282    /** 
     
    136136typedef pjmedia_event_dummy_data pjmedia_event_mouse_btn_down_data; 
    137137 
    138 /** Additional parameters for key frame found event */ 
    139 typedef pjmedia_event_dummy_data pjmedia_event_key_frame_found_data; 
    140  
    141 /** Additional parameters for key frame missing event */ 
    142 typedef pjmedia_event_dummy_data pjmedia_event_key_frame_missing_data; 
     138/** Additional parameters for keyframe found event */ 
     139typedef pjmedia_event_dummy_data pjmedia_event_keyframe_found_data; 
     140 
     141/** Additional parameters for keyframe missing event */ 
     142typedef pjmedia_event_dummy_data pjmedia_event_keyframe_missing_data; 
    143143 
    144144/** 
     
    206206        pjmedia_event_mouse_btn_down_data       mouse_btn_down; 
    207207 
    208         /** Key frame found event data */ 
    209         pjmedia_event_key_frame_found_data      key_frm_found; 
    210  
    211         /** Key frame missing event data */ 
    212         pjmedia_event_key_frame_missing_data    key_frm_missing; 
     208        /** Keyframe found event data */ 
     209        pjmedia_event_keyframe_found_data       keyframe_found; 
     210 
     211        /** Keyframe missing event data */ 
     212        pjmedia_event_keyframe_missing_data     keyframe_missing; 
    213213 
    214214        /** Storage for user event data */ 
  • pjproject/trunk/pjmedia/include/pjmedia/vid_codec.h

    r3893 r3901  
    7676 
    7777} pjmedia_vid_packing; 
     78 
     79 
     80/** 
     81 * Enumeration of video frame info flag for the bit_info field in the 
     82 * pjmedia_frame. 
     83 */ 
     84typedef enum pjmedia_vid_frm_bit_info 
     85{ 
     86    /** 
     87     * The video frame is keyframe. 
     88     */ 
     89    PJMEDIA_VID_FRM_KEYFRAME    = 1 
     90 
     91} pjmedia_vid_frm_bit_info; 
     92 
     93 
     94/** 
     95 * Encoding option. 
     96 */ 
     97typedef struct pjmedia_vid_encode_opt 
     98{ 
     99    /** 
     100     * Flag to force the encoder to generate keyframe for the specified input 
     101     * frame. When this flag is set, application can verify the result by 
     102     * examining PJMEDIA_VID_FRM_KEYFRAME flag in the bit_info field of the 
     103     * output frame. 
     104     */ 
     105    pj_bool_t force_keyframe; 
     106 
     107} pjmedia_vid_encode_opt; 
     108 
    78109 
    79110/**  
     
    179210     * See #pjmedia_vid_codec_modify(). 
    180211     */ 
    181     pj_status_t (*modify)(pjmedia_vid_codec *codec,  
     212    pj_status_t (*modify)(pjmedia_vid_codec *codec, 
    182213                          const pjmedia_vid_codec_param *param); 
    183214 
     
    192223     */ 
    193224    pj_status_t (*encode_begin)(pjmedia_vid_codec *codec, 
     225                                const pjmedia_vid_encode_opt *opt, 
    194226                                const pjmedia_frame *input, 
    195227                                unsigned out_size, 
     
    364396 
    365397/** 
    366  * Initialize pjmedia_vid_codec structure with default values. 
    367  * 
    368  * @param codec     The codec to be initialized. 
    369  * @param sig       Codec's object signature (see signatures.h) 
    370  */ 
    371 PJ_DECL(void) pjmedia_vid_codec_reset(pjmedia_vid_codec *codec, 
    372                                       pjmedia_obj_sig sig); 
    373  
    374 /** 
    375398 * Initialize codec manager. If there is no the default video codec manager, 
    376399 * this function will automatically set the default video codec manager to 
     
    729752 * 
    730753 * @param codec         The codec instance. 
     754 * @param opt           Optional encoding options. 
    731755 * @param input         The input frame. 
    732756 * @param out_size      The length of buffer in the output frame. This 
     
    742766PJ_INLINE(pj_status_t) 
    743767pjmedia_vid_codec_encode_begin( pjmedia_vid_codec *codec, 
     768                                const pjmedia_vid_encode_opt *opt, 
    744769                                const pjmedia_frame *input, 
    745770                                unsigned out_size, 
     
    747772                                pj_bool_t *has_more) 
    748773{ 
    749     return (*codec->op->encode_begin)(codec, input, out_size, output, 
     774    return (*codec->op->encode_begin)(codec, opt, input, out_size, output, 
    750775                                      has_more); 
    751776} 
  • pjproject/trunk/pjmedia/include/pjmedia/vid_stream.h

    r3786 r3901  
    299299 
    300300/** 
    301  * Pause the individual channel in the stream. 
    302  * 
    303  * @param stream        The video channel. 
    304  * @param dir           Which direction to pause. 
     301 * Pause stream channels. 
     302 * 
     303 * @param stream        The video stream. 
     304 * @param dir           Which channel direction to pause. 
    305305 * 
    306306 * @return              PJ_SUCCESS on success. 
     
    310310 
    311311/** 
    312  * Resume the individual channel in the stream. 
    313  * 
    314  * @param stream        The video channel. 
    315  * @param dir           Which direction to resume. 
     312 * Resume stream channels. 
     313 * 
     314 * @param stream        The video stream. 
     315 * @param dir           Which channel direction to resume. 
    316316 * 
    317317 * @return              PJ_SUCCESS on success; 
     
    322322 
    323323/** 
     324 * Force stream to send video keyframe on the next transmission. 
     325 * 
     326 * @param stream        The video stream. 
     327 * 
     328 * @return              PJ_SUCCESS on success; 
     329 */ 
     330PJ_DECL(pj_status_t) pjmedia_vid_stream_send_keyframe( 
     331                                                pjmedia_vid_stream *stream); 
     332 
     333 
     334/** 
    324335 * @} 
    325336 */ 
  • 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; 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/colorbar_dev.c

    r3893 r3901  
    578578    struct cbar_stream *stream = (struct cbar_stream*)strm; 
    579579 
     580    frame->type = PJMEDIA_FRAME_TYPE_VIDEO; 
     581    frame->bit_info = 0; 
    580582    frame->timestamp = stream->ts; 
    581583    stream->ts.u64 += stream->ts_inc; 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/dshow_dev.c

    r3893 r3901  
    578578    } 
    579579 
    580     frame.type = PJMEDIA_TYPE_VIDEO; 
     580    frame.type = PJMEDIA_FRAME_TYPE_VIDEO; 
    581581    IMediaSample_GetPointer(pMediaSample, (BYTE **)&frame.buf); 
    582582    frame.size = IMediaSample_GetActualDataLength(pMediaSample); 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/ios_dev.m

    r3750 r3901  
    361361    CVPixelBufferLockBaseAddress(imageBuffer, 0);  
    362362     
    363     frame.type = PJMEDIA_TYPE_VIDEO; 
     363    frame.type = PJMEDIA_FRAME_TYPE_VIDEO; 
    364364    frame.buf = CVPixelBufferGetBaseAddress(imageBuffer); 
    365365    frame.size = stream->frame_size; 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/qt_dev.m

    r3736 r3901  
    372372        return; 
    373373     
    374     frame.type = PJMEDIA_TYPE_VIDEO; 
     374    frame.type = PJMEDIA_FRAME_TYPE_VIDEO; 
    375375    frame.buf = [sampleBuffer bytesForAllSamples]; 
    376376    frame.size = size; 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/v4l2_dev.c

    r3895 r3901  
    691691 
    692692    frame->type = PJMEDIA_FRAME_TYPE_VIDEO; 
     693    frame->bit_info = 0; 
    693694    frame->size = buf.bytesused; 
    694695    frame->timestamp.u64 = PJ_UINT64(1) * PJ_TIME_VAL_MSEC(time) * 
  • pjproject/trunk/pjmedia/src/pjmedia/errno.c

    r3664 r3901  
    105105    PJ_BUILD_ERR( PJMEDIA_CODEC_EPCMFRMINLEN,   "Invalid PCM frame length" ), 
    106106    PJ_BUILD_ERR( PJMEDIA_CODEC_EINMODE,        "Invalid codec mode (no fmtp?)" ), 
     107    PJ_BUILD_ERR( PJMEDIA_CODEC_EBADBITSTREAM,  "Bad or corrupted bitstream" ), 
    107108 
    108109    /* Media errors. */ 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_codec.c

    r3893 r3901  
    7171static void sort_codecs(pjmedia_vid_codec_mgr *mgr); 
    7272 
    73 /* 
    74  * Initialize pjmedia_vid_codec structure with default values. 
    75  */ 
    76 PJ_DEF(void) pjmedia_vid_codec_reset(pjmedia_vid_codec *codec, 
    77                                     pjmedia_obj_sig sig) 
    78 { 
    79     pj_bzero(codec, sizeof(*codec)); 
    80 } 
    8173 
    8274/* 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c

    r3898 r3901  
    6969#endif 
    7070 
     71 
    7172/** 
    7273 * Media channel. 
     
    124125    pjmedia_event            fmt_event;     /**< Buffered fmt_changed event 
    125126                                                 to avoid deadlock          */ 
     127    pjmedia_event            miss_keyframe_event;  
     128                                            /**< Buffered missing keyframe 
     129                                                 event for delayed republish*/ 
    126130 
    127131    unsigned                 frame_size;    /**< Size of encoded base frame.*/ 
     
    131135    pjmedia_frame           *rx_frames;     /**< Temp. buffer for incoming 
    132136                                                 frame assembly.            */ 
     137 
     138    pj_bool_t                force_keyframe;/**< Forced to encode keyframe? */ 
    133139 
    134140#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 
     
    352358            pj_memcpy(&stream->fmt_event, event, sizeof(*event)); 
    353359            return PJ_SUCCESS; 
     360 
     361        case PJMEDIA_EVENT_KEYFRAME_MISSING: 
     362            /* Republish this event later from get_frame(). */ 
     363            pj_memcpy(&stream->miss_keyframe_event, event, sizeof(*event)); 
     364            return PJ_SUCCESS; 
     365 
    354366        default: 
    355367            break; 
     
    764776    pj_bool_t has_more_data = PJ_FALSE; 
    765777    pj_size_t total_sent = 0; 
    766  
     778    pjmedia_vid_encode_opt enc_opt; 
    767779 
    768780#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0 
     
    797809    frame_out.size = 0; 
    798810 
     811    /* Init encoding option */ 
     812    pj_bzero(&enc_opt, sizeof(enc_opt)); 
     813    if (stream->force_keyframe) { 
     814        /* Force encoder to generate keyframe */ 
     815        enc_opt.force_keyframe = PJ_TRUE; 
     816        stream->force_keyframe = PJ_FALSE; 
     817        TRC_((channel->port.info.name.ptr, 
     818              "Forcing encoder to generate keyframe")); 
     819    } 
     820 
    799821    /* Encode! */ 
    800     status = pjmedia_vid_codec_encode_begin(stream->codec, frame, 
     822    status = pjmedia_vid_codec_encode_begin(stream->codec, &enc_opt, frame, 
    801823                                            channel->buf_size - 
    802824                                               sizeof(pjmedia_rtp_hdr), 
     
    10801102    } 
    10811103 
     1104    if (stream->miss_keyframe_event.type != PJMEDIA_EVENT_NONE) { 
     1105        pjmedia_event_publish(NULL, port, &stream->miss_keyframe_event, 
     1106                              PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     1107        stream->miss_keyframe_event.type = PJMEDIA_EVENT_NONE; 
     1108    } 
     1109 
    10821110    pj_mutex_lock( stream->jb_mutex ); 
    10831111 
     
    14251453 
    14261454    /* Set up jitter buffer */ 
    1427     pjmedia_jbuf_set_adaptive( stream->jb, jb_init, jb_min_pre, jb_max_pre); 
    1428     //pjmedia_jbuf_enable_discard(stream->jb, PJ_FALSE); 
     1455    pjmedia_jbuf_set_adaptive(stream->jb, jb_init, jb_min_pre, jb_max_pre); 
     1456    pjmedia_jbuf_set_discard(stream->jb, PJMEDIA_JB_DISCARD_NONE); 
    14291457 
    14301458    /* Init RTCP session: */ 
     
    20912119} 
    20922120 
     2121 
     2122/* 
     2123 * Force stream to send video keyframe. 
     2124 */ 
     2125PJ_DEF(pj_status_t) pjmedia_vid_stream_send_keyframe( 
     2126                                                pjmedia_vid_stream *stream) 
     2127{ 
     2128    PJ_ASSERT_RETURN(stream, PJ_EINVAL); 
     2129 
     2130    if (!pjmedia_vid_stream_is_running(stream, PJMEDIA_DIR_ENCODING)) 
     2131        return PJ_EINVALIDOP; 
     2132 
     2133    stream->force_keyframe = PJ_TRUE; 
     2134 
     2135    return PJ_SUCCESS; 
     2136} 
     2137 
     2138 
    20932139#endif /* PJMEDIA_HAS_VIDEO */ 
  • pjproject/trunk/pjmedia/src/test/vid_codec_test.c

    r3893 r3901  
    9595    enc_frames[enc_cnt].size = enc_size_left; 
    9696 
    97     status = pjmedia_vid_codec_encode_begin(codec, frame, enc_size_left, 
     97    status = pjmedia_vid_codec_encode_begin(codec, NULL, frame, enc_size_left, 
    9898                                            &enc_frames[enc_cnt], &has_more); 
    9999    if (status != PJ_SUCCESS) goto on_error; 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r3894 r3901  
    26342634         * Handle INFO method. 
    26352635         */ 
    2636         if (tsx->role == PJSIP_ROLE_UAC &&  
     2636        const pj_str_t STR_APPLICATION = { "application", 11}; 
     2637        const pj_str_t STR_DTMF_RELAY  = { "dtmf-relay", 10 }; 
     2638        pjsip_msg_body *body = NULL; 
     2639        pj_bool_t dtmf_info = PJ_FALSE; 
     2640         
     2641        if (tsx->role == PJSIP_ROLE_UAC) { 
     2642            if (e->body.tsx_state.type == PJSIP_EVENT_TX_MSG) 
     2643                body = e->body.tsx_state.src.tdata->msg->body; 
     2644            else 
     2645                body = e->body.tsx_state.tsx->last_tx->msg->body; 
     2646        } else { 
     2647            if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) 
     2648                body = e->body.tsx_state.src.rdata->msg_info.msg->body; 
     2649        } 
     2650         
     2651        /* Check DTMF content in the INFO message */ 
     2652        if (body && body->len && 
     2653            pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 && 
     2654            pj_stricmp(&body->content_type.subtype, &STR_DTMF_RELAY)==0) 
     2655        { 
     2656            dtmf_info = PJ_TRUE; 
     2657        } 
     2658 
     2659        if (dtmf_info && tsx->role == PJSIP_ROLE_UAC &&  
    26372660            (tsx->state == PJSIP_TSX_STATE_COMPLETED || 
    26382661               (tsx->state == PJSIP_TSX_STATE_TERMINATED && 
     
    26522675                          tsx->status_text.ptr)); 
    26532676            } 
    2654         } else if (tsx->role == PJSIP_ROLE_UAS && 
     2677        } else if (dtmf_info && tsx->role == PJSIP_ROLE_UAS && 
    26552678                   tsx->state == PJSIP_TSX_STATE_TRYING) 
    26562679        { 
     
    28832906        if (vid_idx == -1 || call_info.media[vid_idx].dir == PJMEDIA_DIR_NONE) { 
    28842907            PJ_LOG(3,(THIS_FILE, 
    2885                       "Just rejected incoming video offer on call %d" 
    2886                       "use \"vid call add\" to enable video!", 
    2887                       call_id)); 
     2908                      "Just rejected incoming video offer on call %d, " 
     2909                      "use \"vid call enable %d\" or \"vid call add\" to enable video!", 
     2910                      call_id, vid_idx)); 
    28882911        } 
    28892912    } 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3891 r3901  
    331331#   define PJSUA_HAS_VIDEO              PJMEDIA_HAS_VIDEO 
    332332#endif 
     333 
     334 
     335/** 
     336 * Interval between two keyframe requests, in milliseconds. 
     337 * 
     338 * Default: 500 ms 
     339 */ 
     340#ifndef PJSUA_VID_REQ_KEYFRAME_INTERVAL 
     341#   define PJSUA_VID_REQ_KEYFRAME_INTERVAL      500 
     342#endif 
     343 
    333344 
    334345/** 
     
    33723383 
    33733384/** 
     3385 * Enumeration of video keyframe request methods. Keyframe request is 
     3386 * triggered by decoder, usually when the incoming video stream cannot 
     3387 * be decoded properly due to missing video keyframe. 
     3388 */ 
     3389typedef enum pjsua_vid_req_keyframe_method 
     3390{ 
     3391    /** 
     3392     * Requesting keyframe via SIP INFO message. Note that incoming keyframe 
     3393     * request via SIP INFO will always be handled even if this flag is unset. 
     3394     */ 
     3395    PJSUA_VID_REQ_KEYFRAME_SIP_INFO     = 1, 
     3396 
     3397    /** 
     3398     * Requesting keyframe via Picture Loss Indication of RTCP feedback. 
     3399     * This is currently not supported. 
     3400     */ 
     3401    PJSUA_VID_REQ_KEYFRAME_RTCP_PLI     = 2 
     3402 
     3403} pjsua_vid_req_keyframe_method; 
     3404 
     3405 
     3406/** 
    33743407 * Call settings. 
    33753408 */ 
     
    33773410{ 
    33783411    /** 
    3379      * Bitmask of pjsua_call_flag constants. 
     3412     * Bitmask of #pjsua_call_flag constants. 
    33803413     * 
    33813414     * Default: 0 
    33823415     */ 
    33833416    unsigned         flag; 
     3417 
     3418    /** 
     3419     * This flag controls what methods to request keyframe are allowed on 
     3420     * the call. Value is bitmask of #pjsua_vid_req_keyframe_method. 
     3421     */ 
     3422    unsigned         req_keyframe_method; 
    33843423 
    33853424    /** 
     
    36493688     */ 
    36503689    PJSUA_CALL_VID_STRM_STOP_TRANSMIT, 
     3690 
     3691    /** 
     3692     * Send keyframe in the video stream. This will force the stream to 
     3693     * generate and send video keyframe as soon as possible. No 
     3694     * re-INVITE/UPDATE is to be transmitted to remote with this operation. 
     3695     */ 
     3696    PJSUA_CALL_VID_STRM_SEND_KEYFRAME 
    36513697 
    36523698} pjsua_call_vid_strm_op; 
     
    46644710extern const pjsip_method pjsip_message_method; 
    46654711 
     4712 
     4713/** 
     4714 * The INFO method (defined in pjsua_call.c) 
     4715 */ 
     4716extern const pjsip_method pjsip_info_method; 
    46664717 
    46674718 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r3893 r3901  
    8585                                            address)                        */ 
    8686    pjmedia_srtp_use     rem_srtp_use; /**< Remote's SRTP usage policy.     */ 
     87    pj_timestamp         last_req_keyframe;/**< Last TX keyframe request.   */ 
    8788 
    8889    pjsua_med_tp_state_cb      med_init_cb;/**< Media transport 
     
    478479} pjsua_im_data; 
    479480 
     481pj_status_t pjsua_media_apply_xml_control(pjsua_call_id call_id, 
     482                                          const pj_str_t *xml_st); 
     483 
    480484 
    481485/** 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r3892 r3901  
    3535#define LOCK_CODEC_MAX_RETRY         5 
    3636 
     37 
     38/* 
     39 * The INFO method. 
     40 */ 
     41const pjsip_method pjsip_info_method =  
     42{ 
     43    PJSIP_OTHER_METHOD, 
     44    { "INFO", 4 } 
     45}; 
     46 
     47 
    3748/* This callback receives notification from invite session when the 
    3849 * session state has changed. 
     
    501512#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) 
    502513    opt->video_cnt = 1; 
    503     //{ 
    504     //  unsigned i; 
    505     //  for (i = 0; i < PJ_ARRAY_SIZE(opt->vid_cap_dev); ++i) 
    506     //      opt->vid_cap_dev[i] = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 
    507     //} 
     514    opt->req_keyframe_method = PJSUA_VID_REQ_KEYFRAME_SIP_INFO | 
     515                             PJSUA_VID_REQ_KEYFRAME_RTCP_PLI; 
    508516#endif 
    509517} 
     
    41914199                      call->index, tsx->status_code)); 
    41924200        } 
     4201    } else if (tsx->role==PJSIP_ROLE_UAS && 
     4202        tsx->state==PJSIP_TSX_STATE_TRYING && 
     4203        pjsip_method_cmp(&tsx->method, &pjsip_info_method)==0) 
     4204    { 
     4205        /* 
     4206         * Incoming INFO request for media control. 
     4207         */ 
     4208        const pj_str_t STR_APPLICATION       = { "application", 11}; 
     4209        const pj_str_t STR_MEDIA_CONTROL_XML = { "media_control+xml", 17 }; 
     4210        pjsip_rx_data *rdata = e->body.tsx_state.src.rdata; 
     4211        pjsip_msg_body *body = rdata->msg_info.msg->body; 
     4212 
     4213        if (body && body->len && 
     4214            pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 && 
     4215            pj_stricmp(&body->content_type.subtype, &STR_MEDIA_CONTROL_XML)==0) 
     4216        { 
     4217            pjsip_tx_data *tdata; 
     4218            pj_str_t control_st; 
     4219            pj_status_t status; 
     4220 
     4221            /* Apply and answer the INFO request */ 
     4222            pj_strset(&control_st, (char*)body->data, body->len); 
     4223            status = pjsua_media_apply_xml_control(call->index, &control_st); 
     4224            if (status == PJ_SUCCESS) { 
     4225                status = pjsip_endpt_create_response(tsx->endpt, rdata, 
     4226                                                     200, NULL, &tdata); 
     4227                if (status == PJ_SUCCESS) 
     4228                    status = pjsip_tsx_send_msg(tsx, tdata); 
     4229            } else { 
     4230                status = pjsip_endpt_create_response(tsx->endpt, rdata, 
     4231                                                     400, NULL, &tdata); 
     4232                if (status == PJ_SUCCESS) 
     4233                    status = pjsip_tsx_send_msg(tsx, tdata); 
     4234            } 
     4235        } 
    41934236    } 
    41944237 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r3893 r3901  
    12591259    pjsua_call_media *call_med = (pjsua_call_media*)user_data; 
    12601260    pjsua_call *call = call_med->call; 
     1261    pj_status_t status = PJ_SUCCESS; 
     1262   
     1263    switch(event->type) { 
     1264        case PJMEDIA_EVENT_KEYFRAME_MISSING: 
     1265            if (call->opt.req_keyframe_method & PJSUA_VID_REQ_KEYFRAME_SIP_INFO) 
     1266            { 
     1267                pj_timestamp now; 
     1268 
     1269                pj_get_timestamp(&now); 
     1270                if (pj_elapsed_msec(&call_med->last_req_keyframe, &now) >= 
     1271                    PJSUA_VID_REQ_KEYFRAME_INTERVAL) 
     1272                { 
     1273                    pjsua_msg_data msg_data; 
     1274                    const pj_str_t SIP_INFO = {"INFO", 4}; 
     1275                    const char *BODY_TYPE = "application/media_control+xml"; 
     1276                    const char *BODY = 
     1277                        "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" 
     1278                        "<media_control><vc_primitive><to_encoder>" 
     1279                        "<picture_fast_update/>" 
     1280                        "</to_encoder></vc_primitive></media_control>"; 
     1281 
     1282                    PJ_LOG(4,(THIS_FILE,  
     1283                              "Sending video keyframe request via SIP INFO")); 
     1284 
     1285                    pjsua_msg_data_init(&msg_data); 
     1286                    pj_cstr(&msg_data.content_type, BODY_TYPE); 
     1287                    pj_cstr(&msg_data.msg_body, BODY); 
     1288                    status = pjsua_call_send_request(call->index, &SIP_INFO,  
     1289                                                     &msg_data); 
     1290                    if (status != PJ_SUCCESS) { 
     1291                        pj_perror(3, THIS_FILE, status, 
     1292                                  "Failed requesting keyframe via SIP INFO"); 
     1293                    } else { 
     1294                        call_med->last_req_keyframe = now; 
     1295                    } 
     1296                } 
     1297            } 
     1298            break; 
     1299 
     1300        default: 
     1301            break; 
     1302    } 
    12611303 
    12621304    if (pjsua_var.ua_cfg.cb.on_call_media_event && call) { 
     
    12651307    } 
    12661308 
    1267     return PJ_SUCCESS; 
     1309    return status; 
    12681310} 
    12691311 
     
    41884230 
    41894231 
     4232pj_status_t pjsua_media_apply_xml_control(pjsua_call_id call_id, 
     4233                                          const pj_str_t *xml_st) 
     4234{ 
     4235    pjsua_call *call = &pjsua_var.calls[call_id]; 
     4236    const pj_str_t PICT_FAST_UPDATE = {"picture_fast_update", 19}; 
     4237 
     4238#if PJMEDIA_HAS_VIDEO 
     4239    if (pj_strstr(xml_st, &PICT_FAST_UPDATE)) { 
     4240        unsigned i; 
     4241 
     4242        PJ_LOG(4,(THIS_FILE, "Received keyframe request via SIP INFO")); 
     4243 
     4244        for (i = 0; i < call->med_cnt; ++i) { 
     4245            pjsua_call_media *cm = &call->media[i]; 
     4246            if (cm->type != PJMEDIA_TYPE_VIDEO || !cm->strm.v.stream) 
     4247                continue; 
     4248 
     4249            pjmedia_vid_stream_send_keyframe(cm->strm.v.stream); 
     4250        } 
     4251 
     4252        return PJ_SUCCESS; 
     4253    } 
     4254#endif 
     4255 
     4256    /* Just to avoid compiler warning of unused var */ 
     4257    PJ_UNUSED_ARG(xml_st); 
     4258 
     4259    return PJ_ENOTSUP; 
     4260} 
     4261 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c

    r3893 r3901  
    20012001 
    20022002 
     2003static pj_status_t call_send_vid_keyframe(pjsua_call *call, 
     2004                                          int med_idx) 
     2005{ 
     2006    pjsua_call_media *call_med; 
     2007 
     2008    /* Verify and normalize media index */ 
     2009    if (med_idx == -1) { 
     2010        int first_active; 
     2011         
     2012        call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL); 
     2013        if (first_active == -1) 
     2014            return PJ_ENOTFOUND; 
     2015 
     2016        med_idx = first_active; 
     2017    } 
     2018 
     2019    call_med = &call->media[med_idx]; 
     2020 
     2021    /* Verify media type and stream instance. */ 
     2022    if (call_med->type != PJMEDIA_TYPE_VIDEO || !call_med->strm.v.stream) 
     2023        return PJ_EINVAL; 
     2024 
     2025    return pjmedia_vid_stream_send_keyframe(call_med->strm.v.stream); 
     2026} 
     2027 
     2028 
    20032029/* 
    20042030 * Start, stop, and/or manipulate video transmission for the specified call. 
     
    20702096        status = call_set_tx_video(call, param_.med_idx, PJ_FALSE); 
    20712097        break; 
     2098    case PJSUA_CALL_VID_STRM_SEND_KEYFRAME: 
     2099        status = call_send_vid_keyframe(call, param_.med_idx); 
     2100        break; 
    20722101    default: 
    20732102        status = PJ_EINVALIDOP; 
Note: See TracChangeset for help on using the changeset viewer.