Changeset 3901 for pjproject/trunk
- Timestamp:
- Dec 7, 2011 10:43:28 AM (13 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/errno.h
r3664 r3901 347 347 */ 348 348 #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 */ 349 354 350 355 -
pjproject/trunk/pjmedia/include/pjmedia/event.h
r3893 r3901 71 71 72 72 /** 73 * Video key 74 */ 75 PJMEDIA_EVENT_KEY _FRAME_FOUND = PJMEDIA_FOURCC('I', 'F', 'R', 'F'),76 77 /** 78 * Video decoding error due to missing key 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'), 81 81 82 82 /** … … 136 136 typedef pjmedia_event_dummy_data pjmedia_event_mouse_btn_down_data; 137 137 138 /** Additional parameters for key 139 typedef pjmedia_event_dummy_data pjmedia_event_key _frame_found_data;140 141 /** Additional parameters for key 142 typedef pjmedia_event_dummy_data pjmedia_event_key _frame_missing_data;138 /** Additional parameters for keyframe found event */ 139 typedef pjmedia_event_dummy_data pjmedia_event_keyframe_found_data; 140 141 /** Additional parameters for keyframe missing event */ 142 typedef pjmedia_event_dummy_data pjmedia_event_keyframe_missing_data; 143 143 144 144 /** … … 206 206 pjmedia_event_mouse_btn_down_data mouse_btn_down; 207 207 208 /** Key 209 pjmedia_event_key _frame_found_data key_frm_found;210 211 /** Key 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; 213 213 214 214 /** Storage for user event data */ -
pjproject/trunk/pjmedia/include/pjmedia/vid_codec.h
r3893 r3901 76 76 77 77 } pjmedia_vid_packing; 78 79 80 /** 81 * Enumeration of video frame info flag for the bit_info field in the 82 * pjmedia_frame. 83 */ 84 typedef 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 */ 97 typedef 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 78 109 79 110 /** … … 179 210 * See #pjmedia_vid_codec_modify(). 180 211 */ 181 pj_status_t (*modify)(pjmedia_vid_codec *codec, 212 pj_status_t (*modify)(pjmedia_vid_codec *codec, 182 213 const pjmedia_vid_codec_param *param); 183 214 … … 192 223 */ 193 224 pj_status_t (*encode_begin)(pjmedia_vid_codec *codec, 225 const pjmedia_vid_encode_opt *opt, 194 226 const pjmedia_frame *input, 195 227 unsigned out_size, … … 364 396 365 397 /** 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 /**375 398 * Initialize codec manager. If there is no the default video codec manager, 376 399 * this function will automatically set the default video codec manager to … … 729 752 * 730 753 * @param codec The codec instance. 754 * @param opt Optional encoding options. 731 755 * @param input The input frame. 732 756 * @param out_size The length of buffer in the output frame. This … … 742 766 PJ_INLINE(pj_status_t) 743 767 pjmedia_vid_codec_encode_begin( pjmedia_vid_codec *codec, 768 const pjmedia_vid_encode_opt *opt, 744 769 const pjmedia_frame *input, 745 770 unsigned out_size, … … 747 772 pj_bool_t *has_more) 748 773 { 749 return (*codec->op->encode_begin)(codec, input, out_size, output,774 return (*codec->op->encode_begin)(codec, opt, input, out_size, output, 750 775 has_more); 751 776 } -
pjproject/trunk/pjmedia/include/pjmedia/vid_stream.h
r3786 r3901 299 299 300 300 /** 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. 305 305 * 306 306 * @return PJ_SUCCESS on success. … … 310 310 311 311 /** 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. 316 316 * 317 317 * @return PJ_SUCCESS on success; … … 322 322 323 323 /** 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 */ 330 PJ_DECL(pj_status_t) pjmedia_vid_stream_send_keyframe( 331 pjmedia_vid_stream *stream); 332 333 334 /** 324 335 * @} 325 336 */ -
pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c
r3893 r3901 78 78 static pj_status_t ffmpeg_codec_get_param(pjmedia_vid_codec *codec, 79 79 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); 80 static 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); 85 86 static pj_status_t ffmpeg_codec_encode_more(pjmedia_vid_codec *codec, 86 87 unsigned out_size, … … 137 138 pjmedia_vid_codec_param param; /**< Codec param */ 138 139 pj_pool_t *pool; /**< Pool for each instance */ 139 pj_timestamp last_tx; /**< Timestamp of last140 transmit */141 140 142 141 /* Format info and apply format param */ … … 150 149 void *enc_buf; 151 150 unsigned enc_buf_size; 151 pj_bool_t enc_buf_is_keyframe; 152 152 unsigned enc_frame_len; 153 153 unsigned enc_processed; 154 154 void *dec_buf; 155 155 unsigned dec_buf_size; 156 pj_timestamp last_dec_keyframe_ts; 156 157 157 158 /* The ffmpeg codec states. */ … … 982 983 /* Create pool for codec instance */ 983 984 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); 985 986 if (!codec) { 986 987 status = PJ_ENOMEM; 987 988 goto on_error; 988 989 } 989 pjmedia_vid_codec_reset(codec, PJMEDIA_SIG_VID_CODEC_FFMPEG);990 990 codec->op = &ffmpeg_op; 991 991 codec->factory = factory; … … 1362 1362 */ 1363 1363 static pj_status_t ffmpeg_codec_encode_whole(pjmedia_vid_codec *codec, 1364 const pjmedia_vid_encode_opt *opt, 1364 1365 const pjmedia_frame *input, 1365 1366 unsigned output_buf_len, … … 1402 1403 } 1403 1404 1405 /* Force keyframe */ 1406 if (opt && opt->force_keyframe) 1407 avframe.pict_type = AV_PICTURE_TYPE_I; 1408 1404 1409 err = avcodec_encode_video(ff->enc_ctx, out_buf, out_buf_len, &avframe); 1405 1410 if (err < 0) { … … 1408 1413 } else { 1409 1414 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; 1410 1418 } 1411 1419 … … 1413 1421 } 1414 1422 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) 1423 static 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) 1420 1429 { 1421 1430 ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data; … … 1425 1434 1426 1435 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); 1428 1438 } else { 1429 1439 pjmedia_frame whole_frm; … … 1434 1444 whole_frm.buf = ff->enc_buf; 1435 1445 whole_frm.size = ff->enc_buf_size; 1436 status = ffmpeg_codec_encode_whole(codec, input,1446 status = ffmpeg_codec_encode_whole(codec, opt, input, 1437 1447 whole_frm.size, &whole_frm); 1438 1448 if (status != PJ_SUCCESS) 1439 1449 return status; 1440 1450 1451 ff->enc_buf_is_keyframe = (whole_frm.bit_info & 1452 PJMEDIA_VID_FRM_KEYFRAME); 1441 1453 ff->enc_frame_len = (unsigned)whole_frm.size; 1442 1454 ff->enc_processed = 0; … … 1454 1466 output->size = payload_len; 1455 1467 1468 if (ff->enc_buf_is_keyframe) 1469 output->bit_info |= PJMEDIA_VID_FRM_KEYFRAME; 1470 1456 1471 *has_more = (ff->enc_processed < ff->enc_frame_len); 1457 1472 } … … 1490 1505 output->size = payload_len; 1491 1506 1507 if (ff->enc_buf_is_keyframe) 1508 output->bit_info |= PJMEDIA_VID_FRM_KEYFRAME; 1509 1492 1510 *has_more = (ff->enc_processed < ff->enc_frame_len); 1493 1511 … … 1495 1513 } 1496 1514 1515 1516 static 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 } 1497 1590 1498 1591 /* … … 1558 1651 #endif 1559 1652 if (err < 0) { 1653 pjmedia_event event; 1654 1560 1655 output->type = PJMEDIA_FRAME_TYPE_NONE; 1561 1656 output->size = 0; 1562 1657 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; 1564 1665 } else if (got_picture) { 1565 1666 pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp; 1566 1667 pj_uint8_t *q = (pj_uint8_t*)output->buf; 1567 1668 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. 1571 1673 */ 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; 1623 1678 1624 1679 /* Check provided buffer size */ … … 1650 1705 output->type = PJMEDIA_FRAME_TYPE_VIDEO; 1651 1706 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 }1662 1707 } else { 1663 1708 output->type = PJMEDIA_FRAME_TYPE_NONE; -
pjproject/trunk/pjmedia/src/pjmedia-videodev/colorbar_dev.c
r3893 r3901 578 578 struct cbar_stream *stream = (struct cbar_stream*)strm; 579 579 580 frame->type = PJMEDIA_FRAME_TYPE_VIDEO; 581 frame->bit_info = 0; 580 582 frame->timestamp = stream->ts; 581 583 stream->ts.u64 += stream->ts_inc; -
pjproject/trunk/pjmedia/src/pjmedia-videodev/dshow_dev.c
r3893 r3901 578 578 } 579 579 580 frame.type = PJMEDIA_ TYPE_VIDEO;580 frame.type = PJMEDIA_FRAME_TYPE_VIDEO; 581 581 IMediaSample_GetPointer(pMediaSample, (BYTE **)&frame.buf); 582 582 frame.size = IMediaSample_GetActualDataLength(pMediaSample); -
pjproject/trunk/pjmedia/src/pjmedia-videodev/ios_dev.m
r3750 r3901 361 361 CVPixelBufferLockBaseAddress(imageBuffer, 0); 362 362 363 frame.type = PJMEDIA_ TYPE_VIDEO;363 frame.type = PJMEDIA_FRAME_TYPE_VIDEO; 364 364 frame.buf = CVPixelBufferGetBaseAddress(imageBuffer); 365 365 frame.size = stream->frame_size; -
pjproject/trunk/pjmedia/src/pjmedia-videodev/qt_dev.m
r3736 r3901 372 372 return; 373 373 374 frame.type = PJMEDIA_ TYPE_VIDEO;374 frame.type = PJMEDIA_FRAME_TYPE_VIDEO; 375 375 frame.buf = [sampleBuffer bytesForAllSamples]; 376 376 frame.size = size; -
pjproject/trunk/pjmedia/src/pjmedia-videodev/v4l2_dev.c
r3895 r3901 691 691 692 692 frame->type = PJMEDIA_FRAME_TYPE_VIDEO; 693 frame->bit_info = 0; 693 694 frame->size = buf.bytesused; 694 695 frame->timestamp.u64 = PJ_UINT64(1) * PJ_TIME_VAL_MSEC(time) * -
pjproject/trunk/pjmedia/src/pjmedia/errno.c
r3664 r3901 105 105 PJ_BUILD_ERR( PJMEDIA_CODEC_EPCMFRMINLEN, "Invalid PCM frame length" ), 106 106 PJ_BUILD_ERR( PJMEDIA_CODEC_EINMODE, "Invalid codec mode (no fmtp?)" ), 107 PJ_BUILD_ERR( PJMEDIA_CODEC_EBADBITSTREAM, "Bad or corrupted bitstream" ), 107 108 108 109 /* Media errors. */ -
pjproject/trunk/pjmedia/src/pjmedia/vid_codec.c
r3893 r3901 71 71 static void sort_codecs(pjmedia_vid_codec_mgr *mgr); 72 72 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 }81 73 82 74 /* -
pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c
r3898 r3901 69 69 #endif 70 70 71 71 72 /** 72 73 * Media channel. … … 124 125 pjmedia_event fmt_event; /**< Buffered fmt_changed event 125 126 to avoid deadlock */ 127 pjmedia_event miss_keyframe_event; 128 /**< Buffered missing keyframe 129 event for delayed republish*/ 126 130 127 131 unsigned frame_size; /**< Size of encoded base frame.*/ … … 131 135 pjmedia_frame *rx_frames; /**< Temp. buffer for incoming 132 136 frame assembly. */ 137 138 pj_bool_t force_keyframe;/**< Forced to encode keyframe? */ 133 139 134 140 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 … … 352 358 pj_memcpy(&stream->fmt_event, event, sizeof(*event)); 353 359 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 354 366 default: 355 367 break; … … 764 776 pj_bool_t has_more_data = PJ_FALSE; 765 777 pj_size_t total_sent = 0; 766 778 pjmedia_vid_encode_opt enc_opt; 767 779 768 780 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0 … … 797 809 frame_out.size = 0; 798 810 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 799 821 /* Encode! */ 800 status = pjmedia_vid_codec_encode_begin(stream->codec, frame,822 status = pjmedia_vid_codec_encode_begin(stream->codec, &enc_opt, frame, 801 823 channel->buf_size - 802 824 sizeof(pjmedia_rtp_hdr), … … 1080 1102 } 1081 1103 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 1082 1110 pj_mutex_lock( stream->jb_mutex ); 1083 1111 … … 1425 1453 1426 1454 /* Set up jitter buffer */ 1427 pjmedia_jbuf_set_adaptive( 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); 1429 1457 1430 1458 /* Init RTCP session: */ … … 2091 2119 } 2092 2120 2121 2122 /* 2123 * Force stream to send video keyframe. 2124 */ 2125 PJ_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 2093 2139 #endif /* PJMEDIA_HAS_VIDEO */ -
pjproject/trunk/pjmedia/src/test/vid_codec_test.c
r3893 r3901 95 95 enc_frames[enc_cnt].size = enc_size_left; 96 96 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, 98 98 &enc_frames[enc_cnt], &has_more); 99 99 if (status != PJ_SUCCESS) goto on_error; -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r3894 r3901 2634 2634 * Handle INFO method. 2635 2635 */ 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 && 2637 2660 (tsx->state == PJSIP_TSX_STATE_COMPLETED || 2638 2661 (tsx->state == PJSIP_TSX_STATE_TERMINATED && … … 2652 2675 tsx->status_text.ptr)); 2653 2676 } 2654 } else if ( tsx->role == PJSIP_ROLE_UAS &&2677 } else if (dtmf_info && tsx->role == PJSIP_ROLE_UAS && 2655 2678 tsx->state == PJSIP_TSX_STATE_TRYING) 2656 2679 { … … 2883 2906 if (vid_idx == -1 || call_info.media[vid_idx].dir == PJMEDIA_DIR_NONE) { 2884 2907 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)); 2888 2911 } 2889 2912 } -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r3891 r3901 331 331 # define PJSUA_HAS_VIDEO PJMEDIA_HAS_VIDEO 332 332 #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 333 344 334 345 /** … … 3372 3383 3373 3384 /** 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 */ 3389 typedef 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 /** 3374 3407 * Call settings. 3375 3408 */ … … 3377 3410 { 3378 3411 /** 3379 * Bitmask of pjsua_call_flag constants.3412 * Bitmask of #pjsua_call_flag constants. 3380 3413 * 3381 3414 * Default: 0 3382 3415 */ 3383 3416 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; 3384 3423 3385 3424 /** … … 3649 3688 */ 3650 3689 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 3651 3697 3652 3698 } pjsua_call_vid_strm_op; … … 4664 4710 extern const pjsip_method pjsip_message_method; 4665 4711 4712 4713 /** 4714 * The INFO method (defined in pjsua_call.c) 4715 */ 4716 extern const pjsip_method pjsip_info_method; 4666 4717 4667 4718 -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r3893 r3901 85 85 address) */ 86 86 pjmedia_srtp_use rem_srtp_use; /**< Remote's SRTP usage policy. */ 87 pj_timestamp last_req_keyframe;/**< Last TX keyframe request. */ 87 88 88 89 pjsua_med_tp_state_cb med_init_cb;/**< Media transport … … 478 479 } pjsua_im_data; 479 480 481 pj_status_t pjsua_media_apply_xml_control(pjsua_call_id call_id, 482 const pj_str_t *xml_st); 483 480 484 481 485 /** -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r3892 r3901 35 35 #define LOCK_CODEC_MAX_RETRY 5 36 36 37 38 /* 39 * The INFO method. 40 */ 41 const pjsip_method pjsip_info_method = 42 { 43 PJSIP_OTHER_METHOD, 44 { "INFO", 4 } 45 }; 46 47 37 48 /* This callback receives notification from invite session when the 38 49 * session state has changed. … … 501 512 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) 502 513 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; 508 516 #endif 509 517 } … … 4191 4199 call->index, tsx->status_code)); 4192 4200 } 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 } 4193 4236 } 4194 4237 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r3893 r3901 1259 1259 pjsua_call_media *call_med = (pjsua_call_media*)user_data; 1260 1260 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 } 1261 1303 1262 1304 if (pjsua_var.ua_cfg.cb.on_call_media_event && call) { … … 1265 1307 } 1266 1308 1267 return PJ_SUCCESS;1309 return status; 1268 1310 } 1269 1311 … … 4188 4230 4189 4231 4232 pj_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 2001 2001 2002 2002 2003 static 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 2003 2029 /* 2004 2030 * Start, stop, and/or manipulate video transmission for the specified call. … … 2070 2096 status = call_set_tx_video(call, param_.med_idx, PJ_FALSE); 2071 2097 break; 2098 case PJSUA_CALL_VID_STRM_SEND_KEYFRAME: 2099 status = call_send_vid_keyframe(call, param_.med_idx); 2100 break; 2072 2101 default: 2073 2102 status = PJ_EINVALIDOP;
Note: See TracChangeset
for help on using the changeset viewer.