diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-11-22 03:38:07 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-11-22 03:38:07 +0000 |
commit | 73db8a7c28401f6e53db42c53346f497c318e561 (patch) | |
tree | 70c561cbadbdcbb451bffd5c04754878133ac9c1 | |
parent | a1bcb76d307a30ca557a67c3bf9d82acb4e03d70 (diff) | |
download | xine-lib-73db8a7c28401f6e53db42c53346f497c318e561.tar.gz xine-lib-73db8a7c28401f6e53db42c53346f497c318e561.tar.bz2 |
at least rv30 is somewhat working (colors still wrong)
CVS patchset: 3330
CVS date: 2002/11/22 03:38:07
-rw-r--r-- | src/demuxers/demux_real.c | 299 | ||||
-rw-r--r-- | src/libreal/xine_decoder.c | 165 |
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; } |