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

📄 mmsh.c

📁 libmms开发库源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
              lprintf("seekable stream\n");              this->stream_type = MMSH_SEEKABLE;            } else {              if (strstr(features, "broadcast")) {                lprintf("live stream\n");                this->stream_type = MMSH_LIVE;              }            }          }        }      }            if (len == -1) {        done = 1;      } else {        len = 0;      }    } else {      len ++;    }  }  if (this->stream_type == MMSH_UNKNOWN) {    lprintf ("mmsh: unknown stream type\n");    this->stream_type = MMSH_SEEKABLE; /* FIXME ? */  }  return 1;}static int get_chunk_header (mms_io_t *io, mmsh_t *this) {  uint8_t chunk_header[CHUNK_HEADER_LENGTH];  uint8_t ext_header[EXT_HEADER_LENGTH];  int read_len;  int ext_header_len;  lprintf ("get_chunk_header\n");  /* read chunk header */  read_len = io_read(io, this->s, chunk_header, CHUNK_HEADER_LENGTH);  if (read_len != CHUNK_HEADER_LENGTH) {    lprintf ("chunk header read failed, %d != %d\n", len, CHUNK_HEADER_LENGTH);    return 0;  }  this->chunk_type       = LE_16 (&chunk_header[0]);  this->chunk_length     = LE_16 (&chunk_header[2]);  switch (this->chunk_type) {    case CHUNK_TYPE_DATA:      ext_header_len = 8;      break;    case CHUNK_TYPE_END:      ext_header_len = 4;      break;    case CHUNK_TYPE_ASF_HEADER:      ext_header_len = 8;      break;    case CHUNK_TYPE_RESET:      ext_header_len = 4;      break;    default:      ext_header_len = 0;  }  /* read extended header */  if (ext_header_len > 0) {    read_len = io_read (io, this->s, ext_header, ext_header_len);    if (read_len != ext_header_len) {      lprintf ("extended header read failed. %d != %d\n", read_len, ext_header_len);      return 0;    }  }  /* display debug infos */#ifdef DEBUG  switch (this->chunk_type) {    case CHUNK_TYPE_DATA:      this->chunk_seq_number = LE_32 (&ext_header[0]);      lprintf ("chunk type:       CHUNK_TYPE_DATA\n");      lprintf ("chunk length:     %d\n", this->chunk_length);      lprintf ("chunk seq:        %d\n", this->chunk_seq_number);      lprintf ("unknown:          %d\n", ext_header[4]);      lprintf ("mmsh seq:         %d\n", ext_header[5]);      lprintf ("len2:             %d\n", LE_16(&ext_header[6]));      break;    case CHUNK_TYPE_END:      this->chunk_seq_number = LE_32 (&ext_header[0]);      lprintf ("chunk type:       CHUNK_TYPE_END\n");      lprintf ("continue: %d\n", this->chunk_seq_number);      break;    case CHUNK_TYPE_ASF_HEADER:      lprintf ("chunk type:       CHUNK_TYPE_ASF_HEADER\n");      lprintf ("chunk length:     %d\n", this->chunk_length);      lprintf ("unknown:          %2X %2X %2X %2X %2X %2X\n",	       ext_header[0], ext_header[1], ext_header[2], ext_header[3],	       ext_header[4], ext_header[5]);      lprintf ("len2:             %d\n", LE_16(&ext_header[6]));      break;    case CHUNK_TYPE_RESET:      lprintf ("chunk type:       CHUNK_TYPE_RESET\n");      lprintf ("chunk seq:        %d\n", this->chunk_seq_number);      lprintf ("unknown:          %2X %2X %2X %2X\n",	       ext_header[0], ext_header[1], ext_header[2], ext_header[3]);      break;    default:      lprintf ("unknown chunk:    %4X\n", this->chunk_type);  }#endif  this->chunk_length -= ext_header_len;  return 1;}static int get_header (mms_io_t *io, mmsh_t *this) {  int len = 0;  lprintf("get_header\n");  this->asf_header_len = 0;  this->asf_header_read = 0;  /* read chunk */  while (1) {    if (get_chunk_header(io, this)) {      if (this->chunk_type == CHUNK_TYPE_ASF_HEADER) {        if ((this->asf_header_len + this->chunk_length) > ASF_HEADER_SIZE) {	  lprintf ("mmsh: the asf header exceed %d bytes\n", ASF_HEADER_SIZE);          return 0;        } else {	  len = io_read(io, this->s, this->asf_header + this->asf_header_len,			this->chunk_length);          this->asf_header_len += len;          if (len != this->chunk_length) {            return 0;          }        }      } else {        break;      }    } else {      lprintf("get_chunk_header failed\n");      return 0;    }  }  if (this->chunk_type == CHUNK_TYPE_DATA) {    /* read the first data chunk */    len = io_read (io, this->s, this->buf, this->chunk_length);    if (len != this->chunk_length) {      return 0;    } else {      return 1;    }  } else {    /* unexpected packet type */    return 0;  }}static void interp_header (mms_io_t *io, mmsh_t *this) {  int i;  lprintf ("interp_header, header_len=%d\n", this->asf_header_len);  this->packet_length = 0;  /*   * parse asf header   */  i = 30;  while ((i + 24) < 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;    if ((i + length) >= this->asf_header_len) return;    switch (guid) {      case GUID_ASF_FILE_PROPERTIES:        this->packet_length = LE_32(this->asf_header + i + 92 - 24);        if (this->packet_length > CHUNK_SIZE) {          this->packet_length = 0;          break;        }        this->file_length   = LE_64(this->asf_header + i + 40 - 24);        lprintf ("file object, packet length = %d (%d)\n",		 this->packet_length, 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);          this->stream_types[stream_id] = type;          this->stream_ids[this->num_stream_ids] = stream_id;          this->num_stream_ids++;        }        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 ("mmsh: 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 mmsh_proto_s[] = { "mms", "mmsh", NULL };static int mmsh_valid_proto (char *proto) {  int i = 0;  lprintf("mmsh_valid_proto\n");  if (!proto)    return 0;  while(mmsh_proto_s[i]) {    if (!strcasecmp(proto, mmsh_proto_s[i])) {      return 1;    }    i++;  }  return 0;}/* * returns 1 on error */static int mmsh_tcp_connect(mms_io_t *io, mmsh_t *this) {  int progress, res;    if (!this->connect_port) this->connect_port = MMSH_PORT;    /*    * try to connect    */  lprintf("try to connect to %s on port %d \n", this->connect_host, this->connect_port);  this->s = io_connect (io, this->connect_host, this->connect_port);  if (this->s == -1) {    lprintf ("mmsh: failed to connect '%s'\n", this->connect_host);    return 1;  }  /* connection timeout 15s */  progress = 0;  do {//    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 int mmsh_connect_int (mms_io_t *io, mmsh_t *this, int bandwidth) {  int    i;  int    video_stream = -1;  int    audio_stream = -1;  int    max_arate    = -1;  int    min_vrate    = -1;  int    min_bw_left  = 0;  int    stream_id;  int    bandwitdh_left;  char   stream_selection[10 * ASF_MAX_NUM_STREAMS]; /* 10 chars per stream */  int    offset;  /*   * let the negotiations begin...   */  this->num_stream_ids = 0;  /* first request */  lprintf("first http request\n");    snprintf (this->str, SCRATCH_SIZE, mmsh_FirstRequest, this->uri,            this->http_host, this->http_port, 1);  if (!send_command (io, this, this->str))    goto fail;  if (!get_answer (io, this))    goto fail;      get_header(io, this);  interp_header(io, this);    close(this->s);//  report_progress (stream, 20);    /* choose the best quality for the audio stream */  /* i've never seen more than one audio stream */  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 ((audio_stream == -1) || (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 = bandwidth - max_arate;  if (bandwitdh_left < 0) {    bandwitdh_left = 0;  }  lprintf("bandwitdh %d, left %d\n", 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 stream with the lower bitrate */  if ((video_stream == -1) && 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 ((video_stream == -1) ||               (this->bitrates[stream_id] < min_vrate) ||              (!min_vrate)) {            video_stream = stream_id;            min_vrate = this->bitrates[stream_id];          }          break;        default:          break;      }    }  }  lprintf("audio stream %d, video stream %d\n", audio_stream, video_stream);    /* second request */

⌨️ 快捷键说明

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