summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/demuxers/demux_real.c299
-rw-r--r--src/libreal/xine_decoder.c165
2 files changed, 364 insertions, 100 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 }
};
diff --git a/src/libreal/xine_decoder.c b/src/libreal/xine_decoder.c
index b44ade64d..79fd1b042 100644
--- a/src/libreal/xine_decoder.c
+++ b/src/libreal/xine_decoder.c
@@ -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: xine_decoder.c,v 1.2 2002/11/20 11:57:44 mroi Exp $
+ * $Id: xine_decoder.c,v 1.3 2002/11/22 03:38:08 guenter Exp $
*
* thin layer to use real binary-only codecs in xine
*
@@ -54,6 +54,8 @@ typedef struct {
unsigned long (*rvyuv_transform)(char*, char*,unsigned long*,unsigned long*,void*);
} real_class_t;
+#define BUF_SIZE 32768
+#define CHUNK_TAB_SIZE 64
typedef struct realdec_decoder_s {
video_decoder_t video_decoder;
@@ -66,6 +68,14 @@ typedef struct realdec_decoder_s {
int width, height;
+ uint8_t chunk_buffer[BUF_SIZE];
+ int chunk_buffer_size;
+
+ int num_chunks;
+ uint32_t chunk_tab[CHUNK_TAB_SIZE];
+
+ uint64_t pts;
+
} realdec_decoder_t;
/* we need exact positions */
@@ -83,11 +93,11 @@ typedef struct {
#define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 256
-void hexdump (char *buf, int length) {
+static void hexdump (char *buf, int length) {
int i;
- printf ("pnm: ascii contents>");
+ printf ("libreal: ascii contents>");
for (i = 0; i < length; i++) {
unsigned char c = buf[i];
@@ -98,14 +108,14 @@ void hexdump (char *buf, int length) {
}
printf ("\n");
- printf ("pnm: complete hexdump of package follows:\npnm: ");
+ printf ("libreal: complete hexdump of package follows:\nlibreal: ");
for (i = 0; i < length; i++) {
unsigned char c = buf[i];
printf ("%02x", c);
if ((i % 16) == 15)
- printf ("\npnm: ");
+ printf ("\nlibreal: ");
if ((i % 2) == 1)
printf (" ");
@@ -143,6 +153,9 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
init_data.w = BE_16(&buf->content[12]);
init_data.h = BE_16(&buf->content[14]);
+ this->width = init_data.w;
+ this->height = init_data.h;
+
init_data.subformat = BE_32(&buf->content[26]);
init_data.format = BE_32(&buf->content[30]);
@@ -167,6 +180,12 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
this->width,this->height};
unsigned long cmsg_data[3]={0x24,1+((init_data.subformat>>16)&7),
(unsigned long) &cmsg24};
+
+ printf ("libreal: cmsg24:\n");
+ hexdump (cmsg24, sizeof (cmsg24));
+ printf ("libreal: cmsg_data:\n");
+ hexdump (cmsg_data, sizeof (cmsg_data));
+
cls->rvyuv_custom_message (cmsg_data, this->context);
printf ("libreal: special setup for rv30 done\n");
@@ -182,53 +201,92 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
} 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, this->stream);
- img->free(img);
-
- } else {
- /*
- real_decode_data (&this->real, buf->content, buf->content + buf->size,
- buf->pts);
- */
+ if (buf->decoder_flags & BUF_FLAG_FRAME_START) {
+
+ if (this->num_chunks>0) {
+
+ int result;
+ vo_frame_t *img;
+
+ unsigned long transform_out[5];
+ unsigned long transform_in[6]={
+ this->chunk_buffer_size,/* length of the packet (sub-packets appended) */
+ 0, /* unknown, seems to be unused */
+ this->num_chunks-1, /* number of sub-packets - 1 */
+ this->chunk_tab, /* table of sub-packet offsets */
+ 0, /* unknown, seems to be unused */
+ this->pts /* timestamp (the integer value from the stream) */
+ };
+
+ printf ("libreal: got %d chunks in buffer and new frame is starting\n",
+ this->num_chunks);
+
+ this->chunk_tab[0] = this->num_chunks;
+
+ 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 %d bytes:\n", this->chunk_buffer_size);
+ hexdump (this->chunk_buffer, this->chunk_buffer_size);
+
+ printf ("libreal: transform_in:\n");
+ hexdump (transform_in, 6*4);
+
+ result = cls->rvyuv_transform (this->chunk_buffer,
+ img->base[0],
+ transform_in,
+ transform_out,
+ this->context);
+
+ printf ("libreal: decoding result: %d\n", result);
+
+ /* xine_fast_memcpy (dy, sy, this->bih.biWidth); */
+
+ img->draw(img, this->stream);
+ img->free(img);
+
+ }
+
+ /* new frame starting */
+
+ printf ("libreal: new frame starting (%d bytes)\n", buf->size);
+
+ memcpy (this->chunk_buffer, buf->content, buf->size);
+
+ this->chunk_buffer_size = buf->size;
+ this->chunk_tab[1] = 0;
+ this->num_chunks = 1;
+
+ if (buf->pts)
+ this->pts = buf->pts;
+ else
+ this->pts = 0;
+ } else {
+
+ /* buffer another fragment */
+
+ printf ("libreal: another fragment (%d chunks in buffer)\n",
+ this->num_chunks);
+
+ memcpy (this->chunk_buffer+this->chunk_buffer_size, buf->content, buf->size);
+
+ this->num_chunks++;
+ this->chunk_tab[this->num_chunks] = this->chunk_buffer_size;
+ this->chunk_buffer_size += buf->size;
+
+ if (buf->pts)
+ this->pts = buf->pts;
+
+ }
}
#ifdef LOG
@@ -283,7 +341,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen,
this->stream = stream;
this->cls = cls;
- this->context = 0;
+ this->context = 0;
+ this->num_chunks = 0;
return &this->video_decoder;
}