summaryrefslogtreecommitdiff
path: root/src/demuxers/demux_asf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers/demux_asf.c')
-rw-r--r--src/demuxers/demux_asf.c720
1 files changed, 259 insertions, 461 deletions
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c
index ea44508e3..c95bf5460 100644
--- a/src/demuxers/demux_asf.c
+++ b/src/demuxers/demux_asf.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: demux_asf.c,v 1.180 2006/08/08 03:34:15 miguelfreitas Exp $
+ * $Id: demux_asf.c,v 1.181 2006/09/07 07:21:09 tmattern Exp $
*
* demultiplexer for asf streams
*
@@ -70,9 +70,9 @@
#define ASF_MODE_ASF_REF 3
#define ASF_MODE_ENCRYPTED_CONTENT 4
+#define ASF_HEADER_SIZE 8192 /* max header size */
typedef struct {
- int num;
int seq;
int frag_offset;
@@ -89,89 +89,75 @@ typedef struct {
int resync;
int first_seq;
- xine_waveformatex *wavex;
- int wavex_size;
-
- xine_bmiheader *bih;
- int bih_size;
-
int payload_size;
/* palette handling */
- int palette_count;
- palette_entry_t palette[256];
+ int palette_count;
+ palette_entry_t palette[256];
-} asf_stream_t;
+} asf_demux_stream_t;
typedef struct demux_asf_s {
- demux_plugin_t demux_plugin;
+ demux_plugin_t demux_plugin;
- xine_stream_t *stream;
+ xine_stream_t *stream;
- fifo_buffer_t *audio_fifo;
- fifo_buffer_t *video_fifo;
+ fifo_buffer_t *audio_fifo;
+ fifo_buffer_t *video_fifo;
- input_plugin_t *input;
+ input_plugin_t *input;
- int64_t keyframe_ts;
- int keyframe_found;
+ int64_t keyframe_ts;
+ int keyframe_found;
- int seqno;
- uint32_t packet_size;
- uint8_t packet_len_flags;
- uint32_t data_size;
- uint64_t packet_count;
+ int seqno;
+ uint32_t packet_size;
+ uint8_t packet_len_flags;
+ uint32_t data_size;
+ uint64_t packet_count;
- asf_stream_t streams[MAX_NUM_STREAMS];
- uint32_t bitrates[MAX_NUM_STREAMS];
- int num_streams;
- int num_audio_streams;
- int num_video_streams;
- int audio_stream;
- int video_stream;
- int audio_stream_id;
- int video_stream_id;
- int control_stream_id;
-
- char title[512];
- char author[512];
- char copyright[512];
- char comment[512];
-
- uint64_t length;
- uint32_t rate;
- uint64_t preroll;
+ asf_demux_stream_t streams[MAX_NUM_STREAMS];
+ int video_stream;
+ int audio_stream;
+
+ uint64_t length;
+ uint32_t rate;
/* packet filling */
- int packet_size_left;
+ int packet_size_left;
/* discontinuity detection */
- int64_t last_pts[2];
- int send_newpts;
+ int64_t last_pts[2];
+ int send_newpts;
/* only for reading */
- uint32_t packet_padsize;
- int nb_frames;
- uint8_t frame_flag;
- uint8_t packet_prop_flags;
- int frame;
+ uint32_t packet_padsize;
+ int nb_frames;
+ uint8_t frame_flag;
+ uint8_t packet_prop_flags;
+ int frame;
- int status;
+ int status;
/* byte reordering from audio streams */
- int reorder_h;
- int reorder_w;
- int reorder_b;
+ int reorder_h;
+ int reorder_w;
+ int reorder_b;
- int buf_flag_seek;
+ int buf_flag_seek;
/* first packet position */
- int64_t first_packet_pos;
+ int64_t first_packet_pos;
- int mode;
+ int mode;
/* for fewer error messages */
- GUID last_unknown_guid;
+ GUID last_unknown_guid;
+
+ uint8_t asf_header_buffer[ASF_HEADER_SIZE];
+ uint32_t asf_header_len;
+ asf_header_t *asf_header;
+
} demux_asf_t ;
typedef struct {
@@ -306,29 +292,30 @@ static void get_str16_nolen(demux_asf_t *this, int len,
static void asf_send_audio_header (demux_asf_t *this, int stream) {
buf_element_t *buf;
- asf_stream_t *asf_stream = &this->streams[stream];
- xine_waveformatex *wavex = asf_stream->wavex;
+ asf_demux_stream_t *demux_stream = &this->streams[stream];
+ asf_stream_t *asf_stream = this->asf_header->streams[stream];
+ xine_waveformatex *wavex = (xine_waveformatex *)asf_stream->private_data;
if (!this->audio_fifo)
return;
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- if (asf_stream->wavex_size > buf->max_size) {
+ if (asf_stream->private_data_length > buf->max_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_asf: private decoder data length (%d) is greater than fifo buffer length (%d)\n",
- asf_stream->wavex_size, buf->max_size);
+ asf_stream->private_data_length, buf->max_size);
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return;
}
- memcpy (buf->content, wavex, asf_stream->wavex_size);
+ memcpy (buf->content, wavex, asf_stream->private_data_length);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, wavex->wFormatTag);
- lprintf ("wavex header is %d bytes long\n", asf_stream->wavex_size);
+ lprintf ("wavex header is %d bytes long\n", asf_stream->private_data_length);
- buf->size = asf_stream->wavex_size;
+ buf->size = asf_stream->private_data_length;
buf->type = this->streams[stream].buf_type;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
buf->decoder_info[1] = wavex->nSamplesPerSec;
@@ -346,17 +333,18 @@ static unsigned long str2ulong(unsigned char *str) {
static void asf_send_video_header (demux_asf_t *this, int stream) {
- buf_element_t *buf;
- asf_stream_t *asf_stream = &this->streams[stream];
- xine_bmiheader *bih = asf_stream->bih;
+ buf_element_t *buf;
+ asf_demux_stream_t *demux_stream = &this->streams[stream];
+ asf_stream_t *asf_stream = this->asf_header->streams[stream];
+ xine_bmiheader *bih = (xine_bmiheader *)(asf_stream->private_data + 11);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_FOURCC, bih->biCompression);
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
- if (asf_stream->bih_size > buf->max_size) {
+ if ((asf_stream->private_data_length-11) > buf->max_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_asf: private decoder data length (%d) is greater than fifo buffer length (%d)\n",
- asf_stream->bih_size, buf->max_size);
+ asf_stream->private_data_length-10, buf->max_size);
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return;
@@ -366,7 +354,7 @@ static void asf_send_video_header (demux_asf_t *this, int stream) {
BUF_FLAG_FRAME_END;
buf->decoder_info[0] = 0;
- buf->size = asf_stream->bih_size;
+ buf->size = asf_stream->private_data_length - 11;
memcpy (buf->content, bih, buf->size);
buf->type = this->streams[stream].buf_type;
@@ -374,14 +362,14 @@ static void asf_send_video_header (demux_asf_t *this, int stream) {
/* send off the palette, if there is one */
- if (asf_stream->palette_count) {
+ if (demux_stream->palette_count) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "demux_asf: stream %d, palette : %d entries\n", stream, asf_stream->palette_count);
+ "demux_asf: stream %d, palette : %d entries\n", stream, demux_stream->palette_count);
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->decoder_flags = BUF_FLAG_SPECIAL|BUF_FLAG_HEADER;
buf->decoder_info[1] = BUF_SPECIAL_PALETTE;
- buf->decoder_info[2] = asf_stream->palette_count;
- buf->decoder_info_ptr[2] = &asf_stream->palette;
+ buf->decoder_info[2] = demux_stream->palette_count;
+ buf->decoder_info_ptr[2] = &demux_stream->palette;
buf->size = 0;
buf->type = this->streams[stream].buf_type;
this->video_fifo->put (this->video_fifo, buf);
@@ -389,320 +377,174 @@ static void asf_send_video_header (demux_asf_t *this, int stream) {
}
static int asf_read_header (demux_asf_t *this) {
+ int i;
- int guid;
- uint64_t gsize;
-
- this->num_streams = 0;
- this->num_video_streams = 0;
- this->num_audio_streams = 0;
-
- get_le64(this);
- get_le32(this);
- get_byte(this);
- get_byte(this);
-
- while (this->status != DEMUX_FINISHED) {
- guid = get_guid(this);
- gsize = get_le64(this);
-
- if (gsize < 24)
- goto fail;
-
- switch (guid) {
- case GUID_ASF_FILE_PROPERTIES:
- {
- uint64_t file_size, send_time;
- uint32_t flags;
-
- guid = get_guid(this);
- file_size = get_le64(this); /* file size */
-
- get_le64(this); /* creation time */
- this->packet_count = get_le64(this); /* nb packets */
-
- this->length = get_le64(this) / 10000; /* duration */
- send_time = get_le64(this); /* send time */
-
- this->preroll = get_le64(this); /* preroll in 1/1000 s */
- this->length -= this->preroll;
-
- flags = get_le32(this); /* flags */
- get_le32(this); /* min packet size */
- this->packet_size = get_le32(this); /* max packet size */
- get_le32(this); /* max bitrate */
-
- if (this->length) {
- /* FIXME: the rate is not constant ! */
- this->rate = (file_size * 1000) / this->length;
- } else {
- this->rate = 0;
- }
-
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->rate * 8);
-
-
- }
- break;
-
- case (GUID_ASF_STREAM_PROPERTIES):
- {
- int type;
- uint32_t total_size, stream_data_size;
- uint16_t flags;
- uint16_t stream_id;
- uint64_t pos1, pos2;
- asf_stream_t *asf_stream = &this->streams[this->num_streams];
-
- pos1 = this->input->get_current_pos (this->input);
-
- guid = get_guid(this);
- switch (guid) {
- case GUID_ASF_AUDIO_MEDIA:
- type = CODEC_TYPE_AUDIO;
- break;
-
- case GUID_ASF_VIDEO_MEDIA:
- type = CODEC_TYPE_VIDEO;
- break;
-
- case GUID_ASF_COMMAND_MEDIA:
- type = CODEC_TYPE_CONTROL;
- break;
-
- default:
- lprintf("unexpected GUID\n");
- pos2 = this->input->get_current_pos (this->input);
- this->input->seek (this->input, gsize - (pos2 - pos1 + 24), SEEK_CUR);
- continue;
- }
-
- guid = get_guid(this);
- get_le64(this);
- total_size = get_le32(this);
- stream_data_size = get_le32(this);
- flags = get_le16(this);
- stream_id = flags & 0x7F; /* stream id */
- if (flags & 0x8000) {
- /* Encrypted stream
- * Parse the end of the header but do not demux the stream.
- */
- if (this->mode != ASF_MODE_ENCRYPTED_CONTENT) {
- xine_log(this->stream->xine, XINE_LOG_MSG,
- _("demux_asf: warning: The stream id=%d is encrypted.\n"), stream_id);
- _x_message(this->stream, XINE_MSG_ENCRYPTED_SOURCE,
- _("Media stream scrambled/encrypted"), NULL);
- this->mode = ASF_MODE_ENCRYPTED_CONTENT;
- }
- }
-
- get_le32(this);
-
- if (type == CODEC_TYPE_AUDIO) {
- uint8_t buffer[6];
-
- asf_stream->wavex = (xine_waveformatex *)realloc(asf_stream->wavex, total_size);
- this->input->read (this->input, (uint8_t *) asf_stream->wavex, total_size);
- _x_waveformatex_le2me( (xine_waveformatex *) asf_stream->wavex );
-
- /*
- printf ("total size: %d bytes\n", total_size);
- */
-
- /*
- this->input->read (this->input, (uint8_t *) &this->wavex[9], this->wavex[8]);
- */
- if (guid == GUID_ASF_AUDIO_SPREAD) {
- this->input->read (this->input, buffer, 6);
- this->reorder_h = buffer[0];
- this->reorder_w = (buffer[2]<<8)|buffer[1];
- this->reorder_b = (buffer[4]<<8)|buffer[3];
- this->reorder_w /= this->reorder_b;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_asf: audio conceal interleave detected (%d x %d x %d)\n",
- this->reorder_w, this->reorder_h, this->reorder_b );
- } else {
- this->reorder_b=this->reorder_h=this->reorder_w=1;
- }
-
- asf_stream->wavex_size = total_size; /* 18 + this->wavex[8]; */
-
- asf_stream->buf_type = _x_formattag_to_buf_audio ( asf_stream->wavex->wFormatTag );
- if ( !asf_stream->buf_type ) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_asf: unknown audio type 0x%x\n", asf_stream->wavex->wFormatTag);
- asf_stream->buf_type = BUF_AUDIO_UNKNOWN;
- }
-
- _x_meta_info_set(this->stream, XINE_META_INFO_AUDIOCODEC, _x_buf_audio_name(asf_stream->buf_type));
-
- this->streams[this->num_streams].fifo = this->audio_fifo;
- this->streams[this->num_streams].stream_id = stream_id;
- this->streams[this->num_streams].frag_offset = 0;
- this->streams[this->num_streams].seq = 0;
- if (this->reorder_h > 1 && this->reorder_w > 1 ) {
- if( !this->streams[this->num_streams].buffer )
- this->streams[this->num_streams].buffer = malloc( DEFRAG_BUFSIZE );
- this->streams[this->num_streams].defrag = 1;
- } else
- this->streams[this->num_streams].defrag = 0;
-
- lprintf ("found an audio stream id=%d \n", stream_id);
-
- this->num_audio_streams++;
- }
- else if (type == CODEC_TYPE_VIDEO) {
-
- uint16_t i;
- uint32_t width;
- uint32_t height;
- int j;
-
- width = get_le32(this); /* width */
- height = get_le32(this); /* height */
- get_byte(this);
-
- i = get_le16(this); /* size */
- asf_stream->bih = (xine_bmiheader *)realloc(asf_stream->bih, i);
-
- if (i > 0) {
- asf_stream->bih_size = i;
- this->input->read (this->input, (uint8_t *) asf_stream->bih, asf_stream->bih_size);
- _x_bmiheader_le2me( (xine_bmiheader *) asf_stream->bih );
-
- asf_stream->buf_type =
- _x_fourcc_to_buf_video(asf_stream->bih->biCompression);
- if( !asf_stream->buf_type ) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_asf: unknown video format %.4s\n", (char*)&asf_stream->bih->biCompression);
-
- asf_stream->buf_type = BUF_VIDEO_UNKNOWN;
- }
-
- _x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, _x_buf_video_name(asf_stream->buf_type));
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, width);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, height);
-
- this->streams[this->num_streams].fifo = this->video_fifo;
- this->streams[this->num_streams].stream_id = stream_id;
- this->streams[this->num_streams].frag_offset = 0;
- this->streams[this->num_streams].defrag = 0;
-
- /* load the palette, if there is one */
- asf_stream->palette_count = asf_stream->bih->biClrUsed;
-
- lprintf ("palette_count: %d\n", asf_stream->palette_count);
- if (asf_stream->palette_count > 256) {
- lprintf ("number of colors exceeded 256 (%d)", asf_stream->palette_count);
- asf_stream->palette_count = 256;
- }
- if ((asf_stream->bih_size - sizeof(xine_bmiheader)) >= (asf_stream->palette_count * 4)) {
- /* load the palette from the end of the strf chunk */
- for (j = 0; j < asf_stream->palette_count; j++) {
- asf_stream->palette[j].b = *((uint8_t *)asf_stream->bih + sizeof(xine_bmiheader) + j * 4 + 0);
- asf_stream->palette[j].g = *((uint8_t *)asf_stream->bih + sizeof(xine_bmiheader) + j * 4 + 1);
- asf_stream->palette[j].r = *((uint8_t *)asf_stream->bih + sizeof(xine_bmiheader) + j * 4 + 2);
- }
- } else {
- /* generate a greyscale palette */
- asf_stream->palette_count = 256;
- for (j = 0; j < asf_stream->palette_count; j++) {
- asf_stream->palette[j].r = j;
- asf_stream->palette[j].g = j;
- asf_stream->palette[j].b = j;
- }
- }
-
- } else
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_asf: invalid bih_size received (%d), v_stream ignored.\n", i );
-
- lprintf ("found a video stream id=%d, buf_type=%08x \n",
- stream_id, this->streams[this->num_streams].buf_type);
-
- this->num_video_streams++;
- }
- else if (type == CODEC_TYPE_CONTROL) {
- this->streams[this->num_streams].stream_id = stream_id;
- this->control_stream_id = stream_id;
-
- /* This code does'nt work
- while (get_byte(this) != 0) {while (get_byte(this) != 0) {}}
- while (get_byte(this) != 0) {while (get_byte(this) != 0) {}}
- */
- lprintf ("found a control stream id=%d \n", stream_id);
+ this->asf_header_len = get_le64(this);
- }
+ if (this->input->read (this->input, this->asf_header_buffer, this->asf_header_len) != this->asf_header_len)
+ return 0;
- this->num_streams++;
- pos2 = this->input->get_current_pos (this->input);
- this->input->seek (this->input, gsize - (pos2 - pos1 + 24), SEEK_CUR);
- }
- break;
+ /* delete previous header */
+ if (this->asf_header) {
+ asf_header_delete(this->asf_header);
+ }
- case GUID_ASF_DATA:
- lprintf ("found data\n");
+ /* the header starts with :
+ * byte 0-15: header guid
+ * byte 16-23: header length
+ */
+ this->asf_header = asf_header_new(this->asf_header_buffer, this->asf_header_len);
+ if (!this->asf_header)
+ return 0;
- goto headers_ok;
- break;
- case GUID_ASF_CONTENT_DESCRIPTION:
- {
- uint16_t len1, len2, len3, len4, len5;
-
- len1 = get_le16(this);
- len2 = get_le16(this);
- len3 = get_le16(this);
- len4 = get_le16(this);
- len5 = get_le16(this);
- get_str16_nolen(this, len1, this->title, sizeof(this->title));
- get_str16_nolen(this, len2, this->author, sizeof(this->author));
- get_str16_nolen(this, len3, this->copyright, sizeof(this->copyright));
- get_str16_nolen(this, len4, this->comment, sizeof(this->comment));
- this->input->seek (this->input, len5, SEEK_CUR);
- /*
- } else if (url_feof(this)) {
- goto fail;
- */
- }
- break;
+ lprintf("asf header parsing ok\n");
- case GUID_ASF_STREAM_BITRATE_PROPERTIES:
- {
- uint16_t streams, stream_id;
- uint16_t i;
+ this->packet_size = this->asf_header->file->packet_size;
+ this->packet_count = this->asf_header->file->data_packet_count;
- lprintf("GUID stream group\n");
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->asf_header->file->max_bitrate);
- streams = get_le16(this);
- for(i = 0; i < streams; i++) {
- stream_id = get_le16(this);
- this->bitrates[stream_id] = get_le32(this);
- }
- }
- break;
+ for (i = 0; i < this->asf_header->stream_count; i++) {
+ asf_stream_t *asf_stream = this->asf_header->streams[i];
+ asf_demux_stream_t *demux_stream = &this->streams[i];
- default:
- this->input->seek (this->input, gsize - 24, SEEK_CUR);
+ if (asf_stream->encrypted_flag) {
+ if (this->mode != ASF_MODE_ENCRYPTED_CONTENT) {
+ xine_log(this->stream->xine, XINE_LOG_MSG,
+ _("demux_asf: warning: The stream id=%d is encrypted.\n"), asf_stream->stream_number);
+ _x_message(this->stream, XINE_MSG_ENCRYPTED_SOURCE,
+ _("Media stream scrambled/encrypted"), NULL);
+ this->mode = ASF_MODE_ENCRYPTED_CONTENT;
+ }
+ }
+ switch (asf_stream->stream_type) {
+ case GUID_ASF_AUDIO_MEDIA:
+
+ _x_waveformatex_le2me( (xine_waveformatex *) asf_stream->private_data );
+ if (asf_stream->error_correction_type == GUID_ASF_AUDIO_SPREAD) {
+ this->reorder_h = asf_stream->error_correction_data[0];
+ this->reorder_w = (asf_stream->error_correction_data[2]<<8)|asf_stream->error_correction_data[1];
+ this->reorder_b = (asf_stream->error_correction_data[4]<<8)|asf_stream->error_correction_data[3];
+ this->reorder_w /= this->reorder_b;
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_asf: audio conceal interleave detected (%d x %d x %d)\n",
+ this->reorder_w, this->reorder_h, this->reorder_b );
+ } else {
+ this->reorder_b = this->reorder_h = this->reorder_w = 1;
+ }
+
+
+ demux_stream->buf_type = _x_formattag_to_buf_audio
+ ( ((xine_waveformatex *)asf_stream->private_data)->wFormatTag );
+ if ( !demux_stream->buf_type ) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_asf: unknown audio type 0x%x\n",
+ ((xine_waveformatex *)asf_stream->private_data)->wFormatTag);
+ demux_stream->buf_type = BUF_AUDIO_UNKNOWN;
+ }
+
+ _x_meta_info_set(this->stream, XINE_META_INFO_AUDIOCODEC, _x_buf_audio_name(demux_stream->buf_type));
+
+ this->streams[i].fifo = this->audio_fifo;
+ this->streams[i].frag_offset = 0;
+ this->streams[i].seq = 0;
+ if (this->reorder_h > 1 && this->reorder_w > 1 ) {
+ if( !this->streams[i].buffer )
+ this->streams[i].buffer = malloc( DEFRAG_BUFSIZE );
+ this->streams[i].defrag = 1;
+ } else
+ this->streams[i].defrag = 0;
+
+ lprintf ("found an audio stream id=%d \n", asf_stream->stream_number);
+ break;
+
+ case GUID_ASF_VIDEO_MEDIA:
+ {
+ /* video private data
+ * 11 bytes : header
+ * 40 bytes : bmiheader
+ * XX bytes : optional palette
+ */
+ uint32_t width, height;
+ uint16_t bmiheader_size;
+ xine_bmiheader *bmiheader;
+
+ width = LE_32(asf_stream->private_data);
+ height = LE_32(asf_stream->private_data + 4);
+ /* there is one unknown byte between height and the bmiheader size */
+ bmiheader_size = LE_16(asf_stream->private_data + 9);
+
+ /* FIXME: bmiheader_size must be >= sizeof(xine_bmiheader) */
+
+ bmiheader = (xine_bmiheader *) (asf_stream->private_data + 11);
+ _x_bmiheader_le2me(bmiheader);
+
+ /* FIXME: check if (bmi_header_size == bmiheader->biSize) ? */
+
+ demux_stream->buf_type = _x_fourcc_to_buf_video(bmiheader->biCompression);
+ if( !demux_stream->buf_type ) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_asf: unknown video format %.4s\n", (char*)&(bmiheader->biCompression));
+
+ demux_stream->buf_type = BUF_VIDEO_UNKNOWN;
+ }
+
+ _x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, _x_buf_video_name(demux_stream->buf_type));
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, width);
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, height);
+
+ this->streams[i].fifo = this->video_fifo;
+ this->streams[i].frag_offset = 0;
+ this->streams[i].defrag = 0;
+
+ /* load the palette, if there is one */
+ demux_stream->palette_count = bmiheader->biClrUsed;
+
+ lprintf ("palette_count: %d\n", demux_stream->palette_count);
+ if (demux_stream->palette_count > 256) {
+ lprintf ("number of colors exceeded 256 (%d)", demux_stream->palette_count);
+ demux_stream->palette_count = 256;
+ }
+ if ((asf_stream->private_data_length - sizeof(xine_bmiheader) - 11) >= (demux_stream->palette_count * 4)) {
+ int j;
+ uint8_t *palette;
+
+ /* according to msdn the palette is located here : */
+ palette = (uint8_t *)bmiheader + bmiheader->biSize;
+
+ /* load the palette */
+ for (j = 0; j < demux_stream->palette_count; j++) {
+ demux_stream->palette[j].b = *(palette + j * 4 + 0);
+ demux_stream->palette[j].g = *(palette + j * 4 + 1);
+ demux_stream->palette[j].r = *(palette + j * 4 + 2);
+ }
+ } else {
+ int j;
+
+ /* generate a greyscale palette */
+ demux_stream->palette_count = 256;
+ for (j = 0; j < demux_stream->palette_count; j++) {
+ demux_stream->palette[j].r = j;
+ demux_stream->palette[j].g = j;
+ demux_stream->palette[j].b = j;
+ }
+ }
+
+ lprintf ("found a video stream id=%d, buf_type=%08x \n",
+ this->asf_header->streams[i]->stream_number, this->streams[i].buf_type);
+ }
+ break;
}
}
- headers_ok:
this->input->seek (this->input, sizeof(GUID) + 10, SEEK_CUR);
this->packet_size_left = 0;
this->first_packet_pos = this->input->get_current_pos (this->input);
return 1;
-
- fail:
- return 0;
}
static int demux_asf_send_headers_common (demux_asf_t *this) {
- int i;
- int stream_id;
- uint32_t buf_type, max_vrate, max_arate;
- uint32_t bitrate = 0;
-
/* will get overridden later */
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 0);
@@ -710,11 +552,8 @@ static int demux_asf_send_headers_common (demux_asf_t *this) {
/*
* initialize asf engine
*/
- this->audio_stream = 0;
- this->video_stream = 0;
- this->audio_stream_id = -1;
- this->video_stream_id = -1;
- this->control_stream_id = 0;
+ this->audio_stream = -1;
+ this->video_stream = -1;
this->packet_size = 0;
this->seqno = 0;
@@ -731,56 +570,31 @@ static int demux_asf_send_headers_common (demux_asf_t *this) {
*/
_x_demux_control_start(this->stream);
- _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, this->title);
- _x_meta_info_set(this->stream, XINE_META_INFO_ARTIST, this->author);
- _x_meta_info_set(this->stream, XINE_META_INFO_COMMENT, this->comment);
-
+ if (this->asf_header->content) {
+ _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, this->asf_header->content->title);
+ _x_meta_info_set(this->stream, XINE_META_INFO_ARTIST, this->asf_header->content->author);
+ _x_meta_info_set(this->stream, XINE_META_INFO_COMMENT, this->asf_header->content->description);
+ }
/* Choose the best audio and the best video stream.
* Use the bitrate to do the choice.
*/
- max_vrate = 0;
- max_arate = 0;
- for (i = 0; i < this->num_streams; i++) {
- buf_type = (this->streams[i].buf_type & BUF_MAJOR_MASK);
- stream_id = this->streams[i].stream_id;
- bitrate = this->bitrates[stream_id];
+ asf_header_choose_streams(this->asf_header, -1, &this->video_stream, &this->audio_stream);
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_asf: stream: %d, bitrate %d bps\n", stream_id, bitrate);
-
- if ((buf_type == BUF_VIDEO_BASE) &&
- (bitrate > max_vrate || this->video_stream_id == -1)) {
-
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_BITRATE,
- bitrate);
-
- max_vrate = bitrate;
- this->video_stream = i;
- this->video_stream_id = stream_id;
- } else if ((buf_type == BUF_AUDIO_BASE) &&
- (bitrate > max_arate || this->audio_stream_id == -1)) {
-
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE,
- bitrate);
-
- max_arate = bitrate;
- this->audio_stream = i;
- this->audio_stream_id = stream_id;
- }
- }
-
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, bitrate);
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_asf: video stream_id: %d, audio stream_id: %d\n", this->video_stream_id, this->audio_stream_id);
+ "demux_asf: video stream_id: %d, audio stream_id: %d\n",
+ this->asf_header->streams[this->video_stream]->stream_number,
+ this->asf_header->streams[this->audio_stream]->stream_number);
- if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO))
+ if (this->audio_stream != -1) {
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
asf_send_audio_header(this, this->audio_stream);
- if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO))
+ }
+ if (this->video_stream != -1) {
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
asf_send_video_header(this, this->video_stream);
+ }
}
return 0;
}
@@ -843,7 +657,7 @@ static void check_newpts (demux_asf_t *this, int64_t pts, int video, int frame_e
}
-static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
+static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *stream,
int frag_offset, int64_t timestamp,
int frag_len) {
@@ -892,6 +706,7 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
this->rate);
buf->pts = timestamp * 90;
+
buf->type = stream->buf_type;
buf->size = bufsize;
timestamp = 0;
@@ -923,7 +738,7 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
}
}
-static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream,
+static void asf_send_buffer_defrag (demux_asf_t *this, asf_demux_stream_t *stream,
int frag_offset, int64_t timestamp,
int frag_len) {
@@ -1216,7 +1031,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
/* return 0 if ok */
static int asf_parse_packet_payload_common(demux_asf_t *this,
uint8_t raw_id,
- asf_stream_t **stream,
+ asf_demux_stream_t **stream,
uint32_t *frag_offset,
uint32_t *rlen) {
uint8_t stream_id;
@@ -1231,25 +1046,15 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
lprintf ("got raw_id=%d, stream_id=%d\n", raw_id, stream_id);
- for (i = 0; i < this->num_streams; i++) {
- lprintf ("this->streams[i].stream_id=%d\n", this->streams[i].stream_id);
- if ((this->streams[i].stream_id == stream_id) &&
- ((stream_id == this->audio_stream_id) || (stream_id == this->video_stream_id))) {
+ for (i = 0; i < this->asf_header->stream_count; i++) {
+ lprintf ("stream_number = %d\n", this->asf_header->streams[i]->stream_number);
+ if ((this->asf_header->streams[i]->stream_number == stream_id) &&
+ ((stream_id == this->asf_header->streams[this->audio_stream]->stream_number) ||
+ (stream_id == this->asf_header->streams[this->video_stream]->stream_number))) {
*stream = &this->streams[i];
break;
}
}
-#ifdef LOG
- /* display "control stream" content */
- if (stream_id && (stream_id == this->control_stream_id)) {
- printf("demux_asf: Control Stream : begin\n");
- for (i = 0; i < (this->packet_size_left - s_hdr_size); i++){
- printf("%c", get_byte(this));
- }
- printf("\ndemux_asf: Control Stream : end\n");
- return 1;
- }
-#endif
switch ((this->packet_prop_flags >> 4) & 3){
case 1:
@@ -1278,7 +1083,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
/* check seq number */
if (*stream) {
- lprintf ("stream_id = %d, seq = %d\n", (*stream)->stream_id, seq);
+ lprintf ("stream_id = %d, seq = %d\n", stream_id, seq);
if ((*stream)->first_seq || (*stream)->skip) {
next_seq = seq;
(*stream)->first_seq = 0;
@@ -1293,7 +1098,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
buf->type = BUF_CONTROL_RESET_DECODER;
(*stream)->fifo->put((*stream)->fifo, buf);
}
- if ((*stream)->stream_id == this->video_stream_id) {
+ if (stream_id == this->asf_header->streams[this->video_stream]->stream_number) {
lprintf ("bad seq: waiting for keyframe\n");
(*stream)->resync = 1;
@@ -1342,7 +1147,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
/* return 0 if ok */
static int asf_parse_packet_compressed_payload(demux_asf_t *this,
- asf_stream_t *stream,
+ asf_demux_stream_t *stream,
uint8_t raw_id,
uint32_t frag_offset,
int64_t *timestamp) {
@@ -1352,7 +1157,7 @@ static int asf_parse_packet_compressed_payload(demux_asf_t *this,
*timestamp = frag_offset;
if (*timestamp)
- *timestamp -= this->preroll;
+ *timestamp -= this->asf_header->file->preroll;
frag_offset = 0;
get_byte (this); s_hdr_size += 1;
@@ -1436,7 +1241,7 @@ static int asf_parse_packet_compressed_payload(demux_asf_t *this,
/* return 0 if ok */
static int asf_parse_packet_payload(demux_asf_t *this,
- asf_stream_t *stream,
+ asf_demux_stream_t *stream,
uint8_t raw_id,
uint32_t frag_offset,
uint32_t rlen,
@@ -1449,7 +1254,7 @@ static int asf_parse_packet_payload(demux_asf_t *this,
payload_size = get_le32(this); s_hdr_size += 4;
*timestamp = get_le32(this); s_hdr_size += 4;
if (*timestamp)
- *timestamp -= this->preroll;
+ *timestamp -= this->asf_header->file->preroll;
if (stream)
stream->payload_size = payload_size;
if ((rlen - 8) > 0)
@@ -1842,7 +1647,7 @@ failure:
static int demux_asf_send_chunk (demux_plugin_t *this_gen) {
demux_asf_t *this = (demux_asf_t *) this_gen;
- asf_stream_t *stream = NULL;
+ asf_demux_stream_t *stream = NULL;
uint32_t frag_offset = 0;
uint32_t rlen = 0;
uint8_t raw_id = 0;
@@ -1905,26 +1710,19 @@ static void demux_asf_dispose (demux_plugin_t *this_gen) {
demux_asf_t *this = (demux_asf_t *) this_gen;
int i;
- for (i=0; i<this->num_streams; i++) {
- asf_stream_t *asf_stream;
+ for (i=0; i<this->asf_header->stream_count; i++) {
+ asf_demux_stream_t *asf_stream;
asf_stream = &this->streams[i];
if( asf_stream->buffer ) {
free( asf_stream->buffer );
asf_stream->buffer = NULL;
}
-
- if (asf_stream->wavex) {
- free (asf_stream->wavex);
- asf_stream->wavex = NULL;
- }
-
- if (asf_stream->bih) {
- free (asf_stream->bih);
- asf_stream->bih = NULL;
- }
}
+ if (this->asf_header)
+ asf_header_delete(this->asf_header);
+
free (this);
}
@@ -1973,7 +1771,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
off_t start_pos, int start_time, int playing) {
demux_asf_t *this = (demux_asf_t *) this_gen;
- asf_stream_t *stream = NULL;
+ asf_demux_stream_t *stream = NULL;
uint32_t frag_offset = 0;
uint32_t rlen = 0;
uint8_t raw_id, stream_id;
@@ -1996,7 +1794,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
/*
* seek to start position
*/
- for(i = 0; i < this->num_streams; i++) {
+ for(i = 0; i < this->asf_header->stream_count; i++) {
this->streams[i].frag_offset = 0;
this->streams[i].first_seq = 1;
this->streams[i].seq = 0;
@@ -2032,7 +1830,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
state = 0;
/* no video stream */
- if (this->video_stream_id == -1) {
+ if (this->video_stream == -1) {
lprintf ("demux_asf_seek: no video stream\n");
state = 2;
}
@@ -2085,7 +1883,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
if (state == 0) {
if (this->keyframe_found) {
- if (this->audio_stream_id == -1) {
+ if (this->audio_stream == -1) {
lprintf ("demux_asf_seek: no audio stream\n");
state = 5;
}
@@ -2095,7 +1893,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
check_newpts (this, ts * 90, 1, 0);
}
} else if (state == 1) {
- if ((stream_id == this->audio_stream_id) && ts &&
+ if ((stream_id == this->asf_header->streams[this->audio_stream]->stream_number) && ts &&
(ts <= this->keyframe_ts)) {
lprintf ("demux_asf_seek: audio packet found at %lld, ts = %lld\n", start_pos, ts);
@@ -2103,7 +1901,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
break;
}
} else if (state == 2) {
- if ((stream_id == this->audio_stream_id) && !frag_offset) {
+ if ((stream_id == this->asf_header->streams[this->audio_stream]->stream_number) && !frag_offset) {
this->keyframe_found = 1;
this->keyframe_ts = ts;
state = 5; /* end */
@@ -2165,7 +1963,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
input_plugin_t *input) {
demux_asf_t *this;
- char buf[MAX_PREVIEW_SIZE+1];
+ uint8_t buf[MAX_PREVIEW_SIZE+1];
int len;
switch (stream->content_detection_method) {
@@ -2255,11 +2053,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
}
if(len > 0) {
buf[len] = '\0';
- if( strstr(buf,"asx") || strstr(buf,"ASX") )
+ if( strstr((char*)buf,"asx") || strstr((char*)buf,"ASX") )
this->mode = ASF_MODE_ASX_REF;
- if( strstr(buf,"[Reference]") )
+ if( strstr((char*)buf,"[Reference]") )
this->mode = ASF_MODE_HTTP_REF;
- if( strstr(buf,"ASF ") )
+ if( strstr((char*)buf,"ASF ") )
this->mode = ASF_MODE_ASF_REF;
}