[Mplayerxp-cvslog] SF.net SVN: mplayerxp:[425] mplayerxp
Brought to you by:
olov
From: <nic...@us...> - 2012-11-21 15:49:39
|
Revision: 425 http://mplayerxp.svn.sourceforge.net/mplayerxp/?rev=425&view=rev Author: nickols_k Date: 2012-11-21 15:49:25 +0000 (Wed, 21 Nov 2012) Log Message: ----------- more c++ sources + constantization Modified Paths: -------------- mplayerxp/input2/input.h mplayerxp/libmpstream/Makefile mplayerxp/libmpstream/cddb.cpp mplayerxp/libmpstream/http.h mplayerxp/libmpstream/mrl.h mplayerxp/libmpstream/network.h mplayerxp/libmpstream/pnm.h mplayerxp/libmpstream/s_dvdread.c mplayerxp/libmpstream/s_vcdnav.c mplayerxp/libmpstream/stream.h mplayerxp/mplayerxp.h mplayerxp/osdep/timer-lx.cpp mplayerxp/osdep/timer.h mplayerxp/xmpcore/sig_hand.h mplayerxp/xmpcore/xmp_core.h Added Paths: ----------- mplayerxp/libmpstream/asf_mmst_streaming.cpp mplayerxp/libmpstream/asf_streaming.cpp mplayerxp/libmpstream/cookies.cpp mplayerxp/libmpstream/http.cpp mplayerxp/libmpstream/mrl.cpp mplayerxp/libmpstream/network.cpp mplayerxp/libmpstream/pnm.cpp mplayerxp/libmpstream/rtp.cpp mplayerxp/libmpstream/s_ftp.cpp mplayerxp/libmpstream/s_network.cpp mplayerxp/libmpstream/s_rtsp.cpp mplayerxp/libmpstream/s_udp.cpp mplayerxp/libmpstream/tcp.cpp mplayerxp/libmpstream/udp.cpp mplayerxp/libmpstream/url.cpp Removed Paths: ------------- mplayerxp/libmpstream/asf_mmst_streaming.c mplayerxp/libmpstream/asf_streaming.c mplayerxp/libmpstream/cookies.c mplayerxp/libmpstream/http.c mplayerxp/libmpstream/mrl.c mplayerxp/libmpstream/network.c mplayerxp/libmpstream/pnm.c mplayerxp/libmpstream/rtp.c mplayerxp/libmpstream/s_ftp.c mplayerxp/libmpstream/s_network.c mplayerxp/libmpstream/s_rtsp.c mplayerxp/libmpstream/s_udp.c mplayerxp/libmpstream/tcp.c mplayerxp/libmpstream/udp.c mplayerxp/libmpstream/url.c Modified: mplayerxp/input2/input.h =================================================================== --- mplayerxp/input2/input.h 2012-11-21 14:09:25 UTC (rev 424) +++ mplayerxp/input2/input.h 2012-11-21 15:49:25 UTC (rev 425) @@ -156,12 +156,6 @@ extern void mp_input_print_cmds(any_t*handle); extern void mp_input_print_binds(any_t*handle); -#ifdef __cplusplus -extern "C" { -#endif // Interruptible usleep: (used by libmpdemux) extern MPXP_Rc mp_input_check_interrupt(any_t* handle,int time); -#ifdef __cplusplus -} #endif -#endif Modified: mplayerxp/libmpstream/Makefile =================================================================== --- mplayerxp/libmpstream/Makefile 2012-11-21 14:09:25 UTC (rev 424) +++ mplayerxp/libmpstream/Makefile 2012-11-21 15:49:25 UTC (rev 425) @@ -21,19 +21,20 @@ ifeq ($(USE_DVDREAD),yes) SRCS += s_dvdread.c endif -SRCS += url.c +CXXSRCS += url.cpp ifeq ($(USE_OSS_AUDIO),yes) CXXSRCS += s_oss.cpp endif ifeq ($(USE_LIBVCD),yes) SRCS += s_vcdnav.c endif -SRCS += mrl.c +CXXSRCS += mrl.cpp SUBDIRS = tvi ifeq ($(HAVE_STREAMING),yes) SUBDIRS += freesdp librtsp realrtsp -SRCS += asf_streaming.c asf_mmst_streaming.c cookies.c http.c network.c rtp.c pnm.c s_ftp.c s_udp.c s_rtsp.c s_network.c tcp.c udp.c +CXXSRCS += asf_streaming.cpp asf_mmst_streaming.cpp s_ftp.cpp s_udp.cpp s_network.cpp +CXXSRCS+=s_rtsp.cpp network.cpp http.cpp cookies.cpp rtp.cpp pnm.cpp tcp.cpp udp.cpp endif CXXSRCS+= stream.cpp cache2.cpp Deleted: mplayerxp/libmpstream/asf_mmst_streaming.c =================================================================== --- mplayerxp/libmpstream/asf_mmst_streaming.c 2012-11-21 14:09:25 UTC (rev 424) +++ mplayerxp/libmpstream/asf_mmst_streaming.c 2012-11-21 15:49:25 UTC (rev 425) @@ -1,664 +0,0 @@ -// mmst implementation taken from the xine-mms plugin made by majormms (http://geocities.com/majormms/) -// -// ported to mplayer by Abhijeet Phatak <abh...@ya...> -// date : 16 April 2002 -// -// information about the mms protocol can be find at http://get.to/sdp -// - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <inttypes.h> - -#include "mp_config.h" -#include "mplayerxp.h" - -#include "tcp.h" -#include "url.h" -#include "libmpdemux/asf.h" -#include "stream.h" - -#include "network.h" - -#ifndef HAVE_WINSOCK2 -#define closesocket close -#else -#include <winsock2.h> -#endif -#ifndef USE_SETLOCALE -#undef USE_ICONV -#endif - -#ifdef USE_ICONV -#ifdef HAVE_GICONV -#include <giconv.h> -#else -#include <iconv.h> -#endif -#ifdef USE_LANGINFO -#include <langinfo.h> -#endif -#endif -#include "stream_msg.h" -#include "osdep/mplib.h" - -#define BUF_SIZE 102400 -#define HDR_BUF_SIZE 8192 -#define MAX_STREAMS 20 - -typedef struct -{ - uint8_t buf[BUF_SIZE]; - int num_bytes; - -} command_t; - -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 put_32 (command_t *cmd, uint32_t value) -{ - cmd->buf[cmd->num_bytes ] = value % 256; - value = value >> 8; - cmd->buf[cmd->num_bytes+1] = value % 256 ; - value = value >> 8; - cmd->buf[cmd->num_bytes+2] = value % 256 ; - value = value >> 8; - cmd->buf[cmd->num_bytes+3] = value % 256 ; - - cmd->num_bytes += 4; -} - -static uint32_t get_32 (unsigned char *cmd, int offset) -{ - uint32_t ret; - - ret = cmd[offset] ; - ret |= cmd[offset+1]<<8 ; - ret |= cmd[offset+2]<<16 ; - ret |= cmd[offset+3]<<24 ; - - return ret; -} - -static void send_command (int s, int command, uint32_t switches, - uint32_t extra, int length, - char *data) -{ - command_t cmd; - int len8; - - len8 = (length + 7) / 8; - - cmd.num_bytes = 0; - - put_32 (&cmd, 0x00000001); /* start sequence */ - put_32 (&cmd, 0xB00BFACE); /* #-)) */ - put_32 (&cmd, len8*8 + 32); - put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */ - put_32 (&cmd, len8 + 4); - put_32 (&cmd, seq_num); - seq_num++; - put_32 (&cmd, 0x0); /* unknown */ - put_32 (&cmd, 0x0); - put_32 (&cmd, len8+2); - put_32 (&cmd, 0x00030000 | command); /* dir | command */ - put_32 (&cmd, switches); - put_32 (&cmd, extra); - - memcpy (&cmd.buf[48], data, length); - if (length & 7) - memset(&cmd.buf[48 + length], 0, 8 - (length & 7)); - - if (send (s, cmd.buf, len8*8+48, 0) != (len8*8+48)) { - MSG_ERR ("write error\n"); - } -} - -#ifdef USE_ICONV -static iconv_t url_conv; -#endif - -static void string_utf16(char *dest, char *src, int len) -{ - int i; -#ifdef USE_ICONV - size_t len1, len2; - char *ip, *op; - - if (url_conv != (iconv_t)(-1)) - { - memset(dest, 0, 1000); - len1 = len; len2 = 1000; - ip = src; op = dest; - - iconv(url_conv, &ip, &len1, &op, &len2); - } - else - { -#endif - if (len > 499) len = 499; - for (i=0; i<len; i++) { - dest[i*2] = src[i]; - dest[i*2+1] = 0; - } - /* trailing zeroes */ - dest[i*2] = 0; - dest[i*2+1] = 0; -#ifdef USE_ICONV - } -#endif -} - -static void get_answer (int s) -{ - char data[BUF_SIZE]; - int command = 0x1b; - - while (command == 0x1b) { - int len; - - len = recv (s, data, BUF_SIZE, 0) ; - if (!len) { - MSG_ERR ("\nalert! eof\n"); - return; - } - - command = get_32 (data, 36) & 0xFFFF; - - if (command == 0x1b) - send_command (s, 0x1b, 0, 0, 0, data); - } -} - -static int get_data (int s, char *buf, size_t count) -{ - ssize_t len; - size_t total = 0; - - while (total < count) { - - len = recv (s, &buf[total], count-total, 0); - - if (len<=0) { - MSG_ERR ("read error:"); - return 0; - } - - total += len; - - if (len != 0) { -// printf ("[%d/%d]", total, count); - fflush (stdout); - } - - } - - return 1; - -} - -static int get_header (int s, uint8_t *header, streaming_ctrl_t *streaming_ctrl) -{ - unsigned char pre_header[8]; - int header_len; - - header_len = 0; - - while (1) { - if (!get_data (s, pre_header, 8)) { - MSG_ERR ("pre-header read failed\n"); - return 0; - } - if (pre_header[4] == 0x02) { - - int packet_len; - - packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; - -// printf ("asf header packet detected, len=%d\n", packet_len); - - if (packet_len < 0 || packet_len > HDR_BUF_SIZE - header_len) { - MSG_FATAL("Invalid header size, giving up\n"); - return 0; - } - - if (!get_data (s, &header[header_len], packet_len)) { - MSG_ERR("header data read failed\n"); - return 0; - } - - header_len += packet_len; - - if ( (header[header_len-1] == 1) && (header[header_len-2]==1)) { - - - if( streaming_bufferize( streaming_ctrl, header, header_len )<0 ) { - return -1; - } - - // printf ("get header packet finished\n"); - - return (header_len); - - } - - } else { - - int32_t packet_len; - int command; - char data[BUF_SIZE]; - - if (!get_data (s, (char*)&packet_len, 4)) { - MSG_ERR ("packet_len read failed\n"); - return 0; - } - - packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; - -// printf ("command packet detected, len=%d\n", packet_len); - - if (packet_len < 0 || packet_len > BUF_SIZE) { - MSG_FATAL("Invalid rtsp packet size, giving up\n"); - return 0; - } - - if (!get_data (s, data, packet_len)) { - MSG_ERR ("command data read failed\n"); - return 0; - } - - command = get_32 (data, 24) & 0xFFFF; - -// printf ("command: %02x\n", command); - - if (command == 0x1b) - send_command (s, 0x1b, 0, 0, 0, data); - - } - -// printf ("get header packet succ\n"); - } -} - -static int interp_header (uint8_t *header, int header_len) -{ - int i; - int packet_length=-1; - - /* - * parse header - */ - - i = 30; - while (i<header_len) { - - uint64_t guid_1, guid_2, length; - - 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; - - 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; - -// printf ("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) ) { - MSG_V ("header object\n"); - } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) { - MSG_V ("data object\n"); - } else if ((guid_1 == 0x6553200cc000e48eULL) && (guid_2 == 0x11cfa9478cabdca1ULL)) { - - packet_length = get_32(header, i+92-24); - - MSG_V ("file object, packet length = %d (%d)\n", - 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; - - MSG_V ("stream object, stream id: %d\n", stream_id); - - if (num_stream_ids < MAX_STREAMS) { - stream_ids[num_stream_ids] = stream_id; - num_stream_ids++; - } else { - MSG_ERR("asf_mmst: too many id, stream skipped"); - } - - } else { - MSG_V ("unknown object\n"); - } - -// printf ("length : %lld\n", length); - - i += length-24; - - } - - return packet_length; - -} - - -static int get_media_packet (int s, int padding, streaming_ctrl_t *stream_ctrl) { - unsigned char pre_header[8]; - char data[BUF_SIZE]; - - if (!get_data (s, pre_header, 8)) { - MSG_ERR ("pre-header read failed\n"); - return 0; - } - -// for (i=0; i<8; i++) -// printf ("pre_header[%d] = %02x (%d)\n", -// i, pre_header[i], pre_header[i]); - - if (pre_header[4] == 0x04) { - - int packet_len; - - packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; - -// printf ("asf media packet detected, len=%d\n", packet_len); - - if (packet_len < 0 || packet_len > BUF_SIZE) { - MSG_FATAL("Invalid rtsp packet size, giving up\n"); - return 0; - } - - if (!get_data (s, data, packet_len)) { - MSG_ERR ("media data read failed\n"); - return 0; - } - - streaming_bufferize(stream_ctrl, data, padding); - - } else { - - int32_t packet_len; - int command; - - if (!get_data (s, (char*)&packet_len, 4)) { - MSG_ERR ("packet_len read failed\n"); - return 0; - } - - packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; - - if (packet_len < 0 || packet_len > BUF_SIZE) { - MSG_FATAL("Invalid rtsp packet size, giving up\n"); - return 0; - } - - if (!get_data (s, data, packet_len)) { - MSG_ERR ("command data read failed\n"); - return 0; - } - - if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) - || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) { - - MSG_ERR ("missing signature\n"); - return -1; - } - - command = get_32 (data, 24) & 0xFFFF; - -// printf ("\ncommand packet detected, len=%d cmd=0x%X\n", packet_len, command); - - if (command == 0x1b) - send_command (s, 0x1b, 0, 0, 0, data); - else if (command == 0x1e) { - MSG_OK ("everything done. Thank you for downloading a media file containing proprietary and patentend technology.\n"); - return 0; - } - else if (command == 0x21 ) { - // Looks like it's new in WMS9 - // Unknown command, but ignoring it seems to work. - return 0; - } - else if (command != 0x05) { - MSG_ERR ("unknown command %02x\n", command); - return -1; - } - } - -// printf ("get media packet succ\n"); - - 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; - - while( stream_ctrl->buffer_size==0 ) { - // buffer is empty - fill it! - int ret = get_media_packet( fd, packet_length1, stream_ctrl); - if( ret<0 ) { - MSG_ERR("get_media_packet error : %s\n",strerror(errno)); - return -1; - } else if (ret==0) //EOF? - return ret; - } - - len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos; - if(len>size) len=size; - memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len ); - stream_ctrl->buffer_pos += len; - if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) { - mp_free( stream_ctrl->buffer ); - stream_ctrl->buffer = NULL; - stream_ctrl->buffer_size = 0; - stream_ctrl->buffer_pos = 0; - } - return len; - -} - -static int asf_mmst_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) -{ - return -1; - // Shut up gcc warning - fd++; - pos++; - streaming_ctrl=NULL; -} - -int asf_mmst_streaming_start(any_t* libinput,stream_t *stream) -{ - char str[1024]; - char data[BUF_SIZE]; - uint8_t asf_header[HDR_BUF_SIZE]; - int asf_header_len; - int len, i, packet_length; - char *path, *unescpath; - URL_t *url1 = stream->streaming_ctrl->url; - int s = stream->fd; - - if( s>0 ) { - closesocket( stream->fd ); - stream->fd = -1; - } - - /* parse url */ - path = strchr(url1->file,'/') + 1; - - /* mmst filename are not url_escaped by MS MediaPlayer and are expected as - * "plain text" by the server, so need to decode it here - */ - unescpath=mp_malloc(strlen(path)+1); - if (!unescpath) { - MSG_FATAL("Memory allocation failed!\n"); - return -1; - } - url_unescape_string(unescpath,path); - path=unescpath; - - if( url1->port==0 ) { - url1->port=1755; - } - s = tcp_connect2Server(libinput, url1->hostname, url1->port, 0); - if( s<0 ) { - mp_free(path); - return s; - } - MSG_INFO ("connected\n"); - - seq_num=0; - - /* - * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. - * This command is sent at the very start of protocol initiation. It sends local information to the serve - * cmd 1 0x01 - * */ - - /* prepare for the url encoding conversion */ -#ifdef USE_ICONV -#ifdef USE_LANGINFO - url_conv = iconv_open("UTF-16LE",nl_langinfo(CODESET)); -#else - url_conv = iconv_open("UTF-16LE", NULL); -#endif -#endif - - snprintf (str, 1023, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", url1->hostname); - string_utf16 (data, str, strlen(str)); -// send_command(s, commandno ....) - send_command (s, 1, 0, 0x0004000b, strlen(str) * 2+2, data); - - len = recv (s, data, BUF_SIZE, 0) ; - - /*This sends details of the local machine IP address to a Funnel system at the server. - * Also, the TCP or UDP transport selection is sent. - * - * here 192.168.0.129 is local ip address TCP/UDP states the tronsport we r using - * and 1037 is the local TCP or UDP socket number - * cmd 2 0x02 - * */ - - string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037", 24); - memset (data, 0, 8); - send_command (s, 2, 0, 0, 24*2+10, data); - - len = recv (s, data, BUF_SIZE, 0) ; - - /* This command sends file path (at server) and file name request to the server. - * 0x5 */ - - string_utf16 (&data[8], path, strlen(path)); - memset (data, 0, 8); - send_command (s, 5, 0, 0, strlen(path)*2+10, data); - mp_free(path); - - get_answer (s); - - /* The ASF header chunk request. Includes ?session' variable for pre header value. - * After this command is sent, - * the server replies with 0x11 command and then the header chunk with header data follows. - * 0x15 */ - - memset (data, 0, 40); - data[32] = 2; - - 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); -// printf("---------------------------------- asf_header %d\n",asf_header); - if (asf_header_len==0) { //error reading header - closesocket(s); - return -1; - } - packet_length = interp_header (asf_header, asf_header_len); - - - /* - * This command is the media stream MBR selector. Switches are always 6 bytes in length. - * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. - * Where: - * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. - * It is not yet understood what all this means. - * And the last [02] byte is probably the header ?session' value. - * - * 0x33 */ - - memset (data, 0, 40); - - if (mp_conf.audio_id > 0) { - data[2] = 0xFF; - data[3] = 0xFF; - data[4] = mp_conf.audio_id; - send_command(s, 0x33, num_stream_ids, 0xFFFF | mp_conf.audio_id << 16, 8, data); - } else { - for (i=1; i<num_stream_ids; i++) { - data [ (i-1) * 6 + 2 ] = 0xFF; - data [ (i-1) * 6 + 3 ] = 0xFF; - data [ (i-1) * 6 + 4 ] = stream_ids[i]; - data [ (i-1) * 6 + 5 ] = 0x00; - } - - send_command (s, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data); - } - - get_answer (s); - - /* Start sending file from packet xx. - * This command is also used for resume downloads or requesting a lost packet. - * Also used for seeking by sending a play point value which seeks to the media time point. - * Includes ?session' value in pre header and the maximum media stream time. - * 0x07 */ - - memset (data, 0, 40); - - for (i=8; i<16; i++) - data[i] = 0xFF; - - data[20] = 0x04; - - send_command (s, 0x07, 1, 0xFFFF | stream_ids[0] << 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; - - packet_length1 = packet_length; - MSG_V("mmst packet_length = %d\n",packet_length); - -#ifdef USE_ICONV - if (url_conv != (iconv_t)(-1)) - iconv_close(url_conv); -#endif - - return 0; -} Copied: mplayerxp/libmpstream/asf_mmst_streaming.cpp (from rev 417, mplayerxp/libmpstream/asf_mmst_streaming.c) =================================================================== --- mplayerxp/libmpstream/asf_mmst_streaming.cpp (rev 0) +++ mplayerxp/libmpstream/asf_mmst_streaming.cpp 2012-11-21 15:49:25 UTC (rev 425) @@ -0,0 +1,664 @@ +// mmst implementation taken from the xine-mms plugin made by majormms (http://geocities.com/majormms/) +// +// ported to mplayer by Abhijeet Phatak <abh...@ya...> +// date : 16 April 2002 +// +// information about the mms protocol can be find at http://get.to/sdp +// + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <inttypes.h> + +#include "mp_config.h" +#include "mplayerxp.h" + +#include "tcp.h" +#include "url.h" +#include "libmpdemux/asf.h" +#include "stream.h" + +#include "network.h" + +#ifndef HAVE_WINSOCK2 +#define closesocket close +#else +#include <winsock2.h> +#endif +#ifndef USE_SETLOCALE +#undef USE_ICONV +#endif + +#ifdef USE_ICONV +#ifdef HAVE_GICONV +#include <giconv.h> +#else +#include <iconv.h> +#endif +#ifdef USE_LANGINFO +#include <langinfo.h> +#endif +#endif +#include "stream_msg.h" +#include "osdep/mplib.h" + +#define BUF_SIZE 102400 +#define HDR_BUF_SIZE 8192 +#define MAX_STREAMS 20 + +typedef struct +{ + uint8_t buf[BUF_SIZE]; + int num_bytes; + +} command_t; + +static int seq_num; +static int num_stream_ids; +static int stream_ids[MAX_STREAMS]; + +static int get_data (int s,unsigned char *buf, size_t count); + +static void put_32 (command_t *cmd, uint32_t value) +{ + cmd->buf[cmd->num_bytes ] = value % 256; + value = value >> 8; + cmd->buf[cmd->num_bytes+1] = value % 256 ; + value = value >> 8; + cmd->buf[cmd->num_bytes+2] = value % 256 ; + value = value >> 8; + cmd->buf[cmd->num_bytes+3] = value % 256 ; + + cmd->num_bytes += 4; +} + +static uint32_t get_32 (unsigned char *cmd, int offset) +{ + uint32_t ret; + + ret = cmd[offset] ; + ret |= cmd[offset+1]<<8 ; + ret |= cmd[offset+2]<<16 ; + ret |= cmd[offset+3]<<24 ; + + return ret; +} + +static void send_command (int s, int command, uint32_t switches, + uint32_t extra, int length, + unsigned char *data) +{ + command_t cmd; + int len8; + + len8 = (length + 7) / 8; + + cmd.num_bytes = 0; + + put_32 (&cmd, 0x00000001); /* start sequence */ + put_32 (&cmd, 0xB00BFACE); /* #-)) */ + put_32 (&cmd, len8*8 + 32); + put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */ + put_32 (&cmd, len8 + 4); + put_32 (&cmd, seq_num); + seq_num++; + put_32 (&cmd, 0x0); /* unknown */ + put_32 (&cmd, 0x0); + put_32 (&cmd, len8+2); + put_32 (&cmd, 0x00030000 | command); /* dir | command */ + put_32 (&cmd, switches); + put_32 (&cmd, extra); + + memcpy (&cmd.buf[48], data, length); + if (length & 7) + memset(&cmd.buf[48 + length], 0, 8 - (length & 7)); + + if (send (s, cmd.buf, len8*8+48, 0) != (len8*8+48)) { + MSG_ERR ("write error\n"); + } +} + +#ifdef USE_ICONV +static iconv_t url_conv; +#endif + +static void string_utf16(unsigned char *dest,const char *src, int len) +{ + int i; +#ifdef USE_ICONV + size_t len1, len2; + char *ip, *op; + + if (url_conv != (iconv_t)(-1)) + { + memset(dest, 0, 1000); + len1 = len; len2 = 1000; + ip = src; op = dest; + + iconv(url_conv, &ip, &len1, &op, &len2); + } + else + { +#endif + if (len > 499) len = 499; + for (i=0; i<len; i++) { + dest[i*2] = src[i]; + dest[i*2+1] = 0; + } + /* trailing zeroes */ + dest[i*2] = 0; + dest[i*2+1] = 0; +#ifdef USE_ICONV + } +#endif +} + +static void get_answer (int s) +{ + unsigned char data[BUF_SIZE]; + int command = 0x1b; + + while (command == 0x1b) { + int len; + + len = recv (s, data, BUF_SIZE, 0) ; + if (!len) { + MSG_ERR ("\nalert! eof\n"); + return; + } + + command = get_32 (data, 36) & 0xFFFF; + + if (command == 0x1b) + send_command (s, 0x1b, 0, 0, 0, data); + } +} + +static int get_data (int s,unsigned char *buf, size_t count) +{ + ssize_t len; + size_t total = 0; + + while (total < count) { + + len = recv (s, &buf[total], count-total, 0); + + if (len<=0) { + MSG_ERR ("read error:"); + return 0; + } + + total += len; + + if (len != 0) { +// printf ("[%d/%d]", total, count); + fflush (stdout); + } + + } + + return 1; + +} + +static int get_header (int s, uint8_t *header, streaming_ctrl_t *streaming_ctrl) +{ + unsigned char pre_header[8]; + int header_len; + + header_len = 0; + + while (1) { + if (!get_data (s, pre_header, 8)) { + MSG_ERR ("pre-header read failed\n"); + return 0; + } + if (pre_header[4] == 0x02) { + + int packet_len; + + packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; + +// printf ("asf header packet detected, len=%d\n", packet_len); + + if (packet_len < 0 || packet_len > HDR_BUF_SIZE - header_len) { + MSG_FATAL("Invalid header size, giving up\n"); + return 0; + } + + if (!get_data (s, &header[header_len], packet_len)) { + MSG_ERR("header data read failed\n"); + return 0; + } + + header_len += packet_len; + + if ( (header[header_len-1] == 1) && (header[header_len-2]==1)) { + + + if( streaming_bufferize( streaming_ctrl, header, header_len )<0 ) { + return -1; + } + + // printf ("get header packet finished\n"); + + return (header_len); + + } + + } else { + + int32_t packet_len; + int command; + unsigned char data[BUF_SIZE]; + + if (!get_data (s, (unsigned char*)&packet_len, 4)) { + MSG_ERR ("packet_len read failed\n"); + return 0; + } + + packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; + +// printf ("command packet detected, len=%d\n", packet_len); + + if (packet_len < 0 || packet_len > BUF_SIZE) { + MSG_FATAL("Invalid rtsp packet size, giving up\n"); + return 0; + } + + if (!get_data (s, data, packet_len)) { + MSG_ERR ("command data read failed\n"); + return 0; + } + + command = get_32 (data, 24) & 0xFFFF; + +// printf ("command: %02x\n", command); + + if (command == 0x1b) + send_command (s, 0x1b, 0, 0, 0, data); + + } + +// printf ("get header packet succ\n"); + } +} + +static int interp_header (uint8_t *header, int header_len) +{ + int i; + int packet_length=-1; + + /* + * parse header + */ + + i = 30; + while (i<header_len) { + + uint64_t guid_1, guid_2, length; + + 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; + + 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; + +// printf ("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) ) { + MSG_V ("header object\n"); + } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) { + MSG_V ("data object\n"); + } else if ((guid_1 == 0x6553200cc000e48eULL) && (guid_2 == 0x11cfa9478cabdca1ULL)) { + + packet_length = get_32(header, i+92-24); + + MSG_V ("file object, packet length = %d (%d)\n", + 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; + + MSG_V ("stream object, stream id: %d\n", stream_id); + + if (num_stream_ids < MAX_STREAMS) { + stream_ids[num_stream_ids] = stream_id; + num_stream_ids++; + } else { + MSG_ERR("asf_mmst: too many id, stream skipped"); + } + + } else { + MSG_V ("unknown object\n"); + } + +// printf ("length : %lld\n", length); + + i += length-24; + + } + + return packet_length; + +} + + +static int get_media_packet (int s, int padding, streaming_ctrl_t *stream_ctrl) { + unsigned char pre_header[8]; + unsigned char data[BUF_SIZE]; + + if (!get_data (s, pre_header, 8)) { + MSG_ERR ("pre-header read failed\n"); + return 0; + } + +// for (i=0; i<8; i++) +// printf ("pre_header[%d] = %02x (%d)\n", +// i, pre_header[i], pre_header[i]); + + if (pre_header[4] == 0x04) { + + int packet_len; + + packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; + +// printf ("asf media packet detected, len=%d\n", packet_len); + + if (packet_len < 0 || packet_len > BUF_SIZE) { + MSG_FATAL("Invalid rtsp packet size, giving up\n"); + return 0; + } + + if (!get_data (s, data, packet_len)) { + MSG_ERR ("media data read failed\n"); + return 0; + } + + streaming_bufferize(stream_ctrl, data, padding); + + } else { + + int32_t packet_len; + int command; + + if (!get_data (s, (unsigned char*)&packet_len, 4)) { + MSG_ERR ("packet_len read failed\n"); + return 0; + } + + packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; + + if (packet_len < 0 || packet_len > BUF_SIZE) { + MSG_FATAL("Invalid rtsp packet size, giving up\n"); + return 0; + } + + if (!get_data (s, data, packet_len)) { + MSG_ERR ("command data read failed\n"); + return 0; + } + + if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) + || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) { + + MSG_ERR ("missing signature\n"); + return -1; + } + + command = get_32 (data, 24) & 0xFFFF; + +// printf ("\ncommand packet detected, len=%d cmd=0x%X\n", packet_len, command); + + if (command == 0x1b) + send_command (s, 0x1b, 0, 0, 0, data); + else if (command == 0x1e) { + MSG_OK ("everything done. Thank you for downloading a media file containing proprietary and patentend technology.\n"); + return 0; + } + else if (command == 0x21 ) { + // Looks like it's new in WMS9 + // Unknown command, but ignoring it seems to work. + return 0; + } + else if (command != 0x05) { + MSG_ERR ("unknown command %02x\n", command); + return -1; + } + } + +// printf ("get media packet succ\n"); + + 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; + + while( stream_ctrl->buffer_size==0 ) { + // buffer is empty - fill it! + int ret = get_media_packet( fd, packet_length1, stream_ctrl); + if( ret<0 ) { + MSG_ERR("get_media_packet error : %s\n",strerror(errno)); + return -1; + } else if (ret==0) //EOF? + return ret; + } + + len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos; + if(len>size) len=size; + memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len ); + stream_ctrl->buffer_pos += len; + if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) { + mp_free( stream_ctrl->buffer ); + stream_ctrl->buffer = NULL; + stream_ctrl->buffer_size = 0; + stream_ctrl->buffer_pos = 0; + } + return len; + +} + +static int asf_mmst_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) +{ + return -1; + // Shut up gcc warning + fd++; + pos++; + streaming_ctrl=NULL; +} + +int asf_mmst_streaming_start(any_t* libinput,stream_t *stream) +{ + char str[1024]; + unsigned char data[BUF_SIZE]; + uint8_t asf_header[HDR_BUF_SIZE]; + int asf_header_len; + int len, i, packet_length; + char *path, *unescpath; + URL_t *url1 = stream->streaming_ctrl->url; + int s = stream->fd; + + if( s>0 ) { + closesocket( stream->fd ); + stream->fd = -1; + } + + /* parse url */ + path = strchr(url1->file,'/') + 1; + + /* mmst filename are not url_escaped by MS MediaPlayer and are expected as + * "plain text" by the server, so need to decode it here + */ + unescpath=new char [strlen(path)+1]; + if (!unescpath) { + MSG_FATAL("Memory allocation failed!\n"); + return -1; + } + url_unescape_string(unescpath,path); + path=unescpath; + + if( url1->port==0 ) { + url1->port=1755; + } + s = tcp_connect2Server(libinput, url1->hostname, url1->port, 0); + if( s<0 ) { + mp_free(path); + return s; + } + MSG_INFO ("connected\n"); + + seq_num=0; + + /* + * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. + * This command is sent at the very start of protocol initiation. It sends local information to the serve + * cmd 1 0x01 + * */ + + /* prepare for the url encoding conversion */ +#ifdef USE_ICONV +#ifdef USE_LANGINFO + url_conv = iconv_open("UTF-16LE",nl_langinfo(CODESET)); +#else + url_conv = iconv_open("UTF-16LE", NULL); +#endif +#endif + + snprintf (str, 1023, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", url1->hostname); + string_utf16 (data, str, strlen(str)); +// send_command(s, commandno ....) + send_command (s, 1, 0, 0x0004000b, strlen(str) * 2+2, data); + + len = recv (s, data, BUF_SIZE, 0) ; + + /*This sends details of the local machine IP address to a Funnel system at the server. + * Also, the TCP or UDP transport selection is sent. + * + * here 192.168.0.129 is local ip address TCP/UDP states the tronsport we r using + * and 1037 is the local TCP or UDP socket number + * cmd 2 0x02 + * */ + + string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037", 24); + memset (data, 0, 8); + send_command (s, 2, 0, 0, 24*2+10, data); + + len = recv (s, data, BUF_SIZE, 0) ; + + /* This command sends file path (at server) and file name request to the server. + * 0x5 */ + + string_utf16 (&data[8], path, strlen(path)); + memset (data, 0, 8); + send_command (s, 5, 0, 0, strlen(path)*2+10, data); + mp_free(path); + + get_answer (s); + + /* The ASF header chunk request. Includes ?session' variable for pre header value. + * After this command is sent, + * the server replies with 0x11 command and then the header chunk with header data follows. + * 0x15 */ + + memset (data, 0, 40); + data[32] = 2; + + 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); +// printf("---------------------------------- asf_header %d\n",asf_header); + if (asf_header_len==0) { //error reading header + closesocket(s); + return -1; + } + packet_length = interp_header (asf_header, asf_header_len); + + + /* + * This command is the media stream MBR selector. Switches are always 6 bytes in length. + * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. + * Where: + * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. + * It is not yet understood what all this means. + * And the last [02] byte is probably the header ?session' value. + * + * 0x33 */ + + memset (data, 0, 40); + + if (mp_conf.audio_id > 0) { + data[2] = 0xFF; + data[3] = 0xFF; + data[4] = mp_conf.audio_id; + send_command(s, 0x33, num_stream_ids, 0xFFFF | mp_conf.audio_id << 16, 8, data); + } else { + for (i=1; i<num_stream_ids; i++) { + data [ (i-1) * 6 + 2 ] = 0xFF; + data [ (i-1) * 6 + 3 ] = 0xFF; + data [ (i-1) * 6 + 4 ] = stream_ids[i]; + data [ (i-1) * 6 + 5 ] = 0x00; + } + + send_command (s, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data); + } + + get_answer (s); + + /* Start sending file from packet xx. + * This command is also used for resume downloads or requesting a lost packet. + * Also used for seeking by sending a play point value which seeks to the media time point. + * Includes ?session' value in pre header and the maximum media stream time. + * 0x07 */ + + memset (data, 0, 40); + + for (i=8; i<16; i++) + data[i] = 0xFF; + + data[20] = 0x04; + + send_command (s, 0x07, 1, 0xFFFF | stream_ids[0] << 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; + + packet_length1 = packet_length; + MSG_V("mmst packet_length = %d\n",packet_length); + +#ifdef USE_ICONV + if (url_conv != (iconv_t)(-1)) + iconv_close(url_conv); +#endif + + return 0; +} Deleted: mplayerxp/libmpstream/asf_streaming.c =================================================================== --- mplayerxp/libmpstream/asf_streaming.c 2012-11-21 14:09:25 UTC (rev 424) +++ mplayerxp/libmpstream/asf_streaming.c 2012-11-21 15:49:25 UTC (rev 425) @@ -1,878 +0,0 @@ -#include <stdio.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "mp_config.h" -#include "mplayerxp.h" -#ifndef HAVE_WINSOCK2 -#define closesocket close -#else -#include <winsock2.h> -#endif - -#include "url.h" -#include "tcp.h" -#include "http.h" -#include "libmpdemux/asf.h" - -#include "stream.h" - -#include "network.h" -#include "stream_msg.h" -#include "osdep/mplib.h" - -#if defined( ARCH_X86 ) || defined(ARCH_X86_64) -#define ASF_LOAD_GUID_PREFIX(guid) (*(uint32_t *)(guid)) -#else -#define ASF_LOAD_GUID_PREFIX(guid) \ - ((guid)[3] << 24 | (guid)[2] << 16 | (guid)[1] << 8 | (guid)[0]) -#endif - -// ASF streaming support several network protocol. -// One use UDP, not known, yet! -// Another is HTTP, this one is known. -// So for now, we use the HTTP protocol. -// -// We can try several protocol for asf streaming -// * first the UDP protcol, if there is a firewall, UDP -// packets will not come back, so the mmsu will failed. -// * Then we can try TCP, but if there is a proxy for -// internet connection, the TCP connection will not get -// through -// * Then we can try HTTP. -// -// Note: MMS/HTTP support is now a "well known" support protocol, -// it has been tested for while, not like MMST support. -// WMP sequence is MMSU then MMST and then HTTP. -// In MPlayer case since HTTP support is more reliable, -// we are doing HTTP first then we try MMST if HTTP fail. -static int asf_http_streaming_start(any_t*,stream_t *stream, int *demuxer_type ); -int asf_mmst_streaming_start(stream_t *stream ); - -/* - ASF streaming support several network protocol. - One use UDP, not known, yet! - Another is HTTP, this one is known. - So for now, we use the HTTP protocol. - - We can try several protocol for asf streaming - * first the UDP protcol, if there is a firewall, UDP - packets will not come back, so the mmsu will failed. - * Then we can try TCP, but if there is a proxy for - internet connection, the TCP connection will not get - through - * Then we can try HTTP. - - Note: MMS/HTTP support is now a "well known" support protocol, - it has been tested for while, not like MMST support. - WMP sequence is MMSU then MMST and then HTTP. - In MPlayer case since HTTP support is more reliable, - we are doing HTTP first then we try MMST if HTTP fail. -*/ -int asf_streaming_start(any_t* libinput, stream_t *stream, int *demuxer_type) { - char *proto = stream->streaming_ctrl->url->protocol; - int fd = -1; - int port = stream->streaming_ctrl->url->port; - - // Is protocol even valid mms,mmsu,mmst,http,http_proxy? - if (!(!strncasecmp(proto, "mmst", 4) || !strncasecmp(proto, "mmsu", 4) || - !strncasecmp(proto, "http_proxy", 10) || !strncasecmp(proto, "mms", 3) || - !strncasecmp(proto, "http", 4))) - { - MSG_ERR("Unknown protocol: %s\n", proto ); - return -1; - } - - // Is protocol mms or mmsu? - if (!strncasecmp(proto, "mmsu", 4) || !strncasecmp(proto, "mms", 3)) - { - MSG_V("Trying ASF/UDP...\n"); - //fd = asf_mmsu_streaming_start( stream ); - if( fd>-1 ) return fd; //mmsu support is not implemented yet - using this code - MSG_V(" ===> ASF/UDP failed\n"); - if( fd==-2 ) return -1; - } - - //Is protocol mms or mmst? - if (!strncasecmp(proto, "mmst", 4) || !strncasecmp(proto, "mms", 3)) - { - MSG_V("Trying ASF/TCP...\n"); - fd = asf_mmst_streaming_start( stream ); - stream->streaming_ctrl->url->port = port; - if( fd>-1 ) return fd; - MSG_V(" ===> ASF/TCP failed\n"); - if( fd==-2 ) return -1; - } - - //Is protocol http, http_proxy, or mms? - if (!strncasecmp(proto, "http_proxy", 10) || !strncasecmp(proto, "http", 4) || - !strncasecmp(proto, "mms", 3)) - { - MSG_V("Trying ASF/HTTP...\n"); - fd = asf_http_streaming_start(libinput, stream, demuxer_type ); - stream->streaming_ctrl->url->port = port; - if( fd>-1 ) return fd; - MSG_V(" ===> ASF/HTTP failed\n"); - if( fd==-2 ) return -1; - } - - //everything failed - return -1; -} - -int -asf_streaming(ASF_stream_chunck_t *stream_chunck, int *drop_packet ) { - if( drop_packet!=NULL ) *drop_packet = 0; - - if( stream_chunck->size<8 ) { - MSG_ERR("Ahhhh, stream_chunck size is too small: %d\n", stream_chunck->size); - return -1; - } - if( stream_chunck->size!=stream_chunck->size_confirm ) { - MSG_ERR("size_confirm mismatch!: %d %d\n", stream_chunck->size, stream_chunck->size_confirm); - return -1; - } - switch(stream_chunck->type) { - case ASF_STREAMING_CLEAR: // $C Clear ASF configuration - MSG_V("=====> Clearing ASF stream configuration!\n"); - if( drop_packet!=NULL ) *drop_packet = 1; - return stream_chunck->size; - break; - case ASF_STREAMING_DATA: // $D Data follows - break; - case ASF_STREAMING_END_TRANS: // $E Transfer complete - MSG_V("=====> Transfer complete\n"); - if( drop_packet!=NULL ) *drop_packet = 1; - return stream_chunck->size; - break; - case ASF_STREAMING_HEADER: // $H ASF header chunk follows - MSG_V("=====> ASF header chunk follows\n"); - break; - default: - MSG_V("=====> Unknown stream type 0x%x\n", stream_chunck->type ); - } - return stream_chunck->size+4; -} - -static const char asf_stream_header_guid[16] = {0x91, 0x07, 0xdc, 0xb7, - 0xb7, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}; -static const char asf_file_header_guid[16] = {0xa1, 0xdc, 0xab, 0x8c, - 0x47, 0xa9, 0xcf, 0x11, 0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}; -static const char asf_content_desc_guid[16] = {0x33, 0x26, 0xb2, 0x75, - 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}; -static const char asf_stream_group_guid[16] = {0xce, 0x75, 0xf8, 0x7b, - 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2}; -static const char asf_data_chunk_guid[16] = {0x36, 0x26, 0xb2, 0x75, - 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}; -static int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len) -{ - int i; - for (i = cur_pos; i < buf_len - 19; i++) { - if (memcmp(&buf[i], guid, 16) == 0) - return i + 16 + 8; // point after guid + length - } - return -1; -} - -static int max_idx(int s_count, int *s_rates, int bound) { - int i, best = -1, rate = -1; - for (i = 0; i < s_count; i++) { - if (s_rates[i] > rate && s_rates[i] <= bound) { - rate = s_rates[i]; - best = i; - } - } - return best; -} - -static int -asf_streaming_parse_header(int fd, streaming_ctrl_t* streaming_ctrl) { - ASF_header_t asfh; - ASF_stream_chunck_t chunk; - asf_http_streaming_ctrl_t* asf_ctrl = (asf_http_streaming_ctrl_t*) streaming_ctrl->data; - char* buffer=NULL, *chunk_buffer=NULL; - int i,r,size,pos = 0; - int start; - int buffer_size = 0; - int chunk_size2read = 0; - int bw = streaming_ctrl->bandwidth; - int *v_rates = NULL, *a_rates = NULL; - int v_rate = 0, a_rate = 0, a_idx = -1, v_idx = -1; - - if(asf_ctrl == NULL) return -1; - - // The ASF header can be in several network chunks. For example if the content description - // is big, the ASF header will be split in 2 network chunk. - // So we need to retrieve all the chunk before starting to parse the header. - do { - for( r=0; r < (int)sizeof(ASF_stream_chunck_t) ; ) { - i = nop_streaming_read(fd,((char*)&chunk)+r,sizeof(ASF_stream_chunck_t) - r,streaming_ctrl); - if(i <= 0) return -1; - r += i; - } - // Endian handling of the stream chunk - le2me_ASF_stream_chunck_t(&chunk); - size = asf_streaming( &chunk, &r) - sizeof(ASF_stream_chunck_t); - if(r) MSG_WARN("Warning : drop header ????\n"); - if(size < 0){ - MSG_ERR("Error while parsing chunk header\n"); - return -1; - } - if (chunk.type != ASF_STREAMING_HEADER) { - MSG_ERR("Don't got a header as first chunk !!!!\n"); - return -1; - } - - // audit: do not overflow buffer_size - if (size > SIZE_MAX - buffer_size) return -1; - buffer = (char*) mp_malloc(size+buffer_size); - if(buffer == NULL) { - MSG_FATAL("Error can't allocate %d bytes buffer\n",size+buffer_size); - return -1; - } - if( chunk_buffer!=NULL ) { - memcpy( buffer, chunk_buffer, buffer_size ); - mp_free( chunk_buffer ); - } - chunk_buffer = buffer; - buffer += buffer_size; - buffer_size += size; - - for(r = 0; r < size;) { - i = nop_streaming_read(fd,buffer+r,size-r,streaming_ctrl); - if(i < 0) { - MSG_ERR("Error while reading network stream\n"); - return -1; - } - r += i; - } - - if( chunk_size2read==0 ) { - if(size < (int)sizeof(asfh)) { - MSG_ERR("Error chunk is too small\n"); - return -1; - } else MSG_DBG2("Got chunk\n"); - memcpy(&asfh,buffer,sizeof(asfh)); - le2me_ASF_header_t(&asfh); - chunk_size2read = asfh.objh.size; - MSG_DBG2("Size 2 read=%d\n", chunk_size2read); - } - } while( buffer_size<chunk_size2read); - buffer = chunk_buffer; - size = buffer_size; - - if(asfh.cno > 256) { - MSG_ERR("Error sub chunks number is invalid\n"); - return -1; - } - - start = sizeof(asfh); - - pos = find_asf_guid(buffer, asf_file_header_guid, start, size); - if (pos >= 0) { - ASF_file_header_t *fileh = (ASF_file_header_t *) &buffer[pos]; - pos += sizeof(ASF_file_header_t); - if (pos > size) goto len_err_out; - le2me_ASF_file_header_t(fileh); -/* - if(fileh.packetsize != fileh.packetsize2) { - printf("Error packetsize check don't match\n"); - return -1; - } -*/ - asf_ctrl->packet_size = fileh->max_packet_size; - // before playing. - // preroll: time in ms to bufferize before playing - streaming_ctrl->prebuffer_size = (unsigned int)(((double)fileh->preroll/1000.0)*((double)fileh->max_bitrate/8.0)); - } - - pos = start; - while ((pos = find_asf_guid(buffer, asf_stream_header_guid, pos, size)) >= 0) - { - ASF_stream_header_t *streamh = (ASF_stream_header_t *)&buffer[pos]; - pos += sizeof(ASF_stream_header_t); - if (pos > size) goto len_err_out; - le2me_ASF_stream_header_t(streamh); - switch(ASF_LOAD_GUID_PREFIX(streamh->type)) { - case 0xF8699E40 : // audio stream - if(asf_ctrl->audio_streams == NULL){ - asf_ctrl->audio_streams = (int*)mp_malloc(sizeof(int)); - asf_ctrl->n_audio = 1; - } else { - asf_ctrl->n_audio++; - asf_ctrl->audio_streams = (int*)mp_realloc(asf_ctrl->audio_streams, - asf_ctrl->n_audio*sizeof(int)); - } - asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = streamh->stream_no; - break; - case 0xBC19EFC0 : // video stream - if(asf_ctrl->video_streams == NULL){ - asf_ctrl->video_streams = (int*)mp_malloc(sizeof(int)); - asf_ctrl->n_video = 1; - } else { - asf_ctrl->n_video++; - asf_ctrl->video_streams = (int*)mp_realloc(asf_ctrl->video_streams, - asf_ctrl->n_video*sizeof(int)); - } - asf_ctrl->video_streams[asf_ctrl->n_video-1] = streamh->stream_no; - break; - } - } - - // always allocate to avoid lots of ifs later - v_rates = mp_calloc(asf_ctrl->n_video, sizeof(int)); - a_rates = mp_calloc(asf_ctrl->n_audio, sizeof(int)); - - pos = find_asf_guid(buffer, asf_stream_group_guid, start, size); - if (pos >= 0) { - // stream bitrate properties object - int stream_count; - char *ptr = &buffer[pos]; - - MSG_V("Stream bitrate properties object\n"); - stream_count = le2me_16(*(uint16_t*)ptr); - ptr += sizeof(uint16_t); - if (ptr > &buffer[size]) goto len_err_out; - MSG_V(" stream count=[0x%x][%u]\n", - stream_count, stream_count ); - for( i=0 ; i<stream_count ; i++ ) { - uint32_t rate; - int id; - int j; - id = le2me_16(*(uint16_t*)ptr); - ptr += sizeof(uint16_t); - if (ptr > &buffer[size]) goto len_err_out; - memcpy(&rate, ptr, sizeof(uint32_t));// workaround unaligment bug on sparc - ptr += sizeof(uint32_t); - if (ptr > &buffer[size]) goto len_err_out; - rate = le2me_32(rate); - MSG_V( - " stream id=[0x%x][%u]\n", id, id); - MSG_V( - " max bitrate=[0x%x][%u]\n", rate, rate); - for (j = 0; j < asf_ctrl->n_video; j++) { - if (id == asf_ctrl->video_streams[j]) { - MSG_V(" is video stream\n"); - v_rates[j] = rate; - break; - } - } - for (j = 0; j < asf_ctrl->n_audio; j++) { - if (id == asf_ctrl->audio_streams[j]) { - MSG_V( " is audio stream\n"); - a_rates[j] = rate; - break; - } - } - } - } - mp_free(buffer); - - // automatic stream selection based on bandwidth - if (bw == 0) bw = INT_MAX; - MSG_V( "Max bandwidth set to %d\n", bw); - - if (asf_ctrl->n_audio) { - // find lowest-bitrate audio stream - a_rate = a_rates[0]; - a_idx = 0; - for (i = 0; i < asf_ctrl->n_audio; i++) { - if (a_rates[i] < a_rate) { - a_rate = a_rates[i]; - a_idx = i; - } - } - if (max_idx(asf_ctrl->n_video, v_rates, bw - a_rate) < 0) { - // both audio and video are not possible, try video only next - a_idx = -1; - a_rate = 0; - } - } - // find best video stream - v_idx = max_idx(asf_ctrl->n_video, v_rates, bw - a_rate); - if (v_idx >= 0) - v_rate = v_rates[v_idx]; - - // find best audio stream - a_idx = max_idx(asf_ctrl->n_audio, a_rates, bw - v_rate); - - mp_free(v_rates); - mp_free(a_rates); - - if (a_idx < 0 && v_idx < 0) { - MSG_FATAL( "bandwidth too small, " - "file cannot be played!\n"); - return -1; - } - - if (mp_conf.audio_id > 0) - // a audio stream was forced - asf_ctrl->audio_id = mp_conf.audio_id; - else if (a_idx >= 0) - asf_ctrl->audio_id = asf_ctrl->audio_streams[a_idx]; - else if (asf_ctrl->n_audio) { - MSG_WARN( "bandwidth too small, " - "deselected audio stream\n"); - mp_conf.audio_id = -2; - } - - if (mp_conf.video_id > 0) - // a video stream was forced - asf_ctrl->video_id = mp_conf.video_id; - else if (v_idx >= 0) - asf_ctrl->video_id = asf_ctrl->video_streams[v_idx]; - else if (asf_ctrl->n_video) { - MSG_WARN( "bandwidth too small, " - "deselected video stream\n"); - mp_conf.video_id = -2; - } - - return 1; - -len_err_out: - MSG_FATAL( "Invalid length in ASF header!\n"); - if (buffer) mp_free(buffer); - if (v_rates) mp_free(v_rates); - if (a_rates) mp_free(a_rates); - return -1; -} - -int -asf_http_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) { - static ASF_stream_chunck_t chunk; - int read,chunk_size = 0; - static int rest = 0, drop_chunk = 0, waiting = 0; - asf_http_streaming_ctrl_t *asf_http_ctrl = (asf_http_streaming_ctrl_t*)streaming_ctrl->data; - - while(1) { - if (rest == 0 && waiting == 0) { - read = 0; - while(read < (int)sizeof(ASF_stream_chunck_t)){ - int r = nop_streaming_read( fd, ((char*)&chunk) + read, - sizeof(ASF_stream_chunck_t)-read, - streaming_ctrl ); - if(r <= 0){ - if( r < 0) - MSG_ERR("Error while reading chunk header\n"); - return -1; - } - read += r; - } - - // Endian handling of the stream chunk - le2me_ASF_stream_chunck_t(&chunk); - chunk_size = asf_streaming( &chunk, &drop_chunk ); - if(chunk_size < 0) { - MSG_ERR("Error while parsing chunk header\n"); - return -1; - } - chunk_size -= sizeof(ASF_stream_chunck_t); - - if(chunk.type != ASF_STREAMING_HEADER && (!drop_chunk)) { - if (asf_http_ctrl->packet_size < chunk_size) { - MSG_ERR("Error chunk_size > packet_size\n"); - return -1; - } - waiting = asf_http_ctrl->packet_size; - } else { - waiting = chunk_size; - } - - } else if (rest){ - chunk_size = rest; - rest = 0; - } - - read = 0; - if ( waiting >= chunk_size) { - if (chunk_size > size){ - rest = chunk_size - size; - chunk_size = size; - } - while(read < chunk_size) { - int got = nop_streaming_read( fd,buffer+read,chunk_size-read,streaming_ctrl ); - if(got <= 0) { - if(got < 0) - MSG_ERR("Error while reading chunk\n"); - return -1; - } - read += got; - } - waiting -= read; - if (drop_chunk) continue; - } - if (rest == 0 && waiting > 0 && size-read > 0) { - int s = MIN(waiting,size-read); - memset(buffer+read,0,s); - waiting -= s; - read += s; - } - break; - } - - return read; -} - -int -asf_http_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) { - return -1; - // to shut up gcc warning - fd++; - pos++; - streaming_ctrl=NULL; -} - -int -asf_header_check( HTTP_header_t *http_hdr ) { - ASF_obj_header_t *objh; - if( http_hdr==NULL ) return -1; - if( http_hdr->body==NULL || http_hdr->body_size<sizeof(ASF_obj_header_t) ) return -1; - - objh = (ASF_obj_header_t*)http_hdr->body; - if( ASF_LOAD_GUID_PREFIX(objh->guid)==0x75B22630 ) return 0; - return -1; -} - -int -asf_http_streaming_type(char *content_type, char *features, HTTP_header_t *http_hdr ) { - if( content_type==NULL ) return ASF_Unknown_e; - if( !strcasecmp(content_type, "application/octet-stream") || - !strcasecmp(content_type, "application/vnd.ms.wms-hdr.asfv1") || // New in Corona, first request - !strcasecmp(content_type, "application/x-mms-framed") || // New in Corana, second request - !strcasecmp(content_type, "video/x-ms-asf")) { - - if( strstr(features, "broadcast") ) { - MSG_V("=====> ASF Live stream\n"); - return ASF_Live_e; - } else { - MSG_V("=====> ASF Prerecorded\n"); - return ASF_Prerecorded_e; - } - } else { - // Ok in a perfect world, web servers should be well configured - // so we could used mime type to know the stream type, - // but guess what? All of them are not well configured. - // So we have to check for an asf header :(, but it works :p - if( http_hdr->body_size>sizeof(ASF_obj_header_t) ) { - if( asf_header_check( http_hdr )==0 ) { - MSG_V("=====> ASF Plain text\n"); - return ASF_PlainText_e; - } else if( (!strcasecmp(content_type, "text/html")) ) { - MSG_V("=====> HTML, mplayer is not a browser...yet!\n"); - return ASF_Unknown_e; - } else { - MSG_V("=====> ASF Redirector\n"); - return ASF_Redirector_e; - } - } else { - if( (!strcasecmp(content_type, "audio/x-ms-wax")) || - (!strcasecmp(content_type, "audio/x-ms-wma")) || - (!strcasecmp(content_type, "video/x-ms-asf")) || - (!strcasecmp(content_type, "video/x-ms-afs")) || - (!strcasecmp(content_type, "video/x-ms-wvx")) || - (!strcasecmp(content_type, "video/x-ms-wmv")) || - (!strcasecmp(content_type, "video/x-ms-wma")) ) { - MSG_ERR("=====> ASF Redirector\n"); - return ASF_Redirector_e; - } else if( !strcasecmp(content_type, "text/plain") ) { - MSG_V("=====> ASF Plain text\n"); - return ASF_PlainText_e; - } else { - MSG_V("=====> ASF unknown content-type: %s\n", content_type ); - return ASF_Unknown_e; - } - } - } - return ASF_Unknown_e; -} - -HTTP_header_t * -asf_http_request(streaming_ctrl_t *streaming_ctrl) { - HTTP_header_t *http_hdr; - URL_t *url = NULL; - URL_t *server_url = NULL; - asf_http_streaming_ctrl_t *asf_http_ctrl; - char str[250]; - char *ptr; - int i, enable; - - int offset_hi=0, offset_lo=0, length=0; - int asf_nb_stream=0, stream_id; - - // Sanity check - if( streaming_ctrl==NULL ) return NULL; - url = streaming_ctrl->url; - asf_http_ctrl = (asf_http_streaming_ctrl_t*)streaming_ctrl->data; - if( url==NULL || asf_http_ctrl==NULL ) return NULL; - - // Common header for all requests. - http_hdr = http_new_header(); - http_set_field( http_hdr, "Accept: */*" ); - http_set_field( http_hdr, "User-Agent: NSPlayer/4.1.0.3856" ); - http_add_basic_authentication( http_hdr, url->username, url->password ); - - // Check if we are using a proxy - if( !strcasecmp( url->protocol, "http_proxy" ) ) { - server_url = url_new( (url->file)+1 ); - if( server_url==NULL ) { - MSG_ERR("Invalid proxy URL\n"); - http_free( http_hdr ); - return NULL; - } - http_set_uri( http_hdr, server_url->url ); - sprintf( str, "Host: %.220s:%d", server_url->hostname, server_url->port ); - url_free( server_url ); - } else { - http_set_uri( http_hdr, url->file ); - sprintf( str, "Host: %.220s:%d", url->hostname, url->port ); - } - - http_set_field( http_hdr, str ); - http_set_field( http_hdr, "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}" ); - sprintf(str, - "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=%u", - offset_hi, offset_lo, asf_http_ctrl->request, length ); - http_set_field( http_hdr, str ); - - switch( asf_http_ctrl->streaming_type ) { - case ASF_Live_e: - case ASF_Prerecorded_e: - http_set_field( http_hdr, "Pragma: xPlayStrm=1" ); - ptr = str; - ptr += sprintf( ptr, "Pragma: stream-switch-entry="); - if(asf_http_ctrl->n_audio > 0) { - for( i=0; i<asf_http_ctrl->n_audio ; i++ ) { - stream_id = asf_http_ctrl->audio_streams[i]; - if(stream_id == asf_http_ctrl->audio_id) { - enable = 0; - } else { - enable = 2; - continue; - } - asf_nb_stream++; - ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable); - } - } - if(asf_http_ctrl->n_video > 0) { - for( i=0; i<asf_http_ctrl->n_video ; i++ ) { - stream_id = asf_http_ctrl->video_streams[i]; - if(stream_id == asf_http_ctrl->video_id) { - enable = 0; - } else { - enable = 2; - continue; - } - asf_nb_stream++; - ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable); - } - } - http_set_field( http_hdr, str ); - sprintf( str, "Pragma: stream-switch-count=%d", asf_nb_stream ); - http_set_field( http_hdr, str ); - break; - case ASF_Redirector_e: - break; - case ASF_Unknown_e: - // First request goes here. - break; - default: - MSG_ERR("Unknown asf stream type\n"); - } - - http_set_field( http_hdr, "Connection: Close" ); - http_build_request( http_hdr ); - - return http_hdr; -} - -int -asf_http_parse_response(asf_http_streaming_ctrl_t *asf_http_ctrl, HTTP_header_t *http_hdr ) { - char *content_type, *pragma; - char features[64] = "\0"; - size_t len; - if( http_response_parse(http_hdr)<0 ) { - MSG_ERR("Failed to parse HTTP response\n"); - return -1; - } - switch( http_hdr->status_code ) { - case 200: - break; - case 401: // Authentication required - return ASF_Authenticate_e; - default: - MSG_ERR("Server return %d:%s\n", http_hdr->status_code, http_hdr->reason_phrase); - return -1; - } - - content_type = http_get_field( http_hdr, "Content-Type"); - - pragma = http_get_field( http_hdr, "Pragma"); - while( pragma!=NULL ) { - char *comma_ptr=NULL; - char *end; - // The pragma line can get severals attributes - // separeted with a comma ','. - do { - if( !strncasecmp( pragma, "features=", 9) ) { - pragma += 9; - end = strstr( pragma, "," ); - if( end==NULL ) { - size_t s = strlen(pragma); - if(s > sizeof(features)) { - MSG_WARN("ASF HTTP PARSE WARNING : Pragma %s cuted from %d bytes to %d\n",pragma,s,sizeof(features)); - len = sizeof(features); - } else { - len = s; - } - } else { - len = MIN((unsigned int)(end-pragma),s... [truncated message content] |