mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
added SGI image format, encoding and decoding, courtesy of Todd Kirby
<doubleshot@pacbell.net> Originally committed as revision 2876 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
38088adf63
commit
6a91ec51fd
1
CREDITS
1
CREDITS
@ -15,6 +15,7 @@ Wolfgang Hesseler
|
|||||||
Falk Hueffner
|
Falk Hueffner
|
||||||
Zdenek Kabelac
|
Zdenek Kabelac
|
||||||
Robin Kay
|
Robin Kay
|
||||||
|
Todd Kirby
|
||||||
Nick Kurshev
|
Nick Kurshev
|
||||||
Mike Melanson
|
Mike Melanson
|
||||||
Michael Niedermayer
|
Michael Niedermayer
|
||||||
|
@ -678,6 +678,7 @@ following image formats are supported:
|
|||||||
@item .Y.U.V @tab X @tab X @tab One raw file per component
|
@item .Y.U.V @tab X @tab X @tab One raw file per component
|
||||||
@item Animated GIF @tab X @tab X @tab Only uncompressed GIFs are generated
|
@item Animated GIF @tab X @tab X @tab Only uncompressed GIFs are generated
|
||||||
@item PNG @tab X @tab X @tab 2 bit and 4 bit/pixel not supported yet
|
@item PNG @tab X @tab X @tab 2 bit and 4 bit/pixel not supported yet
|
||||||
|
@item SGI @tab X @tab X @tab SGI RGB image format
|
||||||
@end multitable
|
@end multitable
|
||||||
|
|
||||||
@code{X} means that the encoding (resp. decoding) is supported.
|
@code{X} means that the encoding (resp. decoding) is supported.
|
||||||
|
@ -34,7 +34,7 @@ OBJS+= amr.o
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# image formats
|
# image formats
|
||||||
OBJS+= pnm.o yuv.o png.o jpeg.o gifdec.o
|
OBJS+= pnm.o yuv.o png.o jpeg.o gifdec.o sgi.o
|
||||||
# file I/O
|
# file I/O
|
||||||
OBJS+= avio.o aviobuf.o file.o
|
OBJS+= avio.o aviobuf.o file.o
|
||||||
OBJS+= framehook.o
|
OBJS+= framehook.o
|
||||||
|
@ -112,6 +112,7 @@ void av_register_all(void)
|
|||||||
#endif
|
#endif
|
||||||
av_register_image_format(&jpeg_image_format);
|
av_register_image_format(&jpeg_image_format);
|
||||||
av_register_image_format(&gif_image_format);
|
av_register_image_format(&gif_image_format);
|
||||||
|
av_register_image_format(&sgi_image_format);
|
||||||
#endif //CONFIG_ENCODERS
|
#endif //CONFIG_ENCODERS
|
||||||
|
|
||||||
/* file protocols */
|
/* file protocols */
|
||||||
|
@ -366,6 +366,7 @@ extern AVImageFormat png_image_format;
|
|||||||
#endif
|
#endif
|
||||||
extern AVImageFormat jpeg_image_format;
|
extern AVImageFormat jpeg_image_format;
|
||||||
extern AVImageFormat gif_image_format;
|
extern AVImageFormat gif_image_format;
|
||||||
|
extern AVImageFormat sgi_image_format;
|
||||||
|
|
||||||
/* XXX: use automatic init with either ELF sections or C file parser */
|
/* XXX: use automatic init with either ELF sections or C file parser */
|
||||||
/* modules */
|
/* modules */
|
||||||
|
475
libavformat/sgi.c
Normal file
475
libavformat/sgi.c
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
/*
|
||||||
|
* SGI image format
|
||||||
|
* Todd Kirby <doubleshot@pacbell.net>
|
||||||
|
*
|
||||||
|
* This library 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 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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 this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "avformat.h"
|
||||||
|
#include "avio.h"
|
||||||
|
|
||||||
|
/* #define DEBUG */
|
||||||
|
|
||||||
|
#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
|
||||||
|
|
||||||
|
#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
|
||||||
|
(((uint8_t*)(x))[1] << 16) | \
|
||||||
|
(((uint8_t*)(x))[2] << 8) | \
|
||||||
|
((uint8_t*)(x))[3])
|
||||||
|
|
||||||
|
/* sgi image file signature */
|
||||||
|
#define SGI_MAGIC 474
|
||||||
|
|
||||||
|
#define SGI_HEADER_SIZE 512
|
||||||
|
|
||||||
|
#define SGI_GRAYSCALE 1
|
||||||
|
#define SGI_RGB 3
|
||||||
|
#define SGI_RGBA 4
|
||||||
|
|
||||||
|
#define SGI_SINGLE_CHAN 2
|
||||||
|
#define SGI_MULTI_CHAN 3
|
||||||
|
|
||||||
|
typedef struct SGIInfo{
|
||||||
|
short magic;
|
||||||
|
char rle;
|
||||||
|
char bytes_per_channel;
|
||||||
|
unsigned short dimension;
|
||||||
|
unsigned short xsize;
|
||||||
|
unsigned short ysize;
|
||||||
|
unsigned short zsize;
|
||||||
|
} SGIInfo;
|
||||||
|
|
||||||
|
|
||||||
|
static int sgi_probe(AVProbeData *pd)
|
||||||
|
{
|
||||||
|
/* test for sgi magic */
|
||||||
|
if (pd->buf_size >= 2 && BE_16(&pd->buf[0]) == SGI_MAGIC) {
|
||||||
|
return AVPROBE_SCORE_MAX;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read sgi header fields */
|
||||||
|
static void read_sgi_header(ByteIOContext *f, SGIInfo *info)
|
||||||
|
{
|
||||||
|
info->magic = (unsigned short) get_be16(f);
|
||||||
|
info->rle = get_byte(f);
|
||||||
|
info->bytes_per_channel = get_byte(f);
|
||||||
|
info->dimension = (unsigned short)get_be16(f);
|
||||||
|
info->xsize = (unsigned short) get_be16(f);
|
||||||
|
info->ysize = (unsigned short) get_be16(f);
|
||||||
|
info->zsize = (unsigned short) get_be16(f);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("sgi header fields:\n");
|
||||||
|
printf(" magic: %d\n", info->magic);
|
||||||
|
printf(" rle: %d\n", info->rle);
|
||||||
|
printf(" bpc: %d\n", info->bytes_per_channel);
|
||||||
|
printf(" dim: %d\n", info->dimension);
|
||||||
|
printf(" xsize: %d\n", info->xsize);
|
||||||
|
printf(" ysize: %d\n", info->ysize);
|
||||||
|
printf(" zsize: %d\n", info->zsize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* read an uncompressed sgi image */
|
||||||
|
static int read_uncompressed_sgi(const SGIInfo *si,
|
||||||
|
AVPicture *pict, ByteIOContext *f)
|
||||||
|
{
|
||||||
|
int x, y, z, chan_offset, ret = 0;
|
||||||
|
uint8_t *dest_row, *tmp_row = NULL;
|
||||||
|
|
||||||
|
tmp_row = av_malloc(si->xsize);
|
||||||
|
|
||||||
|
/* skip header */
|
||||||
|
url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
|
||||||
|
|
||||||
|
pict->linesize[0] = si->xsize;
|
||||||
|
|
||||||
|
for (z = 0; z < si->zsize; z++) {
|
||||||
|
|
||||||
|
#ifndef WORDS_BIGENDIAN
|
||||||
|
/* rgba -> bgra for rgba32 on little endian cpus */
|
||||||
|
if (si->zsize == 4 && z != 3)
|
||||||
|
chan_offset = 2 - z;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
chan_offset = z;
|
||||||
|
|
||||||
|
for (y = si->ysize - 1; y >= 0; y--) {
|
||||||
|
dest_row = pict->data[0] + (y * si->xsize * si->zsize);
|
||||||
|
|
||||||
|
if (!get_buffer(f, tmp_row, si->xsize)) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
for (x = 0; x < si->xsize; x++) {
|
||||||
|
dest_row[chan_offset] = tmp_row[x];
|
||||||
|
dest_row += si->zsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
av_free(tmp_row);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* expand an rle row into a channel */
|
||||||
|
static void expand_rle_row(unsigned char *optr, unsigned char *iptr,
|
||||||
|
int chan_offset, int pixelstride)
|
||||||
|
{
|
||||||
|
unsigned char pixel, count;
|
||||||
|
|
||||||
|
#ifndef WORDS_BIGENDIAN
|
||||||
|
/* rgba -> bgra for rgba32 on little endian cpus */
|
||||||
|
if (pixelstride == 4 && chan_offset != 3) {
|
||||||
|
chan_offset = 2 - chan_offset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
optr += chan_offset;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
pixel = *iptr++;
|
||||||
|
|
||||||
|
if (!(count = (pixel & 0x7f))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pixel & 0x80) {
|
||||||
|
while (count--) {
|
||||||
|
*optr = *iptr;
|
||||||
|
optr += pixelstride;
|
||||||
|
iptr++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pixel = *iptr++;
|
||||||
|
|
||||||
|
while (count--) {
|
||||||
|
*optr = pixel;
|
||||||
|
optr += pixelstride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* read a run length encoded sgi image */
|
||||||
|
static int read_rle_sgi(const SGIInfo *sgi_info,
|
||||||
|
AVPicture *pict, ByteIOContext *f)
|
||||||
|
{
|
||||||
|
uint8_t *dest_row, *rle_data = NULL;
|
||||||
|
unsigned long *start_table, *length_table;
|
||||||
|
int y, z, xsize, ysize, zsize, tablen;
|
||||||
|
long start_offset, run_length;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
xsize = sgi_info->xsize;
|
||||||
|
ysize = sgi_info->ysize;
|
||||||
|
zsize = sgi_info->zsize;
|
||||||
|
|
||||||
|
rle_data = av_malloc(xsize);
|
||||||
|
|
||||||
|
/* skip header */
|
||||||
|
url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
|
||||||
|
|
||||||
|
/* size of rle offset and length tables */
|
||||||
|
tablen = ysize * zsize * sizeof(long);
|
||||||
|
|
||||||
|
start_table = (unsigned long *)av_malloc(tablen);
|
||||||
|
length_table = (unsigned long *)av_malloc(tablen);
|
||||||
|
|
||||||
|
if (!get_buffer(f, (uint8_t *)start_table, tablen)) {
|
||||||
|
ret = -1;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!get_buffer(f, (uint8_t *)length_table, tablen)) {
|
||||||
|
ret = -1;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (z = 0; z < zsize; z++) {
|
||||||
|
for (y = 0; y < ysize; y++) {
|
||||||
|
dest_row = pict->data[0] + (ysize - 1 - y) * (xsize * zsize);
|
||||||
|
|
||||||
|
start_offset = BE_32(&start_table[y + z * ysize]);
|
||||||
|
run_length = BE_32(&length_table[y + z * ysize]);
|
||||||
|
|
||||||
|
/* don't seek if already in the correct spot */
|
||||||
|
if (url_ftell(f) != start_offset) {
|
||||||
|
url_fseek(f, start_offset, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_buffer(f, rle_data, run_length);
|
||||||
|
|
||||||
|
expand_rle_row(dest_row, rle_data, z, zsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
av_free(start_table);
|
||||||
|
av_free(length_table);
|
||||||
|
av_free(rle_data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sgi_read(ByteIOContext *f,
|
||||||
|
int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
|
||||||
|
{
|
||||||
|
SGIInfo sgi_info, *s = &sgi_info;
|
||||||
|
AVImageInfo info1, *info = &info1;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
read_sgi_header(f, s);
|
||||||
|
|
||||||
|
if (s->bytes_per_channel != 1) {
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for supported image dimensions */
|
||||||
|
if (s->dimension != 2 && s->dimension != 3) {
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->zsize == SGI_GRAYSCALE) {
|
||||||
|
info->pix_fmt = PIX_FMT_GRAY8;
|
||||||
|
} else if (s->zsize == SGI_RGB) {
|
||||||
|
info->pix_fmt = PIX_FMT_RGB24;
|
||||||
|
} else if (s->zsize == SGI_RGBA) {
|
||||||
|
info->pix_fmt = PIX_FMT_RGBA32;
|
||||||
|
} else {
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->width = s->xsize;
|
||||||
|
info->height = s->ysize;
|
||||||
|
|
||||||
|
ret = alloc_cb(opaque, info);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (s->rle) {
|
||||||
|
return read_rle_sgi(s, &info->pict, f);
|
||||||
|
} else {
|
||||||
|
return read_uncompressed_sgi(s, &info->pict, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* not reached */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ENCODERS
|
||||||
|
static void write_sgi_header(ByteIOContext *f, const SGIInfo *info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
put_be16(f, SGI_MAGIC);
|
||||||
|
put_byte(f, info->rle);
|
||||||
|
put_byte(f, info->bytes_per_channel);
|
||||||
|
put_be16(f, info->dimension);
|
||||||
|
put_be16(f, info->xsize);
|
||||||
|
put_be16(f, info->ysize);
|
||||||
|
put_be16(f, info->zsize);
|
||||||
|
|
||||||
|
/* The rest are constant in this implementation */
|
||||||
|
put_be32(f, 0L); /* pixmin */
|
||||||
|
put_be32(f, 255L); /* pixmax */
|
||||||
|
put_be32(f, 0L); /* dummy */
|
||||||
|
|
||||||
|
/* name */
|
||||||
|
for (i = 0; i < 80; i++) {
|
||||||
|
put_byte(f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
put_be32(f, 0L); /* colormap */
|
||||||
|
|
||||||
|
/* The rest of the 512 byte header is unused. */
|
||||||
|
for (i = 0; i < 404; i++) {
|
||||||
|
put_byte(f, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rle_row(ByteIOContext *f, char *row, int stride, int rowsize)
|
||||||
|
{
|
||||||
|
int length, count, i, x;
|
||||||
|
char *start, repeat = 0;
|
||||||
|
|
||||||
|
for (x = rowsize, length = 0; x > 0;) {
|
||||||
|
start = row;
|
||||||
|
row += (2 * stride);
|
||||||
|
x -= 2;
|
||||||
|
|
||||||
|
while (x > 0 && (row[-2 * stride] != row[-1 * stride] ||
|
||||||
|
row[-1 * stride] != row[0])) {
|
||||||
|
row += stride;
|
||||||
|
x--;
|
||||||
|
};
|
||||||
|
|
||||||
|
row -= (2 * stride);
|
||||||
|
x += 2;
|
||||||
|
|
||||||
|
count = (row - start) / stride;
|
||||||
|
while (count > 0) {
|
||||||
|
i = count > 126 ? 126 : count;
|
||||||
|
count -= i;
|
||||||
|
|
||||||
|
put_byte(f, 0x80 | i);
|
||||||
|
length++;
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
put_byte(f, *start);
|
||||||
|
start += stride;
|
||||||
|
i--;
|
||||||
|
length++;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (x <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = row;
|
||||||
|
repeat = row[0];
|
||||||
|
|
||||||
|
row += stride;
|
||||||
|
x--;
|
||||||
|
|
||||||
|
while (x > 0 && *row == repeat) {
|
||||||
|
row += stride;
|
||||||
|
x--;
|
||||||
|
};
|
||||||
|
|
||||||
|
count = (row - start) / stride;
|
||||||
|
while (count > 0) {
|
||||||
|
i = count > 126 ? 126 : count;
|
||||||
|
count -= i;
|
||||||
|
|
||||||
|
put_byte(f, i);
|
||||||
|
length++;
|
||||||
|
|
||||||
|
put_byte(f, repeat);
|
||||||
|
length++;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
length++;
|
||||||
|
|
||||||
|
put_byte(f, 0);
|
||||||
|
return (length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sgi_write(ByteIOContext *pb, AVImageInfo *info)
|
||||||
|
{
|
||||||
|
SGIInfo sgi_info, *si = &sgi_info;
|
||||||
|
long *offsettab, *lengthtab;
|
||||||
|
int i, y, z;
|
||||||
|
int tablesize, chan_offset;
|
||||||
|
uint8_t *srcrow;
|
||||||
|
|
||||||
|
si->xsize = info->width;
|
||||||
|
si->ysize = info->height;
|
||||||
|
si->rle = 1;
|
||||||
|
si->bytes_per_channel = 1;
|
||||||
|
|
||||||
|
switch(info->pix_fmt) {
|
||||||
|
case PIX_FMT_GRAY8:
|
||||||
|
si->dimension = SGI_SINGLE_CHAN;
|
||||||
|
si->zsize = SGI_GRAYSCALE;
|
||||||
|
break;
|
||||||
|
case PIX_FMT_RGB24:
|
||||||
|
si->dimension = SGI_MULTI_CHAN;
|
||||||
|
si->zsize = SGI_RGB;
|
||||||
|
break;
|
||||||
|
case PIX_FMT_RGBA32:
|
||||||
|
si->dimension = SGI_MULTI_CHAN;
|
||||||
|
si->zsize = SGI_RGBA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_sgi_header(pb, si);
|
||||||
|
|
||||||
|
tablesize = si->zsize * si->ysize * sizeof(long);
|
||||||
|
|
||||||
|
/* skip rle offset and length tables, write them at the end. */
|
||||||
|
url_fseek(pb, tablesize * 2, SEEK_CUR);
|
||||||
|
put_flush_packet(pb);
|
||||||
|
|
||||||
|
lengthtab = av_malloc(tablesize);
|
||||||
|
offsettab = av_malloc(tablesize);
|
||||||
|
|
||||||
|
for (z = 0; z < si->zsize; z++) {
|
||||||
|
|
||||||
|
#ifndef WORDS_BIGENDIAN
|
||||||
|
/* rgba -> bgra for rgba32 on little endian cpus */
|
||||||
|
if (si->zsize == 4 && z != 3)
|
||||||
|
chan_offset = 2 - z;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
chan_offset = z;
|
||||||
|
|
||||||
|
srcrow = info->pict.data[0] + chan_offset;
|
||||||
|
|
||||||
|
for (y = si->ysize -1; y >= 0; y--) {
|
||||||
|
offsettab[(z * si->ysize) + y] = url_ftell(pb);
|
||||||
|
lengthtab[(z * si->ysize) + y] = rle_row(pb, srcrow,
|
||||||
|
si->zsize, si->xsize);
|
||||||
|
srcrow += info->pict.linesize[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url_fseek(pb, 512, SEEK_SET);
|
||||||
|
|
||||||
|
/* write offset table */
|
||||||
|
for (i = 0; i < (si->ysize * si->zsize); i++) {
|
||||||
|
put_be32(pb, offsettab[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write length table */
|
||||||
|
for (i = 0; i < (si->ysize * si->zsize); i++) {
|
||||||
|
put_be32(pb, lengthtab[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
put_flush_packet(pb);
|
||||||
|
|
||||||
|
av_free(lengthtab);
|
||||||
|
av_free(offsettab);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif // CONFIG_ENCODERS
|
||||||
|
|
||||||
|
AVImageFormat sgi_image_format = {
|
||||||
|
"sgi",
|
||||||
|
"sgi,rgb,rgba,bw",
|
||||||
|
sgi_probe,
|
||||||
|
sgi_read,
|
||||||
|
(1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_RGBA32),
|
||||||
|
#ifdef CONFIG_ENCODERS
|
||||||
|
sgi_write,
|
||||||
|
#else
|
||||||
|
NULL,
|
||||||
|
#endif // CONFIG_ENCODERS
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user