diff options
Diffstat (limited to 'src/input/mms.c')
-rw-r--r-- | src/input/mms.c | 281 |
1 files changed, 40 insertions, 241 deletions
diff --git a/src/input/mms.c b/src/input/mms.c index 8843970f6..6c735295e 100644 --- a/src/input/mms.c +++ b/src/input/mms.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: mms.c,v 1.60 2006/07/11 09:37:31 mshopf Exp $ + * $Id: mms.c,v 1.61 2006/09/07 07:21:06 tmattern Exp $ * * MMS over TCP protocol * based on work from major mms @@ -131,25 +131,19 @@ struct mms_s { int buf_size; int buf_read; - uint8_t asf_header[ASF_HEADER_LEN]; + asf_header_t *asf_header; + uint8_t asf_header_buffer[ASF_HEADER_LEN]; uint32_t asf_header_len; uint32_t asf_header_read; + int seq_num; - int num_stream_ids; - int stream_ids[ASF_MAX_NUM_STREAMS]; - int stream_types[ASF_MAX_NUM_STREAMS]; - uint32_t asf_packet_len; - uint64_t file_len; char guid[37]; - uint32_t bitrates[ASF_MAX_NUM_STREAMS]; - uint32_t bitrates_pos[ASF_MAX_NUM_STREAMS]; int bandwidth; - int has_audio; - int has_video; - int live_flag; off_t current_pos; int eos; + + uint8_t live_flag; }; @@ -185,33 +179,6 @@ static void mms_buffer_put_32 (mms_buffer_t *mms_buffer, uint32_t value) { mms_buffer->pos += 4; } -static int get_guid (unsigned char *buffer, int offset) { - int i; - GUID g; - - g.Data1 = LE_32(buffer + offset); - g.Data2 = LE_16(buffer + offset + 4); - g.Data3 = LE_16(buffer + offset + 6); - for(i = 0; i < 8; i++) { - g.Data4[i] = buffer[offset + 8 + i]; - } - - for (i = 1; i < GUID_END; i++) { - if (!memcmp(&g, &guids[i].guid, sizeof(GUID))) { - lprintf ("GUID: %s\n", guids[i].name); - return i; - } - } - - lprintf ("unknown GUID: 0x%x, 0x%x, 0x%x, " - "{ 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx }\n", - g.Data1, g.Data2, g.Data3, - g.Data4[0], g.Data4[1], g.Data4[2], g.Data4[3], - g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]); - - return GUID_ERROR; -} - static void print_command (char *data, int len) { @@ -524,122 +491,22 @@ static int get_asf_header (mms_t *this) { return 1; } -static void interp_asf_header (mms_t *this) { - - unsigned int i; - - this->asf_packet_len = 0; - this->num_stream_ids = 0; - /* - * parse header - */ - - i = 30; - while (i < this->asf_header_len) { - - uint64_t length; - int guid; - - guid = get_guid(this->asf_header, i); - i += 16; - - length = LE_64(this->asf_header + i); - i += 8; - - switch (guid) { - - case GUID_ASF_FILE_PROPERTIES: - - this->asf_packet_len = LE_32(this->asf_header + i + 92 - 24); - if (this->asf_packet_len > BUF_SIZE) { - this->asf_packet_len = 0; - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, - "libmms: asf packet len too large\n"); - break; - } - this->file_len = LE_64(this->asf_header + i + 40 - 24); - lprintf ("file object, file_length = %lld, packet length = %d", - this->file_len, this->asf_packet_len); - break; - - case GUID_ASF_STREAM_PROPERTIES: - { - uint16_t flags; - uint16_t stream_id; - int type; - int encrypted; - - guid = get_guid(this->asf_header, i); - switch (guid) { - case GUID_ASF_AUDIO_MEDIA: - type = ASF_STREAM_TYPE_AUDIO; - this->has_audio = 1; - break; - - case GUID_ASF_VIDEO_MEDIA: - case GUID_ASF_JFIF_MEDIA: - case GUID_ASF_DEGRADABLE_JPEG_MEDIA: - type = ASF_STREAM_TYPE_VIDEO; - this->has_video = 1; - break; - - case GUID_ASF_COMMAND_MEDIA: - type = ASF_STREAM_TYPE_CONTROL; - break; - - default: - type = ASF_STREAM_TYPE_UNKNOWN; - } - - flags = LE_16(this->asf_header + i + 48); - stream_id = flags & 0x7F; - encrypted = flags >> 15; - - lprintf ("stream object, stream id: %d, type: %d, encrypted: %d\n", - stream_id, type, encrypted); - - if (this->num_stream_ids < ASF_MAX_NUM_STREAMS && stream_id < ASF_MAX_NUM_STREAMS) { - this->stream_types[stream_id] = type; - this->stream_ids[this->num_stream_ids] = stream_id; - this->num_stream_ids++; - } else { - lprintf ("too many streams, skipping\n"); - } - - } - break; +static int interp_asf_header (mms_t *this) { - case GUID_ASF_STREAM_BITRATE_PROPERTIES: - { - uint16_t streams = LE_16(this->asf_header + i); - uint16_t stream_id; - int j; - - lprintf ("stream bitrate properties\n"); - lprintf ("streams %d\n", streams); - - for(j = 0; j < streams; j++) { - stream_id = LE_16(this->asf_header + i + 2 + j * 6); - lprintf ("stream id %d\n", stream_id); - this->bitrates[stream_id] = LE_32(this->asf_header + i + 4 + j * 6); - this->bitrates_pos[stream_id] = i + 4 + j * 6; - lprintf ("stream id %d, bitrate %d\n", stream_id, - this->bitrates[stream_id]); - } - } - break; - - default: - lprintf ("unknown object\n"); - break; - } + /* delete previous header */ + if (this->asf_header) { + asf_header_delete(this->asf_header); + } - lprintf ("length : %lld\n", length); + /* the header starts with : + * byte 0-15: header guid + * byte 16-23: header length + */ + this->asf_header = asf_header_new(this->asf_header_buffer + 24, this->asf_header_len - 24); + if (!this->asf_header) + return 0; - if (length > 24) { - i += length - 24; - } - } + return 1; } static const char *const mmst_proto_s[] = { "mms", "mmst", NULL }; @@ -729,99 +596,35 @@ static int mms_choose_best_streams(mms_t *this) { int i; int video_stream = 0; int audio_stream = 0; - unsigned int max_arate = 0; - unsigned int min_vrate = 0; - unsigned int min_bw_left = 0; - int stream_id; - unsigned int bandwitdh_left; int res; - /* command 0x33 */ /* choose the best quality for the audio stream */ - /* i've never seen more than one audio stream */ - lprintf("num_stream_ids=%d\n", this->num_stream_ids); - for (i = 0; i < this->num_stream_ids; i++) { - stream_id = this->stream_ids[i]; - switch (this->stream_types[stream_id]) { - case ASF_STREAM_TYPE_AUDIO: - if (this->bitrates[stream_id] > max_arate) { - audio_stream = stream_id; - max_arate = this->bitrates[stream_id]; - } - break; - default: - break; - } - } - - /* choose a video stream adapted to the user bandwidth */ - bandwitdh_left = (int)( this->bandwidth - max_arate ) < 0 ? 0 : this->bandwidth - max_arate; - lprintf("bandwitdh %d, left %d\n", this->bandwidth, bandwitdh_left); - - min_bw_left = bandwitdh_left; - for (i = 0; i < this->num_stream_ids; i++) { - stream_id = this->stream_ids[i]; - switch (this->stream_types[stream_id]) { - case ASF_STREAM_TYPE_VIDEO: - if (((bandwitdh_left - this->bitrates[stream_id]) < min_bw_left) && - (bandwitdh_left >= this->bitrates[stream_id])) { - video_stream = stream_id; - min_bw_left = bandwitdh_left - this->bitrates[stream_id]; - } - break; - default: - break; - } - } - - /* choose the lower bitrate of */ - if (!video_stream && this->has_video) { - for (i = 0; i < this->num_stream_ids; i++) { - stream_id = this->stream_ids[i]; - switch (this->stream_types[stream_id]) { - case ASF_STREAM_TYPE_VIDEO: - if ((this->bitrates[stream_id] < min_vrate) || - (!min_vrate)) { - video_stream = stream_id; - min_vrate = this->bitrates[stream_id]; - } - break; - default: - break; - } - } - } + + asf_header_choose_streams (this->asf_header, this->bandwidth, &video_stream, &audio_stream); lprintf("selected streams: audio %d, video %d\n", audio_stream, video_stream); lprintf("disabling other streams\n"); memset (this->scmd_body, 0, 40); - for (i = 1; i < this->num_stream_ids; i++) { + for (i = 1; i < this->asf_header->stream_count; i++) { this->scmd_body [ (i - 1) * 6 + 2 ] = 0xFF; this->scmd_body [ (i - 1) * 6 + 3 ] = 0xFF; - this->scmd_body [ (i - 1) * 6 + 4 ] = this->stream_ids[i] ; - this->scmd_body [ (i - 1) * 6 + 5 ] = this->stream_ids[i] >> 8; - if ((this->stream_ids[i] == audio_stream) || - (this->stream_ids[i] == video_stream)) { + this->scmd_body [ (i - 1) * 6 + 4 ] = this->asf_header->streams[i]->stream_number; + this->scmd_body [ (i - 1) * 6 + 5 ] = this->asf_header->streams[i]->stream_number >> 8; + if ((i == audio_stream) || + (i == video_stream)) { this->scmd_body [ (i - 1) * 6 + 6 ] = 0x00; this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; } else { - lprintf("disabling stream %d\n", this->stream_ids[i]); + lprintf("disabling stream %d\n", this->asf_header->streams[i]->stream_number); this->scmd_body [ (i - 1) * 6 + 6 ] = 0x02; this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; - - /* forces the asf demuxer to not choose this stream */ - if (this->bitrates_pos[this->stream_ids[i]]) { - this->asf_header[this->bitrates_pos[this->stream_ids[i]]] = 0; - this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 1] = 0; - this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 2] = 0; - this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 3] = 0; - } } } - if (!send_command (this, 0x33, this->num_stream_ids, - 0xFFFF | this->stream_ids[0] << 16, - this->num_stream_ids * 6 + 2)) { + /* command 0x33 */ + if (!send_command (this, 0x33, this->asf_header->stream_count, + 0xFFFF | this->asf_header->streams[0]->stream_number << 16, + this->asf_header->stream_count * 6 + 2)) { xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "libmms: mms_choose_best_streams failed\n"); return 0; @@ -861,12 +664,8 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { this->scmd_body = this->scmd + CMD_HEADER_LEN + CMD_PREFIX_LEN; this->asf_header_len = 0; this->asf_header_read = 0; - this->num_stream_ids = 0; - this->asf_packet_len = 0; this->buf_size = 0; this->buf_read = 0; - this->has_audio = 0; - this->has_video = 0; this->bandwidth = bandwidth; this->current_pos = 0; this->eos = 0; @@ -1022,7 +821,6 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { goto fail; } - this->num_stream_ids = 0; if (!get_asf_header (this)) goto fail; @@ -1195,7 +993,7 @@ static int get_media_packet (mms_t *this) { lprintf ("asf media packet detected, packet_len=%d, packet_seq=%d\n", header.packet_len, header.packet_seq); - if (header.packet_len > this->asf_packet_len) { + if (header.packet_len > this->asf_header->file->packet_size) { xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "libmms: invalid asf packet len: %d bytes\n", header.packet_len); return 0; @@ -1209,9 +1007,9 @@ static int get_media_packet (mms_t *this) { } /* explicit padding with 0 */ - lprintf("padding: %d bytes\n", this->asf_packet_len - header.packet_len); - memset(this->buf + header.packet_len, 0, this->asf_packet_len - header.packet_len); - this->buf_size = this->asf_packet_len; + lprintf("padding: %d bytes\n", this->asf_header->file->packet_size - header.packet_len); + memset(this->buf + header.packet_len, 0, this->asf_header->file->packet_size - header.packet_len); + this->buf_size = this->asf_header->file->packet_size; } break; } @@ -1228,7 +1026,7 @@ size_t mms_peek_header (mms_t *this, char *data, size_t maxsize) { len = (this->asf_header_len < maxsize) ? this->asf_header_len : maxsize; - memcpy(data, this->asf_header, len); + memcpy(data, this->asf_header_buffer, len); return len; } @@ -1248,7 +1046,7 @@ int mms_read (mms_t *this, char *data, int len) { else n = bytes_left; - xine_fast_memcpy (&data[total], &this->asf_header[this->asf_header_read], n); + xine_fast_memcpy (&data[total], &this->asf_header_buffer[this->asf_header_read], n); this->asf_header_read += n; total += n; @@ -1300,12 +1098,13 @@ void mms_close (mms_t *this) { free(this->password); if (this->uri) free(this->uri); - + if (this->asf_header) + asf_header_delete(this->asf_header); free (this); } uint32_t mms_get_length (mms_t *this) { - return this->file_len; + return this->asf_header->file->file_size; } off_t mms_get_current_pos (mms_t *this) { |