📄 mms.c
字号:
GURI *uri; if (!url) return NULL; /* FIXME: needs proper error-signalling work */ this = (mms_t*) malloc (sizeof (mms_t)); this->custom_data = data; this->url = strdup (url); this->s = -1; this->seq_num = 0; 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->start_packet_seq= 0; this->need_discont = 1; 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; /* FIXME de-xine-ification *//* report_progress (stream, 0); */ uri = gnet_uri_new(this->url); if(!uri) { lprintf ("invalid url\n"); goto fail; } this->proto = uri->scheme; this->user = uri->user; this->host = uri->hostname; this->port = uri->port; this->password = uri->passwd; this->uri = uri->path; if (!mmst_valid_proto(this->proto)) { lprintf ("unsupported protocol\n"); goto fail; } if (mms_tcp_connect(io, this)) { goto fail; } /* FIXME de-xine-ification *//* report_progress (stream, 30); */ #ifdef USE_ICONV url_conv = string_utf16_open();#endif /* * let the negotiations begin... */ /* command 0x1 */ lprintf("send command 0x01\n"); mms_gen_guid(this->guid); sprintf (this->str, "\x1c\x03NSPlayer/7.0.0.1956; {%s}; Host: %s", this->guid, this->host); string_utf16 (url_conv, this->scmd_body, this->str, strlen(this->str) + 2); if (!send_command (io, this, 1, 0, 0x0004000b, strlen(this->str) * 2 + 8)) { /* FIXME: de-xine-ification */ lprintf( "***LOG:*** -- " "libmms: failed to send command 0x01\n"); goto fail; } if ((res = get_answer (io, this)) != 0x01) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: unexpected response: %02x (0x01)\n", res); lprintf("answer: %d\n", res); goto fail; } /* FIXME de-xine-ification *//* report_progress (stream, 40); */ /* TODO: insert network timing request here */ /* command 0x2 */ lprintf("send command 0x02\n"); string_utf16 (url_conv, &this->scmd_body[8], "\002\000\\\\192.168.0.129\\TCP\\1037\0000", 28); memset (this->scmd_body, 0, 8); if (!send_command (io, this, 2, 0, 0, 28 * 2 + 8)) { /* FIXME: de-xine-ification */ lprintf( "***LOG:*** -- " "libmms: failed to send command 0x02\n"); goto fail; } switch (res = get_answer (io, this)) { case 0x02: /* protocol accepted */ break; case 0x03: /* FIXME: de-xine-ification */ lprintf( "***LOG:*** -- " "libmms: protocol failed\n"); goto fail; break; default: lprintf("unexpected response: %02x (0x02 or 0x03)\n", res); goto fail; } /* FIXME de-xine-ification *//* report_progress (stream, 50); */ /* command 0x5 */ { mms_buffer_t command_buffer; lprintf("send command 0x05\n"); mms_buffer_init(&command_buffer, this->scmd_body); mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ string_utf16 (url_conv, this->scmd_body + command_buffer.pos, this->uri, strlen(this->uri)); if (!send_command (io, this, 5, 1, 0xffffffff, strlen(this->uri) * 2 + 12)) goto fail; } switch (res = get_answer (io, this)) { case 0x06: { int xx, yy; /* no authentication required */ /* Warning: sdp is not right here */ xx = this->buf[62]; yy = this->buf[63]; this->live_flag = ((xx == 0) && ((yy & 0xf) == 2)); lprintf("live: live_flag=%d, xx=%d, yy=%d\n", this->live_flag, xx, yy); } break; case 0x1A: /* authentication request, not yet supported */ /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: authentication request, not yet supported\n"); goto fail; break; default: /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: unexpected response: %02x (0x06 or 0x1A)\n", res); goto fail; } /* FIXME de-xine-ification *//* report_progress (stream, 60); */ /* command 0x15 */ lprintf("send command 0x15\n"); { mms_buffer_t command_buffer; mms_buffer_init(&command_buffer, this->scmd_body); mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00800000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x40AC2000); /* ?? */ mms_buffer_put_32 (&command_buffer, ASF_HEADER_PACKET_ID_TYPE); /* Header Packet ID type */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ if (!send_command (io, this, 0x15, 1, 0, command_buffer.pos)) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: failed to send command 0x15\n"); goto fail; } } if ((res = get_answer (io, this)) != 0x11) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: unexpected response: %02x (0x11)\n", res); goto fail; } this->num_stream_ids = 0; if (!get_asf_header (io, this)) goto fail; interp_asf_header (this); /* FIXME de-xine-ification *//* report_progress (stream, 70); */ if (!mms_choose_best_streams(io, this)) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: mms_choose_best_streams failed"); goto fail; } /* FIXME de-xine-ification *//* report_progress (stream, 80); */ /* command 0x07 */ { mms_buffer_t command_buffer; mms_buffer_init(&command_buffer, this->scmd_body); mms_buffer_put_32 (&command_buffer, 0x00000000); /* 64 byte float timestamp */ mms_buffer_put_32 (&command_buffer, 0x00000000); mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* first packet sequence */ mms_buffer_put_8 (&command_buffer, 0xFF); /* max stream time limit (3 bytes) */ mms_buffer_put_8 (&command_buffer, 0xFF); mms_buffer_put_8 (&command_buffer, 0xFF); mms_buffer_put_8 (&command_buffer, 0x00); /* stream time limit flag */ mms_buffer_put_32 (&command_buffer, ASF_MEDIA_PACKET_ID_TYPE); /* asf media packet id type */ if (!send_command (io, this, 0x07, 1, 0x0001FFFF, command_buffer.pos)) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: failed to send command 0x07\n"); goto fail; } }/* report_progress (stream, 100); */#ifdef USE_ICONV string_utf16_close(url_conv);#endif lprintf("mms_connect: passed\n" ); return this;fail: if (this->s != -1) close (this->s); if (this->url) free(this->url); if (this->proto) free(this->proto); if (this->host) free(this->host); if (this->user) free(this->user); if (this->password) free(this->password); if (this->uri) free(this->uri); free (this); return NULL;}static int get_media_packet (mms_io_t *io, mms_t *this) { mms_packet_header_t header; off_t len; switch (get_packet_header (io, this, &header)) { case MMS_PACKET_ERR: /* FIXME: de-xine-ification */ lprintf( "***LOG:*** -- " "libmms: failed to read mms packet header\n"); return 0; break; case MMS_PACKET_COMMAND: { int command; command = get_packet_command (io, this, header.packet_len); switch (command) { case 0x1e: { uint32_t error_code; /* Warning: sdp is incomplete. Do not stop if error_code==1 */ error_code = LE_32(this->buf + CMD_HEADER_LEN); lprintf ("End of the current stream. Continue=%d\n", error_code); if (error_code == 0) { this->eos = 1; return 0; } } break; case 0x20: { lprintf ("new stream.\n"); /* asf header */ if (!get_asf_header (io, this)) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "failed to read new ASF header\n"); return 0; } interp_asf_header (this); if (!mms_choose_best_streams(io, this)) return 0; /* send command 0x07 */ /* TODO: ugly */ /* command 0x07 */ { mms_buffer_t command_buffer; mms_buffer_init(&command_buffer, this->scmd_body); mms_buffer_put_32 (&command_buffer, 0x00000000); /* 64 byte float timestamp */ mms_buffer_put_32 (&command_buffer, 0x00000000); mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* first packet sequence */ mms_buffer_put_8 (&command_buffer, 0xFF); /* max stream time limit (3 bytes) */ mms_buffer_put_8 (&command_buffer, 0xFF); mms_buffer_put_8 (&command_buffer, 0xFF); mms_buffer_put_8 (&command_buffer, 0x00); /* stream time limit flag */ mms_buffer_put_32 (&command_buffer, ASF_MEDIA_PACKET_ID_TYPE); /* asf media packet id type */ if (!send_command (io, this, 0x07, 1, 0x0001FFFF, command_buffer.pos)) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: failed to send command 0x07\n"); return 0; } } this->current_pos = 0; } break; case 0x1b: { if (!send_command (io, this, 0x1b, 0, 0, 0)) { /* FIXME: de-xine-ification */ lprintf( "***LOG:*** -- " "libmms: failed to send command\n"); return 0; } } break; case 0x05: break; default: /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "unexpected mms command %02x\n", command); } this->buf_size = 0; } break; case MMS_PACKET_ASF_HEADER: /* FIXME: de-xine-ification */ lprintf( "***LOG:*** -- " "libmms: unexpected asf header packet\n"); this->buf_size = 0; break; case MMS_PACKET_ASF_PACKET: { /* media packet */ /* FIXME: probably needs some more sophisticated logic, but until we do seeking, this should work */ if(this->need_discont) { this->need_discont = 0; this->start_packet_seq = header.packet_seq; } 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) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: invalid asf packet len: %d bytes\n", header.packet_len); return 0; } /* simulate a seek */ this->current_pos = (off_t)this->asf_header_len + ((off_t)header.packet_seq - this->start_packet_seq) * (off_t)this->asf_packet_len; len = io_read(io, this->s, this->buf, header.packet_len); if (len != header.packet_len) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: read failed\n"); return 0; } /* explicit padding with 0 */ lprintf("padding: %d bytes\n", this->asf_packet_len - header.packet_len); { char *base = (char *)(this->buf); char *start = base + header.packet_len; char *end = start + this->asf_packet_len - header.packet_len; if ((start > base) && (start < (base+BUF_SIZE-1)) && (start < end) && (end < (base+BUF_SIZE-1))) { memset(this->buf + header.packet_len, 0, this->asf_packet_len - header.packet_len); } if (this->asf_packet_len > BUF_SIZE) { this->buf_size = BUF_SIZE; } else { this->buf_size = this->asf_packet_len; } } } break; } lprintf ("get media packet succ\n"); return 1;}int mms_peek_header (mms_t *this, char *data, int maxsize) { int len; len = (this->asf_header_len < maxsize) ? this->asf_header_len : maxsize; memcpy(data, this->asf_header, len); return len;}int mms_read (mms_io_t *io, mms_t *this, char *data, int len) { int total; total = 0; while (total < len && !this->eos) { if (this->asf_header_read < this->asf_header_len) { int n, bytes_left; bytes_left = this->asf_header_len - this->asf_header_read ; if ((len - total) < bytes_left) n = len-total; else n = bytes_left; memcpy (&data[total], &this->asf_header[this->asf_header_read], n); this->asf_header_read += n; total += n; this->current_pos += n; } else { int n, bytes_left; bytes_left = this->buf_size - this->buf_read; if (bytes_left == 0) { this->buf_size = this->buf_read = 0; if (!get_media_packet (io, this)) { /* FIXME: de-xine-ification */ lprintf ( "***LOG:*** -- " "libmms: get_media_packet failed\n"); return total; } bytes_left = this->buf_size; } if ((len - total) < bytes_left) n = len - total; else n = bytes_left; memcpy (&data[total], &this->buf[this->buf_read], n); this->buf_read += n; total += n; this->current_pos += n; } } return total;}void mms_close (mms_t *this) { if (this->s != -1) close (this->s); if (this->url) free(this->url); if (this->proto) free(this->proto); if (this->host) free(this->host); if (this->user) free(this->user); if (this->password) free(this->password); if (this->uri) free(this->uri); free (this);}uint32_t mms_get_length (mms_t *this) { return this->file_len;}off_t mms_get_current_pos (mms_t *this) { return this->current_pos;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -