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

📄 mms.c

📁 libmms开发库源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * return packet type */static int get_packet_header (mms_io_t *io, mms_t *this, mms_packet_header_t *header) {  size_t len;  int packet_type;  header->packet_len     = 0;  header->packet_seq     = 0;  header->flags          = 0;  header->packet_id_type = 0;  len = io_read(io,  this->s, this->buf, 8);  if (len != 8)    goto error;  if (LE_32(this->buf + 4) == 0xb00bface) {    /* command packet */    header->flags = this->buf[3];    len = io_read(io,  this->s, this->buf + 8, 4);    if (len != 4)      goto error;        header->packet_len = LE_32(this->buf + 8) + 4;    if (header->packet_len > BUF_SIZE - 12) {        header->packet_len = 0;        goto error;    }    lprintf("mms command\n");    packet_type = MMS_PACKET_COMMAND;  } else {    header->packet_seq     = LE_32(this->buf);    header->packet_id_type = this->buf[4];    header->flags          = this->buf[5];    header->packet_len     = (LE_16(this->buf + 6) - 8) & 0xffff;    if (header->packet_id_type == ASF_HEADER_PACKET_ID_TYPE) {      lprintf("asf header\n");      packet_type = MMS_PACKET_ASF_HEADER;    } else {      lprintf("asf packet\n");      packet_type = MMS_PACKET_ASF_PACKET;    }  }    return packet_type;  error:  lprintf("read error, len=%d\n", len);  perror("Could not read packet header");  return MMS_PACKET_ERR;}static int get_packet_command (mms_io_t *io, mms_t *this, uint32_t packet_len) {  int  command = 0;  size_t len;    /* always enter this loop */  lprintf("packet_len: %d bytes\n", packet_len);  len = io_read(io,  this->s, this->buf + 12, packet_len) ;  if (len != packet_len) {    return 0;  }  print_command (this->buf, len);    /* check protocol type ("MMS ") */  if (LE_32(this->buf + 12) != 0x20534D4D) {    lprintf("unknown protocol type: %c%c%c%c (0x%08X)\n",            this->buf[12], this->buf[13], this->buf[14], this->buf[15],            LE_32(this->buf + 12));      return 0;  }  command = LE_32 (this->buf + 36) & 0xFFFF;  lprintf("command = 0x%2x\n", command);      return command;}static int get_answer (mms_io_t *io, mms_t *this) {  int command = 0;  mms_packet_header_t header;  switch (get_packet_header (io, this, &header)) {    case MMS_PACKET_ERR:  /* FIXME: de-xine-ification */      lprintf( "***LOG:*** -- "	      "libmms: failed to read mms packet header\n");      break;    case MMS_PACKET_COMMAND:      command = get_packet_command (io, this, header.packet_len);            if (command == 0x1b) {            if (!send_command (io, this, 0x1b, 0, 0, 0)) {  /* FIXME: de-xine-ification */          lprintf( "***LOG:*** -- "		  "libmms: failed to send command\n");          return 0;        }        /* FIXME: limit recursion */        command = get_answer (io, this);      }      break;    case MMS_PACKET_ASF_HEADER:  /* FIXME: de-xine-ification */      lprintf( "***LOG:*** -- "	      "libmms: unexpected asf header packet\n");      break;    case MMS_PACKET_ASF_PACKET:  /* FIXME: de-xine-ification */      lprintf( "***LOG:*** -- ""libmms: unexpected asf packet\n");      break;  }    return command;}static int get_asf_header (mms_io_t *io, mms_t *this) {  off_t len;  int stop = 0;    this->asf_header_read = 0;  this->asf_header_len = 0;  while (!stop) {    mms_packet_header_t header;    int command;    switch (get_packet_header (io, this, &header)) {      case MMS_PACKET_ERR:  /* FIXME: de-xine-ification */        lprintf( "***LOG:*** -- "	       "libmms: failed to read mms packet header\n");        return 0;        break;      case MMS_PACKET_COMMAND:        command = get_packet_command (io, this, header.packet_len);              if (command == 0x1b) {              if (!send_command (io, this, 0x1b, 0, 0, 0)) {  /* FIXME: de-xine-ification */            lprintf( "***LOG:*** -- "		   "libmms: failed to send command\n");            return 0;          }          command = get_answer (io, this);        } else {  /* FIXME: de-xine-ification */          lprintf( "***LOG:*** -- "		 "libmms: unexpected command packet\n");        }        break;      case MMS_PACKET_ASF_HEADER:      case MMS_PACKET_ASF_PACKET:        if (header.packet_len + this->asf_header_len > ASF_HEADER_LEN) {            lprintf( "***LOG:*** -- "                     "libmms: asf packet too large\n");            return 0;        }        len = io_read(io,  this->s,                              this->asf_header + this->asf_header_len, header.packet_len);        if (len != header.packet_len) {  /* FIXME: de-xine-ification */          lprintf( "***LOG:*** -- "		 "libmms: get_asf_header failed\n");           return 0;        }        this->asf_header_len += header.packet_len;        lprintf("header flags: %d\n", header.flags);        if ((header.flags == 0X08) || (header.flags == 0X0C))          stop = 1;        break;    }  }  lprintf ("get header packet succ\n");  return 1;}static void interp_asf_header (mms_t *this) {  int i;  this->asf_packet_len = 0;  this->num_stream_ids = 0;  /*   * parse header   */     i = 30;  while (i < this->asf_header_len) {        int guid;    uint64_t length;    guid = get_guid(this->asf_header, i);    i += 16;            length = LE_64(this->asf_header + i);    i += 8;    switch (guid) {          case GUID_ASF_FILE_PROPERTIES:        this->asf_packet_len = LE_32(this->asf_header + i + 92 - 24);        if (this->asf_packet_len > BUF_SIZE) {          this->asf_packet_len = 0;          lprintf( "***LOG:*** -- "                   "libmms: asf packet len too large\n");          break;        }        this->file_len       = LE_64(this->asf_header + i + 40 - 24);        lprintf ("file object, packet length = %d (%d)\n",                 this->asf_packet_len, LE_32(this->asf_header + i + 96 - 24));        break;      case GUID_ASF_STREAM_PROPERTIES:        {	  uint16_t flags;          uint16_t stream_id;          int      type;          int      encrypted;          guid = get_guid(this->asf_header, i);          switch (guid) {            case GUID_ASF_AUDIO_MEDIA:              type = ASF_STREAM_TYPE_AUDIO;              this->has_audio = 1;              break;                case GUID_ASF_VIDEO_MEDIA:	    case GUID_ASF_JFIF_MEDIA:	    case GUID_ASF_DEGRADABLE_JPEG_MEDIA:              type = ASF_STREAM_TYPE_VIDEO;              this->has_video = 1;              break;                      case GUID_ASF_COMMAND_MEDIA:              type = ASF_STREAM_TYPE_CONTROL;              break;                    default:              type = ASF_STREAM_TYPE_UNKNOWN;          }          flags = LE_16(this->asf_header + i + 48);	  stream_id = flags & 0x7F;	  encrypted = flags >> 15;          lprintf ("stream object, stream id: %d, type: %d, encrypted: %d\n",		   stream_id, type, encrypted);	  if (this->num_stream_ids < ASF_MAX_NUM_STREAMS && stream_id < ASF_MAX_NUM_STREAMS) {	    this->stream_types[stream_id] = type;	    this->stream_ids[this->num_stream_ids] = stream_id;	    this->num_stream_ids++;	  } else {	    lprintf ("too many streams, skipping\n");	  }        }        break;      case GUID_ASF_STREAM_BITRATE_PROPERTIES:        {          uint16_t streams = LE_16(this->asf_header + i);          uint16_t stream_id;          int j;          lprintf ("stream bitrate properties\n");          lprintf ("streams %d\n", streams);           for(j = 0; j < streams; j++) {            stream_id = LE_16(this->asf_header + i + 2 + j * 6);            lprintf ("stream id %d\n", stream_id);             this->bitrates[stream_id] = LE_32(this->asf_header + i + 4 + j * 6);            this->bitrates_pos[stream_id] = i + 4 + j * 6;            lprintf ("stream id %d, bitrate %d\n", stream_id,                      this->bitrates[stream_id]);          }        }        break;          default:        lprintf ("unknown object\n");        break;    }    lprintf ("length    : %lld\n", length);    if (length > 24) {      i += length - 24;    }  }}const static char *const mmst_proto_s[] = { "mms", "mmst", NULL };static int mmst_valid_proto (char *proto) {  int i = 0;  lprintf("mmst_valid_proto\n");  if (!proto)    return 0;  while(mmst_proto_s[i]) {    if (!strcasecmp(proto, mmst_proto_s[i])) {      return 1;    }    i++;  }  return 0;}/* FIXME: de-xine-ification *//* static void report_progress (void *data, int p) {  xine_event_t             event;  xine_progress_data_t     prg;  prg.description = _("Connecting MMS server (over tcp)...");  prg.percent = p;    event.type = XINE_EVENT_PROGRESS;  event.data = &prg;  event.data_length = sizeof (xine_progress_data_t);    xine_event_send (stream, &event);} *//* * returns 1 on error */static int mms_tcp_connect(mms_io_t *io, mms_t *this) {  int progress, res;    if (!this->port) this->port = MMST_PORT;  /*    * try to connect    */  lprintf("try to connect to %s on port %d \n", this->host, this->port);  this->s = io_connect(io,  this->host, this->port);  if (this->s == -1) {  /* FIXME: de-xine-ification */    lprintf ( "***LOG:*** -- "	    "failed to connect '%s'\n", this->host);    return 1;  }  /* connection timeout 15s */  progress = 0;  do {    /*FIXME: de-xine-ification *//*     report_progress(this->stream, progress); */    res = io_select(io,  this->s, MMS_IO_WRITE_READY, 500);    progress += 1;  } while ((res == MMS_IO_STATUS_TIMEOUT) && (progress < 30));  if (res != MMS_IO_STATUS_READY) {    return 1;  }  lprintf ("connected\n");  return 0;}static void mms_gen_guid(char guid[]) {  static char digit[16] = "0123456789ABCDEF";  int i = 0;  srand(time(NULL));  for (i = 0; i < 36; i++) {    guid[i] = digit[(int) ((16.0*rand())/(RAND_MAX+1.0))];  }  guid[8] = '-'; guid[13] = '-'; guid[18] = '-'; guid[23] = '-';  guid[36] = '\0';}/* * return 0 on error */int static mms_choose_best_streams(mms_io_t *io, mms_t *this) {  int     i;  int     video_stream = 0;  int     audio_stream = 0;  int     max_arate    = 0;  int     min_vrate    = 0;  int     min_bw_left  = 0;  int     stream_id;  int     bandwitdh_left;  int     res;  /* command 0x33 */  /* choose the best quality for the audio stream */  /* i've never seen more than one audio stream */  lprintf("num_stream_ids=%d\n", this->num_stream_ids);  for (i = 0; i < this->num_stream_ids; i++) {    stream_id = this->stream_ids[i];    switch (this->stream_types[stream_id]) {      case ASF_STREAM_TYPE_AUDIO:        if (this->bitrates[stream_id] > max_arate) {          audio_stream = stream_id;          max_arate = this->bitrates[stream_id];        }        break;      default:        break;    }  }    /* choose a video stream adapted to the user bandwidth */  bandwitdh_left = this->bandwidth - max_arate;  if (bandwitdh_left < 0) {    bandwitdh_left = 0;  }  lprintf("bandwitdh %d, left %d\n", this->bandwidth, bandwitdh_left);  min_bw_left = bandwitdh_left;  for (i = 0; i < this->num_stream_ids; i++) {    stream_id = this->stream_ids[i];    switch (this->stream_types[stream_id]) {      case ASF_STREAM_TYPE_VIDEO:        if (((bandwitdh_left - this->bitrates[stream_id]) < min_bw_left) &&            (bandwitdh_left >= this->bitrates[stream_id])) {          video_stream = stream_id;          min_bw_left = bandwitdh_left - this->bitrates[stream_id];        }        break;      default:        break;    }  }    /* choose the lower bitrate of */  if (!video_stream && this->has_video) {    for (i = 0; i < this->num_stream_ids; i++) {      stream_id = this->stream_ids[i];      switch (this->stream_types[stream_id]) {        case ASF_STREAM_TYPE_VIDEO:          if ((this->bitrates[stream_id] < min_vrate) ||              (!min_vrate)) {            video_stream = stream_id;            min_vrate = this->bitrates[stream_id];          }          break;        default:          break;      }    }  }      lprintf("selected streams: audio %d, video %d\n", audio_stream, video_stream);  lprintf("disabling other streams\n");  memset (this->scmd_body, 0, 40);  for (i = 1; i < this->num_stream_ids; i++) {    this->scmd_body [ (i - 1) * 6 + 2 ] = 0xFF;    this->scmd_body [ (i - 1) * 6 + 3 ] = 0xFF;    this->scmd_body [ (i - 1) * 6 + 4 ] = this->stream_ids[i] ;    this->scmd_body [ (i - 1) * 6 + 5 ] = this->stream_ids[i] >> 8;    if ((this->stream_ids[i] == audio_stream) ||        (this->stream_ids[i] == video_stream)) {      this->scmd_body [ (i - 1) * 6 + 6 ] = 0x00;      this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00;    } else {      lprintf("disabling stream %d\n", this->stream_ids[i]);      this->scmd_body [ (i - 1) * 6 + 6 ] = 0x02;      this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00;            /* forces the asf demuxer to not choose this stream */      if (this->bitrates_pos[this->stream_ids[i]]) {        this->asf_header[this->bitrates_pos[this->stream_ids[i]]]     = 0;        this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 1] = 0;        this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 2] = 0;        this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 3] = 0;      }    }  }  if (!send_command (io, this, 0x33, this->num_stream_ids,                      0xFFFF | this->stream_ids[0] << 16,                      this->num_stream_ids * 6 + 2)) {  /* FIXME: de-xine-ification */    lprintf ( "***LOG:*** -- "	     "libmms: mms_choose_best_streams failed\n");    return 0;  }  if ((res = get_answer (io, this)) != 0x21) {    /* FIXME: de-xine-ification */    lprintf ( "***LOG:*** -- "	     "libmms: unexpected response: %02x (0x21)\n", res);  }  return 1;}/* * TODO: error messages *       network timing request *//* FIXME: got somewhat broken during xine_stream_t->(void*) conversion */mms_t *mms_connect (mms_io_t *io, void *data, const char *url, int bandwidth) {#ifdef USE_ICONV  iconv_t url_conv;#else  int     url_conv = 0;#endif  mms_t  *this;  int     res;

⌨️ 快捷键说明

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