History

libavcodec/pgxdec: Add PGX decoder

This patch adds a pgx decoder.

Gautam Ramakrishnan committed 6 years ago

Commit cfe2cf01 parent 76a3ee98 files · +183 −2Browse files

Unified · Split

8 files
  1. Changelog +1 −0
  2. doc/general.texi +2 −0
  3. libavcodec/Makefile +1 −0
  4. libavcodec/allcodecs.c +1 −0
  5. libavcodec/codec_desc.c +7 −0
  6. libavcodec/codec_id.h +1 −0
  7. libavcodec/pgxdec.c +168 −0
  8. libavcodec/version.h +2 −2
Changelog+1−0
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. · 3 unmodified lines
44 version <next>:
55 - AudioToolbox output device
66 - MacCaption demuxer
7+- PGX decoder
78
89
910 version 4.3:
doc/general.texi+2−0
@@ -751,6 +751,8 @@ following image formats are supported: · 750 unmodified lines
751751 @tab Portable GrayMap image
752752 @item PGMYUV @tab X @tab X
753753 @tab PGM with U and V components in YUV 4:2:0
754+@item PGX @tab @tab X
755+ @tab PGX file decoder
754756 @item PIC @tab @tab X
755757 @tab Pictor/PC Paint
756758 @item PNG @tab X @tab X
libavcodec/Makefile+1−0
@@ -536,6 +536,7 @@ OBJS-$(CONFIG_PGM_ENCODER) += pnmenc.o · 535 unmodified lines
536536 OBJS-$(CONFIG_PGMYUV_DECODER) += pnmdec.o pnm.o
537537 OBJS-$(CONFIG_PGMYUV_ENCODER) += pnmenc.o
538538 OBJS-$(CONFIG_PGSSUB_DECODER) += pgssubdec.o
539+OBJS-$(CONFIG_PGX_DECODER) += pgxdec.o
539540 OBJS-$(CONFIG_PICTOR_DECODER) += pictordec.o cga_data.o
540541 OBJS-$(CONFIG_PIXLET_DECODER) += pixlet.o
541542 OBJS-$(CONFIG_PJS_DECODER) += textdec.o ass.o
libavcodec/allcodecs.c+1−0
@@ -238,6 +238,7 @@ extern AVCodec ff_pgm_encoder; · 237 unmodified lines
238238 extern AVCodec ff_pgm_decoder;
239239 extern AVCodec ff_pgmyuv_encoder;
240240 extern AVCodec ff_pgmyuv_decoder;
241+extern AVCodec ff_pgx_decoder;
241242 extern AVCodec ff_pictor_decoder;
242243 extern AVCodec ff_pixlet_decoder;
243244 extern AVCodec ff_png_encoder;
libavcodec/codec_desc.c+7−0
@@ -1405,6 +1405,13 @@ static const AVCodecDescriptor codec_descriptors[] = { · 1404 unmodified lines
14051405 .long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"),
14061406 .props = AV_CODEC_PROP_LOSSY,
14071407 },
1408+ {
1409+ .id = AV_CODEC_ID_PGX,
1410+ .type = AVMEDIA_TYPE_VIDEO,
1411+ .name = "pgx",
1412+ .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"),
1413+ .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
1414+ },
14081415 {
14091416 .id = AV_CODEC_ID_Y41P,
14101417 .type = AVMEDIA_TYPE_VIDEO,
libavcodec/codec_id.h+1−0
@@ -241,6 +241,7 @@ enum AVCodecID { · 240 unmodified lines
241241 AV_CODEC_ID_SCREENPRESSO,
242242 AV_CODEC_ID_RSCC,
243243 AV_CODEC_ID_AVS2,
244+ AV_CODEC_ID_PGX,
244245
245246 AV_CODEC_ID_Y41P = 0x8000,
246247 AV_CODEC_ID_AVRP,
libavcodec/pgxdec.c+168−0
@@ -0,0 +1,168 @@
1+/*
2+ * PGX image format
3+ * Copyright (c) 2020 Gautam Ramakrishnan
4+ *
5+ * This file is part of FFmpeg.
6+ *
7+ * FFmpeg is free software; you can redistribute it and/or
8+ * modify it under the terms of the GNU Lesser General Public
9+ * License as published by the Free Software Foundation; either
10+ * version 2.1 of the License, or (at your option) any later version.
11+ *
12+ * FFmpeg is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+ * Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public
18+ * License along with FFmpeg; if not, write to the Free Software
19+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+ */
21+
22+#include "avcodec.h"
23+#include "internal.h"
24+#include "bytestream.h"
25+#include "libavutil/imgutils.h"
26+
27+static int pgx_get_number(AVCodecContext *avctx, GetByteContext *g, int *number) {
28+ int ret = AVERROR_INVALIDDATA;
29+ char digit;
30+
31+ *number = 0;
32+ while (1) {
33+ uint64_t temp;
34+ if (!bytestream2_get_bytes_left(g))
35+ return AVERROR_INVALIDDATA;
36+ digit = bytestream2_get_byte(g);
37+ if (digit == ' ' || digit == 0xA || digit == 0xD)
38+ break;
39+ else if (digit < '0' || digit > '9')
40+ return AVERROR_INVALIDDATA;
41+
42+ temp = (uint64_t)10 * (*number) + (digit - '0');
43+ if (temp > INT_MAX)
44+ return AVERROR_INVALIDDATA;
45+ *number = temp;
46+ ret = 0;
47+ }
48+
49+ return ret;
50+}
51+
52+static int pgx_decode_header(AVCodecContext *avctx, GetByteContext *g,
53+ int *depth, int *width, int *height,
54+ int *sign)
55+{
56+ int byte;
57+
58+ if (bytestream2_get_bytes_left(g) < 6) {
59+ return AVERROR_INVALIDDATA;
60+ }
61+
62+ bytestream2_skip(g, 6);
63+
64+ // Is the component signed?
65+ byte = bytestream2_peek_byte(g);
66+ if (byte == '+') {
67+ *sign = 0;
68+ bytestream2_skip(g, 1);
69+ } else if (byte == '-') {
70+ *sign = 1;
71+ bytestream2_skip(g, 1);
72+ } else if (byte == 0)
73+ goto error;
74+
75+ byte = bytestream2_peek_byte(g);
76+ if (byte == ' ')
77+ bytestream2_skip(g, 1);
78+ else if (byte == 0)
79+ goto error;
80+
81+ if (pgx_get_number(avctx, g, depth))
82+ goto error;
83+ if (pgx_get_number(avctx, g, width))
84+ goto error;
85+ if (pgx_get_number(avctx, g, height))
86+ goto error;
87+
88+ if (bytestream2_peek_byte(g) == 0xA)
89+ bytestream2_skip(g, 1);
90+ return 0;
91+
92+error:
93+ av_log(avctx, AV_LOG_ERROR, "Error in decoding header.\n");
94+ return AVERROR_INVALIDDATA;
95+}
96+
97+#define WRITE_FRAME(D, PIXEL, suffix) \
98+ static inline void write_frame_ ##D(AVPacket *avpkt, AVFrame *frame, GetByteContext *g, \
99+ int width, int height, int sign, int depth) \
100+ { \
101+ int i, j; \
102+ for (i = 0; i < height; i++) { \
103+ PIXEL *line = (PIXEL*)frame->data[0] + i*frame->linesize[0]/sizeof(PIXEL); \
104+ for (j = 0; j < width; j++) { \
105+ int val; \
106+ if (sign) \
107+ val = (PIXEL)bytestream2_get_ ##suffix(g) + (1 << (depth - 1)); \
108+ else \
109+ val = bytestream2_get_ ##suffix(g); \
110+ val <<= (D - depth); \
111+ *(line + j) = val; \
112+ } \
113+ } \
114+ } \
115+
116+WRITE_FRAME(8, int8_t, byte)
117+WRITE_FRAME(16, int16_t, be16)
118+
119+static int pgx_decode_frame(AVCodecContext *avctx, void *data,
120+ int *got_frame, AVPacket *avpkt)
121+{
122+ AVFrame *p = data;
123+ int ret;
124+ int bpp;
125+ int width, height, depth;
126+ int sign = 0;
127+ GetByteContext g;
128+ bytestream2_init(&g, avpkt->data, avpkt->size);
129+
130+ if ((ret = pgx_decode_header(avctx, &g, &depth, &width, &height, &sign)) < 0)
131+ return ret;
132+
133+ if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
134+ return ret;
135+
136+ if (depth <= 8) {
137+ avctx->pix_fmt = AV_PIX_FMT_GRAY8;
138+ bpp = 8;
139+ } else if (depth <= 16) {
140+ avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
141+ bpp = 16;
142+ } else {
143+ av_log(avctx, AV_LOG_ERROR, "Maximum depth of 16 bits supported.\n");
144+ return AVERROR_PATCHWELCOME;
145+ }
146+ if (bytestream2_get_bytes_left(&g) < width * height * (bpp >> 3))
147+ return AVERROR_INVALIDDATA;
148+ if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
149+ return ret;
150+ p->pict_type = AV_PICTURE_TYPE_I;
151+ p->key_frame = 1;
152+ avctx->bits_per_raw_sample = depth;
153+ if (bpp == 8)
154+ write_frame_8(avpkt, p, &g, width, height, sign, depth);
155+ else if (bpp == 16)
156+ write_frame_16(avpkt, p, &g, width, height, sign, depth);
157+ *got_frame = 1;
158+ return 0;
159+}
160+
161+AVCodec ff_pgx_decoder = {
162+ .name = "pgx",
163+ .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"),
164+ .type = AVMEDIA_TYPE_VIDEO,
165+ .id = AV_CODEC_ID_PGX,
166+ .decode = pgx_decode_frame,
167+ .capabilities = AV_CODEC_CAP_DR1,
168+};
libavcodec/version.h+2−2
@@ -28,8 +28,8 @@ · 27 unmodified lines
2828 #include "libavutil/version.h"
2929
3030 #define LIBAVCODEC_VERSION_MAJOR 58
31−#define LIBAVCODEC_VERSION_MINOR 93
32−#define LIBAVCODEC_VERSION_MICRO 104
31+#define LIBAVCODEC_VERSION_MINOR 94
32+#define LIBAVCODEC_VERSION_MICRO 100
3333
3434 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
3535 LIBAVCODEC_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t