mirror of https://github.com/mpv-player/mpv
demux_gif: remove this demuxer in favor of libavformat
The gif support in libavformat/libavcodec as of ffmpeg commit 5603b2 can handle animated gif. The internal demuxer is not needed anymore.
This commit is contained in:
parent
dd3260185a
commit
7146a57cfe
1
Makefile
1
Makefile
|
@ -35,7 +35,6 @@ SOURCES-$(DVDREAD) += stream/stream_dvd.c \
|
||||||
stream/stream_dvd_common.c
|
stream/stream_dvd_common.c
|
||||||
|
|
||||||
SOURCES-$(FTP) += stream/stream_ftp.c
|
SOURCES-$(FTP) += stream/stream_ftp.c
|
||||||
SOURCES-$(GIF) += demux/demux_gif.c
|
|
||||||
SOURCES-$(HAVE_SYS_MMAN_H) += audio/filter/af_export.c osdep/mmap_anon.c
|
SOURCES-$(HAVE_SYS_MMAN_H) += audio/filter/af_export.c osdep/mmap_anon.c
|
||||||
SOURCES-$(LADSPA) += audio/filter/af_ladspa.c
|
SOURCES-$(LADSPA) += audio/filter/af_ladspa.c
|
||||||
SOURCES-$(LIBASS) += sub/ass_mp.c sub/sd_ass.c
|
SOURCES-$(LIBASS) += sub/ass_mp.c sub/sd_ass.c
|
||||||
|
|
|
@ -337,7 +337,6 @@ Optional features:
|
||||||
--enable-libavfilter enable libavfilter [disabled] [unused]
|
--enable-libavfilter enable libavfilter [disabled] [unused]
|
||||||
|
|
||||||
Codecs:
|
Codecs:
|
||||||
--enable-gif enable GIF support [autodetect]
|
|
||||||
--enable-mng enable MNG input support [autodetect]
|
--enable-mng enable MNG input support [autodetect]
|
||||||
--enable-jpeg enable JPEG input/output support [autodetect]
|
--enable-jpeg enable JPEG input/output support [autodetect]
|
||||||
--enable-libcdio enable libcdio support [autodetect]
|
--enable-libcdio enable libcdio support [autodetect]
|
||||||
|
@ -428,7 +427,6 @@ _dsound=auto
|
||||||
_nas=auto
|
_nas=auto
|
||||||
_mng=auto
|
_mng=auto
|
||||||
_jpeg=auto
|
_jpeg=auto
|
||||||
_gif=auto
|
|
||||||
_gl=auto
|
_gl=auto
|
||||||
_aa=auto
|
_aa=auto
|
||||||
_caca=auto
|
_caca=auto
|
||||||
|
@ -605,8 +603,6 @@ for ac_option do
|
||||||
--disable-mng) _mng=no ;;
|
--disable-mng) _mng=no ;;
|
||||||
--enable-jpeg) _jpeg=yes ;;
|
--enable-jpeg) _jpeg=yes ;;
|
||||||
--disable-jpeg) _jpeg=no ;;
|
--disable-jpeg) _jpeg=no ;;
|
||||||
--enable-gif) _gif=yes ;;
|
|
||||||
--disable-gif) _gif=no ;;
|
|
||||||
--enable-gl) _gl=yes ;;
|
--enable-gl) _gl=yes ;;
|
||||||
--disable-gl) _gl=no ;;
|
--disable-gl) _gl=no ;;
|
||||||
--enable-caca) _caca=yes ;;
|
--enable-caca) _caca=yes ;;
|
||||||
|
@ -2213,91 +2209,6 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
echocheck "GIF support"
|
|
||||||
# This is to appease people who want to force gif support.
|
|
||||||
# If it is forced to yes, then we still do checks to determine
|
|
||||||
# which gif library to use.
|
|
||||||
if test "$_gif" = yes ; then
|
|
||||||
_force_gif=yes
|
|
||||||
_gif=auto
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$_gif" = auto ; then
|
|
||||||
_gif=no
|
|
||||||
for _ld_gif in "-lungif" "-lgif" ; do
|
|
||||||
statement_check gif_lib.h 'QuantizeBuffer(0, 0, 0, 0, 0, 0, 0, 0)' $_ld_gif && _gif=yes && break
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If no library was found, and the user wants support forced,
|
|
||||||
# then we force it on with libgif, as this is the safest
|
|
||||||
# assumption IMHO. (libungif & libregif both create symbolic
|
|
||||||
# links to libgif. We also assume that no x11 support is needed,
|
|
||||||
# because if you are forcing this, then you _should_ know what
|
|
||||||
# you are doing. [ Besides, package maintainers should never
|
|
||||||
# have compiled x11 deps into libungif in the first place. ] )
|
|
||||||
# </rant>
|
|
||||||
# --Joey
|
|
||||||
if test "$_force_gif" = yes && test "$_gif" = no ; then
|
|
||||||
_gif=yes
|
|
||||||
_ld_gif="-lgif"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$_gif" = yes ; then
|
|
||||||
def_gif='#define CONFIG_GIF 1'
|
|
||||||
codecmodules="gif $codecmodules"
|
|
||||||
res_comment="old version, some encoding functions disabled"
|
|
||||||
def_gif_4='#undef CONFIG_GIF_4'
|
|
||||||
extra_ldflags="$extra_ldflags $_ld_gif"
|
|
||||||
|
|
||||||
cat > $TMPC << EOF
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <gif_lib.h>
|
|
||||||
static void catch(int sig) { exit(1); }
|
|
||||||
int main(void) {
|
|
||||||
signal(SIGSEGV, catch); // catch segfault
|
|
||||||
printf("EGifPutExtensionFirst is at address %p\n", EGifPutExtensionFirst);
|
|
||||||
EGifSetGifVersion("89a"); // this will segfault a buggy gif lib.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if cc_check "$_ld_gif" ; then
|
|
||||||
def_gif_4='#define CONFIG_GIF_4 1'
|
|
||||||
res_comment=""
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
def_gif='#undef CONFIG_GIF'
|
|
||||||
def_gif_4='#undef CONFIG_GIF_4'
|
|
||||||
nocodecmodules="gif $nocodecmodules"
|
|
||||||
fi
|
|
||||||
echores "$_gif"
|
|
||||||
|
|
||||||
|
|
||||||
case "$_gif" in yes*)
|
|
||||||
echocheck "broken giflib workaround"
|
|
||||||
def_gif_tvt_hack='#define CONFIG_GIF_TVT_HACK 1'
|
|
||||||
|
|
||||||
cat > $TMPC << EOF
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <gif_lib.h>
|
|
||||||
int main(void) {
|
|
||||||
GifFileType gif = {.UserData = NULL};
|
|
||||||
printf("UserData is at address %p\n", gif.UserData);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if cc_check "$_ld_gif" ; then
|
|
||||||
def_gif_tvt_hack='#undef CONFIG_GIF_TVT_HACK'
|
|
||||||
echores "disabled"
|
|
||||||
else
|
|
||||||
echores "enabled"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# VIDEO + AUDIO #
|
# VIDEO + AUDIO #
|
||||||
#################
|
#################
|
||||||
|
@ -3265,7 +3176,6 @@ DVBIN = $_dvbin
|
||||||
DVDREAD = $_dvdread
|
DVDREAD = $_dvdread
|
||||||
DXR3 = $_dxr3
|
DXR3 = $_dxr3
|
||||||
FTP = $_ftp
|
FTP = $_ftp
|
||||||
GIF = $_gif
|
|
||||||
GL = $_gl
|
GL = $_gl
|
||||||
GL_COCOA = $_gl_cocoa
|
GL_COCOA = $_gl_cocoa
|
||||||
GL_WIN32 = $_gl_win32
|
GL_WIN32 = $_gl_win32
|
||||||
|
@ -3510,9 +3420,6 @@ $def_direct3d
|
||||||
$def_dsound
|
$def_dsound
|
||||||
$def_dvb
|
$def_dvb
|
||||||
$def_dvbin
|
$def_dvbin
|
||||||
$def_gif
|
|
||||||
$def_gif_4
|
|
||||||
$def_gif_tvt_hack
|
|
||||||
$def_gl
|
$def_gl
|
||||||
$def_gl_cocoa
|
$def_gl_cocoa
|
||||||
$def_gl_win32
|
$def_gl_win32
|
||||||
|
|
|
@ -56,7 +56,6 @@ extern const demuxer_desc_t demuxer_desc_mf;
|
||||||
extern const demuxer_desc_t demuxer_desc_avi;
|
extern const demuxer_desc_t demuxer_desc_avi;
|
||||||
extern const demuxer_desc_t demuxer_desc_asf;
|
extern const demuxer_desc_t demuxer_desc_asf;
|
||||||
extern const demuxer_desc_t demuxer_desc_matroska;
|
extern const demuxer_desc_t demuxer_desc_matroska;
|
||||||
extern const demuxer_desc_t demuxer_desc_gif;
|
|
||||||
extern const demuxer_desc_t demuxer_desc_lavf;
|
extern const demuxer_desc_t demuxer_desc_lavf;
|
||||||
extern const demuxer_desc_t demuxer_desc_lavf_preferred;
|
extern const demuxer_desc_t demuxer_desc_lavf_preferred;
|
||||||
extern const demuxer_desc_t demuxer_desc_mng;
|
extern const demuxer_desc_t demuxer_desc_mng;
|
||||||
|
@ -84,9 +83,6 @@ const demuxer_desc_t *const demuxer_list[] = {
|
||||||
&demuxer_desc_avi,
|
&demuxer_desc_avi,
|
||||||
&demuxer_desc_asf,
|
&demuxer_desc_asf,
|
||||||
&demuxer_desc_matroska,
|
&demuxer_desc_matroska,
|
||||||
#ifdef CONFIG_GIF
|
|
||||||
&demuxer_desc_gif,
|
|
||||||
#endif
|
|
||||||
&demuxer_desc_lavf,
|
&demuxer_desc_lavf,
|
||||||
#ifdef CONFIG_MNG
|
#ifdef CONFIG_MNG
|
||||||
&demuxer_desc_mng,
|
&demuxer_desc_mng,
|
||||||
|
|
|
@ -1,339 +0,0 @@
|
||||||
/*
|
|
||||||
* GIF file parser
|
|
||||||
* Copyright (C) 2003 Joey Parrish
|
|
||||||
*
|
|
||||||
* This file is part of MPlayer.
|
|
||||||
*
|
|
||||||
* MPlayer is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* MPlayer 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "core/mp_msg.h"
|
|
||||||
|
|
||||||
#include "stream/stream.h"
|
|
||||||
#include "demux.h"
|
|
||||||
#include "stheader.h"
|
|
||||||
#include "video/memcpy_pic.h"
|
|
||||||
|
|
||||||
#include <gif_lib.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int current_pts;
|
|
||||||
unsigned char *palette;
|
|
||||||
GifFileType *gif;
|
|
||||||
int w, h;
|
|
||||||
int useref;
|
|
||||||
uint8_t *refimg;
|
|
||||||
} gif_priv_t;
|
|
||||||
|
|
||||||
#define GIF_SIGNATURE (('G' << 16) | ('I' << 8) | 'F')
|
|
||||||
|
|
||||||
#ifndef CONFIG_GIF_TVT_HACK
|
|
||||||
// not supported by certain versions of the library
|
|
||||||
static int my_read_gif(GifFileType *gif, uint8_t *buf, int len)
|
|
||||||
{
|
|
||||||
return stream_read(gif->UserData, buf, len);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int gif_check_file(demuxer_t *demuxer)
|
|
||||||
{
|
|
||||||
if (stream_read_int24(demuxer->stream) == GIF_SIGNATURE)
|
|
||||||
return DEMUXER_TYPE_GIF;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void memcpy_transp_pic(uint8_t *dst, uint8_t *src, int w, int h,
|
|
||||||
int dstride, int sstride, int transp, uint8_t trans_col) {
|
|
||||||
if (transp) {
|
|
||||||
dstride -= w;
|
|
||||||
sstride -= w;
|
|
||||||
while (h-- > 0) {
|
|
||||||
int wleft = w;
|
|
||||||
while (wleft-- > 0) {
|
|
||||||
if (*src != trans_col)
|
|
||||||
*dst = *src;
|
|
||||||
dst++; src++;
|
|
||||||
}
|
|
||||||
dst += dstride;
|
|
||||||
src += sstride;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
memcpy_pic(dst, src, w, h, dstride, sstride);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int demux_gif_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
|
|
||||||
{
|
|
||||||
gif_priv_t *priv = demuxer->priv;
|
|
||||||
GifFileType *gif = priv->gif;
|
|
||||||
GifRecordType type = UNDEFINED_RECORD_TYPE;
|
|
||||||
int len = 0;
|
|
||||||
demux_packet_t *dp = NULL;
|
|
||||||
ColorMapObject *effective_map = NULL;
|
|
||||||
uint8_t *buf = NULL;
|
|
||||||
int refmode = 0;
|
|
||||||
int transparency = 0;
|
|
||||||
uint8_t transparent_col = 0;
|
|
||||||
|
|
||||||
while (type != IMAGE_DESC_RECORD_TYPE) {
|
|
||||||
if (DGifGetRecordType(gif, &type) == GIF_ERROR) {
|
|
||||||
PrintGifError();
|
|
||||||
return 0; // oops
|
|
||||||
}
|
|
||||||
if (type == TERMINATE_RECORD_TYPE)
|
|
||||||
return 0; // eof
|
|
||||||
if (type == SCREEN_DESC_RECORD_TYPE) {
|
|
||||||
if (DGifGetScreenDesc(gif) == GIF_ERROR) {
|
|
||||||
PrintGifError();
|
|
||||||
return 0; // oops
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == EXTENSION_RECORD_TYPE) {
|
|
||||||
int code;
|
|
||||||
unsigned char *p = NULL;
|
|
||||||
if (DGifGetExtension(gif, &code, &p) == GIF_ERROR) {
|
|
||||||
PrintGifError();
|
|
||||||
return 0; // oops
|
|
||||||
}
|
|
||||||
if (code == 0xF9) {
|
|
||||||
int frametime = 0;
|
|
||||||
if (p[0] == 4) // is the length correct?
|
|
||||||
{
|
|
||||||
transparency = p[1] & 1;
|
|
||||||
refmode = (p[1] >> 2) & 3;
|
|
||||||
// HACK: specification says
|
|
||||||
// > 0 - No disposal specified. The decoder is not required to take any action.
|
|
||||||
// but browsers treat it the same way as
|
|
||||||
// > 1 - Do not dispose. The graphic is to be left in place.
|
|
||||||
// Some broken files rely on this, e.g.
|
|
||||||
// http://samples.mplayerhq.hu/GIF/broken-gif/CLAIRE.GIF
|
|
||||||
if (refmode == 0) refmode = 1;
|
|
||||||
frametime = (p[3] << 8) | p[2]; // set the time, centiseconds
|
|
||||||
transparent_col = p[4];
|
|
||||||
}
|
|
||||||
priv->current_pts += frametime;
|
|
||||||
} else if ((code == 0xFE) && (verbose)) { // comment extension
|
|
||||||
// print iff verbose
|
|
||||||
printf("GIF comment: ");
|
|
||||||
while (p != NULL) {
|
|
||||||
int length = p[0];
|
|
||||||
char *comments = p + 1;
|
|
||||||
comments[length] = 0;
|
|
||||||
printf("%s", comments);
|
|
||||||
if (DGifGetExtensionNext(gif, &p) == GIF_ERROR) {
|
|
||||||
PrintGifError();
|
|
||||||
return 0; // oops
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
while (p != NULL) {
|
|
||||||
if (DGifGetExtensionNext(gif, &p) == GIF_ERROR) {
|
|
||||||
PrintGifError();
|
|
||||||
return 0; // oops
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DGifGetImageDesc(gif) == GIF_ERROR) {
|
|
||||||
PrintGifError();
|
|
||||||
return 0; // oops
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = calloc(gif->Image.Width, gif->Image.Height);
|
|
||||||
len = gif->Image.Width * gif->Image.Height;
|
|
||||||
if (DGifGetLine(gif, buf, len) == GIF_ERROR) {
|
|
||||||
PrintGifError();
|
|
||||||
free(buf);
|
|
||||||
return 0; // oops
|
|
||||||
}
|
|
||||||
|
|
||||||
AVPacket *avpacket = talloc(NULL, AVPacket);
|
|
||||||
if (av_new_packet(avpacket, priv->w * priv->h) != 0)
|
|
||||||
abort();
|
|
||||||
dp = new_demux_packet_fromdata(avpacket->data, avpacket->size);
|
|
||||||
dp->avpacket = avpacket;
|
|
||||||
|
|
||||||
if (priv->useref)
|
|
||||||
memcpy(dp->buffer, priv->refimg, priv->w * priv->h);
|
|
||||||
else
|
|
||||||
memset(dp->buffer, gif->SBackGroundColor, priv->w * priv->h);
|
|
||||||
|
|
||||||
effective_map = gif->Image.ColorMap;
|
|
||||||
if (effective_map == NULL) effective_map = gif->SColorMap;
|
|
||||||
|
|
||||||
{
|
|
||||||
int y;
|
|
||||||
int cnt = FFMIN(effective_map->ColorCount, 256);
|
|
||||||
int l = av_clip(gif->Image.Left, 0, priv->w);
|
|
||||||
int t = av_clip(gif->Image.Top, 0, priv->h);
|
|
||||||
int w = av_clip(gif->Image.Width, 0, priv->w - l);
|
|
||||||
int h = av_clip(gif->Image.Height, 0, priv->h - t);
|
|
||||||
unsigned char *dest = dp->buffer + priv->w * t + l;
|
|
||||||
|
|
||||||
// copy the palette
|
|
||||||
for (y = 0; y < cnt; y++) {
|
|
||||||
priv->palette[(y * 4) + 0] = effective_map->Colors[y].Blue;
|
|
||||||
priv->palette[(y * 4) + 1] = effective_map->Colors[y].Green;
|
|
||||||
priv->palette[(y * 4) + 2] = effective_map->Colors[y].Red;
|
|
||||||
priv->palette[(y * 4) + 3] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gif->Image.Interlace) {
|
|
||||||
uint8_t *s = buf;
|
|
||||||
int ih = (h - 0 + 7) >> 3;
|
|
||||||
memcpy_transp_pic(dest, s, w, ih,
|
|
||||||
priv->w << 3, gif->Image.Width,
|
|
||||||
transparency, transparent_col);
|
|
||||||
s += ih * w;
|
|
||||||
ih = (h - 4 + 7) >> 3;
|
|
||||||
memcpy_transp_pic(dest + (priv->w << 2), s, w, ih,
|
|
||||||
priv->w << 3, gif->Image.Width,
|
|
||||||
transparency, transparent_col);
|
|
||||||
s += ih * w;
|
|
||||||
ih = (h - 2 + 3) >> 2;
|
|
||||||
memcpy_transp_pic(dest + (priv->w << 1), s, w, ih,
|
|
||||||
priv->w << 2, gif->Image.Width,
|
|
||||||
transparency, transparent_col);
|
|
||||||
s += ih * w;
|
|
||||||
ih = (h - 1 + 1) >> 1;
|
|
||||||
memcpy_transp_pic(dest + priv->w, s, w, ih,
|
|
||||||
priv->w << 1, gif->Image.Width,
|
|
||||||
transparency, transparent_col);
|
|
||||||
} else
|
|
||||||
memcpy_transp_pic(dest, buf, w, h, priv->w, gif->Image.Width,
|
|
||||||
transparency, transparent_col);
|
|
||||||
|
|
||||||
if (refmode == 1) memcpy(priv->refimg, dp->buffer, priv->w * priv->h);
|
|
||||||
if (refmode == 2 && priv->useref) {
|
|
||||||
dest = priv->refimg + priv->w * t + l;
|
|
||||||
memset(buf, gif->SBackGroundColor, len);
|
|
||||||
memcpy_pic(dest, buf, w, h, priv->w, gif->Image.Width);
|
|
||||||
}
|
|
||||||
if (!(refmode & 2)) priv->useref = refmode & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
int palsize = 256 * 4;
|
|
||||||
uint8_t *pal = av_packet_new_side_data(avpacket, AV_PKT_DATA_PALETTE,
|
|
||||||
palsize);
|
|
||||||
if (pal)
|
|
||||||
memcpy(pal, priv->palette, palsize);
|
|
||||||
|
|
||||||
demuxer->video->dpos++;
|
|
||||||
dp->pts = ((float)priv->current_pts) / 100;
|
|
||||||
dp->pos = stream_tell(demuxer->stream);
|
|
||||||
ds_add_packet(demuxer->video, dp);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static demuxer_t* demux_open_gif(demuxer_t* demuxer)
|
|
||||||
{
|
|
||||||
gif_priv_t *priv = calloc(1, sizeof(gif_priv_t));
|
|
||||||
sh_video_t *sh_video = NULL;
|
|
||||||
GifFileType *gif = NULL;
|
|
||||||
|
|
||||||
priv->current_pts = 0;
|
|
||||||
demuxer->seekable = 0; // FIXME
|
|
||||||
|
|
||||||
// go back to the beginning
|
|
||||||
stream_seek(demuxer->stream,demuxer->stream->start_pos);
|
|
||||||
|
|
||||||
#ifdef CONFIG_GIF_TVT_HACK
|
|
||||||
// without the TVT functionality of libungif, a hard seek must be
|
|
||||||
// done to the beginning of the file. this is because libgif is
|
|
||||||
// unable to use mplayer's cache, and without this lseek libgif will
|
|
||||||
// not read from the beginning of the file and the command will fail.
|
|
||||||
// with this hack enabled, you will lose the ability to stream a GIF.
|
|
||||||
lseek(demuxer->stream->fd, 0, SEEK_SET);
|
|
||||||
gif = DGifOpenFileHandle(demuxer->stream->fd);
|
|
||||||
#else
|
|
||||||
gif = DGifOpen(demuxer->stream, my_read_gif);
|
|
||||||
#endif
|
|
||||||
if (!gif) {
|
|
||||||
PrintGifError();
|
|
||||||
free(priv);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new video stream header
|
|
||||||
sh_video = new_sh_video(demuxer, 0);
|
|
||||||
|
|
||||||
// make sure the demuxer knows about the new video stream header
|
|
||||||
// (even though new_sh_video() ought to take care of it)
|
|
||||||
demuxer->video->sh = sh_video;
|
|
||||||
|
|
||||||
// make sure that the video demuxer stream header knows about its
|
|
||||||
// parent video demuxer stream (this is getting wacky), or else
|
|
||||||
// video_read_properties() will choke
|
|
||||||
sh_video->ds = demuxer->video;
|
|
||||||
|
|
||||||
sh_video->format = mmioFOURCC('r', 'a', 'w', ' ');
|
|
||||||
|
|
||||||
sh_video->fps = 5.0f;
|
|
||||||
sh_video->frametime = 1.0f / sh_video->fps;
|
|
||||||
|
|
||||||
int size = sizeof(*sh_video->bih) + (256 * 4);
|
|
||||||
sh_video->bih = calloc(1, size);
|
|
||||||
sh_video->bih->biSize = size;
|
|
||||||
sh_video->bih->biCompression = sh_video->format;
|
|
||||||
sh_video->bih->biWidth = priv->w = (uint16_t)gif->SWidth;
|
|
||||||
sh_video->bih->biHeight = priv->h = (uint16_t)gif->SHeight;
|
|
||||||
sh_video->bih->biBitCount = 8;
|
|
||||||
sh_video->bih->biPlanes = 2;
|
|
||||||
priv->palette = (unsigned char *)(sh_video->bih + 1);
|
|
||||||
priv->refimg = malloc(priv->w * priv->h);
|
|
||||||
|
|
||||||
priv->gif = gif;
|
|
||||||
demuxer->priv = priv;
|
|
||||||
|
|
||||||
return demuxer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void demux_close_gif(demuxer_t* demuxer)
|
|
||||||
{
|
|
||||||
gif_priv_t *priv = demuxer->priv;
|
|
||||||
if (!priv) return;
|
|
||||||
if (priv->gif && DGifCloseFile(priv->gif) == GIF_ERROR)
|
|
||||||
PrintGifError();
|
|
||||||
free(priv->refimg);
|
|
||||||
free(priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const demuxer_desc_t demuxer_desc_gif = {
|
|
||||||
"GIF demuxer",
|
|
||||||
"gif",
|
|
||||||
"GIF",
|
|
||||||
"Joey Parrish",
|
|
||||||
"",
|
|
||||||
DEMUXER_TYPE_GIF,
|
|
||||||
0, // unsafe autodetect
|
|
||||||
gif_check_file,
|
|
||||||
demux_gif_fill_buffer,
|
|
||||||
demux_open_gif,
|
|
||||||
demux_close_gif,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
Loading…
Reference in New Issue