~ubuntu-branches/ubuntu/trusty/libav/trusty

« back to all changes in this revision

Viewing changes to libavformat/udp.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2011-04-19 15:04:55 UTC
  • mfrom: (1.2.1 upstream)
  • mto: (1.3.4 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20110419150455-c1nac6gjm3t2aa4n
Tags: 4:0.7~b1-1
* New upstream version
* bump SONAME and SHLIBS
* configure flags --disable-stripping was removed upstream
* the MAINTAINERS file was removed upstream
* remove patch disable-configuration-warning.patch
* drop avfilter confflags, it is enable by default in 0.7
* libfaad wrapper has been removed upstream
* also update the *contents* of the lintian overrides

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * UDP prototype streaming system
3
3
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4
4
 *
5
 
 * This file is part of FFmpeg.
 
5
 * This file is part of Libav.
6
6
 *
7
 
 * FFmpeg is free software; you can redistribute it and/or
 
7
 * Libav is free software; you can redistribute it and/or
8
8
 * modify it under the terms of the GNU Lesser General Public
9
9
 * License as published by the Free Software Foundation; either
10
10
 * version 2.1 of the License, or (at your option) any later version.
11
11
 *
12
 
 * FFmpeg is distributed in the hope that it will be useful,
 
12
 * Libav is distributed in the hope that it will be useful,
13
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
15
 * Lesser General Public License for more details.
16
16
 *
17
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
 
18
 * License along with Libav; if not, write to the Free Software
19
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
 */
21
21
 
25
25
 */
26
26
 
27
27
#define _BSD_SOURCE     /* Needed for using struct ip_mreq with recent glibc */
 
28
#define _DARWIN_C_SOURCE /* Needed for using IP_MULTICAST_TTL on OS X */
28
29
#include "avformat.h"
 
30
#include "avio_internal.h"
 
31
#include "libavutil/parseutils.h"
29
32
#include <unistd.h>
30
33
#include "internal.h"
31
34
#include "network.h"
32
35
#include "os_support.h"
33
 
#if HAVE_SYS_SELECT_H
34
 
#include <sys/select.h>
35
 
#endif
 
36
#include "url.h"
36
37
#include <sys/time.h>
37
38
 
38
39
#ifndef IPV6_ADD_MEMBERSHIP
39
40
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
40
41
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
41
42
#endif
42
 
#ifndef IN_MULTICAST
43
 
#define IN_MULTICAST(a) ((((uint32_t)(a)) & 0xf0000000) == 0xe0000000)
44
 
#endif
45
 
#ifndef IN6_IS_ADDR_MULTICAST
46
 
#define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *) (a))[0] == 0xff)
47
 
#endif
48
43
 
49
44
typedef struct {
50
45
    int udp_fd;
55
50
    int reuse_socket;
56
51
    struct sockaddr_storage dest_addr;
57
52
    int dest_addr_len;
 
53
    int is_connected;
58
54
} UDPContext;
59
55
 
60
56
#define UDP_TX_BUF_SIZE 32768
96
92
        }
97
93
    }
98
94
#endif
99
 
#if HAVE_STRUCT_IPV6_MREQ
 
95
#if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6)
100
96
    if (addr->sa_family == AF_INET6) {
101
97
        struct ipv6_mreq mreq6;
102
98
 
125
121
        }
126
122
    }
127
123
#endif
128
 
#if HAVE_STRUCT_IPV6_MREQ
 
124
#if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6)
129
125
    if (addr->sa_family == AF_INET6) {
130
126
        struct ipv6_mreq mreq6;
131
127
 
182
178
    return addr_len;
183
179
}
184
180
 
185
 
static int is_multicast_address(struct sockaddr_storage *addr)
186
 
{
187
 
    if (addr->ss_family == AF_INET) {
188
 
        return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
189
 
    }
190
 
#if HAVE_STRUCT_SOCKADDR_IN6
191
 
    if (addr->ss_family == AF_INET6) {
192
 
        return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
193
 
    }
194
 
#endif
195
 
 
196
 
    return 0;
197
 
}
198
 
 
199
181
static int udp_socket_create(UDPContext *s,
200
182
                             struct sockaddr_storage *addr, int *addr_len)
201
183
{
256
238
 *         'pkt_size=n'  : set max packet size
257
239
 *         'reuse=1'     : enable reusing the socket
258
240
 *
259
 
 * @param s1 media file context
 
241
 * @param h media file context
260
242
 * @param uri of the remote server
261
243
 * @return zero if no error.
262
244
 */
263
 
int udp_set_remote_url(URLContext *h, const char *uri)
 
245
int ff_udp_set_remote_url(URLContext *h, const char *uri)
264
246
{
265
247
    UDPContext *s = h->priv_data;
266
 
    char hostname[256];
 
248
    char hostname[256], buf[10];
267
249
    int port;
 
250
    const char *p;
268
251
 
269
 
    ff_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
 
252
    av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
270
253
 
271
254
    /* set the destination address */
272
255
    s->dest_addr_len = udp_set_url(&s->dest_addr, hostname, port);
273
256
    if (s->dest_addr_len < 0) {
274
257
        return AVERROR(EIO);
275
258
    }
276
 
    s->is_multicast = is_multicast_address(&s->dest_addr);
 
259
    s->is_multicast = ff_is_multicast_address((struct sockaddr*) &s->dest_addr);
 
260
    p = strchr(uri, '?');
 
261
    if (p) {
 
262
        if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
 
263
            int was_connected = s->is_connected;
 
264
            s->is_connected = strtol(buf, NULL, 10);
 
265
            if (s->is_connected && !was_connected) {
 
266
                if (connect(s->udp_fd, (struct sockaddr *) &s->dest_addr,
 
267
                            s->dest_addr_len)) {
 
268
                    s->is_connected = 0;
 
269
                    av_log(NULL, AV_LOG_ERROR, "connect: %s\n", strerror(errno));
 
270
                    return AVERROR(EIO);
 
271
                }
 
272
            }
 
273
        }
 
274
    }
277
275
 
278
276
    return 0;
279
277
}
280
278
 
281
279
/**
282
 
 * Return the local port used by the UDP connexion
283
 
 * @param s1 media file context
 
280
 * Return the local port used by the UDP connection
 
281
 * @param h media file context
284
282
 * @return the local port number
285
283
 */
286
 
int udp_get_local_port(URLContext *h)
 
284
int ff_udp_get_local_port(URLContext *h)
287
285
{
288
286
    UDPContext *s = h->priv_data;
289
287
    return s->local_port;
294
292
 * streams at the same time.
295
293
 * @param h media file context
296
294
 */
297
 
#if (LIBAVFORMAT_VERSION_MAJOR >= 53)
 
295
#if !FF_API_UDP_GET_FILE
298
296
static
299
297
#endif
300
298
int udp_get_file_handle(URLContext *h)
315
313
    char buf[256];
316
314
    struct sockaddr_storage my_addr;
317
315
    int len;
 
316
    int reuse_specified = 0;
318
317
 
319
318
    h->is_streamed = 1;
320
319
    h->max_packet_size = 1472;
321
320
 
322
 
    is_output = (flags & URL_WRONLY);
 
321
    is_output = (flags & AVIO_WRONLY);
323
322
 
324
323
    s = av_mallocz(sizeof(UDPContext));
325
324
    if (!s)
331
330
 
332
331
    p = strchr(uri, '?');
333
332
    if (p) {
334
 
        s->reuse_socket = find_info_tag(buf, sizeof(buf), "reuse", p);
335
 
        if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
 
333
        if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) {
 
334
            const char *endptr=NULL;
 
335
            s->reuse_socket = strtol(buf, &endptr, 10);
 
336
            /* assume if no digits were found it is a request to enable it */
 
337
            if (buf == endptr)
 
338
                s->reuse_socket = 1;
 
339
            reuse_specified = 1;
 
340
        }
 
341
        if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
336
342
            s->ttl = strtol(buf, NULL, 10);
337
343
        }
338
 
        if (find_info_tag(buf, sizeof(buf), "localport", p)) {
 
344
        if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
339
345
            s->local_port = strtol(buf, NULL, 10);
340
346
        }
341
 
        if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
 
347
        if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
342
348
            h->max_packet_size = strtol(buf, NULL, 10);
343
349
        }
344
 
        if (find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
 
350
        if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
345
351
            s->buffer_size = strtol(buf, NULL, 10);
346
352
        }
 
353
        if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
 
354
            s->is_connected = strtol(buf, NULL, 10);
 
355
        }
347
356
    }
348
357
 
349
358
    /* fill the dest addr */
350
 
    ff_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
 
359
    av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
351
360
 
352
 
    /* XXX: fix ff_url_split */
 
361
    /* XXX: fix av_url_split */
353
362
    if (hostname[0] == '\0' || hostname[0] == '?') {
354
363
        /* only accepts null hostname if input */
355
 
        if (flags & URL_WRONLY)
 
364
        if (flags & AVIO_WRONLY)
356
365
            goto fail;
357
366
    } else {
358
 
        udp_set_remote_url(h, uri);
 
367
        if (ff_udp_set_remote_url(h, uri) < 0)
 
368
            goto fail;
359
369
    }
360
370
 
361
 
    if (s->is_multicast && !(h->flags & URL_WRONLY))
 
371
    if (s->is_multicast && !(h->flags & AVIO_WRONLY))
362
372
        s->local_port = port;
363
373
    udp_fd = udp_socket_create(s, &my_addr, &len);
364
374
    if (udp_fd < 0)
365
375
        goto fail;
366
376
 
367
 
    if (s->reuse_socket)
 
377
    /* Follow the requested reuse option, unless it's multicast in which
 
378
     * case enable reuse unless explicitely disabled.
 
379
     */
 
380
    if (s->reuse_socket || (s->is_multicast && !reuse_specified)) {
 
381
        s->reuse_socket = 1;
368
382
        if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
369
383
            goto fail;
 
384
    }
370
385
 
371
386
    /* the bind is needed to give a port to the socket now */
372
387
    /* if multicast, try the multicast address bind first */
373
 
    if (s->is_multicast && !(h->flags & URL_WRONLY)) {
 
388
    if (s->is_multicast && !(h->flags & AVIO_WRONLY)) {
374
389
        bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len);
375
390
    }
376
391
    /* bind to the local address if not multicast or if the multicast
383
398
    s->local_port = udp_port(&my_addr, len);
384
399
 
385
400
    if (s->is_multicast) {
386
 
        if (h->flags & URL_WRONLY) {
 
401
        if (h->flags & AVIO_WRONLY) {
387
402
            /* output */
388
403
            if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
389
404
                goto fail;
411
426
        /* make the socket non-blocking */
412
427
        ff_socket_nonblock(udp_fd, 1);
413
428
    }
 
429
    if (s->is_connected) {
 
430
        if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) {
 
431
            av_log(NULL, AV_LOG_ERROR, "connect: %s\n", strerror(errno));
 
432
            goto fail;
 
433
        }
 
434
    }
414
435
 
415
436
    s->udp_fd = udp_fd;
416
437
    return 0;
424
445
static int udp_read(URLContext *h, uint8_t *buf, int size)
425
446
{
426
447
    UDPContext *s = h->priv_data;
427
 
    int len;
428
 
    fd_set rfds;
429
448
    int ret;
430
 
    struct timeval tv;
431
449
 
432
 
    for(;;) {
433
 
        if (url_interrupt_cb())
434
 
            return AVERROR(EINTR);
435
 
        FD_ZERO(&rfds);
436
 
        FD_SET(s->udp_fd, &rfds);
437
 
        tv.tv_sec = 0;
438
 
        tv.tv_usec = 100 * 1000;
439
 
        ret = select(s->udp_fd + 1, &rfds, NULL, NULL, &tv);
440
 
        if (ret < 0) {
441
 
            if (ff_neterrno() == FF_NETERROR(EINTR))
442
 
                continue;
443
 
            return AVERROR(EIO);
444
 
        }
445
 
        if (!(ret > 0 && FD_ISSET(s->udp_fd, &rfds)))
446
 
            continue;
447
 
        len = recv(s->udp_fd, buf, size, 0);
448
 
        if (len < 0) {
449
 
            if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
450
 
                ff_neterrno() != FF_NETERROR(EINTR))
451
 
                return AVERROR(EIO);
452
 
        } else {
453
 
            break;
454
 
        }
 
450
    if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
 
451
        ret = ff_network_wait_fd(s->udp_fd, 0);
 
452
        if (ret < 0)
 
453
            return ret;
455
454
    }
456
 
    return len;
 
455
    ret = recv(s->udp_fd, buf, size, 0);
 
456
    return ret < 0 ? ff_neterrno() : ret;
457
457
}
458
458
 
459
 
static int udp_write(URLContext *h, uint8_t *buf, int size)
 
459
static int udp_write(URLContext *h, const uint8_t *buf, int size)
460
460
{
461
461
    UDPContext *s = h->priv_data;
462
462
    int ret;
463
463
 
464
 
    for(;;) {
 
464
    if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
 
465
        ret = ff_network_wait_fd(s->udp_fd, 1);
 
466
        if (ret < 0)
 
467
            return ret;
 
468
    }
 
469
 
 
470
    if (!s->is_connected) {
465
471
        ret = sendto (s->udp_fd, buf, size, 0,
466
472
                      (struct sockaddr *) &s->dest_addr,
467
473
                      s->dest_addr_len);
468
 
        if (ret < 0) {
469
 
            if (ff_neterrno() != FF_NETERROR(EINTR) &&
470
 
                ff_neterrno() != FF_NETERROR(EAGAIN))
471
 
                return AVERROR(EIO);
472
 
        } else {
473
 
            break;
474
 
        }
475
 
    }
476
 
    return size;
 
474
    } else
 
475
        ret = send(s->udp_fd, buf, size, 0);
 
476
 
 
477
    return ret < 0 ? ff_neterrno() : ret;
477
478
}
478
479
 
479
480
static int udp_close(URLContext *h)
480
481
{
481
482
    UDPContext *s = h->priv_data;
482
483
 
483
 
    if (s->is_multicast && !(h->flags & URL_WRONLY))
 
484
    if (s->is_multicast && !(h->flags & AVIO_WRONLY))
484
485
        udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
485
486
    closesocket(s->udp_fd);
486
487
    av_free(s);
487
488
    return 0;
488
489
}
489
490
 
490
 
URLProtocol udp_protocol = {
491
 
    "udp",
492
 
    udp_open,
493
 
    udp_read,
494
 
    udp_write,
495
 
    NULL, /* seek */
496
 
    udp_close,
 
491
URLProtocol ff_udp_protocol = {
 
492
    .name                = "udp",
 
493
    .url_open            = udp_open,
 
494
    .url_read            = udp_read,
 
495
    .url_write           = udp_write,
 
496
    .url_close           = udp_close,
497
497
    .url_get_file_handle = udp_get_file_handle,
498
498
};