]> git.sesse.net Git - ffmpeg/blob - libavformat/unix.c
vc2enc: optimize and simplify quantization
[ffmpeg] / libavformat / unix.c
1 /*
2  * Unix socket protocol
3  * Copyright (c) 2013 Luca Barbato
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  *
25  * Unix socket url_protocol
26  */
27
28 #include "libavutil/avstring.h"
29 #include "libavutil/opt.h"
30 #include "os_support.h"
31 #include "network.h"
32 #include <sys/un.h>
33 #include "url.h"
34
35 typedef struct UnixContext {
36     const AVClass *class;
37     struct sockaddr_un addr;
38     int timeout;
39     int listen;
40     int type;
41     int fd;
42 } UnixContext;
43
44 #define OFFSET(x) offsetof(UnixContext, x)
45 #define ED AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_ENCODING_PARAM
46 static const AVOption unix_options[] = {
47     { "listen",    "Open socket for listening",             OFFSET(listen),  AV_OPT_TYPE_BOOL,  { .i64 = 0 },                    0,       1, ED },
48     { "timeout",   "Timeout in ms",                         OFFSET(timeout), AV_OPT_TYPE_INT,   { .i64 = -1 },                  -1, INT_MAX, ED },
49     { "type",      "Socket type",                           OFFSET(type),    AV_OPT_TYPE_INT,   { .i64 = SOCK_STREAM },    INT_MIN, INT_MAX, ED, "type" },
50     { "stream",    "Stream (reliable stream-oriented)",     0,               AV_OPT_TYPE_CONST, { .i64 = SOCK_STREAM },    INT_MIN, INT_MAX, ED, "type" },
51     { "datagram",  "Datagram (unreliable packet-oriented)", 0,               AV_OPT_TYPE_CONST, { .i64 = SOCK_DGRAM },     INT_MIN, INT_MAX, ED, "type" },
52     { "seqpacket", "Seqpacket (reliable packet-oriented",   0,               AV_OPT_TYPE_CONST, { .i64 = SOCK_SEQPACKET }, INT_MIN, INT_MAX, ED, "type" },
53     { NULL }
54 };
55
56 static const AVClass unix_class = {
57     .class_name = "unix",
58     .item_name  = av_default_item_name,
59     .option     = unix_options,
60     .version    = LIBAVUTIL_VERSION_INT,
61 };
62
63 static int unix_open(URLContext *h, const char *filename, int flags)
64 {
65     UnixContext *s = h->priv_data;
66     int fd, ret;
67
68     av_strstart(filename, "unix:", &filename);
69     s->addr.sun_family = AF_UNIX;
70     av_strlcpy(s->addr.sun_path, filename, sizeof(s->addr.sun_path));
71
72     if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0)
73         return ff_neterrno();
74
75     if (s->listen) {
76         ret = ff_listen_bind(fd, (struct sockaddr *)&s->addr,
77                              sizeof(s->addr), s->timeout, h);
78         if (ret < 0)
79             goto fail;
80         fd = ret;
81     } else {
82         ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr,
83                                 sizeof(s->addr), s->timeout, h, 0);
84         if (ret < 0)
85             goto fail;
86     }
87
88     s->fd = fd;
89
90     return 0;
91
92 fail:
93     if (s->listen && AVUNERROR(ret) != EADDRINUSE)
94         unlink(s->addr.sun_path);
95     if (fd >= 0)
96         closesocket(fd);
97     return ret;
98 }
99
100 static int unix_read(URLContext *h, uint8_t *buf, int size)
101 {
102     UnixContext *s = h->priv_data;
103     int ret;
104
105     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
106         ret = ff_network_wait_fd(s->fd, 0);
107         if (ret < 0)
108             return ret;
109     }
110     ret = recv(s->fd, buf, size, 0);
111     return ret < 0 ? ff_neterrno() : ret;
112 }
113
114 static int unix_write(URLContext *h, const uint8_t *buf, int size)
115 {
116     UnixContext *s = h->priv_data;
117     int ret;
118
119     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
120         ret = ff_network_wait_fd(s->fd, 1);
121         if (ret < 0)
122             return ret;
123     }
124     ret = send(s->fd, buf, size, MSG_NOSIGNAL);
125     return ret < 0 ? ff_neterrno() : ret;
126 }
127
128 static int unix_close(URLContext *h)
129 {
130     UnixContext *s = h->priv_data;
131     if (s->listen)
132         unlink(s->addr.sun_path);
133     closesocket(s->fd);
134     return 0;
135 }
136
137 static int unix_get_file_handle(URLContext *h)
138 {
139     UnixContext *s = h->priv_data;
140     return s->fd;
141 }
142
143 const URLProtocol ff_unix_protocol = {
144     .name                = "unix",
145     .url_open            = unix_open,
146     .url_read            = unix_read,
147     .url_write           = unix_write,
148     .url_close           = unix_close,
149     .url_get_file_handle = unix_get_file_handle,
150     .priv_data_size      = sizeof(UnixContext),
151     .priv_data_class     = &unix_class,
152     .flags               = URL_PROTOCOL_FLAG_NETWORK,
153 };