[FFmpeg-devel] [PATCH] Add XPM decoder
Paras
paraschadha18 at gmail.com
Fri Mar 10 21:04:18 EET 2017
From: Paras Chadha <paraschadha18 at gmail.com>
Signed-off-by: Paras <paraschadha18 at gmail.com>
---
Changelog | 1 +
doc/general.texi | 2 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/avcodec.h | 1 +
libavcodec/codec_desc.c | 7 +
libavcodec/version.h | 4 +-
libavcodec/xpmdec.c | 409 ++++++++++++++++++++++++++++++++++++++++++++++++
libavformat/img2.c | 1 +
9 files changed, 425 insertions(+), 2 deletions(-)
create mode 100644 libavcodec/xpmdec.c
diff --git a/Changelog b/Changelog
index 13628ca..716b6ff 100644
--- a/Changelog
+++ b/Changelog
@@ -26,6 +26,7 @@ version <next>:
- native Opus encoder
- ScreenPressor decoder
- incomplete ClearVideo decoder
+- XPM decoder
version 3.2:
- libopenmpt demuxer
diff --git a/doc/general.texi b/doc/general.texi
index 30450c0..83f54b3 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -607,6 +607,8 @@ following image formats are supported:
@tab WebP image format, encoding supported through external library libwebp
@item XBM @tab X @tab X
@tab X BitMap image format
+ at item XPM @tab X @tab X
+ @tab X PixMap image format
@item XFace @tab X @tab X
@tab X-Face image format
@item XWD @tab X @tab X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 65ccbad..fc5fa1f 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -645,6 +645,7 @@ OBJS-$(CONFIG_XAN_WC4_DECODER) += xxan.o
OBJS-$(CONFIG_XBIN_DECODER) += bintext.o cga_data.o
OBJS-$(CONFIG_XBM_DECODER) += xbmdec.o
OBJS-$(CONFIG_XBM_ENCODER) += xbmenc.o
+OBJS-$(CONFIG_XPM_DECODER) += xpmdec.o
OBJS-$(CONFIG_XFACE_DECODER) += xfacedec.o xface.o
OBJS-$(CONFIG_XFACE_ENCODER) += xfaceenc.o xface.o
OBJS-$(CONFIG_XL_DECODER) += xl.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 074efd4..81208b2 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -376,6 +376,7 @@ static void register_all(void)
REGISTER_DECODER(XAN_WC3, xan_wc3);
REGISTER_DECODER(XAN_WC4, xan_wc4);
REGISTER_ENCDEC (XBM, xbm);
+ REGISTER_DECODER (XPM, xpm);
REGISTER_ENCDEC (XFACE, xface);
REGISTER_DECODER(XL, xl);
REGISTER_ENCDEC (XWD, xwd);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 30ac236..a862716 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -377,6 +377,7 @@ enum AVCodecID {
AV_CODEC_ID_XWD,
AV_CODEC_ID_CDXL,
AV_CODEC_ID_XBM,
+ AV_CODEC_ID_XPM,
AV_CODEC_ID_ZEROCODEC,
AV_CODEC_ID_MSS1,
AV_CODEC_ID_MSA1,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 06bcfc3..88cfddb 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1591,6 +1591,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
},
{
+ .id = AV_CODEC_ID_XPM,
+ .type = AVMEDIA_TYPE_VIDEO,
+ .name = "xpm",
+ .long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image"),
+ .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
+ },
+ {
.id = AV_CODEC_ID_XWD,
.type = AVMEDIA_TYPE_VIDEO,
.name = "xwd",
diff --git a/libavcodec/version.h b/libavcodec/version.h
index b00e011..3ed5a71 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,8 +28,8 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 57
-#define LIBAVCODEC_VERSION_MINOR 82
-#define LIBAVCODEC_VERSION_MICRO 102
+#define LIBAVCODEC_VERSION_MINOR 83
+#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavcodec/xpmdec.c b/libavcodec/xpmdec.c
new file mode 100644
index 0000000..635f25a
--- /dev/null
+++ b/libavcodec/xpmdec.c
@@ -0,0 +1,409 @@
+/*
+ * XPM image format
+ *
+ * Copyright (c) 2012 Paul B Mahol
+ * Copyright (c) 2016 Paras Chadha
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/parseutils.h"
+#include "libavutil/avstring.h"
+#include "avcodec.h"
+#include "internal.h"
+
+typedef struct XPMContext {
+ uint32_t *pixels;
+ int pixels_size;
+} XPMDecContext;
+
+typedef struct ColorEntry {
+ const char *name; ///< a string representing the name of the color
+ uint8_t rgb_color[3]; ///< RGB values for the color
+} ColorEntry;
+
+static int color_table_compare(const void *lhs, const void *rhs)
+{
+ return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
+}
+
+static const ColorEntry color_table[] = {
+ { "AliceBlue", { 0xF0, 0xF8, 0xFF } },
+ { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } },
+ { "Aqua", { 0x00, 0xFF, 0xFF } },
+ { "Aquamarine", { 0x7F, 0xFF, 0xD4 } },
+ { "Azure", { 0xF0, 0xFF, 0xFF } },
+ { "Beige", { 0xF5, 0xF5, 0xDC } },
+ { "Bisque", { 0xFF, 0xE4, 0xC4 } },
+ { "Black", { 0x00, 0x00, 0x00 } },
+ { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } },
+ { "Blue", { 0x00, 0x00, 0xFF } },
+ { "BlueViolet", { 0x8A, 0x2B, 0xE2 } },
+ { "Brown", { 0xA5, 0x2A, 0x2A } },
+ { "BurlyWood", { 0xDE, 0xB8, 0x87 } },
+ { "CadetBlue", { 0x5F, 0x9E, 0xA0 } },
+ { "Chartreuse", { 0x7F, 0xFF, 0x00 } },
+ { "Chocolate", { 0xD2, 0x69, 0x1E } },
+ { "Coral", { 0xFF, 0x7F, 0x50 } },
+ { "CornflowerBlue", { 0x64, 0x95, 0xED } },
+ { "Cornsilk", { 0xFF, 0xF8, 0xDC } },
+ { "Crimson", { 0xDC, 0x14, 0x3C } },
+ { "Cyan", { 0x00, 0xFF, 0xFF } },
+ { "DarkBlue", { 0x00, 0x00, 0x8B } },
+ { "DarkCyan", { 0x00, 0x8B, 0x8B } },
+ { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } },
+ { "DarkGray", { 0xA9, 0xA9, 0xA9 } },
+ { "DarkGreen", { 0x00, 0x64, 0x00 } },
+ { "DarkKhaki", { 0xBD, 0xB7, 0x6B } },
+ { "DarkMagenta", { 0x8B, 0x00, 0x8B } },
+ { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } },
+ { "Darkorange", { 0xFF, 0x8C, 0x00 } },
+ { "DarkOrchid", { 0x99, 0x32, 0xCC } },
+ { "DarkRed", { 0x8B, 0x00, 0x00 } },
+ { "DarkSalmon", { 0xE9, 0x96, 0x7A } },
+ { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } },
+ { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } },
+ { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } },
+ { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } },
+ { "DarkViolet", { 0x94, 0x00, 0xD3 } },
+ { "DeepPink", { 0xFF, 0x14, 0x93 } },
+ { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } },
+ { "DimGray", { 0x69, 0x69, 0x69 } },
+ { "DodgerBlue", { 0x1E, 0x90, 0xFF } },
+ { "FireBrick", { 0xB2, 0x22, 0x22 } },
+ { "FloralWhite", { 0xFF, 0xFA, 0xF0 } },
+ { "ForestGreen", { 0x22, 0x8B, 0x22 } },
+ { "Fuchsia", { 0xFF, 0x00, 0xFF } },
+ { "Gainsboro", { 0xDC, 0xDC, 0xDC } },
+ { "GhostWhite", { 0xF8, 0xF8, 0xFF } },
+ { "Gold", { 0xFF, 0xD7, 0x00 } },
+ { "GoldenRod", { 0xDA, 0xA5, 0x20 } },
+ { "Gray", { 0x80, 0x80, 0x80 } },
+ { "Green", { 0x00, 0x80, 0x00 } },
+ { "GreenYellow", { 0xAD, 0xFF, 0x2F } },
+ { "HoneyDew", { 0xF0, 0xFF, 0xF0 } },
+ { "HotPink", { 0xFF, 0x69, 0xB4 } },
+ { "IndianRed", { 0xCD, 0x5C, 0x5C } },
+ { "Indigo", { 0x4B, 0x00, 0x82 } },
+ { "Ivory", { 0xFF, 0xFF, 0xF0 } },
+ { "Khaki", { 0xF0, 0xE6, 0x8C } },
+ { "Lavender", { 0xE6, 0xE6, 0xFA } },
+ { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } },
+ { "LawnGreen", { 0x7C, 0xFC, 0x00 } },
+ { "LemonChiffon", { 0xFF, 0xFA, 0xCD } },
+ { "LightBlue", { 0xAD, 0xD8, 0xE6 } },
+ { "LightCoral", { 0xF0, 0x80, 0x80 } },
+ { "LightCyan", { 0xE0, 0xFF, 0xFF } },
+ { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
+ { "LightGreen", { 0x90, 0xEE, 0x90 } },
+ { "LightGrey", { 0xD3, 0xD3, 0xD3 } },
+ { "LightPink", { 0xFF, 0xB6, 0xC1 } },
+ { "LightSalmon", { 0xFF, 0xA0, 0x7A } },
+ { "LightSeaGreen", { 0x20, 0xB2, 0xAA } },
+ { "LightSkyBlue", { 0x87, 0xCE, 0xFA } },
+ { "LightSlateGray", { 0x77, 0x88, 0x99 } },
+ { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } },
+ { "LightYellow", { 0xFF, 0xFF, 0xE0 } },
+ { "Lime", { 0x00, 0xFF, 0x00 } },
+ { "LimeGreen", { 0x32, 0xCD, 0x32 } },
+ { "Linen", { 0xFA, 0xF0, 0xE6 } },
+ { "Magenta", { 0xFF, 0x00, 0xFF } },
+ { "Maroon", { 0x80, 0x00, 0x00 } },
+ { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } },
+ { "MediumBlue", { 0x00, 0x00, 0xCD } },
+ { "MediumOrchid", { 0xBA, 0x55, 0xD3 } },
+ { "MediumPurple", { 0x93, 0x70, 0xD8 } },
+ { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } },
+ { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } },
+ { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } },
+ { "MediumTurquoise", { 0x48, 0xD1, 0xCC } },
+ { "MediumVioletRed", { 0xC7, 0x15, 0x85 } },
+ { "MidnightBlue", { 0x19, 0x19, 0x70 } },
+ { "MintCream", { 0xF5, 0xFF, 0xFA } },
+ { "MistyRose", { 0xFF, 0xE4, 0xE1 } },
+ { "Moccasin", { 0xFF, 0xE4, 0xB5 } },
+ { "NavajoWhite", { 0xFF, 0xDE, 0xAD } },
+ { "Navy", { 0x00, 0x00, 0x80 } },
+ { "OldLace", { 0xFD, 0xF5, 0xE6 } },
+ { "Olive", { 0x80, 0x80, 0x00 } },
+ { "OliveDrab", { 0x6B, 0x8E, 0x23 } },
+ { "Orange", { 0xFF, 0xA5, 0x00 } },
+ { "OrangeRed", { 0xFF, 0x45, 0x00 } },
+ { "Orchid", { 0xDA, 0x70, 0xD6 } },
+ { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } },
+ { "PaleGreen", { 0x98, 0xFB, 0x98 } },
+ { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } },
+ { "PaleVioletRed", { 0xD8, 0x70, 0x93 } },
+ { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } },
+ { "PeachPuff", { 0xFF, 0xDA, 0xB9 } },
+ { "Peru", { 0xCD, 0x85, 0x3F } },
+ { "Pink", { 0xFF, 0xC0, 0xCB } },
+ { "Plum", { 0xDD, 0xA0, 0xDD } },
+ { "PowderBlue", { 0xB0, 0xE0, 0xE6 } },
+ { "Purple", { 0x80, 0x00, 0x80 } },
+ { "Red", { 0xFF, 0x00, 0x00 } },
+ { "RosyBrown", { 0xBC, 0x8F, 0x8F } },
+ { "RoyalBlue", { 0x41, 0x69, 0xE1 } },
+ { "SaddleBrown", { 0x8B, 0x45, 0x13 } },
+ { "Salmon", { 0xFA, 0x80, 0x72 } },
+ { "SandyBrown", { 0xF4, 0xA4, 0x60 } },
+ { "SeaGreen", { 0x2E, 0x8B, 0x57 } },
+ { "SeaShell", { 0xFF, 0xF5, 0xEE } },
+ { "Sienna", { 0xA0, 0x52, 0x2D } },
+ { "Silver", { 0xC0, 0xC0, 0xC0 } },
+ { "SkyBlue", { 0x87, 0xCE, 0xEB } },
+ { "SlateBlue", { 0x6A, 0x5A, 0xCD } },
+ { "SlateGray", { 0x70, 0x80, 0x90 } },
+ { "Snow", { 0xFF, 0xFA, 0xFA } },
+ { "SpringGreen", { 0x00, 0xFF, 0x7F } },
+ { "SteelBlue", { 0x46, 0x82, 0xB4 } },
+ { "Tan", { 0xD2, 0xB4, 0x8C } },
+ { "Teal", { 0x00, 0x80, 0x80 } },
+ { "Thistle", { 0xD8, 0xBF, 0xD8 } },
+ { "Tomato", { 0xFF, 0x63, 0x47 } },
+ { "Turquoise", { 0x40, 0xE0, 0xD0 } },
+ { "Violet", { 0xEE, 0x82, 0xEE } },
+ { "Wheat", { 0xF5, 0xDE, 0xB3 } },
+ { "White", { 0xFF, 0xFF, 0xFF } },
+ { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } },
+ { "Yellow", { 0xFF, 0xFF, 0x00 } },
+ { "YellowGreen", { 0x9A, 0xCD, 0x32 } },
+};
+
+static int convert(uint8_t x)
+{
+ if (x >= 'a')
+ x -= 87;
+ else if (x >= 'A')
+ x -= 55;
+ else
+ x -= '0';
+ return x;
+}
+
+/*
+** functions same as strcspn but ignores characters in reject if they are inside a C style comment...
+** @param str, reject - same as that of strcspn
+** @return length till any character in reject does not occur in str
+*/
+static size_t mod_strcspn(const char *str, const char *rej){
+ size_t v1, v2;
+ const char * ptr = str;
+
+ v1 = strcspn(str, "/");
+ v2 = strcspn(str, rej);
+
+ while(v1<v2){
+ ptr += v1+1;
+ if(*(ptr)=='*'){
+ ptr = strstr(ptr, "*/")+2;
+ }
+ else if(*(ptr)=='/'){
+ ptr = strstr(ptr, "\n")+1;
+ }
+ v1 = strcspn(ptr, "/");
+ v2 = strcspn(ptr, rej);
+ }
+
+ return (size_t)(ptr-str)+v2;
+}
+
+static uint32_t hexstring_to_rgba(const char *p, int len){
+ uint32_t ret = 0xFF000000;
+ const ColorEntry *entry;
+ char color_name[100];
+
+ if(*p == '#'){
+ p++;
+ len--;
+ if (len == 3) {
+ ret |= (convert(p[2]) << 4) |
+ (convert(p[1]) << 12) |
+ (convert(p[0]) << 20);
+ } else if (len == 4) {
+ ret = (convert(p[3]) << 4) |
+ (convert(p[2]) << 12) |
+ (convert(p[1]) << 20) |
+ (convert(p[0]) << 28);
+ } else if (len == 6) {
+ ret |= convert(p[5]) |
+ (convert(p[4]) << 4) |
+ (convert(p[3]) << 8) |
+ (convert(p[2]) << 12) |
+ (convert(p[1]) << 16) |
+ (convert(p[0]) << 20);
+ } else if (len == 8) {
+ ret = convert(p[7]) |
+ (convert(p[6]) << 4) |
+ (convert(p[5]) << 8) |
+ (convert(p[4]) << 12) |
+ (convert(p[3]) << 16) |
+ (convert(p[2]) << 20) |
+ (convert(p[1]) << 24) |
+ (convert(p[0]) << 28);
+ }
+ }
+ else{
+ strncpy(color_name, p, len);
+ color_name[len] = '\0';
+
+ entry = bsearch(color_name,
+ color_table,
+ (sizeof(color_table)/sizeof(color_table[0])),
+ sizeof(ColorEntry),
+ color_table_compare);
+
+ ret |= entry->rgb_color[2] |
+ (entry->rgb_color[1] << 8) |
+ (entry->rgb_color[0] << 16);
+ }
+ return ret;
+}
+
+static int ascii2index(const uint8_t *cpixel, int cpp)
+{
+ const uint8_t *p = cpixel;
+ int n = 0, m = 1, i;
+
+ for (i = 0; i < cpp; i++) {
+ if (*p < ' ' || *p > '~')
+ return AVERROR_INVALIDDATA;
+ n += (*p++ - ' ') * m;
+ m *= 95;
+ }
+ return n;
+}
+
+static int xpm_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame, AVPacket *avpkt)
+{
+ XPMDecContext *x = avctx->priv_data;
+ AVFrame *p=data;
+ const uint8_t *end, *ptr = avpkt->data;
+ int ncolors, cpp, ret, i, j;
+ int64_t size;
+ uint32_t *dst;
+
+ avctx->pix_fmt = AV_PIX_FMT_BGRA;
+
+ end = avpkt->data + avpkt->size;
+ if (memcmp(ptr, "/* XPM */", 9)) {
+ av_log(avctx, AV_LOG_ERROR, "missing signature\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ ptr += mod_strcspn(ptr, "\"");
+ if (sscanf(ptr, "\"%u %u %u %u\",",
+ &avctx->width, &avctx->height, &ncolors, &cpp) != 4) {
+ av_log(avctx, AV_LOG_ERROR, "missing image parameters\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if ((ret = ff_set_dimensions(avctx, avctx->width, avctx->height)) < 0)
+ return ret;
+
+ if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
+ return ret;
+
+ if (ncolors <= 0 || cpp <= 0) {
+ av_log(avctx, AV_LOG_ERROR, "invalid number of colors or chars per pixel\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ size = 1;
+ j = 1;
+ for(i=0;i<cpp;i++){
+ size += j*94;
+ j *= 95;
+ }
+
+ if (size<0) {
+ av_log(avctx, AV_LOG_ERROR, "unsupported number of chars per pixel\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ av_fast_padded_malloc(&x->pixels, &x->pixels_size, size);
+ if (!x->pixels)
+ return AVERROR(ENOMEM);
+
+ ptr += mod_strcspn(ptr, ",") + 1;
+ for (i = 0; i < ncolors; i++) {
+ const uint8_t *index;
+ int len;
+
+ ptr += mod_strcspn(ptr, "\"") + 1;
+ if (ptr + cpp > end)
+ return AVERROR_INVALIDDATA;
+ index = ptr;
+ ptr += cpp;
+
+ ptr = strstr(ptr, "c ");
+ if (ptr)
+ ptr += 2;
+ else
+ return AVERROR_INVALIDDATA;
+
+ len = strcspn(ptr, "\" ");
+
+ if ((ret = ascii2index(index, cpp)) < 0)
+ return ret;
+
+ x->pixels[ret] = hexstring_to_rgba(ptr, len);
+
+ ptr += mod_strcspn(ptr, ",") + 1;
+ }
+
+ for (i = 0; i < avctx->height; i++) {
+ dst = (uint32_t *)(p->data[0] + i * p->linesize[0]);
+ ptr += mod_strcspn(ptr, "\"") + 1;
+ for (j = 0; j < avctx->width; j++) {
+ if (ptr + cpp > end)
+ return AVERROR_INVALIDDATA;
+ ret = ascii2index(ptr, cpp);
+ *dst++ = x->pixels[ret];
+ ptr += cpp;
+ }
+ ptr += mod_strcspn(ptr, ",") + 1;
+ }
+
+ p->key_frame = 1;
+ p->pict_type = AV_PICTURE_TYPE_I;
+
+ *got_frame = 1;
+ *(AVFrame *)data = *p;
+
+ return avpkt->size;
+}
+
+static av_cold int xpm_decode_close(AVCodecContext *avctx)
+{
+ XPMDecContext *x = avctx->priv_data;
+ av_freep(&x->pixels);
+
+ return 0;
+}
+
+AVCodec ff_xpm_decoder = {
+ .name = "xpm",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_XPM,
+ .priv_data_size = sizeof(XPMDecContext),
+ .close = xpm_decode_close,
+ .decode = xpm_decode_frame,
+ .capabilities = CODEC_CAP_DR1,
+ .long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image")
+};
diff --git a/libavformat/img2.c b/libavformat/img2.c
index f9f53ff..29df4f0 100644
--- a/libavformat/img2.c
+++ b/libavformat/img2.c
@@ -75,6 +75,7 @@ const IdStrMap ff_img_tags[] = {
{ AV_CODEC_ID_V210X, "yuv10" },
{ AV_CODEC_ID_WEBP, "webp" },
{ AV_CODEC_ID_XBM, "xbm" },
+ { AV_CODEC_ID_XPM, "xpm" },
{ AV_CODEC_ID_XFACE, "xface" },
{ AV_CODEC_ID_XWD, "xwd" },
{ AV_CODEC_ID_NONE, NULL }
--
2.4.11
More information about the ffmpeg-devel
mailing list