Libav
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
rtpdec_asf.c
Go to the documentation of this file.
1
/*
2
* Microsoft RTP/ASF support.
3
* Copyright (c) 2008 Ronald S. Bultje
4
*
5
* This file is part of Libav.
6
*
7
* Libav is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* Libav is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with Libav; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
28
#include "
libavutil/base64.h
"
29
#include "
libavutil/avstring.h
"
30
#include "
libavutil/intreadwrite.h
"
31
#include "
rtp.h
"
32
#include "
rtpdec_formats.h
"
33
#include "
rtsp.h
"
34
#include "
asf.h
"
35
#include "
avio_internal.h
"
36
#include "
internal.h
"
37
45
static
int
rtp_asf_fix_header
(
uint8_t
*buf,
int
len
)
46
{
47
uint8_t
*p = buf, *end = buf +
len
;
48
49
if
(len <
sizeof
(
ff_asf_guid
) * 2 + 22 ||
50
memcmp(p,
ff_asf_header
,
sizeof
(
ff_asf_guid
))) {
51
return
-1;
52
}
53
p +=
sizeof
(
ff_asf_guid
) + 14;
54
do
{
55
uint64_t chunksize =
AV_RL64
(p +
sizeof
(
ff_asf_guid
));
56
if
(memcmp(p,
ff_asf_file_header
,
sizeof
(
ff_asf_guid
))) {
57
if
(chunksize > end - p)
58
return
-1;
59
p += chunksize;
60
continue
;
61
}
62
63
/* skip most of the file header, to min_pktsize */
64
p += 6 * 8 + 3 * 4 +
sizeof
(
ff_asf_guid
) * 2;
65
if
(p + 8 <= end &&
AV_RL32
(p) ==
AV_RL32
(p + 4)) {
66
/* and set that to zero */
67
AV_WL32
(p, 0);
68
return
0;
69
}
70
break
;
71
}
while
(end - p >=
sizeof
(
ff_asf_guid
) + 8);
72
73
return
-1;
74
}
75
82
static
int
packetizer_read
(
void
*opaque,
uint8_t
*buf,
int
buf_size)
83
{
84
return
AVERROR
(EAGAIN);
85
}
86
87
static
void
init_packetizer
(
AVIOContext
*pb,
uint8_t
*buf,
int
len
)
88
{
89
ffio_init_context
(pb, buf, len, 0,
NULL
,
packetizer_read
,
NULL
,
NULL
);
90
91
/* this "fills" the buffer with its current content */
92
pb->
pos
=
len
;
93
pb->
buf_end
= buf +
len
;
94
}
95
96
int
ff_wms_parse_sdp_a_line
(
AVFormatContext
*s,
const
char
*p)
97
{
98
int
ret = 0;
99
if
(
av_strstart
(p,
"pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,"
, &p)) {
100
AVIOContext
pb;
101
RTSPState
*rt = s->
priv_data
;
102
AVDictionary
*opts =
NULL
;
103
int
len
= strlen(p) * 6 / 8;
104
char
*buf =
av_mallocz
(len);
105
av_base64_decode
(buf, p, len);
106
107
if
(
rtp_asf_fix_header
(buf, len) < 0)
108
av_log
(s,
AV_LOG_ERROR
,
109
"Failed to fix invalid RTSP-MS/ASF min_pktsize\n"
);
110
init_packetizer
(&pb, buf, len);
111
if
(rt->
asf_ctx
) {
112
avformat_close_input
(&rt->
asf_ctx
);
113
}
114
if
(!(rt->
asf_ctx
=
avformat_alloc_context
()))
115
return
AVERROR
(ENOMEM);
116
rt->
asf_ctx
->
pb
= &pb;
117
av_dict_set
(&opts,
"no_resync_search"
,
"1"
, 0);
118
ret =
avformat_open_input
(&rt->
asf_ctx
,
""
, &
ff_asf_demuxer
, &opts);
119
av_dict_free
(&opts);
120
if
(ret < 0)
121
return
ret;
122
av_dict_copy
(&s->
metadata
, rt->
asf_ctx
->
metadata
, 0);
123
rt->
asf_pb_pos
=
avio_tell
(&pb);
124
av_free
(buf);
125
rt->
asf_ctx
->
pb
=
NULL
;
126
}
127
return
ret;
128
}
129
130
static
int
asfrtp_parse_sdp_line
(
AVFormatContext
*s,
int
stream_index,
131
PayloadContext
*asf,
const
char
*
line
)
132
{
133
if
(stream_index < 0)
134
return
0;
135
if
(
av_strstart
(line,
"stream:"
, &line)) {
136
RTSPState
*rt = s->
priv_data
;
137
138
s->
streams
[stream_index]->
id
= strtol(line,
NULL
, 10);
139
140
if
(rt->
asf_ctx
) {
141
int
i;
142
143
for
(i = 0; i < rt->
asf_ctx
->
nb_streams
; i++) {
144
if
(s->
streams
[stream_index]->
id
== rt->
asf_ctx
->
streams
[i]->
id
) {
145
*s->
streams
[stream_index]->
codec
=
146
*rt->
asf_ctx
->
streams
[i]->
codec
;
147
s->
streams
[stream_index]->
need_parsing
=
148
rt->
asf_ctx
->
streams
[i]->
need_parsing
;
149
rt->
asf_ctx
->
streams
[i]->
codec
->
extradata_size
= 0;
150
rt->
asf_ctx
->
streams
[i]->
codec
->
extradata
=
NULL
;
151
avpriv_set_pts_info
(s->
streams
[stream_index], 32, 1, 1000);
152
}
153
}
154
}
155
}
156
157
return
0;
158
}
159
160
struct
PayloadContext
{
161
AVIOContext
*
pktbuf
,
pb
;
162
uint8_t
*
buf
;
163
};
164
170
static
int
asfrtp_parse_packet
(
AVFormatContext
*s,
PayloadContext
*asf,
171
AVStream
*st,
AVPacket
*pkt,
172
uint32_t *timestamp,
173
const
uint8_t
*buf,
int
len
, uint16_t seq,
174
int
flags
)
175
{
176
AVIOContext
*pb = &asf->
pb
;
177
int
res, mflags, len_off;
178
RTSPState
*rt = s->
priv_data
;
179
180
if
(!rt->
asf_ctx
)
181
return
-1;
182
183
if
(len > 0) {
184
int
off
, out_len = 0;
185
186
if
(len < 4)
187
return
-1;
188
189
av_freep
(&asf->
buf
);
190
191
ffio_init_context
(pb, buf, len, 0,
NULL
,
NULL
,
NULL
,
NULL
);
192
193
while
(
avio_tell
(pb) + 4 < len) {
194
int
start_off =
avio_tell
(pb);
195
196
mflags =
avio_r8
(pb);
197
if
(mflags & 0x80)
198
flags |=
RTP_FLAG_KEY
;
199
len_off =
avio_rb24
(pb);
200
if
(mflags & 0x20)
201
avio_skip
(pb, 4);
202
if
(mflags & 0x10)
203
avio_skip
(pb, 4);
204
if
(mflags & 0x8)
205
avio_skip
(pb, 4);
206
off =
avio_tell
(pb);
207
208
if
(!(mflags & 0x40)) {
215
if
(asf->
pktbuf
&& len_off !=
avio_tell
(asf->
pktbuf
)) {
216
uint8_t
*p;
217
avio_close_dyn_buf
(asf->
pktbuf
, &p);
218
asf->
pktbuf
=
NULL
;
219
av_free
(p);
220
}
221
if
(!len_off && !asf->
pktbuf
&&
222
(res =
avio_open_dyn_buf
(&asf->
pktbuf
)) < 0)
223
return
res;
224
if
(!asf->
pktbuf
)
225
return
AVERROR
(EIO);
226
227
avio_write
(asf->
pktbuf
, buf + off, len - off);
228
avio_skip
(pb, len - off);
229
if
(!(flags &
RTP_FLAG_MARKER
))
230
return
-1;
231
out_len =
avio_close_dyn_buf
(asf->
pktbuf
, &asf->
buf
);
232
asf->
pktbuf
=
NULL
;
233
}
else
{
242
int
cur_len = start_off + len_off -
off
;
243
int
prev_len = out_len;
244
out_len += cur_len;
245
if
(
FFMIN
(cur_len, len - off) < 0)
246
return
-1;
247
if
((res =
av_reallocp
(&asf->
buf
, out_len)) < 0)
248
return
res;
249
memcpy(asf->
buf
+ prev_len, buf + off,
250
FFMIN
(cur_len, len - off));
251
avio_skip
(pb, cur_len);
252
}
253
}
254
255
init_packetizer
(pb, asf->
buf
, out_len);
256
pb->
pos
+= rt->
asf_pb_pos
;
257
pb->
eof_reached
= 0;
258
rt->
asf_ctx
->
pb
= pb;
259
}
260
261
for
(;;) {
262
int
i;
263
264
res =
ff_read_packet
(rt->
asf_ctx
, pkt);
265
rt->
asf_pb_pos
=
avio_tell
(pb);
266
if
(res != 0)
267
break
;
268
for
(i = 0; i < s->
nb_streams
; i++) {
269
if
(s->
streams
[i]->
id
== rt->
asf_ctx
->
streams
[pkt->
stream_index
]->
id
) {
270
pkt->
stream_index
= i;
271
return
1;
// FIXME: return 0 if last packet
272
}
273
}
274
av_free_packet
(pkt);
275
}
276
277
return
res == 1 ? -1 : res;
278
}
279
280
static
PayloadContext
*
asfrtp_new_context
(
void
)
281
{
282
return
av_mallocz
(
sizeof
(
PayloadContext
));
283
}
284
285
static
void
asfrtp_free_context
(
PayloadContext
*asf)
286
{
287
if
(asf->
pktbuf
) {
288
uint8_t
*p =
NULL
;
289
avio_close_dyn_buf
(asf->
pktbuf
, &p);
290
asf->
pktbuf
=
NULL
;
291
av_free
(p);
292
}
293
av_freep
(&asf->
buf
);
294
av_free
(asf);
295
}
296
297
#define RTP_ASF_HANDLER(n, s, t) \
298
RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
299
.enc_name = s, \
300
.codec_type = t, \
301
.codec_id = AV_CODEC_ID_NONE, \
302
.parse_sdp_a_line = asfrtp_parse_sdp_line, \
303
.alloc = asfrtp_new_context, \
304
.free = asfrtp_free_context, \
305
.parse_packet = asfrtp_parse_packet, \
306
}
307
308
RTP_ASF_HANDLER
(asf_pfv,
"x-asf-pf"
,
AVMEDIA_TYPE_VIDEO
);
309
RTP_ASF_HANDLER
(asf_pfa,
"x-asf-pf"
,
AVMEDIA_TYPE_AUDIO
);
Generated on Tue Mar 1 2016 21:14:51 for Libav by
1.8.4