// Open a BMP stream static int openbmp(char *filename, char *packfilename){ if((handle=openpackfile(filename,packfilename))==-1) return 0; if(readpackfile(handle,&bmp_header,sizeof(s_bmpheader))!=sizeof(s_bmpheader)){ closepackfile(handle); return 0; } if(bmp_header.bm!=0x4D42 || bmp_header.bpp!=8 || bmp_header.compression){ closepackfile(handle); return 0; } current_res[0] = bmp_header.xsize; current_res[1] = bmp_header.ysize; return 1; }
static void closepng() { if (handle >= 0) { closepackfile(handle); } handle = -1; }
void webm_close(webm_context *ctx) { quit_video = 1; thread_join(ctx->the_demux_thread); thread_join(ctx->the_video_thread); close_video(&(ctx->video_ctx)); if (ctx->the_audio_thread) thread_join(ctx->the_audio_thread); if (ctx->audio_track >= 0) close_audio(&(ctx->audio_ctx)); nestegg_destroy(ctx->nestegg_ctx); closepackfile(ctx->packhandle); free(ctx); }
static void closepng() { int y; png_read_destroy_all(); if(row_pointers) { for (y = 0; y < png_height; y++) { free(row_pointers[y]); row_pointers[y] = NULL; } free(row_pointers); row_pointers = NULL; } png_height = 0; if(handle >= 0) { closepackfile(handle); } handle = -1; }
// Open a BMP stream static int openbmp(char *filename, char *packfilename) { #if DC || GP2X || SYMBIAN unsigned char mybmpheader[0x36]; #endif if((handle = openpackfile(filename, packfilename)) == -1) { return 0; } #if DC || GP2X || SYMBIAN if(readpackfile(handle, &mybmpheader, 0x36) != 0x36) { #else if(readpackfile(handle, &bmp_header, sizeof(s_bmpheader)) != sizeof(s_bmpheader)) { #endif closepackfile(handle); return 0; } #if DC || GP2X || SYMBIAN build_bmp_header(&bmp_header, mybmpheader); #else bmp_header.bm = SwapLSB16(bmp_header.bm); bmp_header.numplanes = SwapLSB16(bmp_header.numplanes); bmp_header.bpp = SwapLSB16(bmp_header.bpp); bmp_header.filesize = SwapLSB32(bmp_header.filesize); bmp_header.reserved = SwapLSB32(bmp_header.reserved); bmp_header.picstart = SwapLSB32(bmp_header.picstart); bmp_header.headersize = SwapLSB32(bmp_header.headersize); bmp_header.xsize = SwapLSB32(bmp_header.xsize); bmp_header.ysize = SwapLSB32(bmp_header.ysize); bmp_header.filesize = SwapLSB32(bmp_header.filesize); bmp_header.compression = SwapLSB32(bmp_header.compression); bmp_header.picsize = SwapLSB32(bmp_header.picsize); bmp_header.hres = SwapLSB32(bmp_header.hres); bmp_header.vres = SwapLSB32(bmp_header.vres); bmp_header.numcolors_used = SwapLSB32(bmp_header.numcolors_used); bmp_header.numcolors_important = SwapLSB32(bmp_header.numcolors_important); #endif if(bmp_header.bm != 0x4D42 || bmp_header.bpp != 8 || bmp_header.compression) { closepackfile(handle); return 0; } res[0] = bmp_header.xsize; res[1] = bmp_header.ysize; return 1; } // Read data from the bitmap file static int readbmp(unsigned char *buf, unsigned char *pal, int maxwidth, int maxheight) { unsigned char *linebuffer; int y, s, d; int pb = PAL_BYTES; if(buf) { y = 0; while(y < maxheight && y < bmp_header.ysize) { linebuffer = buf + y * maxwidth; seekpackfile(handle, bmp_header.picstart + ((bmp_header.ysize - y - 1)*bmp_header.xsize), SEEK_SET); readpackfile(handle, linebuffer, bmp_header.xsize); ++y; } } if(pal && (linebuffer = (unsigned char *)malloc(1024))) { seekpackfile(handle, bmp_header.picstart - 1024, SEEK_SET); readpackfile(handle, linebuffer, 1024); if(pb == 512) // 16bit 565 { for(s = 0, d = 0; s < 1024; s += 4, d += 2) { *(unsigned short *)(pal + d) = colour16(linebuffer[s + 2], linebuffer[s + 1], linebuffer[s]); } } else if(pb == 768) // 24bit palette, RGBA-BGR { for(s = 0, d = 0; s < 1024; s += 4, d += 3) { pal[d] = linebuffer[s + 2]; pal[d + 1] = linebuffer[s + 1]; pal[d + 2] = linebuffer[s]; } } else if(pb == 1024) { for(s = 0, d = 0; s < 1024; s += 4, d += 4) { *(unsigned *)(pal + d) = colour32(linebuffer[s + 2], linebuffer[s + 1], linebuffer[s]); } } free(linebuffer); linebuffer = NULL; } return 1; }
// return 1 on success, 0 on error static int openpng(const char *filename, const char *packfilename) { static int warned_about_interlacing = 0; if ((handle = openpackfile(filename, packfilename)) == -1) { goto openpng_abort; } uint64_t magic; if (readpackfile(handle, &magic, 8) != 8) { goto openpng_abort; } if (magic != SwapMSB64(PNG_MAGIC)) { goto openpng_abort; } struct png_chunk_header chunk_header; if (readpackfile(handle, &chunk_header, sizeof(chunk_header)) != sizeof(chunk_header)) { goto openpng_abort; } if (SwapMSB32(chunk_header.chunk_size) != 13 || chunk_header.chunk_name != SwapMSB32(PNG_CHUNK_IHDR)) { goto openpng_abort; } char ihdr_data[13]; uint32_t *ihdr_data32 = (uint32_t *)ihdr_data; if (readpackfile(handle, &ihdr_data, sizeof(ihdr_data)) != sizeof(ihdr_data)) { goto openpng_abort; } uint32_t width = SwapMSB32(ihdr_data32[0]); uint32_t height = SwapMSB32(ihdr_data32[1]); res[0] = width; res[1] = height; // Bit depth must be 8 for our purposes. Compression and filter method must be 0 in all PNGs. if (ihdr_data[8] != 8 || ihdr_data[10] != 0 || ihdr_data[11] != 0) { goto openpng_abort; } // Color type must be grayscale or indexed. else if (ihdr_data[9] != 0 && ihdr_data[9] != 3) { goto openpng_abort; } if (ihdr_data[12] == 1) { if (!warned_about_interlacing) { // Only print this warning once printf("Warning: The image %s is interlaced. For faster load times, use non-interlaced images.\n", filename); warned_about_interlacing = 1; } } // Interlacing mode must be either 0 (disabled) or 1 (Adam7). else if (ihdr_data[12] != 0) { goto openpng_abort; } png_is_interlaced = ihdr_data[12]; return 1; openpng_abort: closepackfile(handle); handle = -1; return 0; }
static void closebmp(){ closepackfile(handle); handle = -1; }
/** * Reads a script file into an allocated buffer. Be sure to call free() on the * returned buffer when you are done with it! * * Returns the buffer on success, NULL on failure. */ static char *readScript(const char *path) { #if 1 // stdio version char *scriptText = NULL; int fileSize; FILE *fp = fopen(path, "rb"); if(!fp) goto error; if (fseek(fp, 0, SEEK_END) < 0) goto error; fileSize = ftell(fp); scriptText = (char*) malloc(fileSize + 1); if (fseek(fp, 0, SEEK_SET) < 0) goto error; if ((int)fread(scriptText, 1, fileSize, fp) != fileSize) goto error; scriptText[fileSize] = 0; fclose(fp); return scriptText; error: // ideally, this error message would include the name of the file that tried to import this file printf("Script error: unable to open file '%s' for importing\n", path); if (scriptText) { free(scriptText); } if (fp) { fclose(fp); } return NULL; #else // packfile I/O version int handle = openpackfile(path, packfile); int size; char *buffer = NULL; if(handle < 0) { goto error; } size = seekpackfile(handle, 0, SEEK_END); if(size < 0) { goto error; } buffer = malloc(size + 1); if(buffer == NULL) { goto error; } if(seekpackfile(handle, 0, SEEK_SET) < 0) { goto error; } if(readpackfile(handle, buffer, size) < 0) { goto error; } closepackfile(handle); buffer[size] = '\0'; return buffer; error: // ideally, this error message would include the name of the file that tried to import this file printf("Script error: unable to open file '%s' for importing\n", path); if(buffer) { free(buffer); } if(handle >= 0) { closepackfile(handle); } return NULL; #endif }
webm_context *webm_start_playback(const char *path, int volume) { webm_context *ctx; nestegg_io io; int video_track = -1, audio_track = -1; quit_video = 0; ctx = malloc(sizeof(*ctx)); if(!ctx) return NULL; memset(ctx, 0, sizeof(*ctx)); // set up I/O callbacks io.read = webm_read; io.seek = webm_seek; io.tell = webm_tell; // open video file ctx->packhandle = openpackfile(path, packfile); if(ctx->packhandle < 0) { printf("Error: Unable to open file %s for playback\n", path); goto error1; } io.userdata = (void*)ctx->packhandle; if(nestegg_init(&(ctx->nestegg_ctx), io, NULL, -1) < 0) goto error2; // get number of tracks unsigned int num_tracks, i; if(nestegg_track_count(ctx->nestegg_ctx, &num_tracks) < 0) goto error3; // find the first video and audio tracks for (i = 0; i < num_tracks; i++) { int track_type = nestegg_track_type(ctx->nestegg_ctx, i); int codec = nestegg_track_codec_id(ctx->nestegg_ctx, i); if (track_type == NESTEGG_TRACK_VIDEO) { if(codec != NESTEGG_CODEC_VP8) { printf("Error: unsupported video codec; only VP8 is supported\n"); goto error3; } video_track = i; } else if (track_type == NESTEGG_TRACK_AUDIO) { if(codec != NESTEGG_CODEC_VORBIS) { printf("Error: unsupported audio codec; only Vorbis is supported\n"); goto error3; } audio_track = i; } } // set up video ctx->video_track = video_track; init_video(ctx->nestegg_ctx, ctx->video_track, &(ctx->video_ctx)); ctx->the_video_thread = thread_create(video_thread, "video", &(ctx->video_ctx)); assert(ctx->the_video_thread); // set up audio, if applicable ctx->audio_track = audio_track; if (audio_track >= 0) { // use the audio track of this file init_audio(ctx->nestegg_ctx, ctx->audio_track, &(ctx->audio_ctx), volume); ctx->the_audio_thread = thread_create(audio_thread, "audio", &(ctx->audio_ctx)); assert(ctx->the_audio_thread); } else if (sound_query_music(NULL, NULL)) { // continue to play the BGM that's already playing ctx->the_audio_thread = thread_create(bgm_update_thread, "bgm", NULL); assert(ctx->the_audio_thread); } // finally, start the demuxing thread ctx->the_demux_thread = thread_create(demux_thread, "demux", ctx); assert(ctx->the_demux_thread); return ctx; error3: nestegg_destroy(ctx->nestegg_ctx); error2: closepackfile(ctx->packhandle); error1: free(ctx); return NULL; }