2 FLI file parser for the MPlayer program
14 #include "stream/stream.h"
22 unsigned int *frame_size
;
25 static void demux_seek_fli(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
){
26 fli_frames_t
*frames
= (fli_frames_t
*)demuxer
->priv
;
27 sh_video_t
*sh_video
= demuxer
->video
->sh
;
28 int newpos
=(flags
&SEEK_ABSOLUTE
)?0:frames
->current_frame
;
29 if(flags
&SEEK_FACTOR
){
31 newpos
+=rel_seek_secs
*frames
->num_frames
;
34 newpos
+=rel_seek_secs
*sh_video
->fps
;
36 if(newpos
<0) newpos
=0; else
37 if(newpos
>frames
->num_frames
) newpos
=frames
->num_frames
;
38 frames
->current_frame
=newpos
;
42 // 0 = EOF or no stream found
43 // 1 = successfully read a packet
44 static int demux_fli_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
){
45 fli_frames_t
*frames
= (fli_frames_t
*)demuxer
->priv
;
46 sh_video_t
*sh_video
= demuxer
->video
->sh
;
48 // see if the end has been reached
49 if (frames
->current_frame
>= frames
->num_frames
)
52 // fetch the frame from the file
53 // first, position the file properly since ds_read_packet() doesn't
54 // seem to do it, even though it takes a file offset as a parameter
55 stream_seek(demuxer
->stream
, frames
->filepos
[frames
->current_frame
]);
56 ds_read_packet(demuxer
->video
,
58 frames
->frame_size
[frames
->current_frame
],
59 frames
->current_frame
/sh_video
->fps
,
60 frames
->filepos
[frames
->current_frame
],
61 0 /* what flags? -> demuxer.h (alex) */
64 // get the next frame ready
65 frames
->current_frame
++;
70 static demuxer_t
* demux_open_fli(demuxer_t
* demuxer
){
71 sh_video_t
*sh_video
= NULL
;
72 fli_frames_t
*frames
= malloc(sizeof(fli_frames_t
));
75 unsigned int frame_size
;
77 unsigned char * header
;
79 // go back to the beginning
80 stream_reset(demuxer
->stream
);
81 stream_seek(demuxer
->stream
, 0);
83 header
= calloc(1, sizeof(BITMAPINFOHEADER
) + 128);
84 stream_read(demuxer
->stream
, header
+ sizeof(BITMAPINFOHEADER
), 128);
85 stream_seek(demuxer
->stream
, 0);
87 demuxer
->movi_start
= 128;
88 demuxer
->movi_end
= stream_read_dword_le(demuxer
->stream
);
90 magic_number
= stream_read_word_le(demuxer
->stream
);
92 if ((magic_number
!= 0xAF11) && (magic_number
!= 0xAF12))
94 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "Bad/unknown magic number (%04x)\n",
101 // fetch the number of frames
102 frames
->num_frames
= stream_read_word_le(demuxer
->stream
);
103 frames
->current_frame
= 0;
105 // allocate enough entries for the indices
106 // audit: num_frames is 16bit so it is safe against overflow
107 frames
->filepos
= malloc(frames
->num_frames
* sizeof(off_t
));
108 frames
->frame_size
= malloc(frames
->num_frames
* sizeof(int));
110 // create a new video stream header
111 sh_video
= new_sh_video(demuxer
, 0);
113 // make sure the demuxer knows about the new video stream header
114 // (even though new_sh_video() ought to take care of it)
115 demuxer
->video
->sh
= sh_video
;
117 // make sure that the video demuxer stream header knows about its
118 // parent video demuxer stream (this is getting wacky), or else
119 // video_read_properties() will choke
120 sh_video
->ds
= demuxer
->video
;
122 // custom fourcc for internal MPlayer use
123 sh_video
->format
= mmioFOURCC('F', 'L', 'I', 'C');
125 sh_video
->disp_w
= stream_read_word_le(demuxer
->stream
);
126 sh_video
->disp_h
= stream_read_word_le(demuxer
->stream
);
128 // pass extradata to codec
129 sh_video
->bih
= (BITMAPINFOHEADER
*)header
;
130 sh_video
->bih
->biSize
= sizeof(BITMAPINFOHEADER
) + 128;
131 sh_video
->bih
->biWidth
= sh_video
->disp_w
;
132 sh_video
->bih
->biHeight
= sh_video
->disp_h
;
134 // skip the video depth and flags
135 stream_skip(demuxer
->stream
, 4);
138 speed
= stream_read_word_le(demuxer
->stream
);
141 if (magic_number
== 0xAF11)
143 sh_video
->fps
= 1000 / speed
;
144 sh_video
->frametime
= 1/sh_video
->fps
;
146 // build the frame index
147 stream_seek(demuxer
->stream
, demuxer
->movi_start
);
149 while ((!stream_eof(demuxer
->stream
)) && (frame_number
< frames
->num_frames
))
151 frames
->filepos
[frame_number
] = stream_tell(demuxer
->stream
);
152 frame_size
= stream_read_dword_le(demuxer
->stream
);
153 magic_number
= stream_read_word_le(demuxer
->stream
);
154 stream_skip(demuxer
->stream
, frame_size
- 6);
156 // if this chunk has the right magic number, index it
157 if ((magic_number
== 0xF1FA) || (magic_number
== 0xF5FA))
159 frames
->frame_size
[frame_number
] = frame_size
;
164 // save the actual number of frames indexed
165 frames
->num_frames
= frame_number
;
167 demuxer
->priv
= frames
;
172 static void demux_close_fli(demuxer_t
* demuxer
) {
173 fli_frames_t
*frames
= demuxer
->priv
;
179 free(frames
->filepos
);
180 if(frames
->frame_size
)
181 free(frames
->frame_size
);
188 static int fli_check_file(demuxer_t
* demuxer
)
192 stream_seek(demuxer
->stream
, 4);
193 id
=stream_read_word_le(demuxer
->stream
);
194 // check for the FLI file magic number
195 if((id
==0xAF11) || (id
==0xAF12))
196 return DEMUXER_TYPE_FLI
;
202 const demuxer_desc_t demuxer_desc_fli
= {
203 "Autodesk FLIC demuxer",
207 "Supports also some extensions",
209 0, // unsafe autodetect (short signature)
211 demux_fli_fill_buffer
,