⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asf_streaming.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <errno.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#ifndef HAVE_WINSOCK2#define closesocket close#else#include <winsock2.h>#endif#include "url.h"#include "http.h"#include "libmpdemux/asf.h"#include "stream.h"#include "libmpdemux/demuxer.h"#include "network.h"#include "tcp.h"#undef memcpy#define memcpy uc_memcpy#ifdef ARCH_X86#define	ASF_LOAD_GUID_PREFIX(guid)	(*(uint32_t *)(guid))#else#define	ASF_LOAD_GUID_PREFIX(guid)	\	((guid)[3] << 24 | (guid)[2] << 16 | (guid)[1] << 8 | (guid)[0])#endifextern int network_bandwidth;int asf_mmst_streaming_start( stream_t *stream );static int asf_http_streaming_start(stream_t *stream, int *demuxer_type);// We can try several protocol for asf streaming// * first the UDP protcol, if there is a firewall, UDP//   packets will not come back, so the mmsu will fail.// * Then we can try TCP, but if there is a proxy for//   internet connection, the TCP connection will not get//   through// * Then we can try HTTP.// // Note: Using 	WMP sequence  MMSU then MMST and then HTTP.static int asf_streaming_start( stream_t *stream, int *demuxer_type) {    char *proto = stream->streaming_ctrl->url->protocol;    int fd = -1;    int port = stream->streaming_ctrl->url->port;    // Is protocol mms or mmsu?    if (!strcasecmp(proto, "mmsu") || !strcasecmp(proto, "mms"))    {		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/UDP...\n");		//fd = asf_mmsu_streaming_start( stream );		if( fd>-1 ) return fd; //mmsu support is not implemented yet - using this code		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/UDP failed\n");		if( fd==-2 ) return -1;	}    //Is protocol mms or mmst?    if (!strcasecmp(proto, "mmst") || !strcasecmp(proto, "mms"))    {		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/TCP...\n");		fd = asf_mmst_streaming_start( stream );		stream->streaming_ctrl->url->port = port;		if( fd>-1 ) return fd;		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/TCP failed\n");		if( fd==-2 ) return -1;	}    //Is protocol http, http_proxy, or mms?     if (!strcasecmp(proto, "http_proxy") || !strcasecmp(proto, "http") ||	!strcasecmp(proto, "mms") || !strcasecmp(proto, "mmshttp"))    {		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/HTTP...\n");		fd = asf_http_streaming_start( stream, demuxer_type );		stream->streaming_ctrl->url->port = port;		if( fd>-1 ) return fd;		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/HTTP failed\n");		if( fd==-2 ) return -1;	}    //everything failed	return -1;}static int asf_streaming(ASF_stream_chunck_t *stream_chunck, int *drop_packet ) {/*	printf("ASF stream chunck size=%d\n", stream_chunck->size);printf("length: %d\n", length );printf("0x%02X\n", stream_chunck->type );*/	if( drop_packet!=NULL ) *drop_packet = 0;	if( stream_chunck->size<8 ) {		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_StreamChunkSize2Small, stream_chunck->size);		return -1;	}	if( stream_chunck->size!=stream_chunck->size_confirm ) {		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_SizeConfirmMismatch, stream_chunck->size, stream_chunck->size_confirm);		return -1;	}/*		printf("  type: 0x%02X\n", stream_chunck->type );	printf("  size: %d (0x%02X)\n", stream_chunck->size, stream_chunck->size );	printf("  sequence_number: 0x%04X\n", stream_chunck->sequence_number );	printf("  unknown: 0x%02X\n", stream_chunck->unknown );	printf("  size_confirm: 0x%02X\n", stream_chunck->size_confirm );*/	switch(stream_chunck->type) {		case ASF_STREAMING_CLEAR:	// $C	Clear ASF configuration			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Clearing ASF stream configuration!\n");			if( drop_packet!=NULL ) *drop_packet = 1;			return stream_chunck->size;			break;		case ASF_STREAMING_DATA:	// $D	Data follows//			printf("=====> Data follows\n");			break;		case ASF_STREAMING_END_TRANS:	// $E	Transfer complete			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Transfer complete\n");			if( drop_packet!=NULL ) *drop_packet = 1;			return stream_chunck->size;			break;		case ASF_STREAMING_HEADER:	// $H	ASF header chunk follows			mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF header chunk follows\n");			break;		default:			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Unknown stream type 0x%x\n", stream_chunck->type );	}	return stream_chunck->size+4;}extern int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len);extern const char asf_file_header_guid[];extern const char asf_stream_header_guid[];extern const char asf_stream_group_guid[];extern int audio_id;extern int video_id;static void close_s(stream_t *stream) {	close(stream->fd);	stream->fd=-1;}static int max_idx(int s_count, int *s_rates, int bound) {  int i, best = -1, rate = -1;  for (i = 0; i < s_count; i++) {    if (s_rates[i] > rate && s_rates[i] <= bound) {      rate = s_rates[i];      best = i;    }  }  return best;}static int asf_streaming_parse_header(int fd, streaming_ctrl_t* streaming_ctrl) {  ASF_header_t asfh;  ASF_stream_chunck_t chunk;  asf_http_streaming_ctrl_t* asf_ctrl = (asf_http_streaming_ctrl_t*) streaming_ctrl->data;  char* buffer=NULL, *chunk_buffer=NULL;  int i,r,size,pos = 0;  int start;  int buffer_size = 0;  int chunk_size2read = 0;  int bw = streaming_ctrl->bandwidth;  int *v_rates = NULL, *a_rates = NULL;  int v_rate = 0, a_rate = 0, a_idx = -1, v_idx = -1;    if(asf_ctrl == NULL) return -1;	// The ASF header can be in several network chunks. For example if the content description	// is big, the ASF header will be split in 2 network chunk.	// So we need to retrieve all the chunk before starting to parse the header.  do {	  for( r=0; r < (int)sizeof(ASF_stream_chunck_t) ; ) {		i = nop_streaming_read(fd,((char*)&chunk)+r,sizeof(ASF_stream_chunck_t) - r,streaming_ctrl);		if(i <= 0) return -1;		r += i;	  }	  // Endian handling of the stream chunk	  le2me_ASF_stream_chunck_t(&chunk);	  size = asf_streaming( &chunk, &r) - sizeof(ASF_stream_chunck_t);	  if(r) mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_ASF_WarnDropHeader);	  if(size < 0){	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader);		return -1;	  }	  if (chunk.type != ASF_STREAMING_HEADER) {	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_NoHeaderAtFirstChunk);	    return -1;	  }	  	  // audit: do not overflow buffer_size	  if (size > SIZE_MAX - buffer_size) return -1;	  buffer = (char*) malloc(size+buffer_size);	  if(buffer == NULL) {	    mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MPDEMUX_ASF_BufferMallocFailed,size+buffer_size);	    return -1;	  }	  if( chunk_buffer!=NULL ) {	  	memcpy( buffer, chunk_buffer, buffer_size );		free( chunk_buffer );	  }	  chunk_buffer = buffer;	  buffer += buffer_size;	  buffer_size += size;	  	  for(r = 0; r < size;) {	    i = nop_streaming_read(fd,buffer+r,size-r,streaming_ctrl);	    if(i < 0) {		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingNetworkStream);		    return -1;	    }	    r += i;	  }  	  if( chunk_size2read==0 ) {		if(size < (int)sizeof(asfh)) {		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunk2Small);		    return -1;		} else mp_msg(MSGT_NETWORK,MSGL_DBG2,"Got chunk\n");	  	memcpy(&asfh,buffer,sizeof(asfh));	  	le2me_ASF_header_t(&asfh);		chunk_size2read = asfh.objh.size;		mp_msg(MSGT_NETWORK,MSGL_DBG2,"Size 2 read=%d\n", chunk_size2read);	  }  } while( buffer_size<chunk_size2read);  buffer = chunk_buffer;  size = buffer_size;	    if(asfh.cno > 256) {    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrSubChunkNumberInvalid);    return -1;  }  start = sizeof(asfh);    pos = find_asf_guid(buffer, asf_file_header_guid, start, size);  if (pos >= 0) {    ASF_file_header_t *fileh = (ASF_file_header_t *) &buffer[pos];    pos += sizeof(ASF_file_header_t);    if (pos > size) goto len_err_out;      le2me_ASF_file_header_t(fileh);/*      if(fileh.packetsize != fileh.packetsize2) {	printf("Error packetsize check don't match\n");	return -1;      }*/      asf_ctrl->packet_size = fileh->max_packet_size;      // before playing.       // preroll: time in ms to bufferize before playing      streaming_ctrl->prebuffer_size = (unsigned int)(((double)fileh->preroll/1000.0)*((double)fileh->max_bitrate/8.0));  }  pos = start;  while ((pos = find_asf_guid(buffer, asf_stream_header_guid, pos, size)) >= 0)  {    ASF_stream_header_t *streamh = (ASF_stream_header_t *)&buffer[pos];    pos += sizeof(ASF_stream_header_t);    if (pos > size) goto len_err_out;      le2me_ASF_stream_header_t(streamh);      switch(ASF_LOAD_GUID_PREFIX(streamh->type)) {      case 0xF8699E40 : // audio stream	if(asf_ctrl->audio_streams == NULL){	  asf_ctrl->audio_streams = malloc(sizeof(int));	  asf_ctrl->n_audio = 1;	} else {	  asf_ctrl->n_audio++;	  asf_ctrl->audio_streams = (int*)realloc(asf_ctrl->audio_streams,						     asf_ctrl->n_audio*sizeof(int));	}	asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = streamh->stream_no;	break;      case 0xBC19EFC0 : // video stream	if(asf_ctrl->video_streams == NULL){	  asf_ctrl->video_streams = malloc(sizeof(int));	  asf_ctrl->n_video = 1;	} else {	  asf_ctrl->n_video++;	  asf_ctrl->video_streams = (int*)realloc(asf_ctrl->video_streams,						     asf_ctrl->n_video*sizeof(int));	}	asf_ctrl->video_streams[asf_ctrl->n_video-1] = streamh->stream_no;	break;      }  }  // always allocate to avoid lots of ifs later  v_rates = calloc(asf_ctrl->n_video, sizeof(int));  a_rates = calloc(asf_ctrl->n_audio, sizeof(int));  pos = find_asf_guid(buffer, asf_stream_group_guid, start, size);  if (pos >= 0) {    // stream bitrate properties object	int stream_count;	char *ptr = &buffer[pos];		mp_msg(MSGT_NETWORK, MSGL_V, "Stream bitrate properties object\n");		stream_count = le2me_16(*(uint16_t*)ptr);		ptr += sizeof(uint16_t);		if (ptr > &buffer[size]) goto len_err_out;		mp_msg(MSGT_NETWORK, MSGL_V, " stream count=[0x%x][%u]\n",		        stream_count, stream_count );		for( i=0 ; i<stream_count ; i++ ) {			uint32_t rate;			int id;			int j;			id = le2me_16(*(uint16_t*)ptr);			ptr += sizeof(uint16_t);			if (ptr > &buffer[size]) goto len_err_out;			memcpy(&rate, ptr, sizeof(uint32_t));// workaround unaligment bug on sparc			ptr += sizeof(uint32_t);			if (ptr > &buffer[size]) goto len_err_out;			rate = le2me_32(rate);			mp_msg(MSGT_NETWORK, MSGL_V,                                "  stream id=[0x%x][%u]\n", id, id);			mp_msg(MSGT_NETWORK, MSGL_V,			        "  max bitrate=[0x%x][%u]\n", rate, rate);			for (j = 0; j < asf_ctrl->n_video; j++) {			  if (id == asf_ctrl->video_streams[j]) {			    mp_msg(MSGT_NETWORK, MSGL_V, "  is video stream\n");			    v_rates[j] = rate;			    break;			  }			}			for (j = 0; j < asf_ctrl->n_audio; j++) {			  if (id == asf_ctrl->audio_streams[j]) {			    mp_msg(MSGT_NETWORK, MSGL_V, "  is audio stream\n");			    a_rates[j] = rate;			    break;			  }			}		}  }  free(buffer);  // automatic stream selection based on bandwidth  if (bw == 0) bw = INT_MAX;  mp_msg(MSGT_NETWORK, MSGL_V, "Max bandwidth set to %d\n", bw);  if (asf_ctrl->n_audio) {    // find lowest-bitrate audio stream    a_rate = a_rates[0];    a_idx = 0;    for (i = 0; i < asf_ctrl->n_audio; i++) {      if (a_rates[i] < a_rate) {        a_rate = a_rates[i];        a_idx = i;      }    }    if (max_idx(asf_ctrl->n_video, v_rates, bw - a_rate) < 0) {      // both audio and video are not possible, try video only next      a_idx = -1;      a_rate = 0;    }  }  // find best video stream  v_idx = max_idx(asf_ctrl->n_video, v_rates, bw - a_rate);  if (v_idx >= 0)    v_rate = v_rates[v_idx];  // find best audio stream  a_idx = max_idx(asf_ctrl->n_audio, a_rates, bw - v_rate);      free(v_rates);  free(a_rates);  if (a_idx < 0 && v_idx < 0) {    mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_Bandwidth2SmallCannotPlay);    return -1;  }  if (audio_id > 0)    // a audio stream was forced    asf_ctrl->audio_id = audio_id;  else if (a_idx >= 0)    asf_ctrl->audio_id = asf_ctrl->audio_streams[a_idx];  else if (asf_ctrl->n_audio) {    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedAudio);    audio_id = -2;  }  if (video_id > 0)    // a video stream was forced    asf_ctrl->video_id = video_id;  else if (v_idx >= 0)    asf_ctrl->video_id = asf_ctrl->video_streams[v_idx];  else if (asf_ctrl->n_video) {    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedVideo);    video_id = -2;  }  return 1;len_err_out:  mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_InvalidLenInHeader);  if (buffer) free(buffer);  if (v_rates) free(v_rates);  if (a_rates) free(a_rates);  return -1;}static int asf_http_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) {  static ASF_stream_chunck_t chunk;  int read,chunk_size = 0;  static int rest = 0, drop_chunk = 0, waiting = 0;  asf_http_streaming_ctrl_t *asf_http_ctrl = (asf_http_streaming_ctrl_t*)streaming_ctrl->data;  while(1) {    if (rest == 0 && waiting == 0) {      read = 0;      while(read < (int)sizeof(ASF_stream_chunck_t)){	int r = nop_streaming_read( fd, ((char*)&chunk) + read, 				    sizeof(ASF_stream_chunck_t)-read, 				    streaming_ctrl );	if(r <= 0){	  if( r < 0) 	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingChunkHeader);	  return -1;	}	read += r;      }            // Endian handling of the stream chunk      le2me_ASF_stream_chunck_t(&chunk);      chunk_size = asf_streaming( &chunk, &drop_chunk );      if(chunk_size < 0) {	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader);	return -1;      }      chunk_size -= sizeof(ASF_stream_chunck_t);	      if(chunk.type != ASF_STREAMING_HEADER && (!drop_chunk)) {	if (asf_http_ctrl->packet_size < chunk_size) {	  mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunkBiggerThanPacket);	  return -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -