@@ -1390,15 +1390,29 @@ static void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl)
1390
1390
}
1391
1391
}
1392
1392
1393
+ static void free_encoder_ctrl_extparam (mfxEncodeCtrl * enc_ctrl )
1394
+ {
1395
+ if (enc_ctrl ) {
1396
+ int i ;
1397
+ for (i = 0 ; i < enc_ctrl -> NumExtParam && i < QSV_MAX_ENC_EXTPARAM ; i ++ ) {
1398
+ if (enc_ctrl -> ExtParam [i ])
1399
+ av_freep (& (enc_ctrl -> ExtParam [i ]));
1400
+ }
1401
+ enc_ctrl -> NumExtParam = 0 ;
1402
+ }
1403
+ }
1404
+
1393
1405
static void clear_unused_frames (QSVEncContext * q )
1394
1406
{
1395
1407
QSVFrame * cur = q -> work_frames ;
1396
1408
while (cur ) {
1397
1409
if (cur -> used && !cur -> surface .Data .Locked ) {
1398
1410
free_encoder_ctrl_payloads (& cur -> enc_ctrl );
1411
+ free_encoder_ctrl_extparam (& cur -> enc_ctrl );
1399
1412
//do not reuse enc_ctrl from previous frame
1400
1413
memset (& cur -> enc_ctrl , 0 , sizeof (cur -> enc_ctrl ));
1401
1414
cur -> enc_ctrl .Payload = cur -> payloads ;
1415
+ cur -> enc_ctrl .ExtParam = cur -> extparam ;
1402
1416
if (cur -> frame -> format == AV_PIX_FMT_QSV ) {
1403
1417
av_frame_unref (cur -> frame );
1404
1418
}
@@ -1436,6 +1450,7 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f)
1436
1450
return AVERROR (ENOMEM );
1437
1451
}
1438
1452
frame -> enc_ctrl .Payload = frame -> payloads ;
1453
+ frame -> enc_ctrl .ExtParam = frame -> extparam ;
1439
1454
* last = frame ;
1440
1455
1441
1456
* f = frame ;
@@ -1537,6 +1552,67 @@ static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
1537
1552
}
1538
1553
}
1539
1554
1555
+ static int set_roi_encode_ctrl (AVCodecContext * avctx , const AVFrame * frame ,
1556
+ mfxEncodeCtrl * enc_ctrl )
1557
+ {
1558
+ AVFrameSideData * sd = NULL ;
1559
+ int mb_size ;
1560
+
1561
+ if (avctx -> codec_id == AV_CODEC_ID_H264 )
1562
+ mb_size = 16 ;
1563
+ else if (avctx -> codec_id == AV_CODEC_ID_H265 )
1564
+ mb_size = 32 ;
1565
+ else
1566
+ return 0 ;
1567
+
1568
+ if (frame )
1569
+ sd = av_frame_get_side_data (frame , AV_FRAME_DATA_REGIONS_OF_INTEREST );
1570
+
1571
+ if (sd ) {
1572
+ mfxExtEncoderROI * enc_roi = NULL ;
1573
+ AVRegionOfInterest * roi ;
1574
+ uint32_t roi_size ;
1575
+ int nb_roi , i ;
1576
+
1577
+ roi = (AVRegionOfInterest * )sd -> data ;
1578
+ roi_size = roi -> self_size ;
1579
+ if (!roi_size || sd -> size % roi_size ) {
1580
+ av_log (avctx , AV_LOG_ERROR , "Invalid ROI Data.\n" );
1581
+ return AVERROR (EINVAL );
1582
+ }
1583
+ nb_roi = sd -> size / roi_size ;
1584
+ if (nb_roi > QSV_MAX_ROI_NUM ) {
1585
+ av_log (avctx , AV_LOG_WARNING , "More ROIs set than "
1586
+ "supported by driver (%d > %d).\n" ,
1587
+ nb_roi , QSV_MAX_ROI_NUM );
1588
+ nb_roi = QSV_MAX_ROI_NUM ;
1589
+ }
1590
+
1591
+ enc_roi = av_mallocz (sizeof (* enc_roi ));
1592
+ if (!enc_roi )
1593
+ return AVERROR (ENOMEM );
1594
+ enc_roi -> Header .BufferId = MFX_EXTBUFF_ENCODER_ROI ;
1595
+ enc_roi -> Header .BufferSz = sizeof (* enc_roi );
1596
+ enc_roi -> NumROI = nb_roi ;
1597
+ enc_roi -> ROIMode = MFX_ROI_MODE_QP_DELTA ;
1598
+ for (i = 0 ; i < nb_roi ; i ++ ) {
1599
+ roi = (AVRegionOfInterest * )(sd -> data + roi_size * i );
1600
+ enc_roi -> ROI [i ].Top = FFALIGN (roi -> top , mb_size );
1601
+ enc_roi -> ROI [i ].Bottom = FFALIGN (roi -> bottom , mb_size );
1602
+ enc_roi -> ROI [i ].Left = FFALIGN (roi -> left , mb_size );
1603
+ enc_roi -> ROI [i ].Right = FFALIGN (roi -> right , mb_size );
1604
+ enc_roi -> ROI [i ].DeltaQP =
1605
+ roi -> qoffset .num * 51 / roi -> qoffset .den ;
1606
+ av_log (avctx , AV_LOG_DEBUG , "ROI: (%d,%d)-(%d,%d) -> %+d.\n" ,
1607
+ roi -> top , roi -> left , roi -> bottom , roi -> right ,
1608
+ enc_roi -> ROI [i ].DeltaQP );
1609
+ }
1610
+ enc_ctrl -> ExtParam [enc_ctrl -> NumExtParam ] = (mfxExtBuffer * )enc_roi ;
1611
+ enc_ctrl -> NumExtParam ++ ;
1612
+ }
1613
+ return 0 ;
1614
+ }
1615
+
1540
1616
static int encode_frame (AVCodecContext * avctx , QSVEncContext * q ,
1541
1617
const AVFrame * frame )
1542
1618
{
@@ -1599,6 +1675,14 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
1599
1675
q -> set_encode_ctrl_cb (avctx , frame , & qsv_frame -> enc_ctrl );
1600
1676
}
1601
1677
1678
+ if ((avctx -> codec_id == AV_CODEC_ID_H264 ||
1679
+ avctx -> codec_id == AV_CODEC_ID_H265 ) &&
1680
+ enc_ctrl && QSV_RUNTIME_VERSION_ATLEAST (q -> ver , 1 , 8 )) {
1681
+ ret = set_roi_encode_ctrl (avctx , frame , enc_ctrl );
1682
+ if (ret < 0 )
1683
+ goto free ;
1684
+ }
1685
+
1602
1686
pkt .sync = av_mallocz (sizeof (* pkt .sync ));
1603
1687
if (!pkt .sync )
1604
1688
goto nomem ;
@@ -1721,6 +1805,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
1721
1805
while (cur ) {
1722
1806
q -> work_frames = cur -> next ;
1723
1807
av_frame_free (& cur -> frame );
1808
+ free_encoder_ctrl_extparam (& cur -> enc_ctrl );
1724
1809
free_encoder_ctrl_payloads (& cur -> enc_ctrl );
1725
1810
av_freep (& cur );
1726
1811
cur = q -> work_frames ;
0 commit comments