summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobin KAY <komadori@users.sourceforge.net>2002-12-20 01:47:01 +0000
committerRobin KAY <komadori@users.sourceforge.net>2002-12-20 01:47:01 +0000
commit3572708fa1fc7464ae75d567a0126326a80d48ee (patch)
treee19ffead5d1559bd0eebe1d9b49d5fb1d2cdeab7 /src
parente497eb1f9172f0e620e807a99b3379b7348d6410 (diff)
downloadxine-lib-3572708fa1fc7464ae75d567a0126326a80d48ee.tar.gz
xine-lib-3572708fa1fc7464ae75d567a0126326a80d48ee.tar.bz2
MNG demuxer added
CVS patchset: 3592 CVS date: 2002/12/20 01:47:01
Diffstat (limited to 'src')
-rw-r--r--src/demuxers/demux_mng.c403
1 files changed, 403 insertions, 0 deletions
diff --git a/src/demuxers/demux_mng.c b/src/demuxers/demux_mng.c
new file mode 100644
index 000000000..5a16b16c1
--- /dev/null
+++ b/src/demuxers/demux_mng.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: demux_mng.c,v 1.1 2002/12/20 01:47:01 komadori Exp $
+ *
+ * demux_mng.c, Demuxer plugin for Multiple-image Network Graphics format
+ *
+ * written and currently maintained by Robin Kay <komadori@myrealbox.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <libmng.h>
+
+#include "xine_internal.h"
+#include "xineutils.h"
+#include "demux.h"
+
+typedef struct {
+ demux_plugin_t demux_plugin;
+ xine_stream_t *stream;
+ config_values_t *config;
+ fifo_buffer_t *video_fifo;
+ input_plugin_t *input;
+
+ int thread_running;
+ int status;
+
+ mng_handle mngh;
+ xine_bmiheader bih;
+ void *image;
+ int started, tick_count, timer_count;
+
+ char last_mrl[1024];
+} demux_mng_t;
+
+typedef struct {
+ demux_class_t demux_class;
+
+ /* class-wide, global variables here */
+
+ xine_t *xine;
+ config_values_t *config;
+} demux_mng_class_t;
+
+static mng_ptr mymng_alloc(mng_uint32 size)
+{
+ return (mng_ptr)calloc(1, size);
+}
+
+static void mymng_free(mng_ptr p, mng_uint32 size)
+{
+ free(p);
+}
+
+mng_bool mymng_open_stream(mng_handle mngh)
+{
+ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ if (this->input->get_current_pos(this->input) != 0) {
+ if ((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) == 0) {
+ return MNG_FALSE;
+ }
+ this->input->seek(this->input, 0, SEEK_SET);
+ }
+
+ return MNG_TRUE;
+}
+
+mng_bool mymng_close_stream(mng_handle mngh)
+{
+ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ this->status = DEMUX_FINISHED;
+
+ return MNG_TRUE;
+}
+
+mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread)
+{
+ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ *bytesread = this->input->read(this->input, buffer, size);
+
+ return MNG_TRUE;
+}
+
+mng_bool mymng_process_header(mng_handle mngh, mng_uint32 width, mng_uint32 height)
+{
+ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ this->bih.biWidth = width;
+ this->bih.biHeight = height;
+
+ this->image = malloc(width * height * 3);
+
+ mng_set_canvasstyle(mngh, MNG_CANVAS_RGB8);
+
+ return MNG_TRUE;
+}
+
+mng_uint32 mymng_get_tick_count(mng_handle mngh)
+{
+ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ return this->tick_count;
+}
+
+mng_bool mymng_set_timer(mng_handle mngh, mng_uint32 msecs)
+{
+ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ this->timer_count = msecs;
+
+ return MNG_TRUE;
+}
+
+mng_ptr mymng_get_canvas_line(mng_handle mngh, mng_uint32 line)
+{
+ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ return this->image + line * this->bih.biWidth * 3;
+}
+
+mng_bool mymng_refresh(mng_handle mngh, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
+{
+ return MNG_TRUE;
+}
+
+/*
+ * !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT!
+ * All the following functions are defined by the xine demuxer API
+ * !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT!
+ */
+
+static int demux_mng_send_chunk(demux_mng_t *this)
+{
+ int size = this->bih.biWidth * this->bih.biHeight * 3;
+ void *image_ptr = this->image;
+
+ int err = mng_display_resume(this->mngh);
+ if ((err != MNG_NOERROR) && (err != MNG_NEEDTIMERWAIT)) {
+ fprintf(stderr, "demux_mng: mng_display_resume returned an error (%d)\n", err);
+ this->status = DEMUX_FINISHED;
+ }
+
+ while (size > 0) {
+ buf_element_t *buf;
+
+ buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
+ buf->type = BUF_VIDEO_RGB;
+ buf->decoder_flags = BUF_FLAG_FRAMERATE;
+ buf->decoder_info[0] = 90 * this->timer_count;
+ buf->input_pos = this->input->get_current_pos(this->input);
+ buf->input_time = this->tick_count / 1000;
+ buf->pts = 90 * this->tick_count;
+
+ if (size > buf->max_size) {
+ buf->size = buf->max_size;
+ }
+ else {
+ buf->size = size;
+ }
+ size -= buf->size;
+
+ memcpy(buf->content, image_ptr, buf->size);
+ image_ptr += buf->size;
+
+ if (size == 0) {
+ buf->decoder_flags |= BUF_FLAG_FRAME_END;
+ }
+
+ this->video_fifo->put(this->video_fifo, buf);
+ }
+
+ this->tick_count += this->timer_count;
+ this->timer_count = 0;
+
+ return this->status;
+}
+
+static void demux_mng_send_headers(demux_mng_t *this)
+{
+ buf_element_t *buf;
+
+ this->video_fifo = this->stream->video_fifo;
+
+ this->status = DEMUX_OK;
+
+ /* load stream information */
+ this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1;
+ this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 0;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->bih.biWidth;
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->bih.biHeight;
+
+ /* send start buffers */
+ xine_demux_control_start(this->stream);
+
+ /* send init info to decoder */
+ this->bih.biBitCount = 24;
+ buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
+ buf->type = BUF_VIDEO_RGB;
+ buf->size = sizeof(xine_bmiheader);
+ memcpy(buf->content, &this->bih, sizeof(xine_bmiheader));
+ buf->decoder_flags = BUF_FLAG_HEADER;
+ this->video_fifo->put(this->video_fifo, buf);
+}
+
+static int demux_mng_seek(demux_mng_t *this, off_t start_pos, int start_time)
+{
+ return this->status;
+}
+
+static void demux_mng_dispose(demux_mng_t *this)
+{
+ mng_cleanup(&this->mngh);
+
+ if (this->image) {
+ free(this->image);
+ }
+
+ free(this);
+}
+
+static int demux_mng_get_status(demux_mng_t *this)
+{
+ return this->status;
+}
+
+static int demux_mng_get_stream_length(demux_mng_t *this)
+{
+ return 0;
+}
+
+static uint32_t demux_mng_get_capabilities(demux_plugin_t *this_gen) {
+ return DEMUX_CAP_NOCAP;
+}
+
+static int demux_mng_get_optional_data(demux_plugin_t *this_gen, void *data, int data_type) {
+ return DEMUX_OPTIONAL_UNSUPPORTED;
+}
+
+static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen)
+{
+ input_plugin_t *input = (input_plugin_t *) input_gen;
+ demux_mng_t *this;
+
+ this = xine_xmalloc (sizeof (demux_mng_t));
+ this->stream = stream;
+ this->input = input;
+
+ this->demux_plugin.send_headers = (void*)demux_mng_send_headers;
+ this->demux_plugin.send_chunk = (void*)demux_mng_send_chunk;
+ this->demux_plugin.seek = (void*)demux_mng_seek;
+ this->demux_plugin.dispose = (void*)demux_mng_dispose;
+ this->demux_plugin.get_status = (void*)demux_mng_get_status;
+ this->demux_plugin.get_stream_length = (void*)demux_mng_get_stream_length;
+ this->demux_plugin.get_video_frame = NULL;
+ this->demux_plugin.got_video_frame_cb= NULL;
+ this->demux_plugin.get_capabilities = demux_mng_get_capabilities;
+ this->demux_plugin.get_optional_data = demux_mng_get_optional_data;
+ this->demux_plugin.demux_class = class_gen;
+
+ this->status = DEMUX_FINISHED;
+
+ switch (stream->content_detection_method) {
+ case METHOD_BY_CONTENT:
+ case METHOD_EXPLICIT:
+ if ((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) == 0) {
+ free(this);
+ return NULL;
+ }
+ break;
+
+ case METHOD_BY_EXTENSION: {
+ char *ending, *mrl;
+
+ mrl = input->get_mrl(input);
+
+ ending = strrchr(mrl, '.');
+ if (!ending) {
+ free(this);
+ return NULL;
+ }
+
+ if (strncasecmp(ending, ".mng", 4) && strncasecmp(ending, ".png", 4)) {
+ free(this);
+ return NULL;
+ }
+ }
+ break;
+
+ default:
+ free(this);
+ return NULL;
+ break;
+ }
+
+ if ((this->mngh = mng_initialize(this, mymng_alloc, mymng_free, MNG_NULL)) == MNG_NULL) {
+ free(this);
+ return NULL;
+ }
+
+ if (mng_setcb_openstream(this->mngh, mymng_open_stream) ||
+ mng_setcb_closestream(this->mngh, mymng_close_stream) ||
+ mng_setcb_readdata(this->mngh, mymng_read_stream) ||
+ mng_setcb_processheader(this->mngh, mymng_process_header) ||
+ mng_setcb_gettickcount(this->mngh, mymng_get_tick_count) ||
+ mng_setcb_settimer(this->mngh, mymng_set_timer) ||
+ mng_setcb_getcanvasline(this->mngh, mymng_get_canvas_line) ||
+ mng_setcb_refresh(this->mngh, mymng_refresh)) {
+ mng_cleanup(&this->mngh);
+ free(this);
+ return NULL;
+ }
+
+ {
+ int err = mng_readdisplay(this->mngh);
+ if ((err != MNG_NOERROR) && (err != MNG_NEEDTIMERWAIT)) {
+ mng_cleanup(&this->mngh);
+ free(this);
+ return NULL;
+ }
+ }
+
+ strncpy (this->last_mrl, input->get_mrl(input), 1024);
+
+ return &this->demux_plugin;
+}
+
+static char *get_description(demux_class_t *this_gen)
+{
+ return "Multiple-image Network Graphics demux plugin";
+}
+
+static char *get_identifier(demux_class_t *this_gen)
+{
+ return "MNG";
+}
+
+static char *get_extensions(demux_class_t *this_gen)
+{
+ return "png mng";
+}
+
+static char *get_mimetypes(demux_class_t *this_gen)
+{
+ return "image/png: png: PNG image"
+ "image/x-png: png: PNG image"
+ "video/mng: mng: MNG animation"
+ "video/x-mng: mng: MNG animation";
+}
+
+static void class_dispose(demux_class_t *this)
+{
+ free (this);
+}
+
+static void *init_plugin(xine_t *xine, void *data)
+{
+ demux_mng_class_t *this;
+
+ this = xine_xmalloc (sizeof (demux_mng_class_t));
+ this->config = xine->config;
+ this->xine = xine;
+
+ this->demux_class.open_plugin = open_plugin;
+ this->demux_class.get_description = get_description;
+ this->demux_class.get_identifier = get_identifier;
+ this->demux_class.get_mimetypes = get_mimetypes;
+ this->demux_class.get_extensions = get_extensions;
+ this->demux_class.dispose = class_dispose;
+
+ return this;
+}
+
+plugin_info_t xine_plugin_info[] = {
+ { PLUGIN_DEMUX, 18, "mng", XINE_VERSION_CODE, NULL, (void*)init_plugin},
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};