Mercurial > mplayer.hg
view libmpdemux/demux_gif.c @ 13395:07708ec98d87
New MD5 sum video output driver. For every frame, it calculates the MD5 sum
and writes a list of those sums to an, optionally specified, output file.
It does not rely on external programs to be installed. The MD5 sum code is
borrowed from the uCIFS library, written by Christopher R. Hertel in 2004
and released under the LGPL license.
Note: This driver is not yet activated and will not be compiled and linked
to libvo. A separate patch will take care of that. This is just for adding
the files to the repository.
author | ivo |
---|---|
date | Mon, 20 Sep 2004 01:01:08 +0000 |
parents | 93375ee56629 |
children | 6b86089c2edd |
line wrap: on
line source
/* GIF file parser for MPlayer by Joey Parrish */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "config.h" #ifdef HAVE_GIF #include "mp_msg.h" #include "help_mp.h" #include "stream.h" #include "demuxer.h" #include "stheader.h" #include <gif_lib.h> static int current_pts = 0; static unsigned char *pallete = NULL; #define GIF_SIGNATURE (('G' << 16) | ('I' << 8) | 'F') #ifndef HAVE_GIF_TVT_HACK // not supported by certain versions of the library int my_read_gif(GifFileType *gif, uint8_t *buf, int len) { return stream_read(gif->UserData, buf, len); } #endif int gif_check_file(demuxer_t *demuxer) { if (stream_read_int24(demuxer->stream) == GIF_SIGNATURE) return 1; return 0; } int demux_gif_fill_buffer(demuxer_t *demuxer) { GifFileType *gif = (GifFileType *)demuxer->priv; sh_video_t *sh_video = (sh_video_t *)demuxer->video->sh; GifRecordType type = UNDEFINED_RECORD_TYPE; int len = 0; demux_packet_t *dp = NULL; ColorMapObject *effective_map = NULL; char *buf = NULL; 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? frametime = (p[1] << 8) | p[2]; // set the time, centiseconds 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 } len = gif->Image.Width * gif->Image.Height; dp = new_demux_packet(len); buf = malloc(len); memset(buf, 0, len); memset(dp->buffer, 0, len); if (DGifGetLine(gif, buf, len) == GIF_ERROR) { PrintGifError(); return 0; // oops } effective_map = gif->Image.ColorMap; if (effective_map == NULL) effective_map = gif->SColorMap; { int y; // copy the pallete for (y = 0; y < 256; y++) { pallete[(y * 4) + 0] = effective_map->Colors[y].Blue; pallete[(y * 4) + 1] = effective_map->Colors[y].Green; pallete[(y * 4) + 2] = effective_map->Colors[y].Red; pallete[(y * 4) + 3] = 0; } for (y = 0; y < gif->Image.Height; y++) { unsigned char *drow = dp->buffer; unsigned char *gbuf = buf + (y * gif->Image.Width); drow += gif->Image.Width * (y + gif->Image.Top); drow += gif->Image.Left; memcpy(drow, gbuf, gif->Image.Width); } } free(buf); demuxer->video->dpos++; dp->pts = ((float)current_pts) / 100; dp->pos = stream_tell(demuxer->stream); ds_add_packet(demuxer->video, dp); return 1; } demuxer_t* demux_open_gif(demuxer_t* demuxer) { sh_video_t *sh_video = NULL; GifFileType *gif = NULL; current_pts = 0; demuxer->seekable = 0; // FIXME // go back to the beginning stream_seek(demuxer->stream,demuxer->stream->start_pos); #ifdef HAVE_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(); 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->disp_w = gif->SWidth; sh_video->disp_h = gif->SHeight; sh_video->format = mmioFOURCC(8, 'R', 'G', 'B'); sh_video->fps = 5.0f; sh_video->frametime = 1.0f / sh_video->fps; sh_video->bih = malloc(sizeof(BITMAPINFOHEADER) + (256 * 4)); sh_video->bih->biCompression = sh_video->format; sh_video->bih->biBitCount = 8; sh_video->bih->biPlanes = 2; pallete = (unsigned char *)(sh_video->bih + 1); demuxer->priv = gif; return demuxer; } void demux_close_gif(demuxer_t* demuxer) { GifFileType *gif = (GifFileType *)demuxer->priv; if(!gif) return; if (DGifCloseFile(gif) == GIF_ERROR) PrintGifError(); demuxer->stream->fd = 0; demuxer->priv = NULL; } #endif /* HAVE_GIF */