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/avstring.h"
24 #include "libavutil/intreadwrite.h"
25 #include "network.h"
26 #include "os_support.h"
27 #include "internal.h"
28 #include "avio_internal.h"
29 #include "url.h"
30 #include "rtpdec.h"
31 #if HAVE_POLL_H
32 #include <poll.h>
33 #endif
34 
35 struct SAPState {
39  uint16_t hash;
40  char *sdp;
41  int eof;
42 };
43 
44 static int sap_probe(AVProbeData *p)
45 {
46  if (av_strstart(p->filename, "sap:", NULL))
47  return AVPROBE_SCORE_MAX;
48  return 0;
49 }
50 
52 {
53  struct SAPState *sap = s->priv_data;
54  if (sap->sdp_ctx)
56  if (sap->ann_fd)
57  ffurl_close(sap->ann_fd);
58  av_freep(&sap->sdp);
60  return 0;
61 }
62 
64 {
65  struct SAPState *sap = s->priv_data;
66  char host[1024], path[1024], url[1024];
68  int port;
69  int ret, i;
70  AVInputFormat* infmt;
71 
72  if (!ff_network_init())
73  return AVERROR(EIO);
74 
75  av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
76  path, sizeof(path), s->filename);
77  if (port < 0)
78  port = 9875;
79 
80  if (!host[0]) {
81  /* Listen for announcements on sap.mcast.net if no host was specified */
82  av_strlcpy(host, "224.2.127.254", sizeof(host));
83  }
84 
85  ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d",
86  port);
87  ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ,
89  if (ret)
90  goto fail;
91 
92  while (1) {
93  int addr_type, auth_len;
94  int pos;
95 
96  ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf) - 1);
97  if (ret == AVERROR(EAGAIN))
98  continue;
99  if (ret < 0)
100  goto fail;
101  recvbuf[ret] = '\0'; /* Null terminate for easier parsing */
102  if (ret < 8) {
103  av_log(s, AV_LOG_WARNING, "Received too short packet\n");
104  continue;
105  }
106 
107  if ((recvbuf[0] & 0xe0) != 0x20) {
108  av_log(s, AV_LOG_WARNING, "Unsupported SAP version packet "
109  "received\n");
110  continue;
111  }
112 
113  if (recvbuf[0] & 0x04) {
114  av_log(s, AV_LOG_WARNING, "Received stream deletion "
115  "announcement\n");
116  continue;
117  }
118  addr_type = recvbuf[0] & 0x10;
119  auth_len = recvbuf[1];
120  sap->hash = AV_RB16(&recvbuf[2]);
121  pos = 4;
122  if (addr_type)
123  pos += 16; /* IPv6 */
124  else
125  pos += 4; /* IPv4 */
126  pos += auth_len * 4;
127  if (pos + 4 >= ret) {
128  av_log(s, AV_LOG_WARNING, "Received too short packet\n");
129  continue;
130  }
131 #define MIME "application/sdp"
132  if (strcmp(&recvbuf[pos], MIME) == 0) {
133  pos += strlen(MIME) + 1;
134  } else if (strncmp(&recvbuf[pos], "v=0\r\n", 5) == 0) {
135  // Direct SDP without a mime type
136  } else {
137  av_log(s, AV_LOG_WARNING, "Unsupported mime type %s\n",
138  &recvbuf[pos]);
139  continue;
140  }
141 
142  sap->sdp = av_strdup(&recvbuf[pos]);
143  break;
144  }
145 
146  av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sap->sdp);
147  ffio_init_context(&sap->sdp_pb, sap->sdp, strlen(sap->sdp), 0, NULL, NULL,
148  NULL, NULL);
149 
150  infmt = av_find_input_format("sdp");
151  if (!infmt)
152  goto fail;
154  if (!sap->sdp_ctx) {
155  ret = AVERROR(ENOMEM);
156  goto fail;
157  }
158  sap->sdp_ctx->max_delay = s->max_delay;
159  sap->sdp_ctx->pb = &sap->sdp_pb;
161  ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
162  if (ret < 0)
163  goto fail;
164  if (sap->sdp_ctx->ctx_flags & AVFMTCTX_NOHEADER)
166  for (i = 0; i < sap->sdp_ctx->nb_streams; i++) {
168  if (!st) {
169  ret = AVERROR(ENOMEM);
170  goto fail;
171  }
172  st->id = i;
174  st->time_base = sap->sdp_ctx->streams[i]->time_base;
175  }
176 
177  return 0;
178 
179 fail:
180  sap_read_close(s);
181  return ret;
182 }
183 
185 {
186  struct SAPState *sap = s->priv_data;
187  int fd = ffurl_get_file_handle(sap->ann_fd);
188  int n, ret;
189  struct pollfd p = {fd, POLLIN, 0};
191 
192  if (sap->eof)
193  return AVERROR_EOF;
194 
195  while (1) {
196  n = poll(&p, 1, 0);
197  if (n <= 0 || !(p.revents & POLLIN))
198  break;
199  ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf));
200  if (ret >= 8) {
201  uint16_t hash = AV_RB16(&recvbuf[2]);
202  /* Should ideally check the source IP address, too */
203  if (recvbuf[0] & 0x04 && hash == sap->hash) {
204  /* Stream deletion */
205  sap->eof = 1;
206  return AVERROR_EOF;
207  }
208  }
209  }
210  ret = av_read_frame(sap->sdp_ctx, pkt);
211  if (ret < 0)
212  return ret;
213  if (s->ctx_flags & AVFMTCTX_NOHEADER) {
214  while (sap->sdp_ctx->nb_streams > s->nb_streams) {
215  int i = s->nb_streams;
217  if (!st) {
218  av_free_packet(pkt);
219  return AVERROR(ENOMEM);
220  }
221  st->id = i;
223  st->time_base = sap->sdp_ctx->streams[i]->time_base;
224  }
225  }
226  return ret;
227 }
228 
230  .name = "sap",
231  .long_name = NULL_IF_CONFIG_SMALL("SAP input"),
232  .priv_data_size = sizeof(struct SAPState),
233  .read_probe = sap_probe,
234  .read_header = sap_read_header,
235  .read_packet = sap_fetch_packet,
236  .read_close = sap_read_close,
237  .flags = AVFMT_NOFILE,
238 };
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.
static int sap_read_close(AVFormatContext *s)
Definition: sapdec.c:51
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:36
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1125
const char * filename
Definition: avformat.h:335
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
AVInputFormat ff_sap_demuxer
Definition: sapdec.c:229
#define AVIO_FLAG_READ
read-only
Definition: avio.h:332
void ff_network_close(void)
Definition: network.c:173
AVIOContext sdp_pb
Definition: sapdec.c:38
int ctx_flags
Format-specific flags, see AVFMTCTX_xx.
Definition: avformat.h:980
int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
Copy the settings of the source AVCodecContext into the destination AVCodecContext.
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...) av_printf_format(7
Assemble a URL string from components.
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
Format I/O context.
Definition: avformat.h:944
uint8_t
int ff_network_init(void)
Definition: network.c:126
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:914
miscellaneous OS support macros and functions.
static AVPacket pkt
Definition: demuxing.c:56
int id
Format-specific stream ID.
Definition: avformat.h:650
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
AVStream ** streams
Definition: avformat.h:992
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
#define AVERROR_EOF
End of file.
Definition: error.h:55
uint16_t hash
Definition: sapdec.c:39
static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sapdec.c:184
#define AV_RB16
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
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:82
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
unsigned int nb_streams
A list of all streams in the file.
Definition: avformat.h:991
#define AV_LOG_VERBOSE
Definition: log.h:157
AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
char filename[1024]
input or output filename
Definition: avformat.h:994
URLContext * ann_fd
Definition: sapdec.c:36
ret
Definition: avfilter.c:821
AVFormatContext * sdp_ctx
Definition: sapdec.c:37
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:399
char * sdp
Definition: sapdec.c:40
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:220
AVIOContext * pb
I/O context.
Definition: avformat.h:977
Definition: url.h:41
synthesis window for stochastic i
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
static int sap_read_header(AVFormatContext *s)
Definition: sapdec.c:63
static int sap_probe(AVProbeData *p)
Definition: sapdec.c:44
int ffurl_close(URLContext *h)
Definition: avio.c:359
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
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:33
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:345
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:71
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:247
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
void * priv_data
Format private data.
Definition: avformat.h:964
int eof
Definition: sapdec.c:41
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
unbuffered private I/O API
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:679
This structure stores compressed data.
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:303