summaryrefslogtreecommitdiff
path: root/src/demuxers/demux_real.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers/demux_real.c')
-rw-r--r--src/demuxers/demux_real.c299
1 files changed, 252 insertions, 47 deletions
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c
index e49342cc1..05fd6fad5 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.11 2002/11/20 11:57:41 mroi Exp $
+ * $Id: demux_real.c,v 1.12 2002/11/22 03:38:07 guenter Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -73,12 +73,6 @@ typedef struct {
} real_packet;
typedef struct {
- int num;
- int32_t buf_type ;
- fifo_buffer_t *fifo;
-} stream_info_t;
-
-typedef struct {
demux_plugin_t demux_plugin;
@@ -98,22 +92,17 @@ typedef struct {
int packet_count;
int bitrate;
- unsigned int video_type;
- unsigned int audio_type;
-
- unsigned int video_width;
- unsigned int video_height;
- unsigned int audio_channels;
- unsigned int audio_sample_rate;
- unsigned int audio_bits;
-
- int num_streams;
- stream_info_t streams[MAX_STREAMS];
+ int video_stream_num;
+ uint32_t video_buf_type;
+ int audio_stream_num;
+ uint32_t audio_buf_type;
unsigned int current_data_chunk_packet_count;
unsigned int next_data_chunk_offset;
char last_mrl[1024];
+
+ int old_seqnum;
} demux_real_t ;
typedef struct {
@@ -201,12 +190,12 @@ static pnm_mdpr_t *pnm_parse_mdpr(const char *data) {
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->stream_name[(int)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->mime_type[(int)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));
@@ -237,6 +226,7 @@ typedef struct dp_hdr_s {
uint32_t chunktab; /* offset to chunk offset array */
} dp_hdr_t;
+#if 0
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) {
@@ -253,7 +243,7 @@ static void send_real_buf (demux_real_t *this, uint32_t timestamp, int len,
buf->content = buf->mem;
- hdr = buf->content;
+ hdr = (dp_hdr_t *) buf->content;
hdr->chunks = 1;
hdr->timestamp = timestamp;
hdr->len = len;
@@ -271,7 +261,7 @@ static void send_real_buf (demux_real_t *this, uint32_t timestamp, int len,
fifo->put (fifo, buf);
}
-
+#endif
static void real_parse_headers (demux_real_t *this) {
@@ -346,14 +336,12 @@ static void real_parse_headers (demux_real_t *this) {
/* 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;
+ this->video_stream_num = mdpr->stream_number;
+ this->video_buf_type = BUF_VIDEO_RV20;
printf ("demux_real: RV20 video detected\n");
@@ -379,8 +367,8 @@ static void real_parse_headers (demux_real_t *this) {
buf_element_t *buf;
- this->streams[this->num_streams].buf_type = BUF_VIDEO_RV30;
- this->streams[this->num_streams].fifo = this->video_fifo;
+ this->video_stream_num = mdpr->stream_number;
+ this->video_buf_type = BUF_VIDEO_RV30;
printf ("demux_real: RV30 video detected\n");
@@ -405,8 +393,8 @@ static void real_parse_headers (demux_real_t *this) {
} 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;
+ this->audio_stream_num = mdpr->stream_number;
+ this->audio_buf_type = BUF_AUDIO_SIPRO;
printf ("demux_real: sipro audio detected\n");
@@ -416,11 +404,8 @@ static void real_parse_headers (demux_real_t *this) {
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) {
@@ -491,13 +476,24 @@ static void real_parse_headers (demux_real_t *this) {
}
}
+static int stream_read_char (demux_real_t *this) {
+ uint8_t ret;
+ this->input->read (this->input, &ret, 1);
+ return ret;
+}
+
+static int stream_read_word (demux_real_t *this) {
+ uint16_t ret;
+ this->input->read (this->input, (char *) &ret, 2);
+ return BE_16(&ret);
+}
+
static int demux_real_send_chunk(demux_plugin_t *this_gen) {
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;
@@ -523,25 +519,234 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
stream, size, offset, pts, keyframe ? ", keyframe" : "");
#endif
- stream_num = -1;
+ if (stream == this->video_stream_num) {
- for (i=0; i<this->num_streams; i++) {
+ int vpkg_header, vpkg_length, vpkg_offset;
+ int vpkg_seqnum = -1;
+ int vpkg_subseq = 0;
+ buf_element_t *buf;
+ int n;
- if (this->streams[i].num == stream)
- stream_num = i;
- }
+ printf ("demux_real: video chunk detected.\n");
+
+ /* sub-demuxer */
+
+ while (size > 2) {
+
+ /*
+ * read packet header
+ * bit 7: 1=last block in block chain
+ * bit 6: 1=short header (only one block?)
+ */
+
+ vpkg_header = stream_read_char (this); size--;
+ printf ("demux_real: hdr: %02x (size=%d)\n", vpkg_header, size);
+
+ if (0x40==(vpkg_header&0xc0)) {
+ /*
+ * seems to be a very short header
+ * 2 bytes, purpose of the second byte yet unknown
+ */
+ int bummer;
+
+ bummer = stream_read_char (this); size--;
+ printf ("demux_real: bummer == %02X\n",bummer);
+
+ vpkg_offset = 0;
+ vpkg_length = size;
+
+ } else {
+
+ if (0==(vpkg_header & 0x40)) {
+ /* sub-seqnum (bits 0-6: number of fragment. bit 7: ???) */
+ vpkg_subseq = stream_read_char (this); size--;
+
+ printf ("demux_real: subseq: %02X ", vpkg_subseq);
+ vpkg_subseq &= 0x7f;
+ }
+
+ /*
+ * size of the complete packet
+ * bit 14 is always one (same applies to the offset)
+ */
+ vpkg_length = stream_read_word (this); size -= 2;
+ printf ("demux_real: l: %02X %02X ", vpkg_length>>8, vpkg_length&0xff);
+ if (!(vpkg_length&0xC000)) {
+ vpkg_length <<= 16;
+ vpkg_length |= stream_read_word (this);
+ printf ("demux_real: l+: %02X %02X ",
+ (vpkg_length>>8)&0xff,vpkg_length&0xff);
+ size-=2;
+ } else
+ vpkg_length &= 0x3fff;
+
+ /*
+ * offset of the following data inside the complete packet
+ * Note: if (hdr&0xC0)==0x80 then offset is relative to the
+ * _end_ of the packet, so it's equal to fragment size!!!
+ */
+
+ vpkg_offset = stream_read_word (this); size -= 2;
+ printf ("demux_real: o: %02X %02X ",
+ vpkg_offset>>8,vpkg_offset&0xff);
+
+ if (!(vpkg_offset&0xC000)) {
+ vpkg_offset <<= 16;
+ vpkg_offset |= stream_read_word (this);
+ printf ("demux_real: o+: %02X %02X ",
+ (vpkg_offset>>8)&0xff,vpkg_offset&0xff);
+ size -= 2;
+ } else
+ vpkg_offset &= 0x3fff;
+
+ vpkg_seqnum = stream_read_char (this); size--;
+ printf ("demux_real: seq: %02X ", vpkg_seqnum);
+ }
+
+ printf ("demux_real: vpkg seqnum=%d, offset=%d, length=%d\n",
+ vpkg_seqnum, vpkg_offset, vpkg_length);
+
+ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+
+ buf->content = buf->mem;
+ buf->pts = timestamp;
+ buf->input_pos = 0 ; /* FIXME */
+ buf->input_time = 0 ; /* FIXME */
+ buf->type = this->video_buf_type;
+ buf->decoder_flags = 0;
+
+
+ if (this->old_seqnum>=0) {
+
+
+ printf ("demux_real: we have an incomplete packet (oldseq=%d new=%d)\n",
+ this->old_seqnum, vpkg_seqnum);
+ /* we have an incomplete packet: */
+ if (this->old_seqnum != vpkg_seqnum) {
+
+ /* this fragment is for new packet, close the old one */
+
+ printf ("demux_real: closing probably incomplete packet\n");
+
+ /* ds_add_packet(ds,dp); */
+ this->old_seqnum = -1;
+
+ buf->decoder_flags |= BUF_FLAG_FRAME_START;
+
+ } else {
+
+ /* append data to it! */
+
+ if (0x80==(vpkg_header&0xc0)){
+
+ /* stream_read(demuxer->stream, dp_data+dp_hdr->len, vpkg_offset); */
+ n = this->input->read (this->input, buf->content, vpkg_offset);
- if (stream_num >= 0) {
+ buf->size = vpkg_offset;
- printf ("demux_real: buf type is %08x\n", this->streams[stream_num].buf_type);
+ if (n<vpkg_offset) {
+ buf->free_buffer(buf);
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ this->video_fifo->put (this->video_fifo, buf);
+
+ size -= vpkg_offset;
+
+ /* we know that this is the last fragment -> we can close the packet! */
+
+ /* ds_add_packet(ds,dp); */
+ this->old_seqnum = -1;
+
+ continue;
+ }
+
+ /* non-last fragment: */
+
+ /* stream_read(demuxer->stream, dp_data+dp_hdr->len, size); */
+ n = this->input->read (this->input, buf->content, size);
+
+ if (n<vpkg_offset) {
+ buf->free_buffer (buf);
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+
+ this->video_fifo->put (this->video_fifo, buf);
+
+ size=0;
+ break; /* no more fragments in this chunk! */
+ }
+ }
+
+ if (0x00 == (vpkg_header&0xc0)) {
+
+ printf ("demux_real: first fragment, %d bytes\n", size);
+
+ /* first fragment: */
+ this->input->seek (this->input, size, SEEK_CUR);
+ /* stream_read(demuxer->stream, dp_data, size); */
+ /* ds->asf_packet=dp; */
+ this->old_seqnum = vpkg_seqnum;
+ size=0;
+
+ n = this->input->read (this->input, buf->content, size);
+
+ buf->size = size;
+
+ if (n<size) {
+ buf->free_buffer (buf);
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+
+ buf->decoder_flags |= BUF_FLAG_FRAME_START;
+
+ this->video_fifo->put (this->video_fifo, buf);
+
+ break;
+ }
+
+ printf ("demux_real: whole packet, %d bytes\n", vpkg_length);
+
+ /* whole packet (not fragmented): */
+ size -= vpkg_length;
+
+ /* stream_read(demuxer->stream, dp_data, vpkg_length); */
+
+ n = this->input->read (this->input, buf->content, vpkg_length);
+
+ buf->size = vpkg_length;
+
+ if (n<vpkg_length) {
+ buf->free_buffer (buf);
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+
+ buf->decoder_flags |= BUF_FLAG_FRAME_START;
+
+ this->video_fifo->put (this->video_fifo, buf);
+
+ /* ds_add_packet(ds,dp); */
+
+ } /* while(len>2) */
+ /*
send_real_buf (this, timestamp, size,
this->streams[stream_num].fifo,
this->streams[stream_num].buf_type,
- 0 /* FIXME */);
- } else
+ 0 );
+ */
+ } else if (stream == this->audio_stream_num) {
this->input->seek(this->input, size, SEEK_CUR);
+ } else {
+ /* discard */
+
+ this->input->seek(this->input, size, SEEK_CUR);
+
+ }
this->current_data_chunk_packet_count--;
/* check if it's time to reload */
@@ -587,8 +792,6 @@ static void demux_real_send_headers(demux_plugin_t *this_gen) {
this->status = DEMUX_OK;
- this->num_streams = 0;
-
/* send start buffers */
xine_demux_control_start(this->stream);
@@ -733,6 +936,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
strncpy (this->last_mrl, input->get_mrl (input), 1024);
+this->old_seqnum = -1;
+
return &this->demux_plugin;
}
@@ -760,7 +965,7 @@ static void class_dispose (demux_class_t *this_gen) {
free (this);
}
-static void *init_plugin (xine_t *xine, void *data) {
+static void *init_class (xine_t *xine, void *data) {
demux_real_class_t *this;
@@ -784,6 +989,6 @@ static void *init_plugin (xine_t *xine, void *data) {
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_DEMUX, 17, "real", XINE_VERSION_CODE, NULL, init_plugin },
+ { PLUGIN_DEMUX, 17, "real", XINE_VERSION_CODE, NULL, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};