Mercurial > mplayer.hg
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 */ |