FFmpeg
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 FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * @brief Microsoft RTP/ASF support
25  * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
26  */
27 
28 #include "libavutil/avassert.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/intreadwrite.h"
32 #include "rtp.h"
33 #include "rtpdec_formats.h"
34 #include "rtsp.h"
35 #include "asf.h"
36 #include "avio_internal.h"
37 #include "internal.h"
38 
39 /**
40  * From MSDN 2.2.1.4, we learn that ASF data packets over RTP should not
41  * contain any padding. Unfortunately, the header min/max_pktsize are not
42  * updated (thus making min_pktsize invalid). Here, we "fix" these faulty
43  * min_pktsize values in the ASF file header.
44  * @return 0 on success, <0 on failure (currently -1).
45  */
46 static int rtp_asf_fix_header(uint8_t *buf, int len)
47 {
48  uint8_t *p = buf, *end = buf + len;
49 
50  if (len < sizeof(ff_asf_guid) * 2 + 22 ||
51  memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
52  return -1;
53  }
54  p += sizeof(ff_asf_guid) + 14;
55  do {
56  uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
57  int skip = 6 * 8 + 3 * 4 + sizeof(ff_asf_guid) * 2;
58  if (memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
59  if (chunksize > end - p)
60  return -1;
61  p += chunksize;
62  continue;
63  }
64 
65  if (end - p < 8 + skip)
66  break;
67  /* skip most of the file header, to min_pktsize */
68  p += skip;
69  if (AV_RL32(p) == AV_RL32(p + 4)) {
70  /* and set that to zero */
71  AV_WL32(p, 0);
72  return 0;
73  }
74  break;
75  } while (end - p >= sizeof(ff_asf_guid) + 8);
76 
77  return -1;
78 }
79 
80 /**
81  * The following code is basically a buffered AVIOContext,
82  * with the added benefit of returning -EAGAIN (instead of 0)
83  * on packet boundaries, such that the ASF demuxer can return
84  * safely and resume business at the next packet.
85  */
86 static int packetizer_read(void *opaque, uint8_t *buf, int buf_size)
87 {
88  return AVERROR(EAGAIN);
89 }
90 
91 static void init_packetizer(AVIOContext *pb, uint8_t *buf, int len)
92 {
93  ffio_init_context(pb, buf, len, 0, NULL, packetizer_read, NULL, NULL);
94 
95  /* this "fills" the buffer with its current content */
96  pb->pos = len;
97  pb->buf_end = buf + len;
98 }
99 
101 {
102  int ret = 0;
103  if (av_strstart(p, "pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,", &p)) {
104  AVIOContext pb = { 0 };
105  RTSPState *rt = s->priv_data;
107  int len = strlen(p) * 6 / 8;
108  char *buf = av_mallocz(len);
110 
111  if (!buf)
112  return AVERROR(ENOMEM);
113  av_base64_decode(buf, p, len);
114 
115  if (rtp_asf_fix_header(buf, len) < 0)
116  av_log(s, AV_LOG_ERROR,
117  "Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
118  init_packetizer(&pb, buf, len);
119  if (rt->asf_ctx) {
121  }
122 
123  if (!(iformat = av_find_input_format("asf")))
125 
127  if (!rt->asf_ctx) {
128  av_free(buf);
129  return AVERROR(ENOMEM);
130  }
131  rt->asf_ctx->pb = &pb;
132  av_dict_set(&opts, "no_resync_search", "1", 0);
133 
134  if ((ret = ff_copy_whiteblacklists(rt->asf_ctx, s)) < 0) {
135  av_dict_free(&opts);
136  return ret;
137  }
138 
139  ret = avformat_open_input(&rt->asf_ctx, "", iformat, &opts);
140  av_dict_free(&opts);
141  if (ret < 0) {
142  av_free(pb.buffer);
143  return ret;
144  }
145  av_dict_copy(&s->metadata, rt->asf_ctx->metadata, 0);
146  rt->asf_pb_pos = avio_tell(&pb);
147  av_free(pb.buffer);
148  rt->asf_ctx->pb = NULL;
149  }
150  return ret;
151 }
152 
153 static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
154  PayloadContext *asf, const char *line)
155 {
156  if (stream_index < 0)
157  return 0;
158  if (av_strstart(line, "stream:", &line)) {
159  RTSPState *rt = s->priv_data;
160 
161  s->streams[stream_index]->id = strtol(line, NULL, 10);
162 
163  if (rt->asf_ctx) {
164  int i;
165 
166  for (i = 0; i < rt->asf_ctx->nb_streams; i++) {
167  if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) {
168  avcodec_parameters_copy(s->streams[stream_index]->codecpar,
169  rt->asf_ctx->streams[i]->codecpar);
170  s->streams[stream_index]->need_parsing =
171  rt->asf_ctx->streams[i]->need_parsing;
172  avpriv_set_pts_info(s->streams[stream_index], 32, 1, 1000);
173  }
174  }
175  }
176  }
177 
178  return 0;
179 }
180 
181 struct PayloadContext {
184 };
185 
186 /**
187  * @return 0 when a packet was written into /p pkt, and no more data is left;
188  * 1 when a packet was written into /p pkt, and more packets might be left;
189  * <0 when not enough data was provided to return a full packet, or on error.
190  */
192  AVStream *st, AVPacket *pkt,
193  uint32_t *timestamp,
194  const uint8_t *buf, int len, uint16_t seq,
195  int flags)
196 {
197  AVIOContext *pb = &asf->pb;
198  int res, mflags, len_off;
199  RTSPState *rt = s->priv_data;
200 
201  if (!rt->asf_ctx)
202  return -1;
203 
204  if (len > 0) {
205  int off, out_len = 0;
206 
207  if (len < 4)
208  return -1;
209 
210  av_freep(&asf->buf);
211 
212  ffio_init_context(pb, (uint8_t *)buf, len, 0, NULL, NULL, NULL, NULL);
213 
214  while (avio_tell(pb) + 4 < len) {
215  int start_off = avio_tell(pb);
216 
217  mflags = avio_r8(pb);
218  len_off = avio_rb24(pb);
219  if (mflags & 0x20) /**< relative timestamp */
220  avio_skip(pb, 4);
221  if (mflags & 0x10) /**< has duration */
222  avio_skip(pb, 4);
223  if (mflags & 0x8) /**< has location ID */
224  avio_skip(pb, 4);
225  off = avio_tell(pb);
226 
227  if (!(mflags & 0x40)) {
228  /**
229  * If 0x40 is not set, the len_off field specifies an offset
230  * of this packet's payload data in the complete (reassembled)
231  * ASF packet. This is used to spread one ASF packet over
232  * multiple RTP packets.
233  */
234  if (asf->pktbuf && len_off != avio_tell(asf->pktbuf)) {
235  ffio_free_dyn_buf(&asf->pktbuf);
236  }
237  if (!len_off && !asf->pktbuf &&
238  (res = avio_open_dyn_buf(&asf->pktbuf)) < 0)
239  return res;
240  if (!asf->pktbuf)
241  return AVERROR(EIO);
242 
243  avio_write(asf->pktbuf, buf + off, len - off);
244  avio_skip(pb, len - off);
245  if (!(flags & RTP_FLAG_MARKER))
246  return -1;
247  out_len = avio_close_dyn_buf(asf->pktbuf, &asf->buf);
248  asf->pktbuf = NULL;
249  } else {
250  /**
251  * If 0x40 is set, the len_off field specifies the length of
252  * the next ASF packet that can be read from this payload
253  * data alone. This is commonly the same as the payload size,
254  * but could be less in case of packet splitting (i.e.
255  * multiple ASF packets in one RTP packet).
256  */
257 
258  int cur_len = start_off + len_off - off;
259  int prev_len = out_len;
260  out_len += cur_len;
261  if (FFMIN(cur_len, len - off) < 0)
262  return -1;
263  if ((res = av_reallocp(&asf->buf, out_len)) < 0)
264  return res;
265  memcpy(asf->buf + prev_len, buf + off,
266  FFMIN(cur_len, len - off));
267  avio_skip(pb, cur_len);
268  }
269  }
270 
271  init_packetizer(pb, asf->buf, out_len);
272  pb->pos += rt->asf_pb_pos;
273  pb->eof_reached = 0;
274  rt->asf_ctx->pb = pb;
275  }
276 
277  for (;;) {
278  int i;
279 
280  res = ff_read_packet(rt->asf_ctx, pkt);
281  rt->asf_pb_pos = avio_tell(pb);
282  if (res != 0)
283  break;
284  for (i = 0; i < s->nb_streams; i++) {
285  if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
286  pkt->stream_index = i;
287  return 1; // FIXME: return 0 if last packet
288  }
289  }
290  av_packet_unref(pkt);
291  }
292 
293  return res == 1 ? -1 : res;
294 }
295 
297 {
298  ffio_free_dyn_buf(&asf->pktbuf);
299  av_freep(&asf->buf);
300 }
301 
302 #define RTP_ASF_HANDLER(n, s, t) \
303 const RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
304  .enc_name = s, \
305  .codec_type = t, \
306  .codec_id = AV_CODEC_ID_NONE, \
307  .priv_data_size = sizeof(PayloadContext), \
308  .parse_sdp_a_line = asfrtp_parse_sdp_line, \
309  .close = asfrtp_close_context, \
310  .parse_packet = asfrtp_parse_packet, \
311 }
312 
313 RTP_ASF_HANDLER(asf_pfv, "x-asf-pf", AVMEDIA_TYPE_VIDEO);
314 RTP_ASF_HANDLER(asf_pfa, "x-asf-pf", AVMEDIA_TYPE_AUDIO);
AVPacket pkt
Definition: rtpdec_qt.c:37
const ff_asf_guid ff_asf_header
Definition: asf.c:23
#define NULL
Definition: coverity.c:32
int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
Parse a Windows Media Server-specific SDP line.
Definition: rtpdec_asf.c:100
Bytestream IO Context.
Definition: avio.h:161
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1459
unsigned char * buf_end
End of the data, may be less than buffer+buffer_size if the read function returned less data than req...
Definition: avio.h:229
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4892
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition: utils.c:164
RTP/JPEG specific private data.
Definition: rdt.c:83
unsigned char * buffer
Start of the buffer.
Definition: avio.h:226
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition: utils.c:537
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:334
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
uint64_t_TMPL AV_RL64
Definition: bytestream.h:87
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1430
Format I/O context.
Definition: avformat.h:1358
static int rtp_asf_fix_header(uint8_t *buf, int len)
From MSDN 2.2.1.4, we learn that ASF data packets over RTP should not contain any padding...
Definition: rtpdec_asf.c:46
uint8_t
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
enum AVStreamParseType need_parsing
Definition: avformat.h:1099
int id
Format-specific stream ID.
Definition: avformat.h:888
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:144
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:218
#define av_log(a,...)
#define ff_const59
The ff_const59 define is not part of the public API and will be removed without further warning...
Definition: avformat.h:549
uint32_t timestamp
current frame timestamp
Definition: rtpdec_ac3.c:31
Private data for the RTSP demuxer.
Definition: rtsp.h:219
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2021
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1598
static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition: rtpdec_asf.c:191
#define RTP_FLAG_MARKER
RTP marker bit was set for this packet.
Definition: rtpdec.h:93
static int packetizer_read(void *opaque, uint8_t *buf, int buf_size)
The following code is basically a buffered AVIOContext, with the added benefit of returning -EAGAIN (...
Definition: rtpdec_asf.c:86
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
ff_const59 AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
Definition: format.c:118
Definition: graph2dot.c:48
simple assert() macros that are a bit more flexible than ISO C assert().
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:641
uint64_t asf_pb_pos
cache for position of the asf demuxer, since we load a new data packet in the bytecontext for each in...
Definition: rtsp.h:312
AVIOContext * pktbuf
Definition: rtpdec_asf.c:182
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
AVDictionary * opts
Definition: movenc.c:50
AVFormatContext * asf_ctx
The following are used for RTP/ASF streams.
Definition: rtsp.h:308
unsigned int avio_rb24(AVIOContext *s)
Definition: aviobuf.c:796
#define FFMIN(a, b)
Definition: common.h:96
static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index, PayloadContext *asf, const char *line)
Definition: rtpdec_asf.c:153
static void init_packetizer(AVIOContext *pb, uint8_t *buf, int len)
Definition: rtpdec_asf.c:91
#define s(width, name)
Definition: cbs_vp9.c:257
int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
Read a transport packet from a media file.
Definition: utils.c:831
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1489
uint8_t ff_asf_guid[16]
Definition: riff.h:90
Stream structure.
Definition: avformat.h:881
static AVInputFormat * iformat
Definition: ffprobe.c:257
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
const ff_asf_guid ff_asf_file_header
Definition: asf.c:27
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:599
void * buf
Definition: avisynth_c.h:766
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:183
static void asfrtp_close_context(PayloadContext *asf)
Definition: rtpdec_asf.c:296
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define AVERROR_DEMUXER_NOT_FOUND
Demuxer not found.
Definition: error.h:53
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
#define RTP_ASF_HANDLER(n, s, t)
Definition: rtpdec_asf.c:302
int ffio_init_context(AVIOContext *s, unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Definition: aviobuf.c:81
int64_t pos
position in the file of the current buffer
Definition: avio.h:238
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: utils.c:4437
#define av_free(p)
int eof_reached
true if was unable to read due to error or eof
Definition: avio.h:239
int len
void * priv_data
Format private data.
Definition: avformat.h:1386
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
Definition: base64.c:79
#define av_freep(p)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
int stream_index
Definition: avcodec.h:1479
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
AVIOContext pb
Definition: rtpdec_asf.c:182
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: avcodec.h:1454
#define AV_WL32(p, v)
Definition: intreadwrite.h:426