qsvenc makes a copy when the input in system memory is not padded as the SDK requires, however the padding area is not filled with right data
Unified · Split
| @@ -1514,6 +1514,64 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f) · 1513 unmodified lines | |||
| 1514 | return 0; | 1514 | return 0; |
| 1515 | } | 1515 | } |
| 1516 | 1516 | ||
| 1517 | static int qsvenc_fill_padding_area(AVFrame *frame, int new_w, int new_h) | ||
| 1518 | { | ||
| 1519 | const AVPixFmtDescriptor *desc; | ||
| 1520 | int max_step[4], filled[4] = { 0 }; | ||
| 1521 | |||
| 1522 | desc = av_pix_fmt_desc_get(frame->format); | ||
| 1523 | av_assert0(desc); | ||
| 1524 | av_image_fill_max_pixsteps(max_step, NULL, desc); | ||
| 1525 | |||
| 1526 | for (int i = 0; i < desc->nb_components; i++) { | ||
| 1527 | const AVComponentDescriptor *comp = &desc->comp[i]; | ||
| 1528 | int sheight, dheight, plane = comp->plane; | ||
| 1529 | ptrdiff_t swidth = av_image_get_linesize(frame->format, | ||
| 1530 | frame->width, | ||
| 1531 | plane); | ||
| 1532 | ptrdiff_t dwidth = av_image_get_linesize(frame->format, | ||
| 1533 | new_w, | ||
| 1534 | plane); | ||
| 1535 | |||
| 1536 | if (swidth < 0 || dwidth < 0) { | ||
| 1537 | av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); | ||
| 1538 | return AVERROR(EINVAL); | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | if (filled[plane]) | ||
| 1542 | continue; | ||
| 1543 | |||
| 1544 | sheight = frame->height; | ||
| 1545 | dheight = new_h; | ||
| 1546 | |||
| 1547 | if (plane) { | ||
| 1548 | sheight = AV_CEIL_RSHIFT(frame->height, desc->log2_chroma_h); | ||
| 1549 | dheight = AV_CEIL_RSHIFT(new_h, desc->log2_chroma_h); | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | // Fill right padding | ||
| 1553 | if (new_w > frame->width) { | ||
| 1554 | for (int j = 0; j < sheight; j++) { | ||
| 1555 | void *line_ptr = frame->data[plane] + j * frame->linesize[plane] + swidth; | ||
| 1556 | |||
| 1557 | av_memcpy_backptr(line_ptr, | ||
| 1558 | max_step[plane], | ||
| 1559 | new_w - frame->width); | ||
| 1560 | } | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | // Fill bottom padding | ||
| 1564 | for (int j = sheight; j < dheight; j++) | ||
| 1565 | memcpy(frame->data[plane] + j * frame->linesize[plane], | ||
| 1566 | frame->data[plane] + (sheight - 1) * frame->linesize[plane], | ||
| 1567 | dwidth); | ||
| 1568 | |||
| 1569 | filled[plane] = 1; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | return 0; | ||
| 1573 | } | ||
| 1574 | |||
| 1517 | static int submit_frame(QSVEncContext *q, const AVFrame *frame, | 1575 | static int submit_frame(QSVEncContext *q, const AVFrame *frame, |
| 1518 | QSVFrame **new_frame) | 1576 | QSVFrame **new_frame) |
| 1519 | { | 1577 | { |
| @@ -1543,8 +1601,9 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, · 23 unmodified lines | |||
| 1543 | /* and to make allocation continious for data[0]/data[1] */ | 1601 | /* and to make allocation continious for data[0]/data[1] */ |
| 1544 | if ((frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) || | 1602 | if ((frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) || |
| 1545 | (frame->data[1] - frame->data[0] != frame->linesize[0] * FFALIGN(qf->frame->height, q->height_align))) { | 1603 | (frame->data[1] - frame->data[0] != frame->linesize[0] * FFALIGN(qf->frame->height, q->height_align))) { |
| 1546 | qf->frame->height = FFALIGN(frame->height, q->height_align); | 1604 | int tmp_w, tmp_h; |
| 1547 | qf->frame->width = FFALIGN(frame->width, q->width_align); | 1605 | qf->frame->height = tmp_h = FFALIGN(frame->height, q->height_align); |
| 1606 | qf->frame->width = tmp_w = FFALIGN(frame->width, q->width_align); | ||
| 1548 | 1607 | ||
| 1549 | qf->frame->format = frame->format; | 1608 | qf->frame->format = frame->format; |
| 1550 | 1609 | ||
| @@ -1562,6 +1621,12 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, · 11 unmodified lines | |||
| 1562 | av_frame_unref(qf->frame); | 1621 | av_frame_unref(qf->frame); |
| 1563 | return ret; | 1622 | return ret; |
| 1564 | } | 1623 | } |
| 1624 | |||
| 1625 | ret = qsvenc_fill_padding_area(qf->frame, tmp_w, tmp_h); | ||
| 1626 | if (ret < 0) { | ||
| 1627 | av_frame_unref(qf->frame); | ||
| 1628 | return ret; | ||
| 1629 | } | ||
| 1565 | } else { | 1630 | } else { |
| 1566 | av_frame_unref(qf->frame); | 1631 | av_frame_unref(qf->frame); |
| 1567 | ret = av_frame_ref(qf->frame, frame); | 1632 | ret = av_frame_ref(qf->frame, frame); |