summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am3
-rw-r--r--src/demuxers/demux_real.c500
-rw-r--r--src/libreal/Makefile.am29
-rw-r--r--src/libreal/xine_decoder.c386
-rw-r--r--src/xine-engine/buffer.h9
6 files changed, 813 insertions, 115 deletions
diff --git a/configure.ac b/configure.ac
index 615fb020f..62ee70e96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1153,6 +1153,7 @@ src/libw32dll/DirectShow/Makefile
src/libxinevdec/Makefile
src/libxineadec/Makefile
src/libxineadec/gsm610/Makefile
+src/libreal/Makefile
src/video_out/Makefile
src/video_out/libdha/Makefile
src/video_out/libdha/bin/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 6d887a28b..4d9c4aec1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,7 +42,8 @@ SUBDIRS = \
liblpcm \
libxinevdec \
libxineadec \
- libvorbis
+ libvorbis \
+ libreal
debug:
@list='$(SUBDIRS)'; for subdir in $$list; do \
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c
index 141a07467..c8df16963 100644
--- a/src/demuxers/demux_real.c
+++ b/src/demuxers/demux_real.c
@@ -21,7 +21,7 @@
* For more information regarding the Real file format, visit:
* http://www.pcisys.net/~melanson/codecs/
*
- * $Id: demux_real.c,v 1.8 2002/11/09 23:22:32 guenter Exp $
+ * $Id: demux_real.c,v 1.9 2002/11/18 03:03:09 guenter Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -40,6 +40,8 @@
#include "demux.h"
#include "bswap.h"
+#define LOG
+
#define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
( (long)(unsigned char)(ch3) | \
( (long)(unsigned char)(ch2) << 8 ) | \
@@ -60,15 +62,23 @@
#define PN_KEYFRAME_FLAG 0x0002
+#define MAX_STREAMS 10
+
typedef struct {
- int stream;
- int64_t offset;
- unsigned int size;
- int64_t pts;
- int keyframe;
+ int stream;
+ int64_t offset;
+ unsigned int size;
+ int64_t pts;
+ int keyframe;
} real_packet;
typedef struct {
+ int num;
+ int32_t buf_type ;
+ fifo_buffer_t *fifo;
+} stream_info_t;
+
+typedef struct {
demux_plugin_t demux_plugin;
@@ -85,6 +95,8 @@ typedef struct {
off_t data_size;
int status;
unsigned int duration;
+ int packet_count;
+ int bitrate;
unsigned int video_type;
unsigned int audio_type;
@@ -95,9 +107,8 @@ typedef struct {
unsigned int audio_sample_rate;
unsigned int audio_bits;
- unsigned int packet_count;
- unsigned int current_packet;
- real_packet *packets;
+ int num_streams;
+ stream_info_t streams[MAX_STREAMS];
unsigned int current_data_chunk_packet_count;
unsigned int next_data_chunk_offset;
@@ -115,30 +126,178 @@ typedef struct {
config_values_t *config;
} demux_real_class_t;
-/* returns 1 if the real file was opened successfully, 0 otherwise */
-static int open_real_file(demux_real_t *this) {
+typedef struct {
+
+ u_int16_t object_version;
+
+ u_int16_t stream_number;
+ u_int32_t max_bit_rate;
+ u_int32_t avg_bit_rate;
+ u_int32_t max_packet_size;
+ u_int32_t avg_packet_size;
+ u_int32_t start_time;
+ u_int32_t preroll;
+ u_int32_t duration;
+ char stream_name_size;
+ char *stream_name;
+ char mime_type_size;
+ char *mime_type;
+ u_int32_t type_specific_len;
+ char *type_specific_data;
+
+} pnm_mdpr_t;
+
+void hexdump (char *buf, int length) {
+
+ int i;
+
+ printf ("pnm: ascii contents>");
+ for (i = 0; i < length; i++) {
+ unsigned char c = buf[i];
+
+ if ((c >= 32) && (c <= 128))
+ printf ("%c", c);
+ else
+ printf (".");
+ }
+ printf ("\n");
+
+ printf ("pnm: complete hexdump of package follows:\npnm: ");
+ for (i = 0; i < length; i++) {
+ unsigned char c = buf[i];
+
+ printf ("%02x", c);
+
+ if ((i % 16) == 15)
+ printf ("\npnm: ");
+
+ if ((i % 2) == 1)
+ printf (" ");
+
+ }
+ printf ("\n");
+}
+
+static pnm_mdpr_t *pnm_parse_mdpr(const char *data) {
+
+ pnm_mdpr_t *mdpr=malloc(sizeof(pnm_mdpr_t));
+
+ mdpr->object_version=BE_16(&data[0]);
+
+ if (mdpr->object_version != 0) {
+ printf("warning: unknown object version in MDPR: 0x%04x\n",
+ mdpr->object_version);
+ }
+
+ mdpr->stream_number=BE_16(&data[2]);
+ mdpr->max_bit_rate=BE_32(&data[4]);
+ mdpr->avg_bit_rate=BE_32(&data[8]);
+ mdpr->max_packet_size=BE_32(&data[12]);
+ mdpr->avg_packet_size=BE_32(&data[16]);
+ mdpr->start_time=BE_32(&data[20]);
+ mdpr->preroll=BE_32(&data[24]);
+ mdpr->duration=BE_32(&data[28]);
+
+ mdpr->stream_name_size=data[32];
+ mdpr->stream_name=malloc(sizeof(char)*(mdpr->stream_name_size+1));
+ memcpy(mdpr->stream_name, &data[33], mdpr->stream_name_size);
+ mdpr->stream_name[mdpr->stream_name_size]=0;
+
+ mdpr->mime_type_size=data[33+mdpr->stream_name_size];
+ mdpr->mime_type=malloc(sizeof(char)*(mdpr->mime_type_size+1));
+ memcpy(mdpr->mime_type, &data[34+mdpr->stream_name_size], mdpr->mime_type_size);
+ mdpr->mime_type[mdpr->mime_type_size]=0;
+
+ mdpr->type_specific_len=BE_32(&data[34+mdpr->stream_name_size+mdpr->mime_type_size]);
+ mdpr->type_specific_data=malloc(sizeof(char)*(mdpr->type_specific_len));
+ memcpy(mdpr->type_specific_data,
+ &data[38+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len);
+
+ printf("pnm: MDPR: stream number: %i\n", mdpr->stream_number);
+ printf("pnm: MDPR: maximal bit rate: %i\n", mdpr->max_bit_rate);
+ printf("pnm: MDPR: average bit rate: %i\n", mdpr->avg_bit_rate);
+ printf("pnm: MDPR: largest packet size: %i bytes\n", mdpr->max_packet_size);
+ printf("pnm: MDPR: average packet size: %i bytes\n", mdpr->avg_packet_size);
+ printf("pnm: MDPR: start time: %i\n", mdpr->start_time);
+ printf("pnm: MDPR: pre-buffer: %i ms\n", mdpr->preroll);
+ printf("pnm: MDPR: duration of stream: %i ms\n", mdpr->duration);
+ printf("pnm: MDPR: stream name: %s\n", mdpr->stream_name);
+ printf("pnm: MDPR: mime type: %s\n", mdpr->mime_type);
+ printf("pnm: MDPR: type specific data:\n");
+ hexdump(mdpr->type_specific_data, mdpr->type_specific_len);
+ printf("\n");
+
+ return mdpr;
+}
+
+typedef struct dp_hdr_s {
+ uint32_t chunks; /* number of chunks */
+ uint32_t timestamp; /* timestamp from packet header */
+ uint32_t len; /* length of actual data */
+ uint32_t chunktab; /* offset to chunk offset array */
+} dp_hdr_t;
+
+static void send_real_buf (demux_real_t *this, uint32_t timestamp, int len,
+ fifo_buffer_t *fifo,
+ uint32_t buf_type, uint32_t decoder_flags) {
+
+ dp_hdr_t *hdr;
+ buf_element_t *buf;
+
+ if (!fifo) {
+ this->input->seek (this->input, len, SEEK_CUR);
+ return;
+ }
+
+ buf = fifo->buffer_pool_alloc (fifo);
+
+ buf->content = buf->mem;
+
+ hdr = buf->content;
+ hdr->chunks = 1;
+ hdr->timestamp = timestamp;
+ hdr->len = len;
+ hdr->chunktab = 0;
+
+ this->input->read (this->input, buf->content+16, len);
+
+ buf->size = len+16;
+
+ buf->input_pos = 0 ; /* FIXME */
+ buf->input_time = 0 ; /* FIXME */
+ buf->type = buf_type;
+ buf->decoder_flags = decoder_flags;
+
+ fifo->put (fifo, buf);
+
+}
+
+
+static void real_parse_headers (demux_real_t *this) {
- char preamble[PREAMBLE_SIZE];
- unsigned int chunk_type = 0;
- unsigned int chunk_size;
+ char preamble[PREAMBLE_SIZE];
+ unsigned int chunk_type = 0;
+ unsigned int chunk_size;
unsigned char *chunk_buffer;
- int field_size;
- int stream_ptr;
- unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
- unsigned char signature[REAL_SIGNATURE_SIZE];
+ int field_size;
+ int stream_ptr;
+ unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
+ unsigned char signature[REAL_SIGNATURE_SIZE];
this->data_start = 0;
this->data_size = 0;
- this->packets = NULL;
- this->current_packet = 0;
this->input->seek(this->input, 0, SEEK_SET);
if (this->input->read(this->input, signature, REAL_SIGNATURE_SIZE) !=
- REAL_SIGNATURE_SIZE)
- return 0;
+ REAL_SIGNATURE_SIZE) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
- if (BE_32(signature) != RMF_TAG)
- return 0;
+ if (BE_32(signature) != RMF_TAG) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
/* skip to the start of the first chunk (the first chunk is 0x12 bytes
* long) and start traversing */
@@ -149,8 +308,10 @@ static int open_real_file(demux_real_t *this) {
while (chunk_type != DATA_TAG) {
if (this->input->read(this->input, preamble, PREAMBLE_SIZE) !=
- PREAMBLE_SIZE)
- return 0;
+ PREAMBLE_SIZE) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
chunk_type = BE_32(&preamble[0]);
chunk_size = BE_32(&preamble[4]);
@@ -163,9 +324,9 @@ static int open_real_file(demux_real_t *this) {
chunk_size -= PREAMBLE_SIZE;
chunk_buffer = xine_xmalloc(chunk_size);
if (this->input->read(this->input, chunk_buffer, chunk_size) !=
- chunk_size) {
- free(chunk_buffer);
- return 0;
+ chunk_size) {
+ this->status = DEMUX_FINISHED;
+ return;
}
if (chunk_type == PROP_TAG) {
@@ -176,6 +337,91 @@ static int open_real_file(demux_real_t *this) {
} else if (chunk_type == MDPR_TAG) {
+ pnm_mdpr_t *mdpr;
+
+ mdpr = pnm_parse_mdpr (chunk_buffer);
+
+ this->bitrate = mdpr->avg_bit_rate;
+ this->stream->stream_info[XINE_STREAM_INFO_BITRATE] = mdpr->avg_bit_rate;
+
+ /* detect streamtype */
+
+ this->streams[this->num_streams].num = mdpr->stream_number;
+
+ if (!strncmp (mdpr->type_specific_data+4, "VIDORV20", 8)) {
+
+ buf_element_t *buf;
+
+ this->streams[this->num_streams].buf_type = BUF_VIDEO_RV20;
+ this->streams[this->num_streams].fifo = this->video_fifo;
+
+ printf ("demux_real: RV20 video detected\n");
+
+ this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1;
+
+ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+
+ buf->content = buf->mem;
+
+ memcpy (buf->content, mdpr->type_specific_data,
+ mdpr->type_specific_len);
+
+ buf->size = mdpr->type_specific_len;
+
+ buf->input_pos = 0 ;
+ buf->input_time = 0 ;
+ buf->type = BUF_VIDEO_RV20;
+ buf->decoder_flags = BUF_FLAG_HEADER;
+
+ this->video_fifo->put (this->video_fifo, buf);
+
+ } else if (!strncmp (mdpr->type_specific_data+4, "VIDORV30", 8)) {
+
+ buf_element_t *buf;
+
+ this->streams[this->num_streams].buf_type = BUF_VIDEO_RV30;
+ this->streams[this->num_streams].fifo = this->video_fifo;
+
+ printf ("demux_real: RV30 video detected\n");
+
+ this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1;
+
+ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+
+ buf->content = buf->mem;
+
+ memcpy (buf->content, mdpr->type_specific_data,
+ mdpr->type_specific_len);
+
+ buf->size = mdpr->type_specific_len;
+
+ buf->input_pos = 0 ;
+ buf->input_time = 0 ;
+ buf->type = BUF_VIDEO_RV30;
+ buf->decoder_flags = BUF_FLAG_HEADER;
+
+ this->video_fifo->put (this->video_fifo, buf);
+
+ } else if ((mdpr->type_specific_len>61)
+ && (!strncmp (mdpr->type_specific_data+57, "sipr", 4))) {
+
+ this->streams[this->num_streams].buf_type = BUF_AUDIO_SIPRO;
+ this->streams[this->num_streams].fifo = this->audio_fifo;
+
+ printf ("demux_real: sipro audio detected\n");
+
+ this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 1;
+
+ } else {
+
+ printf ("demux_real: codec not recognized\n");
+
+ this->streams[this->num_streams].buf_type = 0;
+ this->streams[this->num_streams].fifo = NULL;
+ }
+
+ this->num_streams++;
+ free (mdpr);
} else if (chunk_type == CONT_TAG) {
@@ -227,8 +473,11 @@ static int open_real_file(demux_real_t *this) {
case DATA_TAG:
if (this->input->read(this->input, data_chunk_header,
- DATA_CHUNK_HEADER_SIZE) != DATA_CHUNK_HEADER_SIZE)
- return 0;
+ DATA_CHUNK_HEADER_SIZE) != DATA_CHUNK_HEADER_SIZE) {
+ this->status = DEMUX_FINISHED;
+ return ;
+ }
+
this->current_data_chunk_packet_count = BE_32(&data_chunk_header[2]);
this->next_data_chunk_offset = BE_32(&data_chunk_header[6]);
break;
@@ -240,54 +489,59 @@ static int open_real_file(demux_real_t *this) {
}
}
-
- /* allocate space for the packet list */
- this->packets = xine_xmalloc(this->packet_count * sizeof(real_packet));
-
- return 1;
}
static int demux_real_send_chunk(demux_plugin_t *this_gen) {
- demux_real_t *this = (demux_real_t *) this_gen;
- buf_element_t *buf = NULL;
- char preamble[PREAMBLE_SIZE];
- unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
- char header[DATA_PACKET_HEADER_SIZE];
+ demux_real_t *this = (demux_real_t *) this_gen;
+ char preamble[PREAMBLE_SIZE];
+ unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
+ char header[DATA_PACKET_HEADER_SIZE];
+ int stream_num,i;
+ int stream, size, keyframe;
+ uint32_t timestamp;
+ int64_t pts;
+ off_t offset;
/* load a header from wherever the stream happens to be pointing */
if (this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE) !=
- DATA_PACKET_HEADER_SIZE) {
+ DATA_PACKET_HEADER_SIZE) {
this->status = DEMUX_FINISHED;
return this->status;
}
- /* log the packet information */
- this->packets[this->current_packet].stream = BE_16(&header[4]);
- this->packets[this->current_packet].offset =
- this->input->get_current_pos(this->input);
- this->packets[this->current_packet].size =
- BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE;
- this->packets[this->current_packet].pts =
- BE_32(&header[6]);
- this->packets[this->current_packet].pts *= 90;
- this->packets[this->current_packet].keyframe =
- (header[11] & PN_KEYFRAME_FLAG);
+ /* read the packet information */
+ stream = BE_16(&header[4]);
+ offset = this->input->get_current_pos(this->input);
+ size = BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE;
+ timestamp= BE_32(&header[6]);
+ pts = (int64_t) timestamp * 90;
+ keyframe = header[11] & PN_KEYFRAME_FLAG;
+
+#ifdef LOG
+ printf ("demux_real: packet of stream %d, 0x%X bytes @ %llX, pts = %lld%s\n",
+ stream, size, offset, pts, keyframe ? ", keyframe" : "");
+#endif
+
+ stream_num = -1;
-printf ("packet %d: stream %d, 0x%X bytes @ %llX, pts = %lld%s\n",
-this->current_packet,
-this->packets[this->current_packet].stream,
-this->packets[this->current_packet].size,
-this->packets[this->current_packet].offset,
-this->packets[this->current_packet].pts,
-(this->packets[this->current_packet].keyframe) ? ", keyframe" : "");
+ for (i=0; i<this->num_streams; i++) {
+
+ if (this->streams[i].num == stream)
+ stream_num = i;
+ }
+ if (stream_num >= 0) {
+ printf ("demux_real: buf type is %08x\n", this->streams[stream_num].buf_type);
-this->input->seek(this->input, this->packets[this->current_packet].size,
-SEEK_CUR);
+ send_real_buf (this, timestamp, size,
+ this->streams[stream_num].fifo,
+ this->streams[stream_num].buf_type,
+ 0 /* FIXME */);
+ } else
+ this->input->seek(this->input, size, SEEK_CUR);
- this->current_packet++;
this->current_data_chunk_packet_count--;
/* check if it's time to reload */
@@ -310,7 +564,9 @@ SEEK_CUR);
this->status = DEMUX_FINISHED;
return this->status;
}
-printf ("**** found next DATA tag\n");
+#ifdef LOG
+ printf ("demux_real: **** found next DATA tag\n");
+#endif
this->current_data_chunk_packet_count = BE_32(&data_chunk_header[2]);
this->next_data_chunk_offset = BE_32(&data_chunk_header[6]);
}
@@ -325,19 +581,31 @@ printf ("**** found next DATA tag\n");
static void demux_real_send_headers(demux_plugin_t *this_gen) {
demux_real_t *this = (demux_real_t *) this_gen;
- buf_element_t *buf;
this->video_fifo = this->stream->video_fifo;
this->audio_fifo = this->stream->audio_fifo;
this->status = DEMUX_OK;
+ this->num_streams = 0;
+
/* send start buffers */
-/* xine_demux_control_start(this->stream);
-*/
+ xine_demux_control_start(this->stream);
/* send init info to decoders */
+ this->input->seek (this->input, 0, SEEK_SET);
+
+ this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 0;
+ this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 0;
+ real_parse_headers (this);
+
+
+ /* print vital stats */
+ xine_log (this->stream->xine, XINE_LOG_MSG,
+ _("demux_real: Real media file, running time: %d min, %d sec\n"),
+ this->duration / 1000 / 60,
+ this->duration / 1000 % 60);
xine_demux_control_headers_done (this->stream);
}
@@ -364,7 +632,6 @@ static void demux_real_dispose (demux_plugin_t *this_gen) {
demux_real_t *this = (demux_real_t *) this_gen;
- free(this->packets);
free(this);
}
@@ -388,36 +655,38 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
input_plugin_t *input = (input_plugin_t *) input_gen;
demux_real_t *this;
- if (! (input->get_capabilities(input) & INPUT_CAP_SEEKABLE)) {
- printf(_("demux_real.c: input not seekable, can not handle!\n"));
- return NULL;
- }
-
- this = xine_xmalloc (sizeof (demux_real_t));
- this->stream = stream;
- this->input = input;
-
- this->demux_plugin.send_headers = demux_real_send_headers;
- this->demux_plugin.send_chunk = demux_real_send_chunk;
- this->demux_plugin.seek = demux_real_seek;
- this->demux_plugin.dispose = demux_real_dispose;
- this->demux_plugin.get_status = demux_real_get_status;
- this->demux_plugin.get_stream_length = demux_real_get_stream_length;
- this->demux_plugin.get_video_frame = NULL;
- this->demux_plugin.got_video_frame_cb= NULL;
- this->demux_plugin.demux_class = class_gen;
-
- this->status = DEMUX_FINISHED;
+ printf ("demux_real: open_plugin\n");
switch (stream->content_detection_method) {
case METHOD_BY_CONTENT:
- case METHOD_EXPLICIT:
-
- if (!open_real_file(this)) {
- free (this);
- return NULL;
+ {
+ uint8_t buf[4096];
+
+ if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
+
+ input->seek(input, 0, SEEK_SET);
+
+ if (input->read(input, buf, 4)) {
+
+ if ((buf[0] != 0x2e)
+ || (buf[1] != 'R')
+ || (buf[2] != 'M')
+ || (buf[3] != 'F'))
+ return NULL;
+ }
+ } else if (input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW)) {
+ if ((buf[0] != 0x2e)
+ || (buf[1] != 'R')
+ || (buf[2] != 'M')
+ || (buf[3] != 'F'))
+ return NULL;
+ } else
+ return NULL;
}
+
+
+ printf ("demux_real: by content accepted.\n");
break;
@@ -428,37 +697,41 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
ending = strrchr(mrl, '.');
- if (!ending) {
- free (this);
- return NULL;
- }
-
- if (strncasecmp (ending, ".rm", 3)) {
- free (this);
+ if (!ending)
return NULL;
- }
- if (!open_real_file(this)) {
- free (this);
+ if (strncasecmp (ending, ".rm", 3)
+ && strncasecmp (ending, ".ra", 3)
+ && strncasecmp (ending, ".ram", 4))
return NULL;
- }
}
break;
+ case METHOD_EXPLICIT:
+ break;
+
default:
- free (this);
return NULL;
}
- strncpy (this->last_mrl, input->get_mrl (input), 1024);
- /* print vital stats */
- xine_log (this->stream->xine, XINE_LOG_MSG,
- _("demux_real: Real media file, running time: %d min, %d sec\n"),
- this->duration / 1000 / 60,
- this->duration / 1000 % 60);
+ this = xine_xmalloc (sizeof (demux_real_t));
+ this->stream = stream;
+ this->input = input;
+
+ this->demux_plugin.send_headers = demux_real_send_headers;
+ this->demux_plugin.send_chunk = demux_real_send_chunk;
+ this->demux_plugin.seek = demux_real_seek;
+ this->demux_plugin.dispose = demux_real_dispose;
+ this->demux_plugin.get_status = demux_real_get_status;
+ this->demux_plugin.get_stream_length = demux_real_get_stream_length;
+ this->demux_plugin.get_video_frame = NULL;
+ this->demux_plugin.got_video_frame_cb= NULL;
+ this->demux_plugin.demux_class = class_gen;
+
+ strncpy (this->last_mrl, input->get_mrl (input), 1024);
return &this->demux_plugin;
}
@@ -472,11 +745,12 @@ static char *get_identifier (demux_class_t *this_gen) {
}
static char *get_extensions (demux_class_t *this_gen) {
- return "rm";
+ return "rm ra ram";
}
static char *get_mimetypes (demux_class_t *this_gen) {
- return NULL;
+ return "audio/x-pn-realaudio: ra, rm, ram: Real Media File;"
+ "audio/x-realaudio: ra: Real Media File;";
}
static void class_dispose (demux_class_t *this_gen) {
diff --git a/src/libreal/Makefile.am b/src/libreal/Makefile.am
new file mode 100644
index 000000000..6505cc9c0
--- /dev/null
+++ b/src/libreal/Makefile.am
@@ -0,0 +1,29 @@
+##
+## Process this file with automake to produce Makefile.in
+##
+
+AM_CFLAGS = $(VORBIS_CFLAGS)
+
+LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic
+
+libdir = $(XINE_PLUGINDIR)
+
+lib_LTLIBRARIES = xineplug_decode_real.la
+
+xineplug_decode_real_la_SOURCES = xine_decoder.c
+xineplug_decode_real_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
+
+debug:
+# @$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(OGG_CFLAGS) $(VORBIS_CFLAGS)"
+ @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)"
+
+install-debug: debug
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+mostlyclean-generic:
+ -rm -f *~ \#* .*~ .\#*
+
+maintainer-clean-generic:
+ -@echo "This command is intended for maintainers to use;"
+ -@echo "it deletes files that may require special tools to rebuild."
+ -rm -f Makefile.in
diff --git a/src/libreal/xine_decoder.c b/src/libreal/xine_decoder.c
new file mode 100644
index 000000000..1912dd974
--- /dev/null
+++ b/src/libreal/xine_decoder.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free 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: xine_decoder.c,v 1.1 2002/11/18 03:03:09 guenter Exp $
+ *
+ * thin layer to use real binary-only codecs in xine
+ *
+ * code inspired by work from Florian Schneider for the MPlayer Project
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dlfcn.h>
+
+#include "bswap.h"
+#include "xine_internal.h"
+#include "video_out.h"
+#include "buffer.h"
+
+
+#define LOG
+
+
+
+typedef struct {
+ video_decoder_class_t decoder_class;
+ void *rv_handle;
+
+ unsigned long (*rvyuv_custom_message)(unsigned long*,void*);
+ unsigned long (*rvyuv_free)(void*);
+ unsigned long (*rvyuv_hive_message)(unsigned long,unsigned long);
+ unsigned long (*rvyuv_init)(void*, void*); /* initdata,context */
+ unsigned long (*rvyuv_transform)(char*, char*,unsigned long*,unsigned long*,void*);
+} real_class_t;
+
+
+typedef struct realdec_decoder_s {
+ video_decoder_t video_decoder;
+
+ real_class_t *cls;
+
+ xine_stream_t *stream;
+
+ void *context;
+
+ int width, height;
+
+} realdec_decoder_t;
+
+/* we need exact positions */
+typedef struct {
+ short unk1;
+ short w;
+ short h;
+ short unk3;
+ int unk2;
+ int subformat;
+ int unk5;
+ int format;
+} rv_init_t;
+
+#define DISPLAY_WIDTH 320
+#define DISPLAY_HEIGHT 256
+
+void hexdump (char *buf, int length) {
+
+ int i;
+
+ printf ("pnm: ascii contents>");
+ for (i = 0; i < length; i++) {
+ unsigned char c = buf[i];
+
+ if ((c >= 32) && (c <= 128))
+ printf ("%c", c);
+ else
+ printf (".");
+ }
+ printf ("\n");
+
+ printf ("pnm: complete hexdump of package follows:\npnm: ");
+ for (i = 0; i < length; i++) {
+ unsigned char c = buf[i];
+
+ printf ("%02x", c);
+
+ if ((i % 16) == 15)
+ printf ("\npnm: ");
+
+ if ((i % 2) == 1)
+ printf (" ");
+
+ }
+ printf ("\n");
+}
+
+
+typedef struct dp_hdr_s {
+ uint32_t chunks; /* number of chunks */
+ uint32_t timestamp; /* timestamp from packet header */
+ uint32_t len; /* length of actual data */
+ uint32_t chunktab; /* offset to chunk offset array */
+} dp_hdr_t;
+
+
+static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
+ realdec_decoder_t *this = (realdec_decoder_t *) this_gen;
+ real_class_t *cls = this->cls;
+
+#ifdef LOG
+ printf ("libreal: decode_data, flags=0x%08x ...\n", buf->decoder_flags);
+#endif
+
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
+ /* real_find_sequence_header (&this->real, buf->content, buf->content + buf->size);*/
+ } else if (buf->decoder_flags & BUF_FLAG_HEADER) {
+
+ unsigned int* extrahdr = (unsigned int*) (buf->content+28);
+ int result;
+ rv_init_t init_data = {11, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, 0,
+ 0, 1, 0}; /* rv30 */
+
+ init_data.w = BE_16(&buf->content[12]);
+ init_data.h = BE_16(&buf->content[14]);
+
+ init_data.subformat = BE_32(&buf->content[26]);
+ init_data.format = BE_32(&buf->content[30]);
+
+ hexdump (&init_data, sizeof (init_data));
+
+ hexdump (buf->content, 32);
+ hexdump (extrahdr, 10);
+
+ printf ("libreal: init codec %dx%d... %x %x\n",
+ init_data.w, init_data.h,
+ init_data.subformat, init_data.format );
+
+ this->context = NULL;
+
+ result = cls->rvyuv_init (&init_data, &this->context);
+
+ printf ("libreal: ... done %d\n", result);
+
+ /* setup rv30 codec (codec sub-type and image dimensions): */
+ if (init_data.format>=0x20200002){
+ unsigned long cmsg24[4]={this->width,this->height,
+ this->width,this->height};
+ unsigned long cmsg_data[3]={0x24,1+((init_data.subformat>>16)&7),
+ (unsigned long) &cmsg24};
+ cls->rvyuv_custom_message (cmsg_data, this->context);
+
+ printf ("libreal: special setup for rv30 done\n");
+
+ }
+
+ /*
+ real_init (&this->real, stream->video_out);
+ */
+
+ this->stream->video_out->open(this->stream->video_out);
+
+
+ } else if (this->context) {
+
+ int result;
+ vo_frame_t *img;
+ void *data = buf->content;
+ dp_hdr_t *dp_hdr = (dp_hdr_t*)data;
+ unsigned char *dp_data = ((unsigned char*)data)+sizeof(dp_hdr_t);
+ uint32_t *extra = (uint32_t*)(((char*)data)+dp_hdr->chunktab);
+ unsigned long transform_out[5];
+ unsigned long transform_in[6]={
+ dp_hdr->len, /* length of the packet (sub-packets appended) */
+ 0, /* unknown, seems to be unused */
+ dp_hdr->chunks, /* number of sub-packets - 1 */
+ (unsigned long) extra, /* table of sub-packet offsets */
+ 0, /* unknown, seems to be unused */
+ dp_hdr->timestamp /* timestamp (the integer value from the stream) */
+ };
+
+ img = this->stream->video_out->get_frame (this->stream->video_out,
+ /* this->av_picture.linesize[0], */
+ this->width,
+ this->height,
+ 42,
+ XINE_IMGFMT_YV12,
+ VO_BOTH_FIELDS);
+
+ img->pts = 0; /* FIXME */
+ img->duration = 3000; /* FIXME */
+ img->bad_frame = 0;
+
+ printf ("libreal: decoding:\n");
+ hexdump (data, buf->size);
+
+ result = cls->rvyuv_transform (dp_data,
+ img->base[0],
+ transform_in,
+ transform_out,
+ this->context);
+
+ /* xine_fast_memcpy (dy, sy, this->bih.biWidth); */
+
+ img->draw(img);
+ img->free(img);
+
+ } else {
+ /*
+ real_decode_data (&this->real, buf->content, buf->content + buf->size,
+ buf->pts);
+ */
+ }
+
+#ifdef LOG
+ printf ("libreal: decode_data...done\n");
+#endif
+}
+
+static void realdec_flush (video_decoder_t *this_gen) {
+ realdec_decoder_t *this = (realdec_decoder_t *) this_gen;
+
+#ifdef LOG
+ printf ("libreal: flush\n");
+#endif
+
+}
+
+static void realdec_reset (video_decoder_t *this_gen) {
+ realdec_decoder_t *this = (realdec_decoder_t *) this_gen;
+
+}
+
+static void realdec_discontinuity (video_decoder_t *this_gen) {
+ realdec_decoder_t *this = (realdec_decoder_t *) this_gen;
+
+}
+
+static void realdec_dispose (video_decoder_t *this_gen) {
+
+ realdec_decoder_t *this = (realdec_decoder_t *) this_gen;
+
+#ifdef LOG
+ printf ("libreal: close\n");
+#endif
+
+ free (this);
+}
+
+static video_decoder_t *open_plugin (video_decoder_class_t *class_gen,
+ xine_stream_t *stream) {
+
+ real_class_t *cls = (real_class_t *) class_gen;
+ realdec_decoder_t *this ;
+
+ this = (realdec_decoder_t *) malloc (sizeof (realdec_decoder_t));
+ memset(this, 0, sizeof (realdec_decoder_t));
+
+ this->video_decoder.decode_data = realdec_decode_data;
+ this->video_decoder.flush = realdec_flush;
+ this->video_decoder.reset = realdec_reset;
+ this->video_decoder.discontinuity = realdec_discontinuity;
+ this->video_decoder.dispose = realdec_dispose;
+ this->stream = stream;
+ this->cls = cls;
+
+ this->context = 0;
+
+ return &this->video_decoder;
+}
+
+/*
+ * real plugin class
+ */
+
+static char *get_identifier (video_decoder_class_t *this) {
+ return "realdec";
+}
+
+static char *get_description (video_decoder_class_t *this) {
+ return "real binary-only codec based video decoder plugin";
+}
+
+static void dispose_class (video_decoder_class_t *this) {
+ free (this);
+}
+
+/*
+ * some fake functions to make real codecs happy
+ */
+void *__builtin_vec_new(unsigned long size) {
+ return malloc(size);
+}
+void __builtin_vec_delete(void *mem) {
+ free(mem);
+}
+void __pure_virtual(void) {
+ printf("libreal: FATAL: __pure_virtual() called!\n");
+ /* exit(1); */
+}
+
+/*
+ * real codec loader
+ */
+
+static int load_syms_linux (real_class_t *cls, char *path) {
+
+ printf ("libreal: opening shared obj '%s'\n", path);
+ cls->rv_handle = dlopen (path, RTLD_LAZY);
+
+ if (!cls->rv_handle) {
+ printf ("libreal: error: %s\n", dlerror());
+ return 0;
+ }
+
+ cls->rvyuv_custom_message = dlsym (cls->rv_handle, "RV20toYUV420CustomMessage");
+ cls->rvyuv_free = dlsym (cls->rv_handle, "RV20toYUV420Free");
+ cls->rvyuv_hive_message = dlsym (cls->rv_handle, "RV20toYUV420HiveMessage");
+ cls->rvyuv_init = dlsym (cls->rv_handle, "RV20toYUV420Init");
+ cls->rvyuv_transform = dlsym (cls->rv_handle, "RV20toYUV420Transform");
+
+ if (cls->rvyuv_custom_message &&
+ cls->rvyuv_free &&
+ cls->rvyuv_hive_message &&
+ cls->rvyuv_init &&
+ cls->rvyuv_transform)
+ return 1;
+
+ printf ("libreal: Error resolving symbols! (version incompatibility?)\n");
+ return 0;
+}
+
+static void *init_class (xine_t *xine, void *data) {
+
+ real_class_t *this;
+
+ this = (real_class_t *) xine_xmalloc (sizeof (real_class_t));
+
+ if (!load_syms_linux (this, "/usr/local/RealPlayer8/Codecs/drv3.so.6.0")) {
+ free (this);
+ return NULL;
+ }
+
+ this->decoder_class.open_plugin = open_plugin;
+ this->decoder_class.get_identifier = get_identifier;
+ this->decoder_class.get_description = get_description;
+ this->decoder_class.dispose = dispose_class;
+
+ return this;
+}
+
+/*
+ * exported plugin catalog entry
+ */
+
+static uint32_t supported_types[] = { BUF_VIDEO_RV20, BUF_VIDEO_RV30, 0 };
+
+static decoder_info_t dec_info_real = {
+ supported_types, /* supported types */
+ 6 /* priority */
+};
+
+plugin_info_t xine_plugin_info[] = {
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_VIDEO_DECODER, 12, "real", XINE_VERSION_CODE, &dec_info_real, init_class },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h
index 292c1b461..cf59a9317 100644
--- a/src/xine-engine/buffer.h
+++ b/src/xine-engine/buffer.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: buffer.h,v 1.78 2002/11/15 00:20:34 miguelfreitas Exp $
+ * $Id: buffer.h,v 1.79 2002/11/18 03:03:09 guenter Exp $
*
*
* contents:
@@ -131,6 +131,8 @@ extern "C" {
#define BUF_VIDEO_WC3 0x02300000
#define BUF_VIDEO_YV12 0x02310000
#define BUF_VIDEO_SEGA 0x02320000
+#define BUF_VIDEO_RV20 0x02330000
+#define BUF_VIDEO_RV30 0x02340000
/* audio buffer types: (please keep in sync with buffer_types.c) */
@@ -168,6 +170,11 @@ extern "C" {
#define BUF_AUDIO_GSM610 0x031E0000
#define BUF_AUDIO_EA_ADPCM 0x031F0000
#define BUF_AUDIO_WMAV2 0x03200000
+#define BUF_AUDIO_COOK 0x03210000
+#define BUF_AUDIO_ATRK 0x03220000
+#define BUF_AUDIO_14_4 0x03230000
+#define BUF_AUDIO_28_8 0x03240000
+#define BUF_AUDIO_SIPRO 0x03250000
/* spu buffer types: */