FFmpeg
sapdec.c
Go to the documentation of this file.
1 /*
2  * Session Announcement Protocol (RFC 2974) demuxer
3  * Copyright (c) 2010 Martin Storsjo
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 #include "avformat.h"
23 #include "libavutil/avassert.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/intreadwrite.h"
26 #include "network.h"
27 #include "os_support.h"
28 #include "internal.h"
29 #include "avio_internal.h"
30 #include "url.h"
31 #include "rtpdec.h"
32 #if HAVE_POLL_H
33 #include <poll.h>
34 #endif
35 
36 struct SAPState {
40  uint16_t hash;
41  char *sdp;
42  int eof;
43 };
44 
45 static int sap_probe(const AVProbeData *p)
46 {
47  if (av_strstart(p->filename, "sap:", NULL))
48  return AVPROBE_SCORE_MAX;
49  return 0;
50 }
51 
53 {
54  struct SAPState *sap = s->priv_data;
55  if (sap->sdp_ctx)
57  if (sap->ann_fd)
58  ffurl_close(sap->ann_fd);
59  av_freep(&sap->sdp);
61  return 0;
62 }
63 
65 {
66  struct SAPState *sap = s->priv_data;
67  char host[1024], path[1024], url[1024];
69  int port;
70  int ret, i;
72 
73  if (!ff_network_init())
74  return AVERROR(EIO);
75 
76  av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
77  path, sizeof(path), s->url);
78  if (port < 0)
79  port = 9875;
80 
81  if (!host[0]) {
82  /* Listen for announcements on sap.mcast.net if no host was specified */
83  av_strlcpy(host, "224.2.127.254", sizeof(host));
84  }
85 
86  ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d",
87  port);
88  ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_READ,
91  if (ret)
92  goto fail;
93 
94  while (1) {
95  int addr_type, auth_len;
96  int pos;
97 
98  ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf) - 1);
99  if (ret == AVERROR(EAGAIN))
100  continue;
101  if (ret < 0)
102  goto fail;
103  recvbuf[ret] = '\0'; /* Null terminate for easier parsing */
104  if (ret < 8) {
105  av_log(s, AV_LOG_WARNING, "Received too short packet\n");
106  continue;
107  }
108 
109  if ((recvbuf[0] & 0xe0) != 0x20) {
110  av_log(s, AV_LOG_WARNING, "Unsupported SAP version packet "
111  "received\n");
112  continue;
113  }
114 
115  if (recvbuf[0] & 0x04) {
116  av_log(s, AV_LOG_WARNING, "Received stream deletion "
117  "announcement\n");
118  continue;
119  }
120  addr_type = recvbuf[0] & 0x10;
121  auth_len = recvbuf[1];
122  sap->hash = AV_RB16(&recvbuf[2]);
123  pos = 4;
124  if (addr_type)
125  pos += 16; /* IPv6 */
126  else
127  pos += 4; /* IPv4 */
128  pos += auth_len * 4;
129  if (pos + 4 >= ret) {
130  av_log(s, AV_LOG_WARNING, "Received too short packet\n");
131  continue;
132  }
133 #define MIME "application/sdp"
134  if (strcmp(&recvbuf[pos], MIME) == 0) {
135  pos += strlen(MIME) + 1;
136  } else if (strncmp(&recvbuf[pos], "v=0\r\n", 5) == 0) {
137  // Direct SDP without a mime type
138  } else {
139  av_log(s, AV_LOG_WARNING, "Unsupported mime type %s\n",
140  &recvbuf[pos]);
141  continue;
142  }
143 
144  sap->sdp = av_strdup(&recvbuf[pos]);
145  break;
146  }
147 
148  av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sap->sdp);
149  ffio_init_context(&sap->sdp_pb, sap->sdp, strlen(sap->sdp), 0, NULL, NULL,
150  NULL, NULL);
151 
152  infmt = av_find_input_format("sdp");
153  if (!infmt)
154  goto fail;
156  if (!sap->sdp_ctx) {
157  ret = AVERROR(ENOMEM);
158  goto fail;
159  }
160  sap->sdp_ctx->max_delay = s->max_delay;
161  sap->sdp_ctx->pb = &sap->sdp_pb;
163 
164  if ((ret = ff_copy_whiteblacklists(sap->sdp_ctx, s)) < 0)
165  goto fail;
166 
167  ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
168  if (ret < 0)
169  goto fail;
170  if (sap->sdp_ctx->ctx_flags & AVFMTCTX_NOHEADER)
172  for (i = 0; i < sap->sdp_ctx->nb_streams; i++) {
174  if (!st) {
175  ret = AVERROR(ENOMEM);
176  goto fail;
177  }
178  st->id = i;
180  st->time_base = sap->sdp_ctx->streams[i]->time_base;
181  }
182 
183  return 0;
184 
185 fail:
186  sap_read_close(s);
187  return ret;
188 }
189 
191 {
192  struct SAPState *sap = s->priv_data;
193  int fd = ffurl_get_file_handle(sap->ann_fd);
194  int n, ret;
195  struct pollfd p = {fd, POLLIN, 0};
197 
198  if (sap->eof)
199  return AVERROR_EOF;
200 
201  while (1) {
202  n = poll(&p, 1, 0);
203  if (n <= 0 || !(p.revents & POLLIN))
204  break;
205  ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf));
206  if (ret >= 8) {
207  uint16_t hash = AV_RB16(&recvbuf[2]);
208  /* Should ideally check the source IP address, too */
209  if (recvbuf[0] & 0x04 && hash == sap->hash) {
210  /* Stream deletion */
211  sap->eof = 1;
212  return AVERROR_EOF;
213  }
214  }
215  }
216  ret = av_read_frame(sap->sdp_ctx, pkt);
217  if (ret < 0)
218  return ret;
219  if (s->ctx_flags & AVFMTCTX_NOHEADER) {
220  while (sap->sdp_ctx->nb_streams > s->nb_streams) {
221  int i = s->nb_streams;
223  if (!st) {
224  av_packet_unref(pkt);
225  return AVERROR(ENOMEM);
226  }
227  st->id = i;
229  st->time_base = sap->sdp_ctx->streams[i]->time_base;
230  }
231  }
232  return ret;
233 }
234 
236  .name = "sap",
237  .long_name = NULL_IF_CONFIG_SMALL("SAP input"),
238  .priv_data_size = sizeof(struct SAPState),
239  .read_probe = sap_probe,
240  .read_header = sap_read_header,
241  .read_packet = sap_fetch_packet,
242  .read_close = sap_read_close,
243  .flags = AVFMT_NOFILE,
244 };
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition: utils.c:4732
#define NULL
Definition: coverity.c:32
static int sap_read_close(AVFormatContext *s)
Definition: sapdec.c:52
Bytestream IO Context.
Definition: avio.h:161
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:307
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:36
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1636
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
const char * filename
Definition: avformat.h:447
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition: utils.c:164
AVInputFormat ff_sap_demuxer
Definition: sapdec.c:235
static int sap_probe(const AVProbeData *p)
Definition: sapdec.c:45
#define AVIO_FLAG_READ
read-only
Definition: avio.h:654
void ff_network_close(void)
Definition: network.c:116
AVIOContext sdp_pb
Definition: sapdec.c:39
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
static AVPacket pkt
int ctx_flags
Flags signalling stream properties.
Definition: avformat.h:1407
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
Format I/O context.
Definition: avformat.h:1358
uint8_t
int ff_network_init(void)
Definition: network.c:58
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1302
miscellaneous OS support macros and functions.
int id
Format-specific stream ID.
Definition: avformat.h:888
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4459
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
char * protocol_whitelist
&#39;,&#39; separated list of allowed protocols.
Definition: avformat.h:1918
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
#define av_log(a,...)
uint16_t hash
Definition: sapdec.c:40
static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sapdec.c:190
#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
#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:2020
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
char * url
input or output URL.
Definition: avformat.h:1454
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
simple assert() macros that are a bit more flexible than ISO C assert().
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
#define fail()
Definition: checkasm.h:120
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
URLContext * ann_fd
Definition: sapdec.c:37
AVFormatContext * sdp_ctx
Definition: sapdec.c:38
#define s(width, name)
Definition: cbs_vp9.c:257
int n
Definition: avisynth_c.h:760
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:626
char * sdp
Definition: sapdec.c:41
Stream structure.
Definition: avformat.h:881
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition: url.c:36
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:599
Definition: url.h:38
This structure contains the data a format has to probe a file.
Definition: avformat.h:446
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: utils.c:1768
static int sap_read_header(AVFormatContext *s)
Definition: sapdec.c:64
int ffurl_close(URLContext *h)
Definition: avio.c:467
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:458
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
Main libavformat public API header.
#define MIME
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:463
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
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: utils.c:4431
void * priv_data
Format private data.
Definition: avformat.h:1386
int eof
Definition: sapdec.c:42
char * protocol_blacklist
&#39;,&#39; separated list of disallowed protocols.
Definition: avformat.h:1953
#define av_freep(p)
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:654
unbuffered private I/O API
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:910
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
This structure stores compressed data.
Definition: avcodec.h:1454
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
Definition: avio.c:407