comparison libmpdemux/demux_gif.c @ 9133:a45282d6ad32

argh, i forgot to 'cvs add' it (again)
author arpi
date Tue, 28 Jan 2003 01:02:07 +0000
parents
children bd7b5078475e
comparison
equal deleted inserted replaced
9132:c945b963d7c6 9133:a45282d6ad32
1 /*
2 GIF file parser for MPlayer
3 by Joey Parrish
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9
10 #include "config.h"
11
12 #ifdef HAVE_GIF
13
14 #include "mp_msg.h"
15 #include "help_mp.h"
16
17 #include "stream.h"
18 #include "demuxer.h"
19 #include "stheader.h"
20
21 #include <gif_lib.h>
22 static int current_pts = 0;
23 static unsigned char *pallete = NULL;
24
25 #define GIF_SIGNATURE (('G' << 16) | ('I' << 8) | 'F')
26
27 int gif_check_file(demuxer_t *demuxer)
28 {
29 stream_reset(demuxer->stream);
30 stream_seek(demuxer->stream, 0);
31 if (stream_read_int24(demuxer->stream) == GIF_SIGNATURE)
32 return 1;
33 return 0;
34 }
35
36 int demux_gif_fill_buffer(demuxer_t *demuxer)
37 {
38 GifFileType *gif = (GifFileType *)demuxer->priv;
39 sh_video_t *sh_video = (sh_video_t *)demuxer->video->sh;
40 GifRecordType type = UNDEFINED_RECORD_TYPE;
41 int len = 0;
42 demux_packet_t *dp = NULL;
43 ColorMapObject *effective_map = NULL;
44 char *buf = NULL;
45
46 while (type != IMAGE_DESC_RECORD_TYPE) {
47 if (DGifGetRecordType(gif, &type) == GIF_ERROR) {
48 PrintGifError();
49 return 0; // oops
50 }
51 if (type == TERMINATE_RECORD_TYPE)
52 return 0; // eof
53 if (type == SCREEN_DESC_RECORD_TYPE) {
54 if (DGifGetScreenDesc(gif) == GIF_ERROR) {
55 PrintGifError();
56 return 0; // oops
57 }
58 }
59 if (type == EXTENSION_RECORD_TYPE) {
60 int code;
61 unsigned char *p = NULL;
62 if (DGifGetExtension(gif, &code, &p) == GIF_ERROR) {
63 PrintGifError();
64 return 0; // oops
65 }
66 if (code == 0xF9) {
67 int frametime = 0;
68 if (p[0] == 4) // is the length correct?
69 frametime = (p[1] << 8) | p[2]; // set the time, centiseconds
70 current_pts += frametime;
71 } else if ((code == 0xFE) && (verbose)) { // comment extension
72 // print iff verbose
73 printf("GIF comment: ");
74 while (p != NULL) {
75 int length = p[0];
76 char *comments = p + 1;
77 comments[length] = 0;
78 printf("%s", comments);
79 if (DGifGetExtensionNext(gif, &p) == GIF_ERROR) {
80 PrintGifError();
81 return 0; // oops
82 }
83 }
84 printf("\n");
85 // FIXME support these:
86 } else if (code == 0x01) { // plaintext extension
87 } else if (code == 0xFF) { // application extension
88 }
89 while (p != NULL) {
90 if (DGifGetExtensionNext(gif, &p) == GIF_ERROR) {
91 PrintGifError();
92 return 0; // oops
93 }
94 }
95 }
96 }
97
98 if (DGifGetImageDesc(gif) == GIF_ERROR) {
99 PrintGifError();
100 return 0; // oops
101 }
102
103 len = gif->Image.Width * gif->Image.Height;
104 dp = new_demux_packet(len);
105 buf = malloc(len);
106 memset(buf, 0, len);
107 memset(dp->buffer, 0, len);
108
109 if (DGifGetLine(gif, buf, len) == GIF_ERROR) {
110 PrintGifError();
111 return 0; // oops
112 }
113
114 effective_map = gif->Image.ColorMap;
115 if (effective_map == NULL) effective_map = gif->SColorMap;
116
117 {
118 int y;
119
120 // copy the pallete
121 for (y = 0; y < 256; y++) {
122 pallete[(y * 4) + 0] = effective_map->Colors[y].Blue;
123 pallete[(y * 4) + 1] = effective_map->Colors[y].Green;
124 pallete[(y * 4) + 2] = effective_map->Colors[y].Red;
125 pallete[(y * 4) + 3] = 0;
126 }
127
128 for (y = 0; y < gif->Image.Height; y++) {
129 unsigned char *drow = dp->buffer;
130 int x = gif->Image.Height - y - 1; // BGR8 is flipped
131 unsigned char *gbuf = buf + (x * gif->Image.Width);
132
133 drow += gif->Image.Width * (y + gif->Image.Top);
134 drow += gif->Image.Left;
135
136 memcpy(drow, gbuf, gif->Image.Width);
137 }
138 }
139
140 free(buf);
141
142 demuxer->video->dpos++;
143 dp->pts = ((float)current_pts) / 100;
144 dp->pos = stream_tell(demuxer->stream);
145 ds_add_packet(demuxer->video, dp);
146
147 return 1;
148 }
149
150 demuxer_t* demux_open_gif(demuxer_t* demuxer)
151 {
152 sh_video_t *sh_video = NULL;
153 GifFileType *gif = NULL;
154
155 current_pts = 0;
156 demuxer->seekable = 0; // FIXME
157
158 // go back to the beginning
159 stream_reset(demuxer->stream);
160 stream_seek(demuxer->stream, 0);
161 lseek(demuxer->stream->fd, 0, SEEK_SET);
162
163 gif = DGifOpenFileHandle(demuxer->stream->fd);
164 if (!gif) {
165 PrintGifError();
166 return NULL;
167 }
168
169 // create a new video stream header
170 sh_video = new_sh_video(demuxer, 0);
171
172 // make sure the demuxer knows about the new video stream header
173 // (even though new_sh_video() ought to take care of it)
174 demuxer->video->sh = sh_video;
175
176 // make sure that the video demuxer stream header knows about its
177 // parent video demuxer stream (this is getting wacky), or else
178 // video_read_properties() will choke
179 sh_video->ds = demuxer->video;
180
181 sh_video->disp_w = gif->SWidth;
182 sh_video->disp_h = gif->SHeight;
183
184 sh_video->format = mmioFOURCC(8, 'R', 'G', 'B');
185
186 sh_video->fps = 5.0f;
187 sh_video->frametime = 1.0f / sh_video->fps;
188
189 sh_video->bih = malloc(sizeof(BITMAPINFOHEADER) + (256 * 4));
190 sh_video->bih->biCompression = sh_video->format;
191 sh_video->bih->biBitCount = 8;
192 sh_video->bih->biPlanes = 2;
193 pallete = (unsigned char *)(sh_video->bih + 1);
194
195 demuxer->priv = gif;
196
197 return demuxer;
198 }
199
200 void demux_close_gif(demuxer_t* demuxer)
201 {
202 GifFileType *gif = (GifFileType *)demuxer->priv;
203
204 if(!gif)
205 return;
206
207 if (DGifCloseFile(gif) == GIF_ERROR)
208 PrintGifError();
209
210 demuxer->stream->fd = 0;
211 demuxer->priv = NULL;
212 }
213 #endif /* HAVE_GIF */