| @@ -1525,6 +1525,141 @@ end: · 1524 unmodified lines |
| 1525 | 1525 | } |
| 1526 | 1526 | #endif |
| 1527 | 1527 | |
| 1528 | +#if CONFIG_LSCR_DECODER |
| 1529 | +static int decode_frame_lscr(AVCodecContext *avctx, |
| 1530 | + void *data, int *got_frame, |
| 1531 | + AVPacket *avpkt) |
| 1532 | +{ |
| 1533 | + PNGDecContext *const s = avctx->priv_data; |
| 1534 | + GetByteContext *gb = &s->gb; |
| 1535 | + AVFrame *frame = data; |
| 1536 | + int ret, nb_blocks, offset = 0; |
| 1537 | + |
| 1538 | + bytestream2_init(gb, avpkt->data, avpkt->size); |
| 1539 | + |
| 1540 | + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) |
| 1541 | + return ret; |
| 1542 | + |
| 1543 | + nb_blocks = bytestream2_get_le16(gb); |
| 1544 | + |
| 1545 | + if (s->last_picture.f->data[0]) { |
| 1546 | + ret = av_frame_copy(frame, s->last_picture.f); |
| 1547 | + if (ret < 0) |
| 1548 | + return ret; |
| 1549 | + } |
| 1550 | + |
| 1551 | + for (int b = 0; b < nb_blocks; b++) { |
| 1552 | + int x, y, x2, y2, w, h, left; |
| 1553 | + uint32_t csize, size; |
| 1554 | + |
| 1555 | + s->zstream.zalloc = ff_png_zalloc; |
| 1556 | + s->zstream.zfree = ff_png_zfree; |
| 1557 | + s->zstream.opaque = NULL; |
| 1558 | + |
| 1559 | + if ((ret = inflateInit(&s->zstream)) != Z_OK) { |
| 1560 | + av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret); |
| 1561 | + ret = AVERROR_EXTERNAL; |
| 1562 | + goto end; |
| 1563 | + } |
| 1564 | + |
| 1565 | + bytestream2_seek(gb, 2 + b * 12, SEEK_SET); |
| 1566 | + |
| 1567 | + x = bytestream2_get_le16(gb); |
| 1568 | + y = bytestream2_get_le16(gb); |
| 1569 | + x2 = bytestream2_get_le16(gb); |
| 1570 | + y2 = bytestream2_get_le16(gb); |
| 1571 | + s->width = s->cur_w = w = x2-x; |
| 1572 | + s->height = s->cur_h = h = y2-y; |
| 1573 | + |
| 1574 | + if (w <= 0 || x < 0 || x >= avctx->width || w + x > avctx->width || |
| 1575 | + h <= 0 || y < 0 || y >= avctx->height || h + y > avctx->height) { |
| 1576 | + ret = AVERROR_INVALIDDATA; |
| 1577 | + goto end; |
| 1578 | + } |
| 1579 | + |
| 1580 | + size = bytestream2_get_le32(gb); |
| 1581 | + |
| 1582 | + frame->key_frame = (nb_blocks == 1) && |
| 1583 | + (w == avctx->width) && |
| 1584 | + (h == avctx->height) && |
| 1585 | + (x == 0) && (y == 0); |
| 1586 | + |
| 1587 | + bytestream2_seek(gb, 2 + nb_blocks * 12 + offset, SEEK_SET); |
| 1588 | + csize = bytestream2_get_be32(gb); |
| 1589 | + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { |
| 1590 | + ret = AVERROR_INVALIDDATA; |
| 1591 | + goto end; |
| 1592 | + } |
| 1593 | + |
| 1594 | + offset += size; |
| 1595 | + left = size; |
| 1596 | + |
| 1597 | + s->y = 0; |
| 1598 | + s->row_size = w * 3; |
| 1599 | + |
| 1600 | + av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16); |
| 1601 | + if (!s->buffer) { |
| 1602 | + ret = AVERROR(ENOMEM); |
| 1603 | + goto end; |
| 1604 | + } |
| 1605 | + |
| 1606 | + av_fast_padded_malloc(&s->last_row, &s->last_row_size, s->row_size); |
| 1607 | + if (!s->last_row) { |
| 1608 | + ret = AVERROR(ENOMEM); |
| 1609 | + goto end; |
| 1610 | + } |
| 1611 | + |
| 1612 | + s->crow_size = w * 3 + 1; |
| 1613 | + s->crow_buf = s->buffer + 15; |
| 1614 | + s->zstream.avail_out = s->crow_size; |
| 1615 | + s->zstream.next_out = s->crow_buf; |
| 1616 | + s->image_buf = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * 3; |
| 1617 | + s->image_linesize =-frame->linesize[0]; |
| 1618 | + s->bpp = 3; |
| 1619 | + s->pic_state = 0; |
| 1620 | + |
| 1621 | + while (left > 16) { |
| 1622 | + ret = png_decode_idat(s, csize); |
| 1623 | + if (ret < 0) |
| 1624 | + goto end; |
| 1625 | + left -= csize + 16; |
| 1626 | + if (left > 16) { |
| 1627 | + bytestream2_skip(gb, 4); |
| 1628 | + csize = bytestream2_get_be32(gb); |
| 1629 | + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { |
| 1630 | + ret = AVERROR_INVALIDDATA; |
| 1631 | + goto end; |
| 1632 | + } |
| 1633 | + } |
| 1634 | + } |
| 1635 | + |
| 1636 | + inflateEnd(&s->zstream); |
| 1637 | + } |
| 1638 | + |
| 1639 | + frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; |
| 1640 | + |
| 1641 | + av_frame_unref(s->last_picture.f); |
| 1642 | + if ((ret = av_frame_ref(s->last_picture.f, frame)) < 0) |
| 1643 | + return ret; |
| 1644 | + |
| 1645 | + *got_frame = 1; |
| 1646 | +end: |
| 1647 | + inflateEnd(&s->zstream); |
| 1648 | + |
| 1649 | + if (ret < 0) |
| 1650 | + return ret; |
| 1651 | + return avpkt->size; |
| 1652 | +} |
| 1653 | + |
| 1654 | +static void decode_flush(AVCodecContext *avctx) |
| 1655 | +{ |
| 1656 | + PNGDecContext *s = avctx->priv_data; |
| 1657 | + |
| 1658 | + av_frame_unref(s->last_picture.f); |
| 1659 | +} |
| 1660 | + |
| 1661 | +#endif |
| 1662 | + |
| 1528 | 1663 | #if HAVE_THREADS |
| 1529 | 1664 | static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) |
| 1530 | 1665 | { |
| @@ -1581,6 +1716,9 @@ static av_cold int png_dec_init(AVCodecContext *avctx) · 50 unmodified lines |
| 1581 | 1716 | |
| 1582 | 1717 | avctx->color_range = AVCOL_RANGE_JPEG; |
| 1583 | 1718 | |
| 1719 | + if (avctx->codec_id == AV_CODEC_ID_LSCR) |
| 1720 | + avctx->pix_fmt = AV_PIX_FMT_BGR24; |
| 1721 | + |
| 1584 | 1722 | s->avctx = avctx; |
| 1585 | 1723 | s->previous_picture.f = av_frame_alloc(); |
| 1586 | 1724 | s->last_picture.f = av_frame_alloc(); |
| @@ -1653,3 +1791,19 @@ AVCodec ff_png_decoder = { · 66 unmodified lines |
| 1653 | 1791 | .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, |
| 1654 | 1792 | }; |
| 1655 | 1793 | #endif |
| 1794 | + |
| 1795 | +#if CONFIG_LSCR_DECODER |
| 1796 | +AVCodec ff_lscr_decoder = { |
| 1797 | + .name = "lscr", |
| 1798 | + .long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"), |
| 1799 | + .type = AVMEDIA_TYPE_VIDEO, |
| 1800 | + .id = AV_CODEC_ID_LSCR, |
| 1801 | + .priv_data_size = sizeof(PNGDecContext), |
| 1802 | + .init = png_dec_init, |
| 1803 | + .close = png_dec_end, |
| 1804 | + .decode = decode_frame_lscr, |
| 1805 | + .flush = decode_flush, |
| 1806 | + .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, |
| 1807 | + .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, |
| 1808 | +}; |
| 1809 | +#endif |