📄 asf_mmst_streaming.c
字号:
/* * MMST implementation taken from the xine-mms plugin made by * Major MMS (http://geocities.com/majormms/). * Ported to MPlayer by Abhijeet Phatak <abhijeetphatak@yahoo.com>. * * Information about the MMS protocol can be found at http://get.to/sdp * * copyright (C) 2002 Abhijeet Phatak <abhijeetphatak@yahoo.com> * copyright (C) 2002 the xine project * copyright (C) 2000-2001 major mms * * This file is part of MPlayer. * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MPlayer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <errno.h>#include <inttypes.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#ifndef HAVE_WINSOCK2#define closesocket close#else#include <winsock2.h>#endif#ifndef USE_SETLOCALE#undef USE_ICONV#endif#ifdef USE_ICONV#include <iconv.h>#ifdef USE_LANGINFO#include <langinfo.h>#endif#endif#include "url.h"#include "libmpdemux/asf.h"#include "stream.h"#include "network.h"#include "tcp.h"extern int audio_id;extern int video_id;#define BUF_SIZE 102400#define HDR_BUF_SIZE 8192#define MAX_STREAMS 20#undef memcpy#define memcpy uc_memcpytypedef 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)) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_WriteError); }}#ifdef USE_ICONVstatic iconv_t url_conv;#endifstatic 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) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_EOFAlert); 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) { perror ("read error:"); return 0; } total += len; if (len != 0) {// mp_msg(MSGT_NETWORK,MSGL_INFO,"[%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)) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_PreHeaderReadFailed); return 0; } if (pre_header[4] == 0x02) { int packet_len; packet_len = (pre_header[7] << 8 | pre_header[6]) - 8;// mp_msg(MSGT_NETWORK,MSGL_INFO,"asf header packet detected, len=%d\n", packet_len); if (packet_len < 0 || packet_len > HDR_BUF_SIZE - header_len) { mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_MMST_InvalidHeaderSize); return 0; } if (!get_data (s, &header[header_len], packet_len)) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_HeaderDataReadFailed); 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; } // mp_msg(MSGT_NETWORK,MSGL_INFO,"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)) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_packet_lenReadFailed); return 0; } packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; // mp_msg(MSGT_NETWORK,MSGL_INFO,"command packet detected, len=%d\n", packet_len); if (packet_len < 0 || packet_len > BUF_SIZE) { mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize); return 0; } if (!get_data (s, data, packet_len)) { mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_CmdDataReadFailed); return 0; } command = get_32 (data, 24) & 0xFFFF; // mp_msg(MSGT_NETWORK,MSGL_INFO,"command: %02x\n", command); if (command == 0x1b) send_command (s, 0x1b, 0, 0, 0, data); }// mp_msg(MSGT_NETWORK,MSGL_INFO,"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; // mp_msg(MSGT_NETWORK,MSGL_INFO,"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) ) { mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_HeaderObject); } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) { mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_DataObject);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -