[vlc-devel] [PATCH] Flaschen Taschen output: Support for large(r) video sizes
Johannes Lechner
git at fudgy.de
Sat Apr 25 10:06:20 CEST 2020
This patches contains two modifications to make Flaschen Taschen support large(r) video sizes:
(1) Increase of UDP send buffer, allowing maximum-sized UDP packets to be sent
(2) Splitting a frame into multiple UDP packets in case one frame exceeds the maximum UDP packet size
The implemention for (2) draws heavily from the "official" UDPFlaschenTaschen::Send implemention:
https://github.com/hzeller/flaschen-taschen/blob/master/api/lib/udp-flaschen-taschen.cc
---
modules/video_output/flaschen.c | 113 +++++++++++++++++++-------------
1 file changed, 66 insertions(+), 47 deletions(-)
diff --git a/modules/video_output/flaschen.c b/modules/video_output/flaschen.c
index 00e1e66a34..b9f541dc30 100644
--- a/modules/video_output/flaschen.c
+++ b/modules/video_output/flaschen.c
@@ -134,8 +134,9 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
/* Ignore any unexpected incoming packet */
setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0 }, sizeof (int));
-
-
+ /* Increase send buffer size to allow queuing of several "full" UDP packets */
+ setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &(int){ 16 * 65536 }, sizeof (int));
+
*fmtp = fmt;
vd->prepare = NULL;
@@ -155,55 +156,73 @@ static void Close(vout_display_t *vd)
free(sys);
}
+/*
+ * Adaptation of UDPFlaschenTaschen::Send implemention
+ * (https://github.com/hzeller/flaschen-taschen/)
+ */
static void Display(vout_display_t *vd, picture_t *picture)
{
-#ifdef IOV_MAX
- const long iovmax = IOV_MAX;
-#else
- const long iovmax = sysconf(_SC_IOV_MAX);
-#endif
- vout_display_sys_t *sys = vd->sys;
- video_format_t *fmt = &picture->format;
- int result;
-
- char buffer[64];
- int header_len = snprintf(buffer, sizeof(buffer), "P6\n%d %d\n255\n",
- fmt->i_width, fmt->i_height);
- /* TODO: support offset_{x,y,z}? (#FT:...) */
- /* Note the protocol doesn't include any picture order field. */
- /* (maybe add as comment?) */
-
- int iovcnt = 1 + fmt->i_height;
- if (unlikely(iovcnt > iovmax))
- return;
-
- struct iovec iov[iovcnt];
- iov[0].iov_base = buffer;
- iov[0].iov_len = header_len;
-
- uint8_t *src = picture->p->p_pixels;
- for (int i = 1; i < iovcnt; i++)
+ video_format_t *format = &picture->format;
+ uint8_t *pixels = picture->p->p_pixels;
+
+ const int max_data_packet_length = 65507 - 64; // Leave some space for the P6 header
+ const size_t row_size = format->i_width * 3;
+ const int max_send_height = max_data_packet_length / row_size;
+
+ int rows = format->i_height;
+ int row_offset = 0;
+
+ while(rows)
{
- iov[i].iov_base = src;
- iov[i].iov_len = fmt->i_width * 3;
- src += picture->p->i_pitch;
+ // Send as many rows as can fit within one UDP packet
+ const int send_height = (rows < max_send_height) ? rows : max_send_height;
+
+ char p6_header[64];
+ const int p6_header_len = snprintf(p6_header, sizeof(p6_header),
+ "P6\n%d %d\n#FT: %d %d %d\n255\n",
+ format->i_width, send_height,
+ 0, row_offset, 0);
+ //msg_Dbg(vd, "p6_header: %s", p6_header`);
+
+ const int p6_data_len = send_height * row_size;
+
+ // Create and send UDP packet
+ {
+ struct iovec iov[2];
+ iov[0].iov_base = p6_header;
+ iov[0].iov_len = p6_header_len;
+ iov[1].iov_base = pixels;
+ iov[1].iov_len = p6_data_len;
+
+ struct msghdr hdr = {
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_iov = iov,
+ .msg_iovlen = 2,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0 };
+
+ int result;
+ result = sendmsg(vd->sys->fd, &hdr, 0);
+
+ if (result < 0) {
+ msg_Err(vd, "sendmsg: error %s in vout display flaschen, dropping remainder of frame", vlc_strerror_c(errno));
+ // dropping remainder of frame
+ break;
+ }
+ else if (result < (int)(p6_header_len + p6_data_len)) {
+ msg_Err(vd, "sendmsg only sent %d bytes in vout display flaschen, dropping remainder of frame", result);
+ // dropping remainder of frame
+ break;
+ }
+ }
+
+ pixels += p6_data_len;
+
+ rows -= send_height;
+ row_offset += send_height;
}
-
- struct msghdr hdr = {
- .msg_name = NULL,
- .msg_namelen = 0,
- .msg_iov = iov,
- .msg_iovlen = iovcnt,
- .msg_control = NULL,
- .msg_controllen = 0,
- .msg_flags = 0 };
-
- result = sendmsg(sys->fd, &hdr, 0);
- if (result < 0)
- msg_Err(vd, "sendmsg: error %s in vout display flaschen", vlc_strerror_c(errno));
- else if (result < (int)(header_len + fmt->i_width * fmt->i_height * 3))
- msg_Err(vd, "sendmsg only sent %d bytes in vout display flaschen", result);
- /* we might want to drop some frames? */
}
/**
--
2.24.2 (Apple Git-127)
More information about the vlc-devel
mailing list