| @@ -1525,6 +1525,141 @@ end: · 1524 unmodified lines |
| 1525 | } | 1525 | } |
| 1526 | #endif | 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 | #if HAVE_THREADS | 1663 | #if HAVE_THREADS |
| 1529 | static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) | 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 | avctx->color_range = AVCOL_RANGE_JPEG; | 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 | s->avctx = avctx; | 1722 | s->avctx = avctx; |
| 1585 | s->previous_picture.f = av_frame_alloc(); | 1723 | s->previous_picture.f = av_frame_alloc(); |
| 1586 | s->last_picture.f = av_frame_alloc(); | 1724 | s->last_picture.f = av_frame_alloc(); |
| @@ -1653,3 +1791,19 @@ AVCodec ff_png_decoder = { · 66 unmodified lines |
| 1653 | .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, | 1791 | .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, |
| 1654 | }; | 1792 | }; |
| 1655 | #endif | 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 |