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 "demux.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/mem.h"
27 #include "network.h"
28 #include "os_support.h"
29 #include "internal.h"
30 #include "avio_internal.h"
31 #include "url.h"
32 #include "rtpdec.h"
33 #if HAVE_POLL_H
34 #include <poll.h>
35 #endif
36 
37 struct SAPState {
41  uint16_t hash;
42  char *sdp;
43  int eof;
44 };
45 
46 static int sap_probe(const AVProbeData *p)
47 {
48  if (av_strstart(p->filename, "sap:", NULL))
49  return AVPROBE_SCORE_MAX;
50  return 0;
51 }
52 
54 {
55  struct SAPState *sap = s->priv_data;
56  if (sap->sdp_ctx)
58  ffurl_closep(&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];
68  uint8_t recvbuf[RTP_MAX_PACKET_LENGTH];
69  const AVInputFormat *infmt;
70  int port;
71  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);
89  &s->interrupt_callback, NULL,
90  s->protocol_whitelist, s->protocol_blacklist, NULL);
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  if (!sap->sdp) {
146  ret = AVERROR(ENOMEM);
147  goto fail;
148  }
149  break;
150  }
151 
152  av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sap->sdp);
153  ffio_init_read_context(&sap->sdp_pb, sap->sdp, strlen(sap->sdp));
154 
155  infmt = av_find_input_format("sdp");
156  if (!infmt)
157  goto fail;
159  if (!sap->sdp_ctx) {
160  ret = AVERROR(ENOMEM);
161  goto fail;
162  }
163  sap->sdp_ctx->max_delay = s->max_delay;
164  sap->sdp_ctx->pb = &sap->sdp_pb.pub;
165  sap->sdp_ctx->interrupt_callback = s->interrupt_callback;
166 
167  if ((ret = ff_copy_whiteblacklists(sap->sdp_ctx, s)) < 0)
168  goto fail;
169 
170  ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
171  if (ret < 0)
172  goto fail;
173  if (sap->sdp_ctx->ctx_flags & AVFMTCTX_NOHEADER)
174  s->ctx_flags |= AVFMTCTX_NOHEADER;
175  for (i = 0; i < sap->sdp_ctx->nb_streams; i++) {
177  if (!st) {
178  ret = AVERROR(ENOMEM);
179  goto fail;
180  }
181  st->id = i;
183  if (ret < 0)
184  goto fail;
185  st->time_base = sap->sdp_ctx->streams[i]->time_base;
186  }
187 
188  return 0;
189 
190 fail:
191  sap_read_close(s);
192  return ret;
193 }
194 
196 {
197  struct SAPState *sap = s->priv_data;
198  int fd = ffurl_get_file_handle(sap->ann_fd);
199  int n, ret;
200  struct pollfd p = {fd, POLLIN, 0};
201  uint8_t recvbuf[RTP_MAX_PACKET_LENGTH];
202 
203  if (fd < 0)
204  return fd;
205 
206  if (sap->eof)
207  return AVERROR_EOF;
208 
209  while (1) {
210  n = poll(&p, 1, 0);
211  if (n <= 0 || !(p.revents & POLLIN))
212  break;
213  ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf));
214  if (ret >= 8) {
215  uint16_t hash = AV_RB16(&recvbuf[2]);
216  /* Should ideally check the source IP address, too */
217  if (recvbuf[0] & 0x04 && hash == sap->hash) {
218  /* Stream deletion */
219  sap->eof = 1;
220  return AVERROR_EOF;
221  }
222  }
223  }
224  ret = av_read_frame(sap->sdp_ctx, pkt);
225  if (ret < 0)
226  return ret;
227  if (s->ctx_flags & AVFMTCTX_NOHEADER) {
228  while (sap->sdp_ctx->nb_streams > s->nb_streams) {
229  int i = s->nb_streams;
231  if (!st) {
232  return AVERROR(ENOMEM);
233  }
234  st->id = i;
236  st->time_base = sap->sdp_ctx->streams[i]->time_base;
237  }
238  }
239  return ret;
240 }
241 
243  .p.name = "sap",
244  .p.long_name = NULL_IF_CONFIG_SMALL("SAP input"),
245  .p.flags = AVFMT_NOFILE,
246  .priv_data_size = sizeof(struct SAPState),
248  .read_header = sap_read_header,
249  .read_packet = sap_fetch_packet,
250  .read_close = sap_read_close,
251 };
SAPState::hash
uint16_t hash
Definition: sapdec.c:41
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
sap_read_header
static int sap_read_header(AVFormatContext *s)
Definition: sapdec.c:64
AVERROR
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
SAPState::ann_fd
URLContext * ann_fd
Definition: sapdec.c:38
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
ff_sap_demuxer
const FFInputFormat ff_sap_demuxer
Definition: sapdec.c:242
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1368
SAPState
Definition: sapdec.c:37
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
MIME
#define MIME
ffio_init_read_context
void ffio_init_read_context(FFIOContext *s, const uint8_t *buffer, int buffer_size)
Wrap a buffer in an AVIOContext for reading.
Definition: aviobuf.c:99
ff_network_close
void ff_network_close(void)
Definition: network.c:121
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: demux.c:1547
hash
uint8_t hash[HASH_SIZE]
Definition: movenc.c:58
sap_read_close
static int sap_read_close(AVFormatContext *s)
Definition: sapdec.c:53
os_support.h
FFIOContext
Definition: avio_internal.h:28
ff_network_init
int ff_network_init(void)
Definition: network.c:63
AVPROBE_SCORE_MAX
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:463
avformat_close_input
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: demux.c:366
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1573
fail
#define fail()
Definition: checkasm.h:193
pkt
AVPacket * pkt
Definition: movenc.c:60
AVInputFormat
Definition: avformat.h:548
AVFormatContext::ctx_flags
int ctx_flags
Flags signalling stream properties.
Definition: avformat.h:1349
avformat_open_input
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition: demux.c:216
ffurl_open_whitelist
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:362
SAPState::sdp
char * sdp
Definition: sapdec.c:42
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
SAPState::eof
int eof
Definition: sapdec.c:43
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:553
AVProbeData::filename
const char * filename
Definition: avformat.h:452
ff_url_join
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:40
SAPState::sdp_pb
FFIOContext sdp_pb
Definition: sapdec.c:40
AVFormatContext
Format I/O context.
Definition: avformat.h:1300
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:771
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:787
NULL
#define NULL
Definition: coverity.c:32
AVFMTCTX_NOHEADER
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1251
ff_copy_whiteblacklists
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition: avformat.c:912
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1342
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:451
rtpdec.h
AVFormatContext::nb_streams
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1356
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:162
FFIOContext::pub
AVIOContext pub
Definition: avio_internal.h:29
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:468
SAPState::sdp_ctx
AVFormatContext * sdp_ctx
Definition: sapdec.c:39
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:46
av_strstart
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:36
URLContext
Definition: url.h:35
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
avio_internal.h
av_url_split
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:351
url.h
AVFormatContext::max_delay
int max_delay
Definition: avformat.h:1445
demux.h
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:588
sap_probe
static int sap_probe(const AVProbeData *p)
Definition: sapdec.c:46
AVStream::id
int id
Format-specific stream ID.
Definition: avformat.h:760
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:748
pos
unsigned int pos
Definition: spdifenc.c:414
avformat.h
network.h
RTP_MAX_PACKET_LENGTH
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:37
sap_fetch_packet
static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sapdec.c:195
av_find_input_format
const AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
Definition: format.c:144
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
read_probe
static int read_probe(const AVProbeData *p)
Definition: cdg.c:30
mem.h
AVPacket
This structure stores compressed data.
Definition: packet.h:516
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
FFInputFormat
Definition: demux.h:42
av_strlcpy
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:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
avstring.h
ffurl_get_file_handle
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:814
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:106
AV_RB16
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:98
ffurl_read
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition: url.h:181