[MPlayer-dev-eng] MMS support in mplayer begun
Derek J Witt
djw at flinthills.com
Thu Dec 6 10:21:02 CET 2001
Hi, all. I have started on MMS support in mplayer. I have it at least
connecting to TCP MMS streams. I have included the patch. For some
reason, if I try using "cvs rdiff 120601 main", I keep getting a whole
messful of parsed_root_directory errors. So, I was only able to run
"cvs diff -NR" to get a file. I had to edit the file to get a proper
patch file. But, it didn't include the new file I put in.
So, I have included both the patch and the new file. I do have my test
mms stream being connected. I do send it the correct header. I have yet
to get it to start the actual data packets. But, it should not affect
anything else in mplayer. Let me know what you think.
Thanks.
--
** Derek J Witt **
* Email: mailto:djw at flinthills.com *
* Home Page: http://www.flinthills.com/~djw/ *
*** "...and on the eighth day, God met Bill Gates." - Unknown **
-------------- next part --------------
--- libmpdemux/Makefile 24 Nov 2001 23:58:12 -0000 1.11
+++ libmpdemux/Makefile 6 Dec 2001 09:24:13 -0000
@@ -5,7 +5,7 @@
SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c frequencies.c demux_fli.c
ifeq ($(STREAMING),yes)
-SRCS += asf_streaming.c url.c http.c network.c
+SRCS += asf_streaming.c url.c http.c network.c asf_helper.c
endif
OBJS = $(SRCS:.c=.o)
--- libmpdemux/asf_streaming.c 20 Nov 2001 22:20:20 -0000 1.9
+++ libmpdemux/asf_streaming.c 6 Dec 2001 09:24:14 -0000
@@ -9,7 +9,7 @@
#include "http.h"
#include "asf.h"
#include "network.h"
-
+#include "mmst.h"
#include "stream.h"
static ASF_StreamType_e streaming_type = ASF_Unknown_e;
@@ -20,6 +20,8 @@
// So for now, we use the HTTP protocol.
int
asf_streaming_start( stream_t *stream ) {
+ printf("This ASF network stream uses %s protocol\n", stream->streaming_ctrl->url->protocol);
+
return asf_http_streaming_start( stream );
}
@@ -269,23 +271,73 @@
int i;
int fd = stream->fd;
int done=1;
+ unsigned int MMSCSeq = 0;
+
+ streaming_type = ASF_Live_e;
-streaming_type = ASF_Live_e;
do {
if( fd>0 ) close( fd );
fd = connect2Server( url->hostname, url->port );
if( fd<0 ) return -1;
+ /* START - MMS (TCP/IP) support based on ASFRecorder+ by an anonymous author.
+ * Adapted to MPlayer by Derek J Witt <djw at flinthills.com>.
+ * -- Started on 6 December 2001 at 1:06 am CST.
+ */
+
+ if (strcasecmp(url->protocol, "mms") == 0) {
+ // First, we have to send out the header when we
+ // connect to the MMS server.
+ char GUID[] = "{c77e7400-738a-11d2-9add-0020af0a3278}";
+ char *BufPtr;
+ unsigned int MMSCSize;
+
+ BufPtr = buffer; /* Send Initial Request */
+ BufPtr += my_sprintf(BufPtr, MMSC_HEADER, sizeof(MMSC_HEADER));
+ BufPtr += my_sprintf(BufPtr, MMSC_REQUEST_INIT, sizeof(MMSC_REQUEST_INIT));
+ BufPtr += my_swprintf(BufPtr, "NSPlayer/6.4.0.3845; ", 0);
+ BufPtr += my_swprintf(BufPtr, GUID, 0);
+ BufPtr += my_swprintf(BufPtr, "\0", 1);
+
+ MMSCSize=(int)BufPtr-(int)buffer;
+
+ if(MMSCSize%8)
+ MMSCSize+=8-MMSCSize%8;
+
+ put_long(buffer+MMSC_POS_SIZE, MMSCSize-0x10);
+ put_long(buffer+MMSC_POS_SEQ, MMSCSeq++);
+
+
+ write( fd, buffer, MMSCSize);
+ i = read( fd, buffer, BUFFER_SIZE );
+ my_hex_printf(buffer, i);
+ } else
+ /* END - MMS (TCP/IP) support. */
+
+ {
http_hdr = asf_http_request( url );
-printf("Request [%s]\n", http_hdr->buffer );
+ printf("Request [%s]\n", http_hdr->buffer );
write( fd, http_hdr->buffer, http_hdr->buffer_size );
http_free( http_hdr );
+ i = read( fd, buffer, BUFFER_SIZE );
+
+ //printf("read: %d bytes:\t", i);
+
+ //my_hex_printf(buffer, i);
+ }
+
http_hdr = http_new_header();
do {
i = read( fd, buffer, BUFFER_SIZE );
-printf("read: %d\n", i );
+
+ //printf("read: %d bytes\n", i);
+
+ //my_hex_printf(buffer, i);
+
+ //if (i == 0) break;
+
if( i<0 ) {
perror("read");
http_free( http_hdr );
--- libmpdemux/network.c 22 Nov 2001 17:14:26 -0000 1.11
+++ libmpdemux/network.c 6 Dec 2001 09:24:14 -0000
@@ -32,6 +32,7 @@
#include "network.h"
#include "http.h"
#include "url.h"
+//#include "mmst.h"
#include "asf.h"
static struct {
@@ -245,7 +246,11 @@
// Checking for ASF
if( !strcasecmp(url->protocol, "mms") ) {
- if( url->port==0 ) url->port = 80;
+
+ // START - Derek J Witt, djw at flinthills.com
+ if( url->port==0 ) url->port = 1755;
+ // END - Derek J Witt, djw at flinthills.com
+ // printf("[%s]\n", MMSC_REQUEST_INIT);
return DEMUXER_TYPE_ASF;
}
--- libmpdemux/open.c 1 Dec 2001 23:40:24 -0000 1.26
+++ libmpdemux/open.c 6 Dec 2001 09:24:14 -0000
@@ -381,7 +381,7 @@
//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);
- if( streaming_start( stream , url, *file_format )<0){
+ if( streaming_start( &stream , url, *file_format )<0){
mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, filename);
url_free(url);
return NULL;
-------------- next part --------------
/*
* Some helper functions needed for the MMS protocol.
* Adapted from ASFRecorder+ (originally written by an anonymous author (http://yaan2.linux.net.cn)
* Adapted by Derek J Witt <djw at flinthills.com> on 6 December 2001.
*/
#include <stdio.h>
#include <stdlib.h>
/* get 64bit integer (Little endian) */
void get_quad(unsigned char *pos, unsigned int *hi, unsigned int *lo)
{
unsigned char c1 = *pos++, c2 = *pos++, c3 = *pos++, c4 = *pos++;
unsigned char c5 = *pos++, c6 = *pos++, c7 = *pos++, c8 = *pos++;
(*hi) = (c8<<24) + (c7<<16) + (c6<<8) + c5;
(*lo) = (c4<<24) + (c3<<16) + (c2<<8) + c1;
}
/* write 64bit integer to stream (Little endian) */
void write_quad(FILE *outfile, unsigned int hi, unsigned int lo)
{
unsigned char c1 = (lo & 0xff), c2 = ((lo>>8) & 0xff), c3 = ((lo>>16) & 0xff), c4 = ((lo>>24) & 0xff);
unsigned char c5 = (hi & 0xff), c6 = ((hi>>8) & 0xff), c7 = ((hi>>16) & 0xff), c8 = ((hi>>24) & 0xff);
fputc(c1, outfile);
fputc(c2, outfile);
fputc(c3, outfile);
fputc(c4, outfile);
fputc(c5, outfile);
fputc(c6, outfile);
fputc(c7, outfile);
fputc(c8, outfile);
}
/* get 32bit integer (Little endian) */
void get_long(unsigned char *pos, unsigned int *val)
{
unsigned char c1 = *pos++, c2 = *pos++, c3 = *pos++, c4 = *pos++;
(*val) = (c4<<24) + (c3<<16) + (c2<<8) + c1;
}
/* put 32 bit integer (Little endian) */
void put_long(unsigned char *pos, unsigned int val)
{
*pos++ = (val & 0xff);
*pos++ = ((val>>8) & 0xff), *pos++ = ((val>>16) & 0xff), *pos++ = ((val>>24) & 0xff);
}
/* write a 32 bit integer to stream (Little endian) */
void write_long(FILE *outfile, unsigned int val)
{
unsigned char c1 = (val & 0xff), c2 = ((val>>8) & 0xff), c3 = ((val>>16) & 0xff), c4 = ((val>>24) & 0xff);
fputc(c1, outfile);
fputc(c2, outfile);
fputc(c3, outfile);
fputc(c4, outfile);
}
/* get short integer (Little endian) */
void get_short(unsigned char *pos, unsigned short *val)
{
unsigned char c1 = *pos++, c2 = *pos++;
(*val) = (c2<<8) + c1;
}
/* write a 32 bit integer to stream (Little endian) */
void write_short(FILE *outfile, unsigned short val)
{
unsigned char c1 = (val & 0xff), c2 = ((val>>8) & 0xff);
fputc(c1, outfile);
fputc(c2, outfile);
}
/* 64 bit subtraction with unsigned integers */
void quad_subtraction(unsigned int *dst_hi, unsigned int *dst_lo, unsigned int hi, unsigned int lo)
{
unsigned int tmp;
*dst_hi -= hi;
tmp = *dst_lo;
*dst_lo -= lo;
/* handle "carry bit" */
if (*dst_lo > tmp) (*dst_hi)--;
}
/* timecode helper functions */
/* get position of timecode in chunk (-1 if unknown) */
int whereis_timecode(unsigned char *Buffer)
{
int tc_start = -1;
/* timecode position varies with type of chunk */
switch(Buffer[3])
{
case 0x00: tc_start = 5; break;
case 0x01: tc_start = 5; break;
case 0x08: tc_start = 6; break;
case 0x09: tc_start = 6; break;
case 0x10: tc_start = 7; break;
case 0x11: tc_start = 7; break;
case 0x48: tc_start = 8; break;
case 0x49: tc_start = 8; break;
case 0x50: tc_start = 9; break;
case 0x51: tc_start = 9; break;
default: tc_start = -1; //gui_showstatus(STATUS_ERROR, "unknown format type: $%02x\n", (int)Buffer[3]);
}
return tc_start;
}
/* Create a randomized GUID string to avoid filtering ASFRecorder's */
/* stream requests by means of detecting any hardcoded GUIDs */
void randomize_guid(unsigned char *buf)
{
int digit, dig;
time_t curtime;
*buf++='{';
time(&curtime);
srand(curtime);
for (digit=0; digit <32; digit++)
{
if (digit==8 || digit == 12 || digit == 16 || digit == 20) *buf++='-';
dig = rand()%0xf;
if (dig<10)
*buf++='0'+dig;
else
*buf++='A'+(dig-10);
}
*buf++='}';
*buf++='\0';
}
/* create a timecode string from a timecode in milliseconds */
char *createtimestring(unsigned int timecode)
{
static char timecodestring[64];
if (timecode/1000 >= 24*3600)
sprintf(timecodestring, "%d:%02d:%02d:%02d.%03d", (timecode/1000)/(24*3600), ((timecode/1000)/3600)%24, ((timecode/1000)/60)%60, (timecode/1000)%60, timecode%1000);
else
if (timecode/1000 >= 3600)
sprintf(timecodestring, "%d:%02d:%02d.%03d", (timecode/1000)/3600, ((timecode/1000)/60)%60, (timecode/1000)%60, timecode%1000);
else
if (timecode/1000 >= 60)
sprintf(timecodestring, "%d:%02d.%03d", (timecode/1000)/60, (timecode/1000)%60, timecode%1000);
else
sprintf(timecodestring, "%d.%03d", (timecode/1000)%60, timecode%1000);
return timecodestring;
}
/* subroutine for base64 encoding (used in HTTP Basic authentification) */
int base64enc(char *data,char *out)
{
char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
int len = strlen(data);
int i,index;
int val;
for (i=0, index=0; i<len; i+=3, index+=4)
{
int quad = 0;
int trip = 0;
val = (0xff & data[i]);
val <<= 8;
if ((i+1) < len) {
val |= (0xff & data[i+1]);
trip = 1;
}
val <<= 8;
if ((i+2) < len) {
val |= (0xff & data[i+2]);
quad = 1;
}
out[index+3] = alphabet[(quad? (val & 0x3f): 64)];
val >>= 6;
out[index+2] = alphabet[(trip? (val & 0x3f): 64)];
val >>= 6;
out[index+1] = alphabet[val & 0x3f];
val >>= 6;
out[index+0] = alphabet[val & 0x3f];
}
out[++index] = 0;
return index;
}
/* helper routine for ASF header parsing */
int find_id(unsigned char *id, unsigned char *Buffer, int bufsize)
{
int offs, i, found;
for (offs = 0; offs < bufsize-16; offs++) {
found=1;
for (i=0; i<16; i++) if (Buffer[offs+i] != id[i]) {
found = 0;
break;
}
if (found) return(offs);
}
return -1;
}
/* These routines are used to parse the packet and find */
/* and modify timecodes for live streams */
unsigned int get_data(unsigned char **bp, unsigned int type)
{
unsigned int res = 0;
switch (type) {
case 0:
break;
case 1:
res = *(*bp+0);
*bp+=1;
break;
case 2:
res = *(*bp+0) + (*(*bp+1) << 8);
*bp+=2;
break;
case 3:
res = *(*bp+0) + (*(*bp+1) << 8) + (*(*bp+2) << 16) + (*(*bp+3) << 24);
*bp+=4;
break;
default:
//gui_showstatus(STATUS_CRITICALERROR, "unknown format type %d\n", type);
break;
}
return res;
}
/* Replace specific characters in the URL string by an escape sequence */
/* works like strcpy(), but without return argument */
void escape_url_string(char *outbuf, char *inbuf)
{
unsigned char c;
do
{
c = *inbuf++;
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
(c >= 0x7f) || /* fareast languages(Chinese, Korean, Japanese) */
c=='-' || c=='_' || c=='.' || c=='!' || c=='~' || /* mark characters */
c=='*' || c=='\'' || c=='(' || c==')' || c=='%' || /* do not touch escape character */
c==';' || c=='/' || c=='?' || c==':' || c=='@' || /* reserved characters */
c=='&' || c=='=' || c=='+' || c=='$' || c==',' || /* see RFC 2396 */
c=='\0' )
{
*outbuf++ = c;
}
else
{
/* all others will be escaped */
unsigned char c1 = ((c & 0xf0) >> 4);
unsigned char c2 = (c & 0x0f);
if (c1 < 10) c1+='0';
else c1+='A';
if (c2 < 10) c2+='0';
else c2+='A';
*outbuf++ = '%';
*outbuf++ = c1;
*outbuf++ = c2;
}
}
while (c != '\0');
}
int my_sprintf(unsigned char *pos, unsigned char *CWord, int number)
{
if(number==0) number = strlen(CWord);
memcpy(pos, CWord, number);
return number;
}
int my_swprintf(unsigned char *pos, unsigned char *CWord, int number)
{
int i, count;
unsigned short *SWord;
if(number==0) number = strlen(CWord);
SWord = malloc(number*2);
for(i=0, count=0 ; i<number ; i++)
{
if((CWord[i] > 0x7f) && (CWord[i+1] > 0x7f))
{
SWord[count++] = CWord[i+1]*256 + CWord[i];
i++;
}
else
{
SWord[count++] = CWord[i];
}
}
memcpy(pos, SWord, count*2);
free(SWord);
//count = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, CWord, number, pos, number);
return count*2;
}
void my_hex_printf(unsigned char *buffer, unsigned int length) {
int i;
printf("Hex:\n");
for (i = 0; i < length; i++)
printf("%2x ", buffer[i]);
printf("\n");
printf("ASCII:\n");
for (i = 0; i < length; i++)
printf("%c", buffer[i]);
printf("\n");
}
More information about the MPlayer-dev-eng
mailing list