- Timestamp:
- Dec 7, 2011 10:43:28 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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;
Note: See TracChangeset
for help on using the changeset viewer.