mirror of https://github.com/FFmpeg/FFmpeg.git
* commit '605387582bd35920b83a26dabbe1c0601f425621': lavf: Support unix sockets Conflicts: configure Merged-by: Michael Niedermayer <michaelni@gmx.at>pull/37/head
commit
8d06ce7941
5 changed files with 182 additions and 0 deletions
@ -0,0 +1,156 @@ |
||||
/*
|
||||
* Unix socket protocol |
||||
* Copyright (c) 2013 Luca Barbato |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* FFmpeg is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* Unix socket url_protocol |
||||
* |
||||
*/ |
||||
|
||||
#include <sys/un.h> |
||||
|
||||
#include "libavutil/avstring.h" |
||||
#include "libavutil/opt.h" |
||||
#include "os_support.h" |
||||
#include "network.h" |
||||
#include "url.h" |
||||
|
||||
typedef struct UnixContext { |
||||
const AVClass *class; |
||||
struct sockaddr_un addr; |
||||
int timeout; |
||||
int listen; |
||||
int type; |
||||
int fd; |
||||
} UnixContext; |
||||
|
||||
#define OFFSET(x) offsetof(UnixContext, x) |
||||
#define ED AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_ENCODING_PARAM |
||||
static const AVOption unix_options[] = { |
||||
{ "listen", "Open socket for listening", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ED }, |
||||
{ "timeout", "Timeout in ms", OFFSET(timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ED }, |
||||
{ "type", "Socket type", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = SOCK_STREAM }, INT_MIN, INT_MAX, ED, "type" }, |
||||
{ "stream", "Stream (reliable stream-oriented)", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_STREAM }, INT_MIN, INT_MAX, ED, "type" }, |
||||
{ "datagram", "Datagram (unreliable packet-oriented)", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_DGRAM }, INT_MIN, INT_MAX, ED, "type" }, |
||||
{ "seqpacket", "Seqpacket (reliable packet-oriented", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_SEQPACKET }, INT_MIN, INT_MAX, ED, "type" }, |
||||
{ NULL } |
||||
}; |
||||
|
||||
static const AVClass unix_class = { |
||||
.class_name = "unix", |
||||
.item_name = av_default_item_name, |
||||
.option = unix_options, |
||||
.version = LIBAVUTIL_VERSION_INT, |
||||
}; |
||||
|
||||
static int unix_open(URLContext *h, const char *filename, int flags) |
||||
{ |
||||
UnixContext *s = h->priv_data; |
||||
int fd, ret; |
||||
|
||||
av_strstart(filename, "unix:", &filename); |
||||
s->addr.sun_family = AF_UNIX; |
||||
av_strlcpy(s->addr.sun_path, filename, sizeof(s->addr.sun_path)); |
||||
|
||||
if ((fd = socket(AF_UNIX, s->type, 0)) < 0) |
||||
return ff_neterrno(); |
||||
|
||||
if (s->listen) { |
||||
fd = ff_listen_bind(fd, (struct sockaddr *)&s->addr, |
||||
sizeof(s->addr), s->timeout, h); |
||||
if (fd < 0) { |
||||
ret = fd; |
||||
goto fail; |
||||
} |
||||
} else { |
||||
ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr, |
||||
sizeof(s->addr), s->timeout, h); |
||||
if (ret < 0) |
||||
goto fail; |
||||
} |
||||
|
||||
s->fd = fd; |
||||
|
||||
return 0; |
||||
|
||||
fail: |
||||
if (s->listen && ret != EADDRINUSE) |
||||
unlink(s->addr.sun_path); |
||||
if (fd >= 0) |
||||
closesocket(fd); |
||||
return ret; |
||||
} |
||||
|
||||
static int unix_read(URLContext *h, uint8_t *buf, int size) |
||||
{ |
||||
UnixContext *s = h->priv_data; |
||||
int ret; |
||||
|
||||
if (!(h->flags & AVIO_FLAG_NONBLOCK)) { |
||||
ret = ff_network_wait_fd(s->fd, 0); |
||||
if (ret < 0) |
||||
return ret; |
||||
} |
||||
ret = recv(s->fd, buf, size, 0); |
||||
return ret < 0 ? ff_neterrno() : ret; |
||||
} |
||||
|
||||
static int unix_write(URLContext *h, const uint8_t *buf, int size) |
||||
{ |
||||
UnixContext *s = h->priv_data; |
||||
int ret; |
||||
|
||||
if (!(h->flags & AVIO_FLAG_NONBLOCK)) { |
||||
ret = ff_network_wait_fd(s->fd, 1); |
||||
if (ret < 0) |
||||
return ret; |
||||
} |
||||
ret = send(s->fd, buf, size, 0); |
||||
return ret < 0 ? ff_neterrno() : ret; |
||||
} |
||||
|
||||
static int unix_close(URLContext *h) |
||||
{ |
||||
UnixContext *s = h->priv_data; |
||||
if (s->listen) |
||||
unlink(s->addr.sun_path); |
||||
closesocket(s->fd); |
||||
return 0; |
||||
} |
||||
|
||||
static int unix_get_file_handle(URLContext *h) |
||||
{ |
||||
UnixContext *s = h->priv_data; |
||||
return s->fd; |
||||
} |
||||
|
||||
URLProtocol ff_unix_protocol = { |
||||
.name = "unix", |
||||
.url_open = unix_open, |
||||
.url_read = unix_read, |
||||
.url_write = unix_write, |
||||
.url_close = unix_close, |
||||
.url_get_file_handle = unix_get_file_handle, |
||||
.priv_data_size = sizeof(UnixContext), |
||||
.priv_data_class = &unix_class, |
||||
.flags = URL_PROTOCOL_FLAG_NETWORK, |
||||
}; |
Loading…
Reference in new issue