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 | 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 | 1575 | static int submit_frame(QSVEncContext *q, const AVFrame *frame, |
| 1518 | 1576 | QSVFrame **new_frame) |
| 1519 | 1577 | { |
| @@ -1543,8 +1601,9 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, · 23 unmodified lines | ||
| 1543 | 1601 | /* and to make allocation continious for data[0]/data[1] */ |
| 1544 | 1602 | if ((frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) || |
| 1545 | 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); | |
| 1547 | − qf->frame->width = FFALIGN(frame->width, q->width_align); | |
| 1604 | + int tmp_w, tmp_h; | |
| 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 | 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 | 1621 | av_frame_unref(qf->frame); |
| 1563 | 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 | 1630 | } else { |
| 1566 | 1631 | av_frame_unref(qf->frame); |
| 1567 | 1632 | ret = av_frame_ref(qf->frame, frame); |