2 * MMS protocol common definitions.
3 * Copyright (c) 2006,2007 Ryan Martell
4 * Copyright (c) 2007 Björn Axelsson
5 * Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com>
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libavutil/intreadwrite.h"
27 #define MMS_MAX_STREAMS 256 /**< arbitrary sanity check value */
29 int ff_mms_read_header(MMSContext
*mms
, uint8_t *buf
, const int size
)
33 int remaining_size
= mms
->asf_header_size
- mms
->asf_header_read_size
;
34 size_to_copy
= FFMIN(size
, remaining_size
);
35 pos
= mms
->asf_header
+ mms
->asf_header_read_size
;
36 memcpy(buf
, pos
, size_to_copy
);
37 if (mms
->asf_header_read_size
== mms
->asf_header_size
) {
38 av_freep(&mms
->asf_header
); // which contains asf header
40 mms
->asf_header_read_size
+= size_to_copy
;
44 int ff_mms_read_data(MMSContext
*mms
, uint8_t *buf
, const int size
)
47 read_size
= FFMIN(size
, mms
->remaining_in_len
);
48 memcpy(buf
, mms
->read_in_ptr
, read_size
);
49 mms
->remaining_in_len
-= read_size
;
50 mms
->read_in_ptr
+= read_size
;
54 int ff_mms_asf_header_parser(MMSContext
*mms
)
56 uint8_t *p
= mms
->asf_header
;
61 if (mms
->asf_header_size
< sizeof(ff_asf_guid
) * 2 + 22 ||
62 memcmp(p
, ff_asf_header
, sizeof(ff_asf_guid
))) {
63 av_log(NULL
, AV_LOG_ERROR
,
64 "Corrupt stream (invalid ASF header, size=%d)\n",
65 mms
->asf_header_size
);
66 return AVERROR_INVALIDDATA
;
69 end
= mms
->asf_header
+ mms
->asf_header_size
;
71 p
+= sizeof(ff_asf_guid
) + 14;
72 while(end
- p
>= sizeof(ff_asf_guid
) + 8) {
74 if (!memcmp(p
, ff_asf_data_header
, sizeof(ff_asf_guid
))) {
75 chunksize
= 50; // see Reference [2] section 5.1
77 chunksize
= AV_RL64(p
+ sizeof(ff_asf_guid
));
79 if (!chunksize
|| chunksize
> end
- p
) {
80 av_log(NULL
, AV_LOG_ERROR
,
81 "Corrupt stream (header chunksize %"PRId64
" is invalid)\n",
83 return AVERROR_INVALIDDATA
;
85 if (!memcmp(p
, ff_asf_file_header
, sizeof(ff_asf_guid
))) {
86 /* read packet size */
87 if (end
- p
> sizeof(ff_asf_guid
) * 2 + 68) {
88 mms
->asf_packet_len
= AV_RL32(p
+ sizeof(ff_asf_guid
) * 2 + 64);
89 if (mms
->asf_packet_len
<= 0 || mms
->asf_packet_len
> sizeof(mms
->in_buffer
)) {
90 av_log(NULL
, AV_LOG_ERROR
,
91 "Corrupt stream (too large pkt_len %d)\n",
93 return AVERROR_INVALIDDATA
;
96 } else if (!memcmp(p
, ff_asf_stream_header
, sizeof(ff_asf_guid
))) {
97 flags
= AV_RL16(p
+ sizeof(ff_asf_guid
)*3 + 24);
98 stream_id
= flags
& 0x7F;
99 //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
100 //we can calcuate the packet size by stream_num.
101 //Please see function send_stream_selection_request().
102 if (mms
->stream_num
< MMS_MAX_STREAMS
&&
103 46 + mms
->stream_num
* 6 < sizeof(mms
->out_buffer
)) {
104 mms
->streams
= av_fast_realloc(mms
->streams
,
105 &mms
->nb_streams_allocated
,
106 (mms
->stream_num
+ 1) * sizeof(MMSStream
));
107 mms
->streams
[mms
->stream_num
].id
= stream_id
;
110 av_log(NULL
, AV_LOG_ERROR
,
111 "Corrupt stream (too many A/V streams)\n");
112 return AVERROR_INVALIDDATA
;
114 } else if (!memcmp(p
, ff_asf_ext_stream_header
, sizeof(ff_asf_guid
))) {
116 int stream_count
= AV_RL16(p
+ 84), ext_len_count
= AV_RL16(p
+ 86);
117 uint64_t skip_bytes
= 88;
118 while (stream_count
--) {
119 if (end
- p
< skip_bytes
+ 4) {
120 av_log(NULL
, AV_LOG_ERROR
,
121 "Corrupt stream (next stream name length is not in the buffer)\n");
122 return AVERROR_INVALIDDATA
;
124 skip_bytes
+= 4 + AV_RL16(p
+ skip_bytes
+ 2);
126 while (ext_len_count
--) {
127 if (end
- p
< skip_bytes
+ 22) {
128 av_log(NULL
, AV_LOG_ERROR
,
129 "Corrupt stream (next extension system info length is not in the buffer)\n");
130 return AVERROR_INVALIDDATA
;
132 skip_bytes
+= 22 + AV_RL32(p
+ skip_bytes
+ 18);
134 if (end
- p
< skip_bytes
) {
135 av_log(NULL
, AV_LOG_ERROR
,
136 "Corrupt stream (the last extension system info length is invalid)\n");
137 return AVERROR_INVALIDDATA
;
139 if (chunksize
- skip_bytes
> 24)
140 chunksize
= skip_bytes
;
142 } else if (!memcmp(p
, ff_asf_head1_guid
, sizeof(ff_asf_guid
))) {
143 chunksize
= 46; // see references [2] section 3.4. This should be set 46.