2
fbmngplay - fb console MNG player.
3
(c) 2001 by Stefan Reinauer, <stepan :at: suse.de>
5
This program is based on mngplay, part of libmng, written and (C) by
6
Ralph Giles <giles :at: ashlu.bc.ca>
8
This program my be redistributed under the terms of the
9
GNU General Public Licence, version 2, or at your preference,
17
#include "fbmngplay.h"
22
unsigned char *bufferstream;
23
unsigned long bufferpos = 0, buffersize = 0;
25
inline void mdelay(unsigned long msec)
30
/* callbacks for the mng decoder */
32
/* memory allocation; data must be zeroed */
33
mng_ptr mngalloc(mng_uint32 size)
35
return (mng_ptr) calloc(1, size);
38
/* memory deallocation */
39
void mngfree(mng_ptr p, mng_uint32 size)
45
mng_bool mngopenstream(mng_handle mng)
49
/* look up our stream struct */
50
mymng = (mngstuff *) mng_get_userdata(mng);
53
mymng->file = fopen(mymng->filename, "rb");
54
if (mymng->file == NULL) {
55
fprintf(stderr, "unable to open '%s'\n", mymng->filename);
62
fseek(mymng->file, 0, SEEK_END);
63
len = ftell(mymng->file);
65
bufferstream = malloc(len);
67
/* Not enough memory for buffers
68
* -> we go back to unbuffered mode
70
printf("Reverted to non buffered mode.\n");
75
fread(bufferstream, 1, len, mymng->file);
84
mng_bool mngclosestream(mng_handle mng)
88
/* look up our stream struct */
89
mymng = (mngstuff *) mng_get_userdata(mng);
94
mymng->file = NULL; /* for safety */
105
/* feed data to the decoder */
106
mng_bool mngreadstream(mng_handle mng, mng_ptr buffer,
107
mng_uint32 size, mng_uint32 * bytesread)
111
/* look up our stream struct */
112
mymng = (mngstuff *) mng_get_userdata(mng);
114
/* read the requested amount of data from the file */
115
*bytesread = fread(buffer, 1, size, mymng->file);
117
*bytesread = (buffersize - bufferpos) <
118
size ? (buffersize - bufferpos) : size;
119
memcpy(buffer, bufferstream + bufferpos, *bytesread);
120
bufferpos += (*bytesread);
125
/* the header's been read. set up the display stuff */
126
mng_bool mngprocessheader(mng_handle mng,
127
mng_uint32 width, mng_uint32 height)
130
unsigned char *copybuffer, *background;
133
mymng = (mngstuff *) mng_get_userdata(mng);
134
mymng->width = width;
135
mymng->height = height;
138
mymng->fbx = (mymng->fbwidth)-width-15;
139
switch (mymng->fbheight) {
152
copybuffer = (unsigned char *) malloc(width * height * 4);
153
if (copybuffer == NULL) {
154
fprintf(stderr, "could not allocate copy buffer.\n");
157
mymng->copybuffer = copybuffer;
159
if (!mymng->background) {
161
(unsigned char *) malloc(width * height *
162
(mymng->fbbpp >> 3));
163
if (background == NULL) {
165
"could not allocate background buffer.\n");
168
mymng->background = background;
170
src = mymng->display + (mymng->fbwidth * mymng->fby +
171
mymng->fbx) * (mymng->fbbpp >> 3);
174
memcpy(background, src,
175
width * (mymng->fbbpp >> 3));
176
background += width * (mymng->fbbpp >> 3);
177
src += mymng->fbwidth * (mymng->fbbpp >> 3);
180
/* tell the mng decoder about our bit-depth choice */
181
/* FIXME: this works on intel. is it correct in general? */
182
mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
187
/* return a row pointer for the decoder to fill */
188
mng_ptr mnggetcanvasline(mng_handle mng, mng_uint32 line)
193
/* dereference our structure */
194
mymng = (mngstuff *) mng_get_userdata(mng);
196
/* we assume any necessary locking has happened
197
outside, in the frame level code */
198
row = mymng->copybuffer + mymng->width * 4 * line;
204
mng_uint32 mnggetticks(mng_handle mng)
210
gettimeofday(&tv, &tz);
211
ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
216
static inline void copyline(unsigned char *dest, unsigned char *src,
217
unsigned char *background, mngstuff * mymng)
220
unsigned int i = mymng->width;
221
unsigned int fr, fg, fb, br, bg, bb, r, g, b, a;
222
unsigned short output, input;
230
a = a * mymng->alpha / 100;
231
switch (mymng->fbbpp) {
233
input = *((unsigned short *) background)++;
234
br = (input >> 8) & 0xf8;
235
bg = (input >> 3) & 0xfc;
236
bb = input << 3 & 0xff;
253
printf("depth not supported.\n");
258
r = ((fr * a) + (br * (0x100 - a))) >> 8;
259
g = ((fg * a) + (bg * (0x100 - a))) >> 8;
260
b = ((fb * a) + (bb * (0x100 - a))) >> 8;
262
switch (mymng->fbbpp) {
264
// dumb 24->16 bit conversion.
269
output = (r << 11) | (g << 5) | b;
270
*((unsigned short *) dest)++ = output;
289
mng_bool mngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
290
mng_uint32 w, mng_uint32 h)
293
unsigned char *dest, *src, *background;
295
if (sconly && current_console()!=start_console)
298
/* dereference our structure */
299
mymng = (mngstuff *) mng_get_userdata(mng);
301
dest = mymng->display + ((mymng->fby * mymng->fbwidth + mymng->fbx)
302
* (mymng->fbbpp >> 3));
303
src = mymng->copybuffer;
304
background = mymng->background;
305
/* refresh the screen with the new frame */
307
copyline(dest, src, background, mymng);
308
dest += mymng->fbwidth * (mymng->fbbpp >> 3);
309
background += mymng->width * (mymng->fbbpp >> 3);
310
src += 4 * mymng->width; // 4 bytes per pixel due to RGBA
314
memset(mymng->copybuffer, 0, 4 * mymng->width * mymng->height);
319
/* interframe delay callback */
320
mng_bool mngsettimer(mng_handle mng, mng_uint32 msecs)
324
/* look up our stream struct */
325
mymng = (mngstuff *) mng_get_userdata(mng);
327
/* set the timer for when the decoder wants to be woken */
328
mymng->delay = msecs;
333
mng_bool mngerror(mng_handle mng, mng_int32 code, mng_int8 severity,
334
mng_chunkid chunktype, mng_uint32 chunkseq,
335
mng_int32 extra1, mng_int32 extra2, mng_pchar text)
340
/* dereference our data so we can get the filename */
341
mymng = (mngstuff *) mng_get_userdata(mng);
342
/* pull out the chuck type as a string */
343
// FIXME: does this assume unsigned char?
344
chunk[0] = (char) ((chunktype >> 24) & 0xFF);
345
chunk[1] = (char) ((chunktype >> 16) & 0xFF);
346
chunk[2] = (char) ((chunktype >> 8) & 0xFF);
347
chunk[3] = (char) ((chunktype) & 0xFF);
350
/* output the error */
351
fprintf(stderr, "error playing '%s' chunk %s (%d):\n",
352
mymng->filename, chunk, chunkseq);
353
fprintf(stderr, "%s\n", text);
358
int mngquit(mng_handle mng)
362
/* dereference our data so we can free it */
363
mymng = (mngstuff *) mng_get_userdata(mng);
365
/* cleanup. this will call mymngclosestream */
380
void restore_area(void)
383
unsigned char *dest, *background;
385
if (sconly && current_console()!=start_console)
388
background = mng->background;
389
height = mng->height;
391
dest = mng->display + (mng->fbwidth * mng->fby +
392
mng->fbx) * (mng->fbbpp >> 3);
394
memcpy(dest, background, width * (mng->fbbpp >> 3));
395
background += width * (mng->fbbpp >> 3);
396
dest += mng->fbwidth * (mng->fbbpp >> 3);
2
fbmngplay - fb console MNG player.
3
(c) 2001 by Stefan Reinauer, <stepan :at: suse.de>
5
This program is based on mngplay, part of libmng, written and (C) by
6
Ralph Giles <giles :at: ashlu.bc.ca>
8
This program my be redistributed under the terms of the
9
GNU General Public Licence, version 2, or at your preference,
17
#include "fbmngplay.h"
22
unsigned char *bufferstream;
23
unsigned long bufferpos = 0, buffersize = 0;
25
inline void mdelay(unsigned long msec)
30
/* callbacks for the mng decoder */
32
/* memory allocation; data must be zeroed */
33
mng_ptr mngalloc(mng_uint32 size)
35
return (mng_ptr) calloc(1, size);
38
/* memory deallocation */
39
void mngfree(mng_ptr p, mng_uint32 size)
45
mng_bool mngopenstream(mng_handle mng)
49
/* look up our stream struct */
50
mymng = (mngstuff *) mng_get_userdata(mng);
53
mymng->file = fopen(mymng->filename, "rb");
54
if (mymng->file == NULL) {
55
fprintf(stderr, "unable to open '%s'\n", mymng->filename);
62
fseek(mymng->file, 0, SEEK_END);
63
len = ftell(mymng->file);
65
bufferstream = malloc(len);
67
/* Not enough memory for buffers
68
* -> we go back to unbuffered mode
70
printf("Reverted to non buffered mode.\n");
75
fread(bufferstream, 1, len, mymng->file);
84
mng_bool mngclosestream(mng_handle mng)
88
/* look up our stream struct */
89
mymng = (mngstuff *) mng_get_userdata(mng);
94
mymng->file = NULL; /* for safety */
105
/* feed data to the decoder */
106
mng_bool mngreadstream(mng_handle mng, mng_ptr buffer,
107
mng_uint32 size, mng_uint32 * bytesread)
111
/* look up our stream struct */
112
mymng = (mngstuff *) mng_get_userdata(mng);
114
/* read the requested amount of data from the file */
115
*bytesread = fread(buffer, 1, size, mymng->file);
117
*bytesread = (buffersize - bufferpos) <
118
size ? (buffersize - bufferpos) : size;
119
memcpy(buffer, bufferstream + bufferpos, *bytesread);
120
bufferpos += (*bytesread);
125
/* the header's been read. set up the display stuff */
126
mng_bool mngprocessheader(mng_handle mng,
127
mng_uint32 width, mng_uint32 height)
130
unsigned char *copybuffer, *background;
133
mymng = (mngstuff *) mng_get_userdata(mng);
134
mymng->width = width;
135
mymng->height = height;
138
mymng->fbx = (mymng->fbwidth)-width-15;
139
switch (mymng->fbheight) {
152
copybuffer = (unsigned char *) malloc(width * height * 4);
153
if (copybuffer == NULL) {
154
fprintf(stderr, "could not allocate copy buffer.\n");
157
mymng->copybuffer = copybuffer;
159
if (!mymng->background) {
161
(unsigned char *) malloc(width * height *
162
(mymng->fbbpp >> 3));
163
if (background == NULL) {
165
"could not allocate background buffer.\n");
168
mymng->background = background;
170
src = mymng->display + (mymng->fbwidth * mymng->fby +
171
mymng->fbx) * (mymng->fbbpp >> 3);
174
memcpy(background, src,
175
width * (mymng->fbbpp >> 3));
176
background += width * (mymng->fbbpp >> 3);
177
src += mymng->fbwidth * (mymng->fbbpp >> 3);
180
/* tell the mng decoder about our bit-depth choice */
181
/* FIXME: this works on intel. is it correct in general? */
182
mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
187
/* return a row pointer for the decoder to fill */
188
mng_ptr mnggetcanvasline(mng_handle mng, mng_uint32 line)
193
/* dereference our structure */
194
mymng = (mngstuff *) mng_get_userdata(mng);
196
/* we assume any necessary locking has happened
197
outside, in the frame level code */
198
row = mymng->copybuffer + mymng->width * 4 * line;
204
mng_uint32 mnggetticks(mng_handle mng)
210
gettimeofday(&tv, &tz);
211
ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
216
static inline void copyline(unsigned char *dest, unsigned char *src,
217
unsigned char *background, mngstuff * mymng)
220
unsigned int i = mymng->width;
221
unsigned int fr, fg, fb, br, bg, bb, r, g, b, a;
222
unsigned short output, input;
230
a = a * mymng->alpha / 100;
231
switch (mymng->fbbpp) {
233
input = *((unsigned short *) background)++;
234
br = (input >> 8) & 0xf8;
235
bg = (input >> 3) & 0xfc;
236
bb = input << 3 & 0xff;
253
printf("depth not supported.\n");
258
r = ((fr * a) + (br * (0x100 - a))) >> 8;
259
g = ((fg * a) + (bg * (0x100 - a))) >> 8;
260
b = ((fb * a) + (bb * (0x100 - a))) >> 8;
262
switch (mymng->fbbpp) {
264
// dumb 24->16 bit conversion.
269
output = (r << 11) | (g << 5) | b;
270
*((unsigned short *) dest)++ = output;
289
mng_bool mngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
290
mng_uint32 w, mng_uint32 h)
293
unsigned char *dest, *src, *background;
295
if (sconly && current_console()!=start_console)
298
/* dereference our structure */
299
mymng = (mngstuff *) mng_get_userdata(mng);
301
dest = mymng->display + ((mymng->fby * mymng->fbwidth + mymng->fbx)
302
* (mymng->fbbpp >> 3));
303
src = mymng->copybuffer;
304
background = mymng->background;
305
/* refresh the screen with the new frame */
307
copyline(dest, src, background, mymng);
308
dest += mymng->fbwidth * (mymng->fbbpp >> 3);
309
background += mymng->width * (mymng->fbbpp >> 3);
310
src += 4 * mymng->width; // 4 bytes per pixel due to RGBA
314
memset(mymng->copybuffer, 0, 4 * mymng->width * mymng->height);
319
/* interframe delay callback */
320
mng_bool mngsettimer(mng_handle mng, mng_uint32 msecs)
324
/* look up our stream struct */
325
mymng = (mngstuff *) mng_get_userdata(mng);
327
/* set the timer for when the decoder wants to be woken */
328
mymng->delay = msecs;
333
mng_bool mngerror(mng_handle mng, mng_int32 code, mng_int8 severity,
334
mng_chunkid chunktype, mng_uint32 chunkseq,
335
mng_int32 extra1, mng_int32 extra2, mng_pchar text)
340
/* dereference our data so we can get the filename */
341
mymng = (mngstuff *) mng_get_userdata(mng);
342
/* pull out the chuck type as a string */
343
// FIXME: does this assume unsigned char?
344
chunk[0] = (char) ((chunktype >> 24) & 0xFF);
345
chunk[1] = (char) ((chunktype >> 16) & 0xFF);
346
chunk[2] = (char) ((chunktype >> 8) & 0xFF);
347
chunk[3] = (char) ((chunktype) & 0xFF);
350
/* output the error */
351
fprintf(stderr, "error playing '%s' chunk %s (%d):\n",
352
mymng->filename, chunk, chunkseq);
353
fprintf(stderr, "%s\n", text);
358
int mngquit(mng_handle mng)
362
/* dereference our data so we can free it */
363
mymng = (mngstuff *) mng_get_userdata(mng);
365
/* cleanup. this will call mymngclosestream */
380
void restore_area(void)
383
unsigned char *dest, *background;
385
if (sconly && current_console()!=start_console)
388
background = mng->background;
389
height = mng->height;
391
dest = mng->display + (mng->fbwidth * mng->fby +
392
mng->fbx) * (mng->fbbpp >> 3);
394
memcpy(dest, background, width * (mng->fbbpp >> 3));
395
background += width * (mng->fbbpp >> 3);
396
dest += mng->fbwidth * (mng->fbbpp >> 3);