00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "mms.h"
00024 #include "asf.h"
00025 #include "libavutil/intreadwrite.h"
00026
00027 #define MMS_MAX_STREAMS 256
00029 int ff_mms_read_header(MMSContext *mms, uint8_t *buf, const int size)
00030 {
00031 char *pos;
00032 int size_to_copy;
00033 int remaining_size = mms->asf_header_size - mms->asf_header_read_size;
00034 size_to_copy = FFMIN(size, remaining_size);
00035 pos = mms->asf_header + mms->asf_header_read_size;
00036 memcpy(buf, pos, size_to_copy);
00037 if (mms->asf_header_read_size == mms->asf_header_size) {
00038 av_freep(&mms->asf_header);
00039 }
00040 mms->asf_header_read_size += size_to_copy;
00041 return size_to_copy;
00042 }
00043
00044 int ff_mms_read_data(MMSContext *mms, uint8_t *buf, const int size)
00045 {
00046 int read_size;
00047 read_size = FFMIN(size, mms->remaining_in_len);
00048 memcpy(buf, mms->read_in_ptr, read_size);
00049 mms->remaining_in_len -= read_size;
00050 mms->read_in_ptr += read_size;
00051 return read_size;
00052 }
00053
00054 int ff_mms_asf_header_parser(MMSContext *mms)
00055 {
00056 uint8_t *p = mms->asf_header;
00057 uint8_t *end;
00058 int flags, stream_id;
00059 mms->stream_num = 0;
00060
00061 if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 ||
00062 memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
00063 av_log(NULL, AV_LOG_ERROR,
00064 "Corrupt stream (invalid ASF header, size=%d)\n",
00065 mms->asf_header_size);
00066 return AVERROR_INVALIDDATA;
00067 }
00068
00069 end = mms->asf_header + mms->asf_header_size;
00070
00071 p += sizeof(ff_asf_guid) + 14;
00072 while(end - p >= sizeof(ff_asf_guid) + 8) {
00073 uint64_t chunksize;
00074 if (!memcmp(p, ff_asf_data_header, sizeof(ff_asf_guid))) {
00075 chunksize = 50;
00076 } else {
00077 chunksize = AV_RL64(p + sizeof(ff_asf_guid));
00078 }
00079 if (!chunksize || chunksize > end - p) {
00080 av_log(NULL, AV_LOG_ERROR,
00081 "Corrupt stream (header chunksize %"PRId64" is invalid)\n",
00082 chunksize);
00083 return AVERROR_INVALIDDATA;
00084 }
00085 if (!memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
00086
00087 if (end - p > sizeof(ff_asf_guid) * 2 + 68) {
00088 mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64);
00089 if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms->in_buffer)) {
00090 av_log(NULL, AV_LOG_ERROR,
00091 "Corrupt stream (too large pkt_len %d)\n",
00092 mms->asf_packet_len);
00093 return AVERROR_INVALIDDATA;
00094 }
00095 }
00096 } else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) {
00097 flags = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
00098 stream_id = flags & 0x7F;
00099
00100
00101
00102 if (mms->stream_num < MMS_MAX_STREAMS &&
00103 46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
00104 mms->streams = av_fast_realloc(mms->streams,
00105 &mms->nb_streams_allocated,
00106 (mms->stream_num + 1) * sizeof(MMSStream));
00107 mms->streams[mms->stream_num].id = stream_id;
00108 mms->stream_num++;
00109 } else {
00110 av_log(NULL, AV_LOG_ERROR,
00111 "Corrupt stream (too many A/V streams)\n");
00112 return AVERROR_INVALIDDATA;
00113 }
00114 } else if (!memcmp(p, ff_asf_ext_stream_header, sizeof(ff_asf_guid))) {
00115 if (end - p >= 88) {
00116 int stream_count = AV_RL16(p + 84), ext_len_count = AV_RL16(p + 86);
00117 uint64_t skip_bytes = 88;
00118 while (stream_count--) {
00119 if (end - p < skip_bytes + 4) {
00120 av_log(NULL, AV_LOG_ERROR,
00121 "Corrupt stream (next stream name length is not in the buffer)\n");
00122 return AVERROR_INVALIDDATA;
00123 }
00124 skip_bytes += 4 + AV_RL16(p + skip_bytes + 2);
00125 }
00126 while (ext_len_count--) {
00127 if (end - p < skip_bytes + 22) {
00128 av_log(NULL, AV_LOG_ERROR,
00129 "Corrupt stream (next extension system info length is not in the buffer)\n");
00130 return AVERROR_INVALIDDATA;
00131 }
00132 skip_bytes += 22 + AV_RL32(p + skip_bytes + 18);
00133 }
00134 if (end - p < skip_bytes) {
00135 av_log(NULL, AV_LOG_ERROR,
00136 "Corrupt stream (the last extension system info length is invalid)\n");
00137 return AVERROR_INVALIDDATA;
00138 }
00139 if (chunksize - skip_bytes > 24)
00140 chunksize = skip_bytes;
00141 }
00142 } else if (!memcmp(p, ff_asf_head1_guid, sizeof(ff_asf_guid))) {
00143 chunksize = 46;
00144 }
00145 p += chunksize;
00146 }
00147
00148 return 0;
00149 }