diff -c -N MPlayer-0.50pre1/configure /home/brian/MPlayer-0.50pre1/configure *** MPlayer-0.50pre1/configure Thu Sep 27 10:40:42 2001 --- /home/brian/MPlayer-0.50pre1/configure Fri Sep 28 14:38:46 2001 *************** *** 1659,1665 **** _streamingdef='#undef STREAMING' if [ $_streaming = yes ]; then ! _streamingsrcs='asf_streaming.c network.c url.c http.c' _streamingdef='#define STREAMING' fi --- 1659,1665 ---- _streamingdef='#undef STREAMING' if [ $_streaming = yes ]; then ! _streamingsrcs='asf_streaming.c network.c url.c http.c rtp.c' _streamingdef='#define STREAMING' fi diff -c -N MPlayer-0.50pre1/network.c /home/brian/MPlayer-0.50pre1/network.c *** MPlayer-0.50pre1/network.c Wed Aug 22 12:40:46 2001 --- /home/brian/MPlayer-0.50pre1/network.c Fri Sep 28 15:03:17 2001 *************** *** 31,36 **** --- 31,37 ---- #include "http.h" #include "url.h" #include "asf.h" + #include "rtp.h" streaming_ctrl_t *streaming_ctrl; *************** *** 123,128 **** --- 124,153 ---- } int + read_rtp_from_server(int fd, char *buffer, int length) { + int ret; + int done=0; + fd_set set; + struct timeval tv; + struct rtpheader rh; + char *data; + int len; + static int got_first = 0; + static int sequence; + + if( buffer==NULL || length<0 ) return -1; + + getrtp2(fd, &rh, &data, &len); + if( got_first && rh.b.sequence != sequence+1 ) + printf("RTP packet sequence error! Expected: %d, received: %d\n", + sequence+1, rh.b.sequence); + got_first = 1; + sequence = rh.b.sequence; + memcpy(buffer, data, len); + return(len); + } + + int readFromServer(int fd, char *buffer, int length) { int ret; int done=0; *************** *** 318,323 **** --- 343,359 ---- return DEMUXER_TYPE_UNKNOWN; } + // Checking for RTP + if( !strcasecmp(url->protocol, "rtp") ) { + if( url->port==0 ) + { + printf("You must enter a port number for RTP streams!\n"); + exit(1); //fixme + } + *fd_out=-1; + return DEMUXER_TYPE_UNKNOWN; + } + // Checking for ASF if( !strcasecmp(url->protocol, "mms") ) { if( url->port==0 ) url->port = 80; *************** *** 448,454 **** streaming_ctrl->fd_net = fd; } ! http_free( http_hdr ); streaming_ctrl->streaming_read = nop_streaming_read; streaming_ctrl->prebuffer_size = 180000; --- 484,490 ---- streaming_ctrl->fd_net = fd; } ! //http_free( http_hdr ); streaming_ctrl->streaming_read = nop_streaming_read; streaming_ctrl->prebuffer_size = 180000; *************** *** 459,472 **** --- 495,597 ---- return fd; } + // Start listening on a UDP port. If multicast, join the group. + int + rtp_open_socket( URL_t *url ) { + int fd; + int socket_server_fd; + int err, err_len; + fd_set set; + struct timeval tv; + struct sockaddr_in server_address; + struct ip_mreq mcast; + + printf("Listening for traffic on %s:%d ...\n", url->hostname, url->port ); + + socket_server_fd = socket(AF_INET, SOCK_DGRAM, 0); + // fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); + if( socket_server_fd==-1 ) { + perror("Failed to create socket"); + return -1; + } + + if( isalpha(url->hostname[0]) ) { + struct hostent *hp =(struct hostent*)gethostbyname( url->hostname ); + if( hp==NULL ) { + printf("Counldn't resolve name: %s\n", url->hostname); + return -1; + } + memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); + } else { + inet_pton(AF_INET, url->hostname, &server_address.sin_addr); + } + server_address.sin_family=AF_INET; + server_address.sin_port=htons(url->port); + + if( bind( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { + if( errno!=EINPROGRESS ) { + perror("Failed to connect to server"); + close(socket_server_fd); + return -1; + } + } + if((ntohl(server_address.sin_addr.s_addr) >> 28) == 0xe) { + mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr; + //mcast.imr_interface.s_addr = inet_addr("10.1.1.2"); + mcast.imr_interface.s_addr = 0; + if( setsockopt( socket_server_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))) { + perror("IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)"); + return -1; + } + } + + //tv.tv_sec = 0; + //tv.tv_usec = (10 * 1000000); // 10 seconds timeout + FD_ZERO( &set ); + FD_SET( socket_server_fd, &set ); + //if( select(socket_server_fd+1, &set, NULL, NULL, &tv)>0 ) { + if( select(socket_server_fd+1, &set, NULL, NULL, NULL)>0 ) { + err_len = sizeof( err ); + getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len ); + if( err ) { + printf("Timeout! No data from host %s\n", url->hostname ); + printf("Socket error: %d\n", err ); + close(socket_server_fd); + return -1; + } + } + return socket_server_fd; + } + + int + rtp_streaming_start( streaming_ctrl_t *streaming_ctrl ) { + int fd; + if( streaming_ctrl==NULL ) return -1; + + fd = streaming_ctrl->fd_net; + if( fd<0 ) { + fd = rtp_open_socket( *(streaming_ctrl->url) ); + if( fd<0 ) return -1; + streaming_ctrl->fd_net = fd; + } + + streaming_ctrl->streaming_read = nop_streaming_read; + streaming_ctrl->prebuffer_size = 180000; + streaming_ctrl->buffering = 1; + streaming_ctrl->status = streaming_playing_e; + return fd; + } + void network_streaming(void *arg) { + URL_t **url; char buffer[BUFFER_SIZE]; fd_set fd_net_in; int ret; arg = arg; + do { FD_ZERO( &fd_net_in ); FD_SET( streaming_ctrl->fd_net, &fd_net_in ); *************** *** 477,483 **** return; //exit(1); // FIXME! } if( FD_ISSET( streaming_ctrl->fd_net, &fd_net_in ) ) { ! ret = readFromServer( streaming_ctrl->fd_net, buffer, BUFFER_SIZE ); if( ret<=0 ) { streaming_ctrl->status=streaming_stopped_e; } else { --- 602,613 ---- return; //exit(1); // FIXME! } if( FD_ISSET( streaming_ctrl->fd_net, &fd_net_in ) ) { ! url = streaming_ctrl->url; ! if( !strcmp((*url)->protocol, "rtp" )) ! ret = read_rtp_from_server( streaming_ctrl->fd_net, buffer, BUFFER_SIZE ); ! else ! ret = readFromServer( streaming_ctrl->fd_net, buffer, BUFFER_SIZE ); ! if( ret<=0 ) { streaming_ctrl->status=streaming_stopped_e; } else { *************** *** 546,568 **** streaming_ctrl->fd_pipe_in = fd_file; } #endif ! ! switch( streaming_type ) { ! case DEMUXER_TYPE_ASF: ! // Send the appropriate HTTP request ! fd = asf_http_streaming_start( streaming_ctrl ); ! break; ! case DEMUXER_TYPE_AVI: ! case DEMUXER_TYPE_MPEG_ES: ! case DEMUXER_TYPE_MPEG_PS: ! fd = nop_streaming_start( streaming_ctrl ); ! break; ! case DEMUXER_TYPE_UNKNOWN: ! default: ! printf("Unable to detect the streaming type\n"); ! close( fd ); ! free( streaming_ctrl ); ! return -1; } if( fd<0 ) { --- 676,706 ---- streaming_ctrl->fd_pipe_in = fd_file; } #endif ! // For RTP streams, we usually don't know the stream type until we open it. ! if( !strcmp( (*url)->protocol, "rtp")) ! { ! fd = rtp_streaming_start( streaming_ctrl ); ! } ! // For connection-oriented streams, we can usually determine the streaming type. ! else ! { ! switch( streaming_type ) { ! case DEMUXER_TYPE_ASF: ! // Send the appropriate HTTP request ! fd = asf_http_streaming_start( streaming_ctrl ); ! break; ! case DEMUXER_TYPE_AVI: ! case DEMUXER_TYPE_MPEG_ES: ! case DEMUXER_TYPE_MPEG_PS: ! fd = nop_streaming_start( streaming_ctrl ); ! break; ! case DEMUXER_TYPE_UNKNOWN: ! default: ! printf("Unable to detect the streaming type\n"); ! close( fd ); ! free( streaming_ctrl ); ! return -1; ! } } if( fd<0 ) { diff -c -N MPlayer-0.50pre1/open.c /home/brian/MPlayer-0.50pre1/open.c *** MPlayer-0.50pre1/open.c Wed Sep 26 17:19:07 2001 --- /home/brian/MPlayer-0.50pre1/open.c Fri Sep 28 14:44:11 2001 *************** *** 255,270 **** url = url_new(filename); if(url) { (*file_format)=autodetectProtocol( url, &f ); ! if( (*file_format)==DEMUXER_TYPE_UNKNOWN ) { ! mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, filename); ! url_free(url); ! return NULL; ! } f=streaming_start( &url, f, *file_format ); if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, url->url); return NULL; } mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ConnToServer, url->hostname ); stream=new_stream(f,STREAMTYPE_STREAM); ! return NULL; } #endif --- 255,274 ---- url = url_new(filename); if(url) { (*file_format)=autodetectProtocol( url, &f ); ! /* For rtp:// streams we probably don't know the type yet... */ ! if( strcmp(url->protocol, "rtp" )) ! { ! if( (*file_format)==DEMUXER_TYPE_UNKNOWN ) { ! mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, filename); ! url_free(url); ! return NULL; ! } ! } f=streaming_start( &url, f, *file_format ); if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, url->url); return NULL; } mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ConnToServer, url->hostname ); stream=new_stream(f,STREAMTYPE_STREAM); ! return stream; } #endif diff -c -N MPlayer-0.50pre1/rtp.c /home/brian/MPlayer-0.50pre1/rtp.c *** MPlayer-0.50pre1/rtp.c Wed Dec 31 16:00:00 1969 --- /home/brian/MPlayer-0.50pre1/rtp.c Fri Sep 28 15:36:26 2001 *************** *** 0 **** --- 1,193 ---- + /* Imported from the dvbstream-0.2 project */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + + /* MPEG-2 TS RTP stack */ + + #define DEBUG 1 + #include "rtp.h" + + void initrtp(struct rtpheader *foo) { /* fill in the MPEG-2 TS deefaults */ + /* Note: MPEG-2 TS defines a timestamping base frequency of 90000 Hz. */ + foo->b.v=2; + foo->b.p=0; + foo->b.x=0; + foo->b.cc=0; + foo->b.m=0; + foo->b.pt=33; /* MPEG-2 TS */ + foo->b.sequence=rand() & 65535; + foo->timestamp=rand(); + foo->ssrc=rand(); + } + + /* Send a single RTP packet, converting the RTP header to network byte order. */ + int sendrtp(int fd, struct sockaddr_in *sSockAddr, struct rtpheader *foo, char *data, int len) { + char *buf=(char*)alloca(len+sizeof(struct rtpheader)); + int *cast=(int *)foo; + int *outcast=(int *)buf; + outcast[0]=htonl(cast[0]); + outcast[1]=htonl(cast[1]); + memmove(outcast+2,data,len); + fprintf(stderr,"v=%x %x\n",foo->b.v,buf[0]); + return sendto(fd,buf,len+3,0,(struct sockaddr *)sSockAddr,sizeof(*sSockAddr)); + } + + int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) { + static char buf[1600]; + unsigned int intP; + char* charP = (char*) &intP; + int headerSize; + int lengthPacket; + lengthPacket=recv(fd,buf,1590,0); + if (lengthPacket==0) + exit(1); + if (lengthPacket<0) { + fprintf(stderr,"socket read error\n"); + exit(2); + } + if (lengthPacket<12) { + fprintf(stderr,"packet too small (%d) to be an rtp frame (>12bytes)\n", lengthPacket); + exit(3); + } + rh->b.v = (unsigned int) ((buf[0]>>6)&0x03); + rh->b.p = (unsigned int) ((buf[0]>>5)&0x01); + rh->b.x = (unsigned int) ((buf[0]>>4)&0x01); + rh->b.cc = (unsigned int) ((buf[0]>>0)&0x0f); + rh->b.m = (unsigned int) ((buf[1]>>7)&0x01); + rh->b.pt = (unsigned int) ((buf[1]>>0)&0x7f); + intP = 0; + memcpy(charP+2,&buf[2],2); + rh->b.sequence = ntohl(intP); + intP = 0; + memcpy(charP,&buf[4],4); + rh->timestamp = ntohl(intP); + + headerSize = 12 + 4*rh->b.cc; /* in bytes */ + + *lengthData = lengthPacket - headerSize; + *data = (char*) buf + headerSize; + + // fprintf(stderr,"Reading rtp: v=%x p=%x x=%x cc=%x m=%x pt=%x seq=%x ts=%x lgth=%d\n",rh->b.v,rh->b.p,rh->b.x,rh->b.cc,rh->b.m,rh->b.pt,rh->b.sequence,rh->timestamp,lengthPacket); + + return(0); + } + + /* Send a single RTP packet, converting the RTP header to network byte order. */ + int sendrtp2(int fd, struct sockaddr_in *sSockAddr, struct rtpheader *foo, char *data, int len) { + char *buf=(char*)alloca(len+72); + unsigned int intP; + char* charP = (char*) &intP; + int headerSize; + buf[0] = 0x00; + buf[0] |= ((((char) foo->b.v)<<6)&0xc0); + buf[0] |= ((((char) foo->b.p)<<5)&0x20); + buf[0] |= ((((char) foo->b.x)<<4)&0x10); + buf[0] |= ((((char) foo->b.cc)<<0)&0x0f); + buf[1] = 0x00; + buf[1] |= ((((char) foo->b.m)<<7)&0x80); + buf[1] |= ((((char) foo->b.pt)<<0)&0x7f); + intP = htonl(foo->b.sequence); + memcpy(&buf[2],charP+2,2); + intP = htonl(foo->timestamp); + memcpy(&buf[4],&intP,4); + /* SSRC: not implemented */ + buf[8] = 0x0f; + buf[9] = 0x0f; + buf[10] = 0x0f; + buf[11] = 0x0f; + headerSize = 12 + 4*foo->b.cc; /* in bytes */ + memcpy(buf+headerSize,data,len); + + // fprintf(stderr,"Sending rtp: v=%x p=%x x=%x cc=%x m=%x pt=%x seq=%x ts=%x lgth=%d\n",foo->b.v,foo->b.p,foo->b.x,foo->b.cc,foo->b.m,foo->b.pt,foo->b.sequence,foo->timestamp,len+headerSize); + + foo->b.sequence++; + return sendto(fd,buf,len+headerSize,0,(struct sockaddr *)sSockAddr,sizeof(*sSockAddr)); + } + + + int getrtp(int fd, struct rtpheader *rh, char** data, int* lengthData) { + static char buf[1600]; + int headerSize; + int lengthPacket; + int i; + + lengthPacket=recv(fd,buf,1590,0); + headerSize = 3; + *lengthData = lengthPacket - headerSize; + *data = (char*) buf + headerSize; + fprintf(stderr,"[%d] %02x %x\n",lengthPacket,buf[8],buf[0]); + } + + /* create a sender socket. */ + int makesocket(char *szAddr,unsigned short port,int TTL,struct sockaddr_in *sSockAddr) { + int iRet, iLoop = 1; + struct sockaddr_in sin; + char cTtl = (char)TTL; + char cLoop=0; + + int iSocket = socket( AF_INET, SOCK_DGRAM, 0 ); + + if (iSocket < 0) { + fprintf(stderr,"socket() failed.\n"); + exit(1); + } + + sSockAddr->sin_family = sin.sin_family = AF_INET; + sSockAddr->sin_port = sin.sin_port = htons(port); + sSockAddr->sin_addr.s_addr = inet_addr(szAddr); + + iRet = setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &iLoop, sizeof(int)); + if (iRet < 0) { + fprintf(stderr,"setsockopt SO_REUSEADDR failed\n"); + exit(1); + } + + iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_TTL, &cTtl, sizeof(char)); + if (iRet < 0) { + fprintf(stderr,"setsockopt IP_MULTICAST_TTL failed. multicast in kernel?\n"); + exit(1); + } + + cLoop = 1; /* !? */ + iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_LOOP, + &cLoop, sizeof(char)); + if (iRet < 0) { + fprintf(stderr,"setsockopt IP_MULTICAST_LOOP failed. multicast in kernel?\n"); + exit(1); + } + + return iSocket; + } + + /* create a receiver socket, i.e. join the multicast group. */ + int makeclientsocket(char *szAddr,unsigned short port,int TTL,struct sockaddr_in *sSockAddr) { + int socket=makesocket(szAddr,port,TTL,sSockAddr); + struct ip_mreq blub; + struct sockaddr_in sin; + unsigned int tempaddr; + sin.sin_family=AF_INET; + sin.sin_port=htons(port); + sin.sin_addr.s_addr=inet_addr(szAddr); + if (bind(socket,&sin,sizeof(sin))) { + perror("bind failed"); + exit(1); + } + tempaddr=inet_addr(szAddr); + if ((ntohl(tempaddr) >> 28) == 0xe) { + blub.imr_multiaddr.s_addr = inet_addr(szAddr); + blub.imr_interface.s_addr = 0; + if (setsockopt(socket,IPPROTO_IP,IP_ADD_MEMBERSHIP,&blub,sizeof(blub))) { + perror("setsockopt IP_ADD_MEMBERSHIP failed (multicast kernel?)"); + exit(1); + } + } + return socket; + } + diff -c -N MPlayer-0.50pre1/rtp.h /home/brian/MPlayer-0.50pre1/rtp.h *** MPlayer-0.50pre1/rtp.h Wed Dec 31 16:00:00 1969 --- /home/brian/MPlayer-0.50pre1/rtp.h Fri Sep 28 14:38:09 2001 *************** *** 0 **** --- 1,31 ---- + #ifndef _RTP_H + #define _RTP_H + + #include + + struct rtpbits { + unsigned int v:2; /* version: 2 */ + unsigned int p:1; /* is there padding appended: 0 */ + unsigned int x:1; /* number of extension headers: 0 */ + unsigned int cc:4; /* number of CSRC identifiers: 0 */ + unsigned int m:1; /* marker: 0 */ + unsigned int pt:7; /* payload type: 33 for MPEG2 TS - RFC 1890 */ + unsigned int sequence:16; /* sequence number: random */ + }; + + struct rtpheader { /* in network byte order */ + struct rtpbits b; + int timestamp; /* start: random */ + int ssrc; /* random */ + }; + + + void initrtp(struct rtpheader *foo); /* fill in the MPEG-2 TS deefaults */ + int sendrtp(int fd, struct sockaddr_in *sSockAddr, struct rtpheader *foo, char *data, int len); + int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData); + int sendrtp2(int fd, struct sockaddr_in *sSockAddr, struct rtpheader *foo, char *data, int len); + int getrtp(int fd, struct rtpheader *rh, char** data, int* lengthData); + int makesocket(char *szAddr,unsigned short port,int TTL,struct sockaddr_in *sSockAddr); + int makeclientsocket(char *szAddr,unsigned short port,int TTL,struct sockaddr_in *sSockAddr); + + #endif