Index: stream/asf_mmst_streaming.c =================================================================== --- stream/asf_mmst_streaming.c (revisione 29002) +++ stream/asf_mmst_streaming.c (copia locale) @@ -55,7 +55,9 @@ #endif #include "url.h" +#include "libavutil/intreadwrite.h" #include "libmpdemux/asf.h" +#include "libmpdemux/asfguid.h" #include "stream.h" @@ -67,7 +69,7 @@ #define BUF_SIZE 102400 #define HDR_BUF_SIZE 8192 -#define MAX_STREAMS 20 +#define MAX_STREAMS 128 typedef struct { @@ -76,12 +78,27 @@ } command_t; +typedef enum {ASF_NO_STREAM, ASF_AUDIO_STREAM, ASF_VIDEO_STREAM} ASFtype; + +struct asf_mms_streaming_ctrl { + ASFtype stream_type[MAX_STREAMS]; + uint32_t stream_bitrates[MAX_STREAMS]; + uint32_t packet_size; + int audio_id, video_id; +}; + static int seq_num; -static int num_stream_ids; -static int stream_ids[MAX_STREAMS]; static int get_data (int s, char *buf, size_t count); +static void close_stream(stream_t *stream) +{ + // FIXME: Send the close file message to server + closesocket(stream->fd); + streaming_ctrl_free(stream->streaming_ctrl); + stream->fd = -1; +} + static void put_32 (command_t *cmd, uint32_t value) { cmd->buf[cmd->num_bytes ] = value % 256; @@ -307,94 +324,71 @@ } } -static int interp_header (uint8_t *header, int header_len) +static int interp_header (uint8_t *header, int len, streaming_ctrl_t *streaming_ctrl) { - int i; - int packet_length=-1; + struct asf_mms_streaming_ctrl *mms_ctrl = streaming_ctrl->data; + int stream_id; + int pos = find_asf_guid(header, asf_file_header_guid, sizeof(ASF_header_t), len); - /* - * parse header - */ + if (pos >= 0) { + ASF_file_header_t *file_properties = (ASF_file_header_t *) &header[pos]; + pos += sizeof(ASF_file_header_t); + if (pos > len) goto len_err_out; + mms_ctrl->packet_size = (uint32_t) AV_RL32(&file_properties->max_packet_size); + } + else { + mp_msg(MSGT_NETWORK, MSGL_FATAL, "File properties object in ASF header not found, exiting.\n"); + return -1; + } - i = 30; - while (i= 0) { + ASF_stream_header_t *stream_properties = (ASF_stream_header_t *)&header[pos]; + pos += sizeof(ASF_stream_header_t); + if (pos > len) goto len_err_out; + stream_id = stream_properties->flags & 0x7F; + mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_StreamObjectStreamID, stream_id); + switch(ASF_LOAD_GUID_PREFIX(stream_properties->type)) { + case ASF_GUID_PREFIX_audio_stream: + mms_ctrl->stream_type[stream_id] = ASF_AUDIO_STREAM; + if (!mms_ctrl->audio_id) + mms_ctrl->audio_id = stream_id; + break; + case ASF_GUID_PREFIX_video_stream: + mms_ctrl->stream_type[stream_id] = ASF_VIDEO_STREAM; + if (!mms_ctrl->video_id) + mms_ctrl->video_id = stream_id; + break; + } + } - guid_2 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) - | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) - | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) - | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); - i += 8; + if (!(mms_ctrl->audio_id || mms_ctrl->video_id)) { + mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_NoStreamFound); + return -1; + } - guid_1 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) - | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) - | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) - | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); - i += 8; - -// mp_msg(MSGT_NETWORK,MSGL_INFO,"guid found: %016llx%016llx\n", guid_1, guid_2); - - length = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) - | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) - | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) - | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); - - i += 8; - - if ( (guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22630ULL) ) { - mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_HeaderObject); - } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) { - mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_DataObject); - } else if ((guid_1 == 0x6553200cc000e48eULL) && (guid_2 == 0x11cfa9478cabdca1ULL)) { - - packet_length = get_32(header, i+92-24); - - mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_FileObjectPacketLen, - packet_length, get_32(header, i+96-24)); - - - } else if ((guid_1 == 0x6553200cc000e68eULL) && (guid_2 == 0x11cfa9b7b7dc0791ULL)) { - - int stream_id = header[i+48] | header[i+49] << 8; - - mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_StreamObjectStreamID, stream_id); - - if (num_stream_ids < MAX_STREAMS) { - stream_ids[num_stream_ids] = stream_id; - num_stream_ids++; - } else { - mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_2ManyStreamID); - } - - } else { -#if 0 - int b = i; - printf ("unknown object (guid: %016llx, %016llx, len: %lld)\n", guid_1, guid_2, length); - for (; b < length; b++) - { - if (isascii(header[b]) || isalpha(header[b])) - printf("%c ", header[b]); - else - printf("%x ", header[b]); - } - printf("\n"); -#else - mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_MMST_UnknownObject); -#endif + pos = find_asf_guid(header, asf_stream_group_guid, sizeof(ASF_header_t), len); + if (pos >= 0) { + int stream_count, i; + if (pos + 2 > len) goto len_err_out; + stream_count = AV_RL16(&header[pos]); + pos += 2; + for (i = 0; i < stream_count; i++) { + if (pos + 6 > len) goto len_err_out; + stream_id = AV_RL16(&header[pos]) & 0x7F; + mms_ctrl->stream_bitrates[stream_id] = AV_RL32(&header[pos + 2]); + mp_msg(MSGT_NETWORK, MSGL_INFO, "stream ID: %d - bitrate: %d bit/s\n", stream_id, mms_ctrl->stream_bitrates[stream_id]); + pos += 6; + } } -// mp_msg(MSGT_NETWORK,MSGL_INFO,"length : %lld\n", length); + return 0; - i += length-24; - - } - - return packet_length; - +len_err_out: + mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_InvalidLenInHeader); + return -1; } - static int get_media_packet (int s, int padding, streaming_ctrl_t *stream_ctrl) { unsigned char pre_header[8]; char data[BUF_SIZE]; @@ -483,16 +477,14 @@ return 1; } - -static int packet_length1; - static int asf_mmst_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) { int len; + struct asf_mms_streaming_ctrl *mms_ctrl = stream_ctrl->data; while( stream_ctrl->buffer_size==0 ) { // buffer is empty - fill it! - int ret = get_media_packet( fd, packet_length1, stream_ctrl); + int ret = get_media_packet( fd, mms_ctrl->packet_size, stream_ctrl); if( ret<0 ) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_GetMediaPacketErr,strerror(errno)); return -1; @@ -529,10 +521,12 @@ char data[BUF_SIZE]; uint8_t asf_header[HDR_BUF_SIZE]; int asf_header_len; - int len, i, packet_length; + int len, i; char *path, *unescpath; URL_t *url1 = stream->streaming_ctrl->url; int s = stream->fd; + struct asf_mms_streaming_ctrl *mms_ctrl; + int num_stream_ids = 0, offset = 0, first_id = 0; if( s>0 ) { closesocket( stream->fd ); @@ -622,7 +616,6 @@ send_command (s, 0x15, 1, 0, 40, data); - num_stream_ids = 0; /* get_headers(s, asf_header); */ asf_header_len = get_header (s, asf_header, stream->streaming_ctrl); @@ -631,8 +624,14 @@ closesocket(s); return -1; } - packet_length = interp_header (asf_header, asf_header_len); + mms_ctrl = calloc(1, sizeof(struct asf_mms_streaming_ctrl)); + stream->streaming_ctrl->data = (void *) mms_ctrl; + if (interp_header (asf_header, asf_header_len, stream->streaming_ctrl) < 0) { + closesocket(s); + free(mms_ctrl); + return -1; + } /* * This command is the media stream MBR selector. Switches are always 6 bytes in length. @@ -646,22 +645,56 @@ memset (data, 0, 40); + if (video_id == -2) /* video disabled */ + mms_ctrl->video_id = 0; + if (audio_id == -2) /* sound disabled */ + mms_ctrl->audio_id = 0; + if (audio_id > 0) { - data[2] = 0xFF; - data[3] = 0xFF; - data[4] = audio_id; - send_command(s, 0x33, num_stream_ids, 0xFFFF | audio_id << 16, 8, data); - } else { - for (i=1; istream_type[audio_id] == ASF_AUDIO_STREAM) + mms_ctrl->audio_id = audio_id; + else { + mp_msg(MSGT_NETWORK,MSGL_ERR,"Invalid audio stream selection (-aid %d), ignored.\n", audio_id); + audio_id = -1; + } } + if (video_id > 0) { + if (mms_ctrl->stream_type[video_id] == ASF_VIDEO_STREAM) + mms_ctrl->video_id = video_id; + else { + mp_msg(MSGT_NETWORK,MSGL_ERR,"Invalid video stream selection (-vid %d), ignored.\n", video_id); + video_id = -1; + } + } - send_command (s, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data); + for (i = 1; i < MAX_STREAMS; i++) { + if (mms_ctrl->stream_type[i] != ASF_NO_STREAM) { + num_stream_ids++; + if (!first_id) + first_id = i; + else { + offset++; + data [(offset-1) * 6 + 2] = 0xFF; + data [(offset-1) * 6 + 3] = 0xFF; + data [(offset-1) * 6 + 4] = i; + data [(offset-1) * 6 + 5] = 0x00; + } + if (i == mms_ctrl->audio_id || i == mms_ctrl->video_id) { + // stream request + data [(offset-1) * 6 + 6] = 0x00; + data [(offset-1) * 6 + 7] = 0x00; + mp_msg(MSGT_NETWORK,MSGL_INFO,"Stream %d selected\n", i); + } + else { + // disable stream + data [(offset-1) * 6 + 6] = 0x02; + data [(offset-1) * 6 + 7] = 0x00; + } + } } + send_command (s, 0x33, num_stream_ids, 0xFFFF | first_id << 16, (num_stream_ids)*6+2, data); + get_answer (s); /* Start sending file from packet xx. @@ -677,16 +710,16 @@ data[20] = 0x04; - send_command (s, 0x07, 1, 0xFFFF | stream_ids[0] << 16, 24, data); + send_command (s, 0x07, 1, 0xFFFF | first_id << 16, 24, data); stream->fd = s; stream->streaming_ctrl->streaming_read = asf_mmst_streaming_read; stream->streaming_ctrl->streaming_seek = asf_mmst_streaming_seek; stream->streaming_ctrl->buffering = 1; stream->streaming_ctrl->status = streaming_playing_e; + stream->close = close_stream; - packet_length1 = packet_length; - mp_msg(MSGT_NETWORK,MSGL_INFO,"mmst packet_length = %d\n", packet_length); + mp_msg(MSGT_NETWORK,MSGL_INFO,"mmst packet_length = %d\n", mms_ctrl->packet_size); #ifdef CONFIG_ICONV if (url_conv != (iconv_t)(-1))