Пример #1
0
static int qcp_probe(AVProbeData *pd)
{
    if (AV_RL32(pd->buf  ) == AV_RL32("RIFF") &&
        AV_RL64(pd->buf+8) == AV_RL64("QLCMfmt "))
        return AVPROBE_SCORE_MAX;
    return 0;
}
Пример #2
0
static int asf_header_parser(MMSContext *mms)
{
    uint8_t *p = mms->asf_header;
    uint8_t *end;
    int flags, stream_id, real_header_size;
    mms->stream_num = 0;

    if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 ||
        memcmp(p, ff_asf_header, sizeof(ff_asf_guid)))
        return -1;

    real_header_size = AV_RL64(p + sizeof(ff_asf_guid));
    end = mms->asf_header + real_header_size;

    p += sizeof(ff_asf_guid) + 14;
    while(end - p >= sizeof(ff_asf_guid) + 8) {
        uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
        if (!chunksize || chunksize > end - p) {
            dprintf(NULL, "chunksize is exceptional value:%d!\n", chunksize);
            return -1;
        }
        if (!memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
            /* read packet size */
            if (end - p > sizeof(ff_asf_guid) * 2 + 68) {
                mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64);
                if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms->in_buffer)) {
                    dprintf(NULL,"Too large packet len:%d"
                        " may overwrite in_buffer when padding", mms->asf_packet_len);
                    return -1;
                }
            }
        } else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) {
            flags     = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
            stream_id = flags & 0x7F;
            //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
            //we can calcuate the packet size by stream_num.
            //Please see function send_stream_selection_request().
            if (mms->stream_num < MAX_STREAMS &&
                    46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
                mms->streams[mms->stream_num].id = stream_id;
                mms->stream_num++;
            } else {
                dprintf(NULL, "Too many streams.\n");
                return -1;
            }
        }
        p += chunksize;
    }

    return 0;
}
Пример #3
0
/**
 * From MSDN 2.2.1.4, we learn that ASF data packets over RTP should not
 * contain any padding. Unfortunately, the header min/max_pktsize are not
 * updated (thus making min_pktsize invalid). Here, we "fix" these faulty
 * min_pktsize values in the ASF file header.
 * @return 0 on success, <0 on failure (currently -1).
 */
static int rtp_asf_fix_header(uint8_t *buf, int len)
{
    uint8_t *p = buf, *end = buf + len;

    if (len < sizeof(ff_asf_guid) * 2 + 22 ||
        memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
        return -1;
    }
    p += sizeof(ff_asf_guid) + 14;
    do {
        uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
        if (memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
            if (chunksize > end - p)
                return -1;
            p += chunksize;
            continue;
        }

        /* skip most of the file header, to min_pktsize */
        p += 6 * 8 + 3 * 4 + sizeof(ff_asf_guid) * 2;
        if (p + 8 <= end && AV_RL32(p) == AV_RL32(p + 4)) {
            /* and set that to zero */
            AV_WL32(p, 0);
            return 0;
        }
        break;
    } while (end - p >= sizeof(ff_asf_guid) + 8);

    return -1;
}
Пример #4
0
static int asf_header_parser(MMSContext *mms)
{
    uint8_t *p = mms->asf_header;
    uint8_t *end;
    int flags, stream_id;
    mms->stream_num = 0;

    if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 ||
        memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
        av_log(NULL, AV_LOG_ERROR,
               "Corrupt stream (invalid ASF header, size=%d)\n",
               mms->asf_header_size);
        return AVERROR_INVALIDDATA;
    }

    end = mms->asf_header + mms->asf_header_size;

    p += sizeof(ff_asf_guid) + 14;
    while(end - p >= sizeof(ff_asf_guid) + 8) {
        uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
        if (!chunksize || chunksize > end - p) {
            av_log(NULL, AV_LOG_ERROR,
                   "Corrupt stream (header chunksize %"PRId64" is invalid)\n",
                   chunksize);
            return AVERROR_INVALIDDATA;
        }
        if (!memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
            /* read packet size */
            if (end - p > sizeof(ff_asf_guid) * 2 + 68) {
                mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64);
                if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms->in_buffer)) {
                    av_log(NULL, AV_LOG_ERROR,
                           "Corrupt stream (too large pkt_len %d)\n",
                           mms->asf_packet_len);
                    return AVERROR_INVALIDDATA;
                }
            }
        } else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) {
            flags     = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
            stream_id = flags & 0x7F;
            //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
            //we can calcuate the packet size by stream_num.
            //Please see function send_stream_selection_request().
            if (mms->stream_num < MAX_STREAMS &&
                    46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
                mms->streams[mms->stream_num].id = stream_id;
                mms->stream_num++;
            } else {
                av_log(NULL, AV_LOG_ERROR,
                       "Corrupt stream (too many A/V streams)\n");
                return AVERROR_INVALIDDATA;
            }
        } else if (!memcmp(p, ff_asf_head1_guid, sizeof(ff_asf_guid))) {
            chunksize = 46; // see references [2] section 3.4. This should be set 46.
        }
        p += chunksize;
    }

    return 0;
}
Пример #5
0
static uint64_t inline get_k2(const uint8_t *src)
{
    uint64_t k = AV_RL64(src + 8);
    k *= c2;
    k = ROT(k, 33);
    k *= c1;
    return k;
}
Пример #6
0
static uint64_t inline get_k1(const uint8_t *src)
{
    uint64_t k = AV_RL64(src);
    k *= c1;
    k = ROT(k, 31);
    k *= c2;
    return k;
}
Пример #7
0
/* param change side data*/
static void dump_paramchange(void *ctx, AVPacketSideData *sd)
{
    int size = sd->size;
    const uint8_t *data = sd->data;
    uint32_t flags, channels, sample_rate, width, height;
    uint64_t layout;

    if (!data || sd->size < 4)
        goto fail;

    flags = AV_RL32(data);
    data += 4;
    size -= 4;

    if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
        if (size < 4)
            goto fail;
        channels = AV_RL32(data);
        data += 4;
        size -= 4;
        av_log(ctx, AV_LOG_INFO, "channel count %d, ", channels);
    }
    if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
        if (size < 8)
            goto fail;
        layout = AV_RL64(data);
        data += 8;
        size -= 8;
        av_log(ctx, AV_LOG_INFO,
               "channel layout: %s, ", av_get_channel_name(layout));
    }
    if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
        if (size < 4)
            goto fail;
        sample_rate = AV_RL32(data);
        data += 4;
        size -= 4;
        av_log(ctx, AV_LOG_INFO, "sample_rate %d, ", sample_rate);
    }
    if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
        if (size < 8)
            goto fail;
        width = AV_RL32(data);
        data += 4;
        size -= 4;
        height = AV_RL32(data);
        data += 4;
        size -= 4;
        av_log(ctx, AV_LOG_INFO, "width %d height %d", width, height);
    }

    return;
fail:
    av_log(ctx, AV_LOG_INFO, "unknown param");
}
Пример #8
0
static double get_f64l(uint8_t *p)
{
    return av_int2double(AV_RL64(p));
}
Пример #9
0
static int nist_probe(AVProbeData *p)
{
    if (AV_RL64(p->buf) == AV_RL64("NIST_1A\x0a"))
        return AVPROBE_SCORE_MAX;
    return 0;
}
Пример #10
0
Файл: mxg.c Проект: Arcen/FFmpeg
static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    int ret;
    unsigned int size;
    uint8_t *startmarker_ptr, *end, *search_end, marker;
    MXGContext *mxg = s->priv_data;

    while (!url_feof(s->pb) && !s->pb->error){
        if (mxg->cache_size <= OVERREAD_SIZE) {
            /* update internal buffer */
            ret = mxg_update_cache(s, DEFAULT_PACKET_SIZE + OVERREAD_SIZE);
            if (ret < 0)
                return ret;
        }
        end = mxg->buffer_ptr + mxg->cache_size;

        /* find start marker - 0xff */
        if (mxg->cache_size > OVERREAD_SIZE) {
            search_end = end - OVERREAD_SIZE;
            startmarker_ptr = mxg_find_startmarker(mxg->buffer_ptr, search_end);
        } else {
            search_end = end;
            startmarker_ptr = mxg_find_startmarker(mxg->buffer_ptr, search_end);
            if (startmarker_ptr >= search_end - 1 ||
                *(startmarker_ptr + 1) != EOI) break;
        }

        if (startmarker_ptr != search_end) { /* start marker found */
            marker = *(startmarker_ptr + 1);
            mxg->buffer_ptr = startmarker_ptr + 2;
            mxg->cache_size = end - mxg->buffer_ptr;

            if (marker == SOI) {
                mxg->soi_ptr = startmarker_ptr;
            } else if (marker == EOI) {
                if (!mxg->soi_ptr) {
                    av_log(s, AV_LOG_WARNING, "Found EOI before SOI, skipping\n");
                    continue;
                }

                pkt->pts = pkt->dts = mxg->dts;
                pkt->stream_index = 0;
                pkt->destruct = NULL;
                pkt->size = mxg->buffer_ptr - mxg->soi_ptr;
                pkt->data = mxg->soi_ptr;

                if (mxg->soi_ptr - mxg->buffer > mxg->cache_size) {
                    if (mxg->cache_size > 0) {
                        memcpy(mxg->buffer, mxg->buffer_ptr, mxg->cache_size);
                    }

                    mxg->buffer_ptr = mxg->buffer;
                }
                mxg->soi_ptr = 0;

                return pkt->size;
            } else if ( (SOF0 <= marker && marker <= SOF15) ||
                        (SOS  <= marker && marker <= COM) ) {
                /* all other markers that start marker segment also contain
                   length value (see specification for JPEG Annex B.1) */
                size = AV_RB16(mxg->buffer_ptr);
                if (size < 2)
                    return AVERROR(EINVAL);

                if (mxg->cache_size < size) {
                    ret = mxg_update_cache(s, size);
                    if (ret < 0)
                        return ret;
                    startmarker_ptr = mxg->buffer_ptr - 2;
                    mxg->cache_size = 0;
                } else {
                    mxg->cache_size -= size;
                }

                mxg->buffer_ptr += size;

                if (marker == APP13 && size >= 16) { /* audio data */
                    /* time (GMT) of first sample in usec since 1970, little-endian */
                    pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8);
                    pkt->stream_index = 1;
                    pkt->destruct = NULL;
                    pkt->size = size - 14;
                    pkt->data = startmarker_ptr + 16;

                    if (startmarker_ptr - mxg->buffer > mxg->cache_size) {
                        if (mxg->cache_size > 0) {
                            memcpy(mxg->buffer, mxg->buffer_ptr, mxg->cache_size);
                        }
                        mxg->buffer_ptr = mxg->buffer;
                    }

                    return pkt->size;
                } else if (marker == COM && size >= 18 &&
                           !strncmp(startmarker_ptr + 4, "MXF", 3)) {
                    /* time (GMT) of video frame in usec since 1970, little-endian */
                    mxg->dts = AV_RL64(startmarker_ptr + 12);
                }
            }
        } else {
            /* start marker not found */
            mxg->buffer_ptr = search_end;
            mxg->cache_size = OVERREAD_SIZE;
        }
    }

    return AVERROR_EOF;
}
Пример #11
0
int ff_mms_asf_header_parser(MMSContext *mms)
{
    uint8_t *p = mms->asf_header;
    uint8_t *end;
    int flags, stream_id;
    mms->stream_num = 0;

    if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 ||
        memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
        av_log(NULL, AV_LOG_ERROR,
               "Corrupt stream (invalid ASF header, size=%d)\n",
               mms->asf_header_size);
        return AVERROR_INVALIDDATA;
    }

    end = mms->asf_header + mms->asf_header_size;

    p += sizeof(ff_asf_guid) + 14;
    while(end - p >= sizeof(ff_asf_guid) + 8) {
        uint64_t chunksize;
        if (!memcmp(p, ff_asf_data_header, sizeof(ff_asf_guid))) {
            chunksize = 50; // see Reference [2] section 5.1
        } else {
            chunksize = AV_RL64(p + sizeof(ff_asf_guid));
        }
        if (!chunksize || chunksize > end - p) {
            av_log(NULL, AV_LOG_ERROR,
                   "Corrupt stream (header chunksize %"PRId64" is invalid)\n",
                   chunksize);
            return AVERROR_INVALIDDATA;
        }
        if (!memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
            /* read packet size */
            if (end - p > sizeof(ff_asf_guid) * 2 + 68) {
                mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64);
		   mms->file_size = AV_RL64(p + sizeof(ff_asf_guid) * 2 + 8);
		   mms->flags =AV_RL32(p+sizeof(ff_asf_guid)*2+56);
                if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms->in_buffer)) {
                    av_log(NULL, AV_LOG_ERROR,
                           "Corrupt stream (too large pkt_len %d)\n",
                           mms->asf_packet_len);
                    return AVERROR_INVALIDDATA;
                }
            }
        } else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) {
            flags     = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
            stream_id = flags & 0x7F;
            //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
            //we can calcuate the packet size by stream_num.
            //Please see function send_stream_selection_request().
            if (mms->stream_num < MMS_MAX_STREAMS &&
                    46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
                mms->streams = av_fast_realloc(mms->streams,
                                   &mms->nb_streams_allocated,
                                   (mms->stream_num + 1) * sizeof(MMSStream));
                mms->streams[mms->stream_num].id = stream_id;
                mms->stream_num++;
            } else {
                av_log(NULL, AV_LOG_ERROR,
                       "Corrupt stream (too many A/V streams)\n");
                return AVERROR_INVALIDDATA;
            }
        } else if (!memcmp(p, ff_asf_ext_stream_header, sizeof(ff_asf_guid))) {
            if (end - p >= 88) {
                int stream_count = AV_RL16(p + 84), ext_len_count = AV_RL16(p + 86);
                uint64_t skip_bytes = 88;
                while (stream_count--) {
                    if (end - p < skip_bytes + 4) {
                        av_log(NULL, AV_LOG_ERROR,
                               "Corrupt stream (next stream name length is not in the buffer)\n");
                        return AVERROR_INVALIDDATA;
                    }
                    skip_bytes += 4 + AV_RL16(p + skip_bytes + 2);
                }
                while (ext_len_count--) {
                    if (end - p < skip_bytes + 22) {
                        av_log(NULL, AV_LOG_ERROR,
                               "Corrupt stream (next extension system info length is not in the buffer)\n");
                        return AVERROR_INVALIDDATA;
                    }
                    skip_bytes += 22 + AV_RL32(p + skip_bytes + 18);
                }
                if (end - p < skip_bytes) {
                    av_log(NULL, AV_LOG_ERROR,
                           "Corrupt stream (the last extension system info length is invalid)\n");
                    return AVERROR_INVALIDDATA;
                }
                if (chunksize - skip_bytes > 24)
                    chunksize = skip_bytes;
            }
        } else if (!memcmp(p, ff_asf_head1_guid, sizeof(ff_asf_guid))) {
            chunksize = 46; // see references [2] section 3.4. This should be set 46.
        }
        p += chunksize;
    }

    return 0;
}
Пример #12
0
static int skeleton_header(AVFormatContext *s, int idx)
{
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
    AVStream *st = s->streams[idx];
    uint8_t *buf = os->buf + os->pstart;
    int version_major, version_minor;
    int64_t start_num, start_den;
    uint64_t start_granule;
    int target_idx, start_time;

    strcpy(st->codec->codec_name, "skeleton");
    st->codec->codec_type = AVMEDIA_TYPE_DATA;

    if (os->psize < 8)
        return -1;

    if (!strncmp(buf, "fishead", 8)) {
        if (os->psize < 64)
            return -1;

        version_major = AV_RL16(buf+8);
        version_minor = AV_RL16(buf+10);

        if (version_major != 3) {
            av_log(s, AV_LOG_WARNING, "Unknown skeleton version %d.%d\n",
                   version_major, version_minor);
            return -1;
        }

        // This is the overall start time. We use it for the start time of
        // of the skeleton stream since if left unset lavf assumes 0,
        // which we don't want since skeleton is timeless
        // FIXME: the real meaning of this field is "start playback at
        // this time which can be in the middle of a packet
        start_num = AV_RL64(buf+12);
        start_den = AV_RL64(buf+20);

        if (start_den) {
            int base_den;
            av_reduce(&start_time, &base_den, start_num, start_den, INT_MAX);
            avpriv_set_pts_info(st, 64, 1, base_den);
            os->lastpts =
            st->start_time = start_time;
        }
    } else if (!strncmp(buf, "fisbone", 8)) {
        if (os->psize < 52)
            return -1;

        target_idx = ogg_find_stream(ogg, AV_RL32(buf+12));
        start_granule = AV_RL64(buf+36);
        if (os->start_granule != OGG_NOGRANULE_VALUE) {
            av_log_missing_feature(s,
                                   "multiple fisbone for the same stream", 0);
            return 1;
        }
        if (target_idx >= 0 && start_granule != OGG_NOGRANULE_VALUE) {
            os->start_granule = start_granule;
        }
    }

    return 1;
}
Пример #13
0
static int get_ext_stream_properties(char *buf, int buf_len, int stream_num, struct asf_priv* asf, int is_video)
{
  int pos=0;
  uint8_t *buffer = &buf[0];
  uint64_t avg_ft;
  unsigned bitrate;

  while ((pos = find_asf_guid(buf, asf_ext_stream_header, pos, buf_len)) >= 0) {
    int this_stream_num, stnamect, payct, i;
    int buf_max_index=pos+50;
    if (buf_max_index > buf_len) return 0;
    buffer = &buf[pos];

    // the following info is available
    // some of it may be useful but we're skipping it for now
    // starttime(8 bytes), endtime(8),
    // leak-datarate(4), bucket-datasize(4), init-bucket-fullness(4),
    // alt-leak-datarate(4), alt-bucket-datasize(4), alt-init-bucket-fullness(4),
    // max-object-size(4),
    // flags(4) (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)

    buffer += 8+8;
    bitrate = AV_RL32(buffer);
    buffer += 8*4;
    this_stream_num=AV_RL16(buffer);buffer+=2;

    if (this_stream_num == stream_num) {
      buf_max_index+=14;
      if (buf_max_index > buf_len) return 0;
      buffer+=2; //skip stream-language-id-index
      avg_ft = AV_RL64(buffer); // provided in 100ns units
      buffer+=8;
      asf->bps = bitrate / 8;

      // after this are values for stream-name-count and
      // payload-extension-system-count
      // followed by associated info for each
      stnamect = AV_RL16(buffer);buffer+=2;
      payct = AV_RL16(buffer);buffer+=2;

      // need to read stream names if present in order
      // to get lengths - values are ignored for now
      for (i=0; i<stnamect; i++) {
        int stream_name_len;
        buf_max_index+=4;
        if (buf_max_index > buf_len) return 0;
        buffer+=2; //language_id_index
        stream_name_len = AV_RL16(buffer);buffer+=2;
        buffer+=stream_name_len; //stream_name
        buf_max_index+=stream_name_len;
        if (buf_max_index > buf_len) return 0;
      }

      if (is_video) {
        asf->vid_repdata_count = payct;
        asf->vid_repdata_sizes = malloc(payct*sizeof(int));
      } else {
        asf->aud_repdata_count = payct;
        asf->aud_repdata_sizes = malloc(payct*sizeof(int));
      }

      for (i=0; i<payct; i++) {
        int payload_len;
        buf_max_index+=22;
        if (buf_max_index > buf_len) return 0;
        // Each payload extension definition starts with a GUID.
        // In dvr-ms files one of these indicates the presence an
        // extension that contains pts values and this is always present
        // in the video and audio streams.
        // Another GUID indicates the presence of an extension
        // that contains useful video frame demuxing information.
        // Note that the extension data in each packet does not contain
        // these GUIDs and that this header section defines the order the data
        // will appear in.
        if (memcmp(buffer, asf_dvr_ms_timing_rep_data, 16) == 0) {
          if (is_video)
            asf->vid_ext_timing_index = i;
          else
            asf->aud_ext_timing_index = i;
        } else if (is_video && memcmp(buffer, asf_dvr_ms_vid_frame_rep_data, 16) == 0)
          asf->vid_ext_frame_index = i;
        buffer+=16;

        payload_len = AV_RL16(buffer);buffer+=2;

        if (is_video)
          asf->vid_repdata_sizes[i] = payload_len;
        else
          asf->aud_repdata_sizes[i] = payload_len;
        buffer+=4;//sys_len
      }

      return 1;
    }
  }
  return 1;
}
Пример #14
0
static int dsf_probe(AVProbeData *p)
{
    if (p->buf_size < 12 || memcmp(p->buf, "DSD ", 4) || AV_RL64(p->buf + 4) != 28)
        return 0;
    return AVPROBE_SCORE_MAX;
}
Пример #15
0
static int asf_streaming_parse_header(int fd, streaming_ctrl_t* streaming_ctrl) {
  ASF_stream_chunck_t chunk;
  asf_http_streaming_ctrl_t* asf_ctrl = 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 {
	  if (asf_read_wrapper(fd, &chunk, sizeof(ASF_stream_chunck_t), streaming_ctrl) <= 0)
	    return -1;
	  // 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 = 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;

	  if (asf_read_wrapper(fd, buffer, size, streaming_ctrl) <= 0)
	    return -1;

	  if( chunk_size2read==0 ) {
		ASF_header_t *asfh = (ASF_header_t *)buffer;
		if(size < (int)sizeof(ASF_header_t)) {
		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunk2Small);
		    return -1;
		} else mp_msg(MSGT_NETWORK,MSGL_DBG2,"Got chunk\n");
		chunk_size2read = AV_RL64(&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;

  start = sizeof(ASF_header_t);

  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;
/*
      if(fileh.packetsize != fileh.packetsize2) {
	printf("Error packetsize check don't match\n");
	return -1;
      }
*/
      asf_ctrl->packet_size = AV_RL32(&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;
      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 = realloc(asf_ctrl->audio_streams,
						     asf_ctrl->n_audio*sizeof(int));
	}
	asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = AV_RL16(&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 = realloc(asf_ctrl->video_streams,
						     asf_ctrl->n_video*sizeof(int));
	}
	asf_ctrl->video_streams[asf_ctrl->n_video-1] = AV_RL16(&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];
	char *end = &buffer[size];

	mp_msg(MSGT_NETWORK, MSGL_V, "Stream bitrate properties object\n");
		if (ptr + 2 > end) goto len_err_out;
		stream_count = AV_RL16(ptr);
		ptr += 2;
		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;
			if (ptr + 6 > end) goto len_err_out;
			id = AV_RL16(ptr);
			ptr += 2;
			rate = AV_RL32(ptr);
			ptr += 4;
			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);
  free(buffer);
  free(v_rates);
  free(a_rates);
  return -1;
}