用户操作
[即时聊天] [发私信] [加为好友]
JohnsonID:51357
20505次访问,排名5825好友0人,关注者0
51357的文章
原创 27 篇
翻译 0 篇
转载 12 篇
评论 12 篇
最近评论
coolboylmk:你就是51357的作者吗?非常喜欢你的作品,51357,longator,中国网爪,都非常棒!
为什么不继续开发longator呢?期待中。。。
怀念当年用56k猫和51357的日子。。。
ScriptBaby:阁下于2000年在delphibbs的一个回复中解释了TWebBrowser内存泄漏的成因和解决办法, 化解了我的一个疑问, 因此我非常感谢您.
我在我的blog中引用了您的回复, 以表示敬意.
http://blog.csdn.net/scriptbaby/archive/2007/05/20/1618486.aspx

btw 从我知道那个问题……
ScriptBaby:阁下是否delphibbs的zhongs?
xuyunlong:看得懂,但有个问题不明白。UDP方式是否还有采用完成端口的必要,如果用,怎么实现呢?UDP下可没有listen和Accept,也返回不了客户端连接的套接口。该把哪个Socket关联到IOCP。
lovefox_zoe:大哥有没有完成端口的例子啊。
文章分类
收藏
相册
音乐
coool link
Ajax基础
C51单片机串行口中断服务程序
cnpack
homepage
STC实现IO_SOFT_SPI接口
UI参考
Visual Studio 2005 Web Application Project Tutorials (with C#)
winx blog
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 HTTP Streaming例子: AsfRecorder.c代码收藏

新一篇: MediaPlayer ActiveX访问自定义的URL协议时问题 | 旧一篇: HTTP Streaming protocol 分析笔记

 AsfRecorder.c 研究
 v1.1
开源项目, 代码来自: http://sourceforge.net/projects/asfrecorder/
主要实现下载http stream file
 
/* The core routine for ASF download/extraction. */
 
int collectdata(int headeronly,
                int dumpheaders,
                FILE *rawfile,
                FILE *outfile,
                int bytesread,
               unsigned char *Buffer,
                int bufsize,
                int sendlen,
                struct hostent *hp,
                char *server_name,
                unsigned int addr,
                unsigned short port,
                int socket_type,
                char *file,
                struct HeaderInfo *hi,
                int maxtime)
{
    SOCKET conn_socket;
    int retval;
 
    SOCKADDR_IN server;
 
    int eol;
    int hdrpos;
    int linepos;
    int linenum;
    char HTTPHeader[1024];
    int resume = 0;
 
    char HTTPLine[512];
    char HTTPMessage[128];
    char *hdrptr;
    int errorcode;
 
   ...
 
conn_socket = my_socket(AF_INET,socket_type,0); /* Open a socket */
...
   retval = my_send(conn_socket,Buffer,sendlen,0);
      
                for (;;)
                {
                    char c;
 
                    if (readfromstream(conn_socket, &c, 1, rawfile) == 1)
                    {
                        if ((c != '\r') && (c != '\n'))
                        {
                            eol = 0;
                            HTTPLine[linepos++] = c;
                        }
                        else
                            HTTPLine[linepos++] = 0;
 
                        if (c == '\n')
                        {
                            if (eol == 0)
                            {
                                linepos = 0;
                                eol = 1;
                                linenum++;
 
                                hdrptr = HTTPLine;
 
                                /* Parse first line of HTTP reply */
                                if (linenum == 1)
                                {
                                    if ((!strnicmp(hdrptr, "HTTP/1.0 ", 9)) ||
                                        (!strnicmp(hdrptr, "HTTP/1.1 ", 9))   )
                                    {
                                        hdrptr+=9;
                                        sscanf(hdrptr, "%d", &errorcode);
                                        hdrptr+=4;
                                        strcpy(HTTPMessage, hdrptr);
                                    }
                                    else
                                    {
                                        gui_seterror("Illegal server reply! Expected HTTP/1.0 or HTTP/1.1\n");
                                        hi->contenttype = unknown_content;
                                    }
                                }
                                else
                                {
                                    /* Parse all other lines of HTTP reply */
                                    if (!strnicmp(hdrptr, "Content-Type: ", 14))
                                    {
                                        hdrptr+=14;
                                        strncpy(ContentType, hdrptr, sizeof(ContentType));
                                    }
 
                                    /* Parse all other lines of HTTP reply */
                                    if (!strnicmp(hdrptr, "Pragma: ", 8))
                                    {
                                        hdrptr+=8;
                                        if (!strnicmp(hdrptr, "features=", 9))
                                        {
                                            hdrptr+=9;
                                            strncpy(Features, hdrptr, sizeof(Features));
                                        }
                                    }
                                }
                            }
                            else
                            {
                                HTTPHeader[hdrpos++] = 0;
                                break;
                            }
                        }
 
                        HTTPHeader[hdrpos++] = c;
                    }
                    else
                    {
                        gui_seterror("readfromstream() returned other than 1!\n");
                        if (eos()) break;
                    }
                }
 
                hi->contenttype = unknown_content;
 
                /* Determine whether this is live content or not */
                if (!stricmp(ContentType, "application/octet-stream"))
                {
                    if (strstr(Features, "broadcast"))
                    {
                        hi->contenttype = live_content;
                    }
                    else
                    {
                        hi->contenttype = prerecorded_content;
                    }
                }
                else
                {
                   
                   ...
                }
 
                ...
 
                /* handle live or prerecorded content */
                if ((!eos()) && ((hi->contenttype == live_content) || (hi->contenttype == prerecorded_content)) )
                {
                    unsigned int starttime_hi = 0xffffffff;
                    unsigned int starttime    = 0xffffffff;
                    unsigned int startseqno   = 0xffffffff;
                    unsigned int maxtimecode = 0;
                    int          endofheaderposition = 0;
                    int          numdatachunks       = 0;
                    int          sizeofdatachunks    = 0;
 
                    int          header_length = 0;
                    int          header_offset = 0;
 
                    /* The main loop for chunk extraction/ASF generation */
                    for (;;)
                    {
                       ...
 
                        /* Check for EOF and extract chunk header */
                        /* bytes are read one by one so this code */
                        /* remains portable to non-INTEL platforms */
 
                        if (eos()) { gui_setstatus("Connection reset\n"); break; }
 
                        /* read basic chunk type */
                        readfromstream(conn_socket, &c1, 1, rawfile);
                        readfromstream(conn_socket, &c2, 1, rawfile);
                        type = (c2<<8) + c1;
 
                        /* These header types correspond to "H$", "D$" and "E$" */
                        /* (Header, Data and End) */
                        if ((type != HEADER_CHUNK) && (type != DATA_CHUNK) && (type != END_CHUNK))
                        {
                            gui_logtext("Unknown header type: $%04x\n", type);
                        }
 
                        if (type == END_CHUNK)
                        {
                            gui_setstatus("Transfer complete.\n");
                            break;
                        }
 
                        if (eos()) { gui_setstatus("Connection reset\n"); break; }
 
                        /* read chunk length (max 64k) */
                        readfromstream(conn_socket, &l1, 1, rawfile);
                        readfromstream(conn_socket, &l2, 1, rawfile);
                        length = (l2<<8) + l1;
 
                        if (eos()) { gui_setstatus("Connection reset\n"); break; }
 
                        /* read chunk sequence number */
                        readfromstream(conn_socket, &s1, 1, rawfile);
                        readfromstream(conn_socket, &s2, 1, rawfile);
                        readfromstream(conn_socket, &s3, 1, rawfile);
                        readfromstream(conn_socket, &s4, 1, rawfile);
                        seqno   = (s4<<24) + (s3<<16) + (s2<<8) + s1;
 
                        if (eos()) { gui_setstatus("Connection reset\n"); break; }
 
                        /* read two unknown bytes */
                        readfromstream(conn_socket, &u1, 1, rawfile);
                        readfromstream(conn_socket, &u2, 1, rawfile);
                        partflag = (u2<<8) + u1;
 
                        if (eos()) { gui_setstatus("Connection reset\n"); break; }
 
                        /* read second length entry (length confirmation) */
                        readfromstream(conn_socket, &l1, 1, rawfile);
                        readfromstream(conn_socket, &l2, 1, rawfile);
                        length2 = (l2<<8) + l1;
 
                        if (eos()) { gui_setstatus("Connection reset\n"); break; }
 
                        /* Sanity check on chunk header. Second length entry must match the first. */
                        if (length2 != length)
                        {
                            gui_logtext("Length confirmation doesn't match!\n");
                            break;
                        }
 
                        /* calculate length of chunk body. */
                        bodylength = length-8;
 
                        /* check if the body length exceeds our buffer size */
                        if (bodylength > bufsize)
                        {
                            gui_logtext("Buffer too small. Chunk is %d bytes!\n", length);
                            break;
                        }
 
                        /* check length of chunk body */
                        if (bodylength <= 0)
                        {
                            gui_logtext("Chunk has no body!\n");
                            break;
                        }
 
                        /* Read chunk's body data */
                        if (type != HEADER_CHUNK) header_offset = 0;
                        got = readfromstream(conn_socket, Buffer + header_offset, bodylength, rawfile);
                        bodylength = header_offset + bodylength;
                        got        = header_offset + got;
 
                        /* Try to extract a timecode from all known chunk/content types */
                        strcpy(timecodestring, "???");
                        timecode = 0;
 
                        /* this only applies to data chunks */
                        if (type == DATA_CHUNK)
                        {
                            int tc_start;
 
                            if (headeronly) break;
 
                            /* save the first seqno available as a reference */
                            if (startseqno == 0xffffffff)
                            {
                                startseqno = seqno;
                            }
 
                            /* fix the seqno for live recordings only */
                            if (hi->time == 0)
                            {
                                /* refer seqno to the point we "zapped in" (for live streams) */
                                if (startseqno != 0xffffffff)
                                    seqno -= startseqno;
                            }
 
                            /* find the location of the time code */
                            if ((tc_start = whereis_timecode(Buffer)) > 0)
                            {
                                /* The timecode is an integer value defining milliseconds */
                                /* enough range for about 50 days! */
                                get_long(&Buffer[tc_start], &timecode);
 
                                /* save the first timecode available as a reference */
                                if (starttime == 0xffffffff)
                                    starttime = timecode;
 
                                /* fix timecode for live recordings only */
                                if (hi->time == 0)
                                {
                                    /* refer timecode to the point we "zapped in" (live streams) */
                                    timecode -= starttime;
 
                                    /* this fixes the timecodes in the memory buffer */
                                    fix_timecodes(Buffer, bodylength, starttime, seqno, hi);
                                }
 
                                /* save max. timecode value */
                                if (timecode > maxtimecode)
                                    maxtimecode = timecode;
 
                                /* create a string with a human-readable form of the timecode */
                                strcpy(timecodestring, createtimestring(timecode));
                            }
                        }
 
                        /* calculate progress indicator (scale: 0....10000) */
                        if (hi->time == 0)
                             /* live streams */
                            if (maxtime == 0)   /* unlimited recording */
                                progress = 0;
                            else                /* limited time recording */
                                progress = (int)((double)timecode*10000/(maxtime*60*1000));
                        else
                            /* prerecorded content */
                            progress = (int)((double)timecode*10000/hi->time);
 
                        /* Print current position in stream download */
                        gui_logtext("%5d kB (%2d%%), HDR: $%04x, part: $%04x, %4d bytes, seq $%08x, tc: %s\n", bytesread/1024, progress/100, (int)type, (int)partflag, length, seqno, timecodestring);
 
                        /* Extract the block size from the ASF header. */
                        /* This block size is essential in the ASF file */
                        /* format. All data chunks in the ASF file must */
                        /* have this length, even if network transmission */
                        /* sent us smaller chunks! */
                        if (type == HEADER_CHUNK)
                        {
                            int offs;
                           
                            /* Headers may be split into several parts with */
                            /* a rising sequence number. This case occurs in */
                            /* audio books on broadcast.com, for example. */
 
                            /* This indicates the first header part */
                            if (partflag & 0x0400)
                            {
                                header_offset = 0;
                                get_long(&Buffer[16], &header_length);
                                header_length += 50;
                            }
 
                            /* header progress indicator */
                            if (bodylength < header_length)
                                gui_setstatus("receiving ASF header (%d/%d)!\n", bodylength, header_length);
 
                            /* Skip parsing the header if it hasn't been received completely */
                            if (!(partflag & 0x0800))
                            {
                                /* next header partition will be appended */
                                header_offset = bodylength;
 
                                /* this prevents saving a partial header to the output file */
                                bodylength = header_length;
                            }
                            else
                            {
                                /* finally got the header */
                                gui_setstatus("received ASF header!\n");
 
                                /* find a specific object in this header */
                                offs = find_id(HDR_ID,Buffer, got);
                                if (offs == -1)
                                {
                                    gui_criticalerror("Unable to parse this ASF header!\n");
                                    break;
                                }
                                else
                                {
                                    /* extract required information */
                                    hi->header_offs = offs;
                                    get_quad(&Buffer[offs+HDR_TOTAL_SIZE_8], &hi->totalsize_hi, &hi->totalsize_lo);
                                    get_quad(&Buffer[offs+HDR_FINE_TOTALTIME_8], &hi->totaltime_hi, &hi->totaltime_lo);
                                    get_long(&Buffer[offs+HDR_PLAYTIME_OFFSET_4], &hi->offset);
                                    get_long(&Buffer[offs+HDR_FLAGS_4], &hi->flags);
                                    get_long(&Buffer[offs+HDR_ASF_CHUNKLENGTH_4], &hi->chunklength);
                                    get_long(&Buffer[offs+HDR_ASF_CHUNKLENGTH_CONFIRM_4], &hi->chunklength2);
                                   
                                    /* check if the extracted chunk length looks good */
                                    if (!(hi->chunklength < MAX_CHUNK_SIZE && (hi->chunklength == hi->chunklength2)))
                                    {
                                        gui_criticalerror(
                                            "Unable to capture this stream!\n"
                                            "This one uses variable chunk sizes,\n"
                                            "which is not supported. Sorry! ;-)\n");
                                       
                                        hi->contenttype = unknown_content;
                                        break;
                                    }
                                   
                                    /* calculate playtime in milliseconds (0 for live streams) */
                                    if (hi->totaltime_hi == 0 && hi->totaltime_lo == 0)
                                    {
                                        hi->time = 0; /* live streams */
                                    }
                                    else
                                        hi->time = (int)((double)429496.7296 * hi->totaltime_hi) + (hi->totaltime_lo / 10000) - hi->offset;
 
                                    /* store position where the ASF header segment ends */
                                    /* and the chunk data segment starts */
                                    hi->endofheader_offs = bodylength - DATSEG_HDR_SIZE;
                                   
                   &n