Mercurial > mplayer.hg
annotate libmpdemux/demux_gif.c @ 17026:3c4b93bc0db3
10l
author | lorenm |
---|---|
date | Tue, 22 Nov 2005 05:32:28 +0000 |
parents | 6b86089c2edd |
children | d2d9d011203f |
rev | line source |
---|---|
9133 | 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 | |
9463
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
27 #ifndef HAVE_GIF_TVT_HACK |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
28 // not supported by certain versions of the library |
9344
bd7b5078475e
1) codecs.conf changed recently and demux_gif no longer needs to spit
arpi
parents:
9133
diff
changeset
|
29 int my_read_gif(GifFileType *gif, uint8_t *buf, int len) { |
bd7b5078475e
1) codecs.conf changed recently and demux_gif no longer needs to spit
arpi
parents:
9133
diff
changeset
|
30 return stream_read(gif->UserData, buf, len); |
bd7b5078475e
1) codecs.conf changed recently and demux_gif no longer needs to spit
arpi
parents:
9133
diff
changeset
|
31 } |
9463
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
32 #endif |
9344
bd7b5078475e
1) codecs.conf changed recently and demux_gif no longer needs to spit
arpi
parents:
9133
diff
changeset
|
33 |
16175 | 34 static int gif_check_file(demuxer_t *demuxer) |
9133 | 35 { |
36 if (stream_read_int24(demuxer->stream) == GIF_SIGNATURE) | |
16175 | 37 return DEMUXER_TYPE_GIF; |
9133 | 38 return 0; |
39 } | |
40 | |
16175 | 41 static int demux_gif_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) |
9133 | 42 { |
43 GifFileType *gif = (GifFileType *)demuxer->priv; | |
44 sh_video_t *sh_video = (sh_video_t *)demuxer->video->sh; | |
45 GifRecordType type = UNDEFINED_RECORD_TYPE; | |
46 int len = 0; | |
47 demux_packet_t *dp = NULL; | |
48 ColorMapObject *effective_map = NULL; | |
49 char *buf = NULL; | |
50 | |
51 while (type != IMAGE_DESC_RECORD_TYPE) { | |
52 if (DGifGetRecordType(gif, &type) == GIF_ERROR) { | |
53 PrintGifError(); | |
54 return 0; // oops | |
55 } | |
56 if (type == TERMINATE_RECORD_TYPE) | |
57 return 0; // eof | |
58 if (type == SCREEN_DESC_RECORD_TYPE) { | |
59 if (DGifGetScreenDesc(gif) == GIF_ERROR) { | |
60 PrintGifError(); | |
61 return 0; // oops | |
62 } | |
63 } | |
64 if (type == EXTENSION_RECORD_TYPE) { | |
65 int code; | |
66 unsigned char *p = NULL; | |
67 if (DGifGetExtension(gif, &code, &p) == GIF_ERROR) { | |
68 PrintGifError(); | |
69 return 0; // oops | |
70 } | |
71 if (code == 0xF9) { | |
72 int frametime = 0; | |
73 if (p[0] == 4) // is the length correct? | |
74 frametime = (p[1] << 8) | p[2]; // set the time, centiseconds | |
75 current_pts += frametime; | |
76 } else if ((code == 0xFE) && (verbose)) { // comment extension | |
77 // print iff verbose | |
78 printf("GIF comment: "); | |
79 while (p != NULL) { | |
80 int length = p[0]; | |
81 char *comments = p + 1; | |
82 comments[length] = 0; | |
83 printf("%s", comments); | |
84 if (DGifGetExtensionNext(gif, &p) == GIF_ERROR) { | |
85 PrintGifError(); | |
86 return 0; // oops | |
87 } | |
88 } | |
89 printf("\n"); | |
90 } | |
91 while (p != NULL) { | |
92 if (DGifGetExtensionNext(gif, &p) == GIF_ERROR) { | |
93 PrintGifError(); | |
94 return 0; // oops | |
95 } | |
96 } | |
97 } | |
98 } | |
99 | |
100 if (DGifGetImageDesc(gif) == GIF_ERROR) { | |
101 PrintGifError(); | |
102 return 0; // oops | |
103 } | |
104 | |
105 len = gif->Image.Width * gif->Image.Height; | |
106 dp = new_demux_packet(len); | |
107 buf = malloc(len); | |
108 memset(buf, 0, len); | |
109 memset(dp->buffer, 0, len); | |
110 | |
111 if (DGifGetLine(gif, buf, len) == GIF_ERROR) { | |
112 PrintGifError(); | |
113 return 0; // oops | |
114 } | |
115 | |
116 effective_map = gif->Image.ColorMap; | |
117 if (effective_map == NULL) effective_map = gif->SColorMap; | |
118 | |
119 { | |
120 int y; | |
121 | |
122 // copy the pallete | |
123 for (y = 0; y < 256; y++) { | |
124 pallete[(y * 4) + 0] = effective_map->Colors[y].Blue; | |
125 pallete[(y * 4) + 1] = effective_map->Colors[y].Green; | |
126 pallete[(y * 4) + 2] = effective_map->Colors[y].Red; | |
127 pallete[(y * 4) + 3] = 0; | |
128 } | |
129 | |
130 for (y = 0; y < gif->Image.Height; y++) { | |
131 unsigned char *drow = dp->buffer; | |
9344
bd7b5078475e
1) codecs.conf changed recently and demux_gif no longer needs to spit
arpi
parents:
9133
diff
changeset
|
132 unsigned char *gbuf = buf + (y * gif->Image.Width); |
9133 | 133 |
134 drow += gif->Image.Width * (y + gif->Image.Top); | |
135 drow += gif->Image.Left; | |
136 | |
137 memcpy(drow, gbuf, gif->Image.Width); | |
138 } | |
139 } | |
140 | |
141 free(buf); | |
142 | |
143 demuxer->video->dpos++; | |
144 dp->pts = ((float)current_pts) / 100; | |
145 dp->pos = stream_tell(demuxer->stream); | |
146 ds_add_packet(demuxer->video, dp); | |
147 | |
148 return 1; | |
149 } | |
150 | |
16175 | 151 static demuxer_t* demux_open_gif(demuxer_t* demuxer) |
9133 | 152 { |
153 sh_video_t *sh_video = NULL; | |
154 GifFileType *gif = NULL; | |
155 | |
156 current_pts = 0; | |
157 demuxer->seekable = 0; // FIXME | |
158 | |
159 // go back to the beginning | |
9345 | 160 stream_seek(demuxer->stream,demuxer->stream->start_pos); |
9133 | 161 |
9463
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
162 #ifdef HAVE_GIF_TVT_HACK |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
163 // without the TVT functionality of libungif, a hard seek must be |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
164 // done to the beginning of the file. this is because libgif is |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
165 // unable to use mplayer's cache, and without this lseek libgif will |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
166 // not read from the beginning of the file and the command will fail. |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
167 // with this hack enabled, you will lose the ability to stream a GIF. |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
168 lseek(demuxer->stream->fd, 0, SEEK_SET); |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
169 gif = DGifOpenFileHandle(demuxer->stream->fd); |
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
170 #else |
9344
bd7b5078475e
1) codecs.conf changed recently and demux_gif no longer needs to spit
arpi
parents:
9133
diff
changeset
|
171 gif = DGifOpen(demuxer->stream, my_read_gif); |
9463
93375ee56629
gif library incompatibility fixes and prefere libungif over libgif. Patch by Joey Parrish <joey@nicewarrior.org>
alex
parents:
9345
diff
changeset
|
172 #endif |
9133 | 173 if (!gif) { |
174 PrintGifError(); | |
175 return NULL; | |
176 } | |
177 | |
178 // create a new video stream header | |
179 sh_video = new_sh_video(demuxer, 0); | |
180 | |
181 // make sure the demuxer knows about the new video stream header | |
182 // (even though new_sh_video() ought to take care of it) | |
183 demuxer->video->sh = sh_video; | |
184 | |
185 // make sure that the video demuxer stream header knows about its | |
186 // parent video demuxer stream (this is getting wacky), or else | |
187 // video_read_properties() will choke | |
188 sh_video->ds = demuxer->video; | |
189 | |
190 sh_video->disp_w = gif->SWidth; | |
191 sh_video->disp_h = gif->SHeight; | |
192 | |
193 sh_video->format = mmioFOURCC(8, 'R', 'G', 'B'); | |
194 | |
195 sh_video->fps = 5.0f; | |
196 sh_video->frametime = 1.0f / sh_video->fps; | |
197 | |
198 sh_video->bih = malloc(sizeof(BITMAPINFOHEADER) + (256 * 4)); | |
199 sh_video->bih->biCompression = sh_video->format; | |
200 sh_video->bih->biBitCount = 8; | |
201 sh_video->bih->biPlanes = 2; | |
202 pallete = (unsigned char *)(sh_video->bih + 1); | |
203 | |
204 demuxer->priv = gif; | |
205 | |
206 return demuxer; | |
207 } | |
208 | |
16175 | 209 static void demux_close_gif(demuxer_t* demuxer) |
9133 | 210 { |
211 GifFileType *gif = (GifFileType *)demuxer->priv; | |
212 | |
213 if(!gif) | |
214 return; | |
215 | |
216 if (DGifCloseFile(gif) == GIF_ERROR) | |
217 PrintGifError(); | |
218 | |
219 demuxer->stream->fd = 0; | |
220 demuxer->priv = NULL; | |
221 } | |
16175 | 222 |
223 | |
224 demuxer_desc_t demuxer_desc_gif = { | |
225 "GIF demuxer", | |
226 "gif", | |
227 "GIF", | |
228 "Joey Parrish", | |
229 "", | |
230 DEMUXER_TYPE_GIF, | |
231 0, // unsafe autodetect | |
232 gif_check_file, | |
233 demux_gif_fill_buffer, | |
234 demux_open_gif, | |
235 demux_close_gif, | |
236 NULL, | |
237 NULL | |
238 }; | |
239 | |
9133 | 240 #endif /* HAVE_GIF */ |