From 4a83e5f2bd80b95f6acf9737462f0c3bce30423a Mon Sep 17 00:00:00 2001 From: bertrand Date: Fri, 18 May 2001 16:14:06 +0000 Subject: [PATCH] Starting implementation of ASF network streaming. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@834 b3059339-0415-0410-9bf9-f77b7e298cf2 --- Makefile | 6 ++- asf.h | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ asf_streaming.c | 54 ++++++++++++++++++++++++ asfheader.c | 24 ++++++++--- demux_asf.c | 6 +++ network.c | 38 +++++++++++++++++ url.c | 93 ++++++++++++++++++++++++++++++++++++++++ url.h | 15 +++++++ 8 files changed, 338 insertions(+), 8 deletions(-) create mode 100644 asf.h create mode 100644 asf_streaming.c create mode 100644 network.c create mode 100644 url.c create mode 100644 url.h diff --git a/Makefile b/Makefile index a2a5653da7..c2a28e606e 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,10 @@ PRG_CFG = codec-cfg prefix = /usr/local BINDIR = ${prefix}/bin # BINDIR = /usr/local/bin -SRCS = find_sub.c aviprint.c dll_init.c dec_audio.c aviwrite.c aviheader.c asfheader.c demux_avi.c demux_asf.c demux_mpg.c demuxer.c stream.c codec-cfg.c subreader.c linux/getch2.c linux/timer-lx.c linux/shmem.c xa/xa_gsm.c lirc_mp.c cfgparser.c mixer.c dvdauth.c spudec.c -OBJS = find_sub.o aviprint.o dll_init.o dec_audio.o aviwrite.o aviheader.o asfheader.o demux_avi.o demux_asf.o demux_mpg.o demuxer.o stream.o codec-cfg.o subreader.o linux/getch2.o linux/timer-lx.o linux/shmem.o xa/xa_gsm.o lirc_mp.o cfgparser.o mixer.o dvdauth.o spudec.o +SRCS = asf_streaming.c find_sub.c aviprint.c dll_init.c dec_audio.c aviwrite.c aviheader.c asfheader.c demux_avi.c demux_asf.c demux_mpg.c demuxer.c stream.c codec-cfg.c subreader.c linux/getch2.c linux/timer-lx.c linux/shmem.c xa/xa_gsm.c lirc_mp.c cfgparser.c mixer.c dvdauth.c spudec.c +#BB: IMHO It's simplier to use the following rule: +#OBJS = $(SRCS:.c=.o) +OBJS = asf_streaming.o find_sub.o aviprint.o dll_init.o dec_audio.o aviwrite.o aviheader.o asfheader.o demux_avi.o demux_asf.o demux_mpg.o demuxer.o stream.o codec-cfg.o subreader.o linux/getch2.o linux/timer-lx.o linux/shmem.o xa/xa_gsm.o lirc_mp.o cfgparser.o mixer.o dvdauth.o spudec.o CFLAGS = $(OPTFLAGS) -Iloader -Ilibvo $(CSS_INC) # -Wall A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 VO_LIBS = -Llibvo -lvo $(X_LIBS) diff --git a/asf.h b/asf.h new file mode 100644 index 0000000000..cf762032a5 --- /dev/null +++ b/asf.h @@ -0,0 +1,110 @@ +#ifndef ASF_H +#define ASF_H + +#include + +/////////////////////// +// MS GUID definition +/////////////////////// +#ifndef GUID_DEFINED +#define GUID_DEFINED +// Size of GUID is 16 bytes! +typedef struct __attribute__((packed)) { + uint32_t Data1; // 4 bytes + uint16_t Data2; // 2 bytes + uint16_t Data3; // 2 bytes + uint8_t Data4[8]; // 8 bytes +} GUID_t; +#endif + +/////////////////////// +// ASF Object Header +/////////////////////// +typedef struct __attribute__((packed)) { + uint8_t guid[16]; + uint64_t size; +} ASF_obj_header_t; + +//////////////// +// ASF Header +//////////////// +typedef struct __attribute__((packed)) { + ASF_obj_header_t objh; + uint32_t cno; // number of subchunks + uint8_t v1; // unknown (0x01) + uint8_t v2; // unknown (0x02) +} ASF_header_t; + +///////////////////// +// ASF File Header +///////////////////// +typedef struct __attribute__((packed)) { + uint8_t client[16]; // Client GUID + uint64_t file_size; + uint64_t creat_time; //File creation time FILETIME 8 + uint64_t packets; //Number of packets UINT64 8 + uint64_t end_timestamp; //Timestamp of the end position UINT64 8 + uint64_t duration; //Duration of the playback UINT64 8 + uint32_t start_timestamp; //Timestamp of the start position UINT32 4 + uint32_t unk1; //Unknown, maybe reserved ( usually contains 0 ) UINT32 4 + uint32_t flags; //Unknown, maybe flags ( usually contains 2 ) UINT32 4 + uint32_t packetsize; //Size of packet, in bytes UINT32 4 + uint32_t packetsize2; //Size of packet ( confirm ) UINT32 4 + uint32_t frame_size; //Size of uncompressed video frame UINT32 4 +} ASF_file_header_t; + +/////////////////////// +// ASF Stream Header +/////////////////////// +typedef struct __attribute__((packed)) { + uint8_t type[16]; // Stream type (audio/video) GUID 16 + uint8_t concealment[16]; // Audio error concealment type GUID 16 + uint64_t unk1; // Unknown, maybe reserved ( usually contains 0 ) UINT64 8 + uint32_t type_size; //Total size of type-specific data UINT32 4 + uint32_t stream_size; //Size of stream-specific data UINT32 4 + uint16_t stream_no; //Stream number UINT16 2 + uint32_t unk2; //Unknown UINT32 4 +} ASF_stream_header_t; + +/////////////////////////// +// ASF Content Description +/////////////////////////// +typedef struct __attribute__((packed)) { + uint16_t title_size; + uint16_t author_size; + uint16_t copyright_size; + uint16_t comment_size; + uint16_t rating_size; +} ASF_content_description_t; + +//////////////////////// +// ASF Segment Header +//////////////////////// +typedef struct __attribute__((packed)) { + uint8_t streamno; + uint8_t seq; + uint32_t x; + uint8_t flag; +} ASF_segmhdr_t; + +////////////////////// +// ASF Stream Chunck +////////////////////// +typedef struct __attribute__((packed)) { + uint16_t type; + uint16_t length; + uint32_t sequence_number; + uint16_t unknown; + uint16_t length2; +} ASF_stream_chunck_t; + + +// Definition of the differents type of ASF streaming +typedef enum { + ASF_Unknown_e, + ASF_Live_e, + ASF_Prerecorded_e, + ASF_Redirector_e +} ASF_StreamType_e; + +#endif diff --git a/asf_streaming.c b/asf_streaming.c new file mode 100644 index 0000000000..e808a9d40f --- /dev/null +++ b/asf_streaming.c @@ -0,0 +1,54 @@ +#include "asf.h" + +#include + +static ASF_StreamType_e stream_type; + +void asf_streaming(char *data, int length) { + ASF_stream_chunck_t *stream_chunck=(ASF_stream_chunck_t*)data; + printf("ASF stream chunck size=%d\n", stream_chunck->length); + + switch(stream_chunck->type) { + case 0x4324: // Clear ASF configuration + printf(" --> Clearing ASF stream configuration!\n"); + break; + case 0x4424: // Data follows + printf(" --> Data follows\n"); + break; + case 0x4524: // Transfer complete + printf(" --> Transfer complete\n"); + break; + case 0x4824: // ASF header chunk follows + printf(" --> ASF header chunk follows\n"); + break; + default: + printf("======> Unknown stream type %d\n", stream_chunck->type ); + } +} + +void asf_steam_type(char *content_type, char *features) { + stream_type = ASF_Unknown_e; + if( !strcasecmp(content_type, "application/octet-stream") ) { + if( strstr(features, "broadcast")) { + printf("-----> Live stream <-------\n"); + stream_type = ASF_Live_e; + } else { + printf("-----> Prerecorded <-------\n"); + stream_type = ASF_Prerecorded_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")) ) { + printf("-----> Redirector <-------\n"); + stream_type = ASF_Redirector_e; + } else { + printf("-----> unknown content-type: %s\n", content_type ); + stream_type = ASF_Unknown_e; + } + } +} diff --git a/asfheader.c b/asfheader.c index 5ee640163c..54141fb94b 100644 --- a/asfheader.c +++ b/asfheader.c @@ -16,6 +16,10 @@ extern int verbose; // defined in mplayer.c #include "codec-cfg.h" #include "stheader.h" +#include "asf.h" + +// BB: Moved to asf.h --------------------- FROM HERE ------------------- +#ifdef 0 typedef struct __attribute__((packed)) { unsigned char guid[16]; unsigned long long size; @@ -60,6 +64,8 @@ typedef struct __attribute__((packed)) { unsigned short comment_size; unsigned short rating_size; } ASF_content_description_t; +#endif +// BB: Moved to asf.h --------------------- TO HERE ------------------- static ASF_header_t asfh; static ASF_obj_header_t objh; @@ -75,13 +81,19 @@ int asf_packetsize=0; //int i; -void print_asf_string(const char* name, char* string, int length){ - int i; - printf("%s", name); - for(i=0;i +#include +#include + +#include + +int +connect2Server(char *host, int port) { + int socket_server_fd; + struct sockaddr_in server_address; + printf(">>>> connect2Server [%s@%d]\n", host, port ); + socket_server_fd = socket(AF_INET, SOCK_STREAM, 0); + if( socket_server_fd==-1 ) { + perror("Failed to create socket"); + exit(1); + } + + if( isalpha(host[0]) ) { + struct hostent *hp; + if( (hp=gethostbyname( host ))==NULL ) { + printf("Unknown host: %s\n", host); + exit(1); + } + memcpy( &server_address.sin_addr.s_addr, hp->h_addr, hp->h_length ); + } else { + inet_pton(AF_INET, host, &server_address.sin_addr); + } + server_address.sin_family=AF_INET; + server_address.sin_port=htons(port); + + if( connect( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { + perror("Failed to connect to server"); + close(socket_Stream_fd); + exit(1); + } + return socket_server_fd; +} + diff --git a/url.c b/url.c new file mode 100644 index 0000000000..f9babc42d0 --- /dev/null +++ b/url.c @@ -0,0 +1,93 @@ +#include +#include +#include + +#include "url.h" + +URL_t* +set_url(char* url) { + int pos1, pos2; + URL_t* Curl; + char *ptr1, *ptr2; + + // Create the URL container + Curl = (URL_t*)malloc(sizeof(URL_t)); + if( Curl==NULL ) { + printf("Memory allocation failed!\n"); + exit(1); + } + // Copy the url in the URL container + Curl->url = (char*)malloc(strlen(url)+1); + if( Curl->url==NULL ) { + printf("Memory allocation failed!\n"); + exit(1); + } + strcpy(Curl->url, url); + + // extract the protocol + ptr1 = strstr(url, "://"); + if( ptr1==NULL ) { + printf("Malformed URL!\n"); + return NULL; + } + pos1 = ptr1-url; + Curl->protocol = (char*)malloc(pos1+1); + strncpy(Curl->protocol, url, pos1); + Curl->protocol[pos1] = '\0'; + + // look if the port is given + ptr2 = strstr(ptr1+3, ":"); + if( ptr2==NULL ) { + // No port is given + // Look if a path is given + ptr2 = strstr(ptr1+3, "/"); + if( ptr2==NULL ) { + // No path/filename + // So we have an URL like http://www.hostname.com + pos2 = strlen(url); + } else { + // We have an URL like http://www.hostname.com/file.txt + pos2 = ptr2-url; + } + } else { + // We have an URL beginning like http://www.hostname.com:1212 + // Get the port number + Curl->port = atoi(ptr2+1); + pos2 = ptr2-url; + } + // copy the hostname in the URL container + Curl->hostname = (char*)malloc(strlen(url)+1); + if( Curl->hostname==NULL ) { + printf("Memory allocation failed!\n"); + exit(1); + } + strncpy(Curl->hostname, ptr1+3, pos2-pos1-3); + + // Look if a path is given + ptr2 = strstr(ptr1+3, "/"); + if( ptr2!=NULL ) { + // A path/filename is given + // check if it's not a trailing '/' + if( strlen(ptr2)>1 ) { + // copy the path/filename in the URL container + Curl->path = (char*)malloc(strlen(ptr2)); + if( Curl->path==NULL ) { + printf("Memory allocation failed!\n"); + exit(1); + } + strcpy(Curl->path, ptr2+1); + } + } + + return Curl; +} + +void +free_url(URL_t* url) { + if(url) return; + if(url->url) free(url->url); + if(url->protocol) free(url->protocol); + if(url->hostname) free(url->hostname); + if(url->path) free(url->path); + free(url); +} diff --git a/url.h b/url.h new file mode 100644 index 0000000000..ef01c5e034 --- /dev/null +++ b/url.h @@ -0,0 +1,15 @@ +#ifndef URL_H +#define URL_H + +typedef struct { + char *url; + char *protocol; + char *hostname; + char *path; + unsigned int port; +} URL_t; + +URL_t* set_url(char* url); +void free_url(URL_t* url); + +#endif