You can subscribe to this list here.
| 2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(235) |
Aug
(290) |
Sep
(419) |
Oct
(496) |
Nov
(545) |
Dec
(434) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2002 |
Jan
(346) |
Feb
(224) |
Mar
(339) |
Apr
(401) |
May
(366) |
Jun
(570) |
Jul
(491) |
Aug
(369) |
Sep
(479) |
Oct
(681) |
Nov
(752) |
Dec
(998) |
| 2003 |
Jan
(902) |
Feb
(510) |
Mar
(590) |
Apr
(467) |
May
(529) |
Jun
(210) |
Jul
(208) |
Aug
(219) |
Sep
(155) |
Oct
(497) |
Nov
(416) |
Dec
(400) |
| 2004 |
Jan
(270) |
Feb
(175) |
Mar
(285) |
Apr
(404) |
May
(271) |
Jun
(323) |
Jul
(196) |
Aug
(145) |
Sep
(238) |
Oct
(260) |
Nov
(382) |
Dec
(437) |
| 2005 |
Jan
(251) |
Feb
(151) |
Mar
(80) |
Apr
(205) |
May
(266) |
Jun
(125) |
Jul
(308) |
Aug
(184) |
Sep
(188) |
Oct
(221) |
Nov
(132) |
Dec
(98) |
| 2006 |
Jan
(123) |
Feb
(150) |
Mar
(161) |
Apr
(152) |
May
(115) |
Jun
(259) |
Jul
(265) |
Aug
(81) |
Sep
(185) |
Oct
(121) |
Nov
(86) |
Dec
(257) |
| 2007 |
Jan
(233) |
Feb
(210) |
Mar
(306) |
Apr
(628) |
May
(347) |
Jun
(373) |
Jul
(71) |
Aug
(122) |
Sep
(53) |
Oct
(66) |
Nov
(156) |
Dec
(451) |
| 2008 |
Jan
(407) |
Feb
(136) |
Mar
(277) |
Apr
(119) |
May
(254) |
Jun
(162) |
Jul
(53) |
Aug
(43) |
Sep
(6) |
Oct
(3) |
Nov
(58) |
Dec
(51) |
| 2009 |
Jan
(161) |
Feb
(43) |
Mar
(30) |
Apr
(31) |
May
(15) |
Jun
(9) |
Jul
(1) |
Aug
(13) |
Sep
(1) |
Oct
(32) |
Nov
(319) |
Dec
(66) |
| 2010 |
Jan
(93) |
Feb
(41) |
Mar
(76) |
Apr
(56) |
May
(15) |
Jun
(21) |
Jul
(35) |
Aug
|
Sep
|
Oct
(6) |
Nov
|
Dec
|
| 2012 |
Jan
(77) |
Feb
(54) |
Mar
(5) |
Apr
(29) |
May
(35) |
Jun
(63) |
Jul
(26) |
Aug
(22) |
Sep
(3) |
Oct
|
Nov
|
Dec
(8) |
| 2013 |
Jan
(14) |
Feb
(5) |
Mar
(8) |
Apr
(12) |
May
(4) |
Jun
(2) |
Jul
(8) |
Aug
(10) |
Sep
(90) |
Oct
(21) |
Nov
(28) |
Dec
(12) |
| 2014 |
Jan
(6) |
Feb
(27) |
Mar
(19) |
Apr
(47) |
May
(67) |
Jun
(22) |
Jul
(6) |
Aug
(19) |
Sep
(1) |
Oct
(2) |
Nov
(15) |
Dec
(11) |
| 2015 |
Jan
|
Feb
(5) |
Mar
(1) |
Apr
(3) |
May
(1) |
Jun
|
Jul
(2) |
Aug
(4) |
Sep
|
Oct
(1) |
Nov
|
Dec
(10) |
| 2016 |
Jan
(1) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
(3) |
Jul
|
Aug
(5) |
Sep
(20) |
Oct
(6) |
Nov
(24) |
Dec
(12) |
| 2017 |
Jan
(37) |
Feb
(159) |
Mar
(206) |
Apr
(167) |
May
(49) |
Jun
(14) |
Jul
(48) |
Aug
(9) |
Sep
(79) |
Oct
(101) |
Nov
(68) |
Dec
(42) |
| 2018 |
Jan
(70) |
Feb
(76) |
Mar
(152) |
Apr
(161) |
May
(15) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Torsten J. <t....@gm...> - 2018-05-11 17:39:52
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1526060350 -7200
# Node ID ac2674b23cf884267839caa90e88f963a46b647f
# Branch default
# Parent 0c67e8ced9453c585789661528dbf89d1fb24ea4
Optimize demux_ts.
- Use HAVE_ZERO_SAFE_MEM.
- Use _X_BE_32 ().
- Move read buffer to end of instace struct.
- Employ pid index table instead of searching on each packet.
- Fast inline memcpy for small packet payloads on x86.
- Defer discontinuity handling to buffer send.
No need to burn cpu on every ts packet, and to tell engine far early.
- Merge some calls to private functions (smaller code with inlining).
- New packet reader.
- Simplify.
- NULL test.
- More debug messages.
- Silence -Wextra warnings.
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -159,7 +159,7 @@
/*
#define LOG
*/
-/* #define LOG_DYNAMIC_PMT */
+#define LOG_DYNAMIC_PMT
#include "group_video.h"
@@ -167,6 +167,8 @@
#include <xine/xineutils.h>
#include <xine/demux.h>
+#include "bswap.h"
+
/*
#define TS_LOG
#define TS_PMT_LOG
@@ -176,6 +178,33 @@
#define TS_HEADER_LOG // prints out the Transport packet header.
*/
+/* Packet readers: 1 (original), 2 (fast experimental) */
+#define TS_PACKET_READER 2
+
+#if ((defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)) && defined(ARCH_X86)
+static void demux_ts_small_memcpy (void *d, const void *s, size_t l) {
+ __asm__ __volatile__ (
+ "cld\n\trep movsb"
+ : "=D" (d), "=S" (s), "=c" (l)
+ : "0" (d), "1" (s), "2" (l)
+ : "cc"
+ );
+}
+#else
+# define demux_ts_small_memcpy(d,s,l) memcpy (d, s, l)
+#endif
+
+/* transport stream packet layer */
+#define TSP_sync_byte 0xff000000
+#define TSP_transport_error 0x00800000
+#define TSP_payload_unit_start 0x00400000
+#define TSP_transport_priority 0x00200000
+#define TSP_pid 0x001fff00
+#define TSP_scrambling_control 0x000000c0
+#define TSP_adaptation_field_1 0x00000020
+#define TSP_adaptation_field_0 0x00000010
+#define TSP_continuity_counter 0x0000000f
+
/*
* The maximum number of PIDs we are prepared to handle in a single program
* is the number that fits in a single-packet PMT.
@@ -185,15 +214,21 @@
/* more PIDS are needed due "auto-detection". 40 spare media entries */
#define MAX_PIDS ((BODY_SIZE - 1 - 13) / 4) + 40
-#define MAX_PMTS 128
+#define MAX_PMTS 126
#define PAT_BUF_SIZE (4 * MAX_PMTS + 20)
#define SYNC_BYTE 0x47
-#define MIN_SYNCS 3
-#define NPKT_PER_READ 96 // 96*188 = 94*192
-
-#define BUF_SIZE (NPKT_PER_READ * (PKT_SIZE + 4))
+#if TS_PACKET_READER == 1
+# define MIN_SYNCS 3
+# define NPKT_PER_READ 96 // 96*188 = 94*192
+# define BUF_SIZE (NPKT_PER_READ * (PKT_SIZE + 4))
+#endif
+
+#if TS_PACKET_READER == 2
+ /* smallest common multiple of 188 and 192 is 9024 */
+# define BUF_SIZE (2 * 9024)
+#endif
#define CORRUPT_PES_THRESHOLD 10
@@ -301,9 +336,9 @@
*/
typedef struct {
unsigned int pid;
- fifo_buffer_t *fifo;
uint32_t type;
int64_t pts;
+ fifo_buffer_t *fifo;
buf_element_t *buf;
unsigned int counter;
uint16_t descriptor_tag; /* +0x100 for PES stream IDs (no available TS descriptor tag?) */
@@ -366,8 +401,8 @@
uint32_t last_pat_crc;
uint32_t transport_stream_id;
/* programs */
- uint32_t program_number[MAX_PMTS];
- uint32_t pmt_pid[MAX_PMTS];
+ uint32_t program_number[MAX_PMTS + 1];
+ uint32_t pmt_pid[MAX_PMTS + 1];
uint8_t *pmt[MAX_PMTS];
int pmt_write_pos[MAX_PMTS];
uint32_t last_pmt_crc;
@@ -403,12 +438,13 @@
/* dvb */
xine_event_queue_t *event_queue;
+
+#if TS_PACKET_READER == 1
/* For syncronisation */
int32_t packet_number;
/* NEW: var to keep track of number of last read packets */
int32_t npkt_read;
-
- uint8_t buf[BUF_SIZE]; /* == PKT_SIZE * NPKT_PER_READ */
+#endif
off_t frame_pos; /* current ts packet position in input stream (bytes from beginning) */
@@ -417,6 +453,17 @@
int64_t tbre_time, tbre_lasttime;
unsigned int tbre_mode, tbre_pid;
+ /* 0x00 | media_index (video/audio/subtitle)
+ * 0x80 | pmt_index (pmt)
+ * 0xff (special/unused) */
+ uint8_t pid_index[0x2000];
[... 1055 lines omitted ...]
- }
- /* DVBSUB */
- else if (pid == this->spu_pid) {
-#ifdef TS_LOG
- printf ("demux_ts: SPU pid: 0x%.4x\n", pid);
-#endif
- demux_ts_buffer_pes (this, originalPkt+data_offset, this->spu_media,
- payload_unit_start_indicator, continuity_counter,
- data_len);
- return;
- }
+ if (pid == 0x1ffb) {
+ /* printf ("demux_ts: PSIP table. Program Guide etc....not supported yet. PID = 0x1ffb\n"); */
+ return;
}
}
@@ -2513,6 +2668,10 @@
} else {
this->input->seek (this->input, start_pos, SEEK_SET);
}
+#if TS_PACKET_READER == 2
+ this->buf_pos = 0;
+ this->buf_size = 0;
+#endif
}
this->send_newpts = 1;
@@ -2566,6 +2725,7 @@
static uint32_t demux_ts_get_capabilities(demux_plugin_t *this_gen)
{
+ (void)this_gen;
return DEMUX_CAP_AUDIOLANG | DEMUX_CAP_SPULANG;
}
@@ -2629,7 +2789,7 @@
for (i = 0; i < ts_size; i++) {
try_again = 0;
if (buf[i] == SYNC_BYTE) {
- for (j = 1; j < packs; j++) {
+ for (j = 1; j < (int)packs; j++) {
if (buf[i + j*ts_size] != SYNC_BYTE) {
try_again = 1;
break;
@@ -2686,7 +2846,22 @@
* if we reach this point, the input has been accepted.
*/
- this = calloc(1, sizeof(*this));
+ this = calloc (1, sizeof (*this));
+ if (!this)
+ return NULL;
+
+#ifndef HAVE_ZERO_SAFE_MEM
+ this->last_pat_crc = 0;
+ this->scrambled_npids = 0;
+ this->audio_tracks_count = 0;
+ this->last_pmt_crc = 0;
+ this->spu_langs_count = 0;
+# if TS_PACKET_READER == 2
+ this->buf_pos = 0;
+ this->buf_size = 0;
+# endif
+#endif
+
this->stream = stream;
this->input = input;
@@ -2704,26 +2879,28 @@
* Initialise our specialised data.
*/
- this->last_pat_crc = 0;
this->transport_stream_id = -1;
for (i = 0; i < MAX_PIDS; i++) {
this->media[i].pid = INVALID_PID;
+#ifndef HAVE_ZERO_SAFE_MEM
this->media[i].buf = NULL;
+#endif
}
for (i = 0; i < MAX_PMTS; i++) {
- this->program_number[i] = INVALID_PROGRAM;
- this->pmt_pid[i] = INVALID_PID;
- this->pmt[i] = NULL;
- this->pmt_write_pos[i] = 0;
+ this->program_number[i] = INVALID_PROGRAM;
+ this->pmt_pid[i] = INVALID_PID;
+#ifndef HAVE_ZERO_SAFE_MEM
+ this->pmt[i] = NULL;
+ this->pmt_write_pos[i] = 0;
+#endif
}
- this->scrambled_npids = 0;
+ memset (this->pid_index, 0xff, sizeof (this->pid_index));
+
this->videoPid = INVALID_PID;
this->pcr_pid = INVALID_PID;
- this->audio_tracks_count = 0;
- this->last_pmt_crc = 0;
this->rate = 1000000; /* byte/sec */
this->tbre_pid = INVALID_PID;
@@ -2732,7 +2909,6 @@
/* DVBSUB */
this->spu_pid = INVALID_PID;
- this->spu_langs_count = 0;
this->current_spu_channel = -1;
/* dvb */
@@ -2750,6 +2926,8 @@
* ts demuxer class
*/
void *demux_ts_init_class (xine_t *xine, const void *data) {
+ (void)xine;
+ (void)data;
static const demux_class_t demux_ts_class = {
.open_plugin = open_plugin,
@@ -2767,4 +2945,3 @@
return (void *)&demux_ts_class;
}
-
|
|
From: Petri H. <phi...@us...> - 2018-05-09 16:24:35
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525883060 -10800
# Node ID 0c67e8ced9453c585789661528dbf89d1fb24ea4
# Branch default
# Parent 4e2b6627c1c6257805890cc0c35815669d6e8509
remove extra if
diff --git a/m4/summary.m4 b/m4/summary.m4
--- a/m4/summary.m4
+++ b/m4/summary.m4
@@ -13,7 +13,7 @@
echo " - rtsp - rtp"
echo " - net - pnm"
echo " - http - ftp"
- if test x"$have_gnutls" = x"yes" && echo " - https"
+ test x"$have_gnutls" = x"yes" && echo " - https"
test x"$have_libssh2" = x"yes" && echo " - sftp - scp"
test x"$have_libnfs" = x"yes" && echo " - nfs"
test x"$enable_mms" != x"no" && echo " - mms"
|
|
From: Petri H. <phi...@us...> - 2018-05-09 16:20:56
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525769917 -10800
# Node ID 3b75aa1c7e6793c78f79d5ae0745259bb7c7fadd
# Branch default
# Parent 6e4f0b9c5406e5c9df2f1858ab44d13dde69113b
input: add TLS layer (using gnutls)
diff --git a/src/input/Makefile.am b/src/input/Makefile.am
--- a/src/input/Makefile.am
+++ b/src/input/Makefile.am
@@ -25,7 +25,8 @@
http_helper.la \
input_helper.la \
media_helper.la \
- net_buf_ctrl.la
+ net_buf_ctrl.la \
+ xine_tls.la
http_helper_la_SOURCES = http_helper.c http_helper.h
http_helper_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
@@ -39,6 +40,10 @@
net_buf_ctrl_la_SOURCES = net_buf_ctrl.c net_buf_ctrl.h
net_buf_ctrl_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) $(PTHREAD_LIBS)
+xine_tls_la_SOURCES = xine_tls.c xine_tls.h
+xine_tls_la_CFLAGS = $(AM_CFLAGS) $(GNUTLS_CFLAGS)
+xine_tls_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) $(GNUTLS_LIBS)
+
#
#
#
@@ -186,7 +191,7 @@
pnm.c \
pnm.h
xineplug_inp_network_la_LIBADD = $(XINE_LIB) $(NET_LIBS) $(LTLIBINTL) \
- libreal.la librtsp.la http_helper.la input_helper.la net_buf_ctrl.la
+ libreal.la librtsp.la http_helper.la input_helper.la net_buf_ctrl.la xine_tls.la
xineplug_inp_rtp_la_SOURCES = input_rtp.c
xineplug_inp_rtp_la_LIBADD = $(XINE_LIB) $(NET_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) net_buf_ctrl.la input_helper.la
--git a/src/input/xine_tls.c b/src/input/xine_tls.c
new file mode 100644
--- /dev/null
+++ b/src/input/xine_tls.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2000-2018 the xine project
+ * Copyright (C) 2018 Petri Hintukainen <phi...@us...>
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define LOG_MODULE "input_tls"
+
+#include "xine_tls.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#endif /* HAVE_GNUTLS */
+
+#include <xine/xine_internal.h>
+#include <xine/xineutils.h>
+#include <xine/io_helper.h>
+
+
+struct xine_tls {
+ xine_stream_t *stream;
+ int fd;
+
+#ifdef HAVE_GNUTLS
+ int enabled;
+ int need_shutdown;
+
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t cred;
+#endif /* HAVE_GNUTLS */
+};
+
+#ifdef HAVE_GNUTLS
+static int handle_gnutls_error(xine_tls_t *t, int err)
+{
+ switch (err) {
+ case GNUTLS_E_AGAIN:
+ errno = EAGAIN;
+ return -1;
+ default:
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": %s\n", gnutls_strerror(err));
+ break;
+ }
+
+ errno = EIO;
+ return -1;
+}
+#endif /* HAVE_GNUTLS */
+
+ssize_t _x_tls_write(xine_tls_t *t, const void *buf, size_t len)
+{
+#ifdef HAVE_GNUTLS
+ if (t->enabled) {
+ int ret = gnutls_record_send(t->session, buf, len);
+ if (ret < 0)
+ return handle_gnutls_error(t, ret);
+ return ret;
+ }
+#endif /* HAVE_GNUTLS */
+
+ return _x_io_tcp_write(t->stream, t->fd, buf, len);
+}
+
+ssize_t _x_tls_read(xine_tls_t *t, void *buf, size_t len)
+{
+#ifdef HAVE_GNUTLS
+ if (t->enabled) {
+ int ret = gnutls_record_recv(t->session, buf, len);
+ if (ret < 0)
+ return handle_gnutls_error(t, ret);
+ return ret;
+ }
+#endif /* HAVE_GNUTLS */
+
+ return _x_io_tcp_read(t->stream, t->fd, buf, len);
+}
+
+ssize_t _x_tls_read_line(xine_tls_t *t, char *buf, size_t buf_size)
+{
+#ifdef HAVE_GNUTLS
+ if (t->enabled) {
+ int i = 0;
+ ssize_t r;
+ char c;
+
+ if (buf_size <= 0)
+ return 0;
+
+ while ((r = _x_tls_read(t, &c, 1)) == 1) {
+ if (c == '\r' || c == '\n')
+ break;
+ if (i+1 == buf_size)
+ break;
+
+ buf[i] = c;
+ i++;
+ }
+
+ if (r == 1 && c == '\r')
[... 92 lines omitted ...]
+ int fh;
+
+ fh = _x_io_tcp_connect(stream, host, port);
+ if (fh == -1) {
+ return NULL;
+ }
+
+ tls = _x_tls_init(stream, fh);
+ if (!tls) {
+ _x_io_tcp_close(stream, fh);
+ }
+
+ return tls;
+}
+
+int _x_tls_handshake(xine_tls_t *t, const char *host, int verify)
+{
+#ifndef HAVE_GNUTLS
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "No TLS support (gnutls disabled in configure)\n");
+ return -1;
+#else /* HAVE_GNUTLS */
+ int ret;
+
+ _x_assert(t->enabled == 0);
+
+ ret = gnutls_global_init();
+ if (ret) {
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "gnutls_global_init() failed: %s (%d)\n",
+ gnutls_strerror(ret), ret);
+ return -1;
+ }
+
+ gnutls_init(&t->session, GNUTLS_CLIENT);
+ if (host) {
+ gnutls_server_name_set(t->session, GNUTLS_NAME_DNS, host, strlen(host));
+ }
+
+ gnutls_certificate_allocate_credentials(&t->cred);
+ gnutls_certificate_set_x509_system_trust(t->cred);
+ gnutls_certificate_set_verify_flags(t->cred, verify ? GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0);
+ gnutls_credentials_set(t->session, GNUTLS_CRD_CERTIFICATE, t->cred);
+
+ gnutls_transport_set_pull_function(t->session, gnutls_tcp_pull);
+ gnutls_transport_set_push_function(t->session, gnutls_tcp_push);
+ gnutls_transport_set_ptr(t->session, t);
+
+ gnutls_priority_set_direct(t->session, "NORMAL", NULL);
+
+ ret = gnutls_handshake(t->session);
+ if (ret) {
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "TLS handshake failed: %s (%d)\n",
+ gnutls_strerror(ret), ret);
+ return -1;
+ }
+
+ t->need_shutdown = 1;
+
+ if (verify < 0)
+ verify = _x_tls_get_verify_tls_cert(t->stream->xine->config);
+
+ if (verify) {
+ unsigned int status;
+ if ((ret = gnutls_certificate_verify_peers2(t->session, &status)) < 0) {
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "Unable to verify peer certificate: %s (%d)\n",
+ gnutls_strerror(ret), ret);
+ return -2;
+ }
+ if (status & GNUTLS_CERT_INVALID) {
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "Peer certificate failed verification\n");
+ return -2;
+ }
+ if (gnutls_certificate_type_get(t->session) != GNUTLS_CRT_X509) {
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "Unsupported certificate type\n");
+ return -2;
+ }
+ if (host) {
+ unsigned int cert_list_size;
+ gnutls_x509_crt_t cert;
+ const gnutls_datum_t *cert_list;
+ gnutls_x509_crt_init(&cert);
+ cert_list = gnutls_certificate_get_peers(t->session, &cert_list_size);
+ gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER);
+ ret = gnutls_x509_crt_check_hostname(cert, host);
+ gnutls_x509_crt_deinit(cert);
+ if (!ret) {
+ xprintf(t->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "The certificate does not match hostname %s\n",
+ host);
+ return -3;
+ }
+ }
+ }
+
+ t->enabled = 1;
+ return 0;
+#endif /* HAVE_GNUTLS */
+}
+
+/*
+ * config helpers
+ */
+
+void _x_tls_register_config_keys(config_values_t *config)
+{
+ config->register_bool(config,
+ "media.network.verify_tls_certificate",
+ 1, _("Verify server TLS certificate"),
+ _("If enabled, server TLS certificate is always checked. "
+ "If check fails, connections to server are not allowed."),
+ 10, NULL, NULL);
+}
+
+int _x_tls_get_verify_tls_cert(config_values_t *config)
+{
+ cfg_entry_t *entry;
+
+ entry = config->lookup_entry(config, "media.network.verify_tls_certificate");
+ if (entry) {
+ return entry->num_value;
+ }
+ return 1;
+}
--git a/src/input/xine_tls.h b/src/input/xine_tls.h
new file mode 100644
--- /dev/null
+++ b/src/input/xine_tls.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2000-2018 the xine project
+ * Copyright (C) 2018 Petri Hintukainen <phi...@us...>
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * input plugin TLS helpers
+ */
+
+#ifndef XINE_INPUT_TLS_H
+#define XINE_INPUT_TLS_H
+
+/*
+ * xine_tls layer is a simple wrapper for _x_io_tcp_*() functions.
+ * _x_io_*() functions can be simply replaced with _x_tls_*() functions.
+ *
+ * Connection is unencrypted until _x_tls_handshake() is called.
+ * Unencrypted TCP connection can be used even if TLS support was not compiled in.
+ */
+
+#include <xine/xine_internal.h>
+
+typedef struct xine_tls xine_tls_t;
+
+/*
+ * TCP connection
+ */
+
+xine_tls_t *_x_tls_connect(xine_stream_t *stream, const char *host, int port);
+xine_tls_t *_x_tls_init(xine_stream_t *stream, int fd);
+void _x_tls_close(xine_tls_t **); /* note: associated socket is also closed */
+
+ssize_t _x_tls_read(xine_tls_t *, void *data, size_t len);
+ssize_t _x_tls_write(xine_tls_t *, const void *data, size_t len);
+ssize_t _x_tls_read_line(xine_tls_t *, char *buf, size_t buf_size);
+
+/*
+ * TLS
+ */
+
+/**
+ * Initialize TLS
+ *
+ * @param host Host name to check certificate against (may be NULL ex. if numeric address).
+ * @param verify verify certificate. 0 - no, 1 - yes, < 0 - fetch value from xine config.
+ * @return < 0 on error.
+ */
+int _x_tls_handshake(xine_tls_t *, const char *host, int verify);
+
+/**
+ * Shutdown TLS (stop encryption).
+ *
+ * Underlying socket remains open.
+ */
+void _x_tls_shutdown(xine_tls_t *);
+
+/*
+ * config helpers
+ */
+
+void _x_tls_register_config_keys(config_values_t *);
+int _x_tls_get_verify_tls_cert(config_values_t *);
+
+#endif /* XINE_INPUT_TLS_H */
|
|
From: Petri H. <phi...@us...> - 2018-05-09 16:20:56
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525882165 -10800
# Node ID 4e2b6627c1c6257805890cc0c35815669d6e8509
# Branch default
# Parent 3b75aa1c7e6793c78f79d5ae0745259bb7c7fadd
input_http: add TLS support (https)
diff --git a/m4/summary.m4 b/m4/summary.m4
--- a/m4/summary.m4
+++ b/m4/summary.m4
@@ -13,6 +13,7 @@
echo " - rtsp - rtp"
echo " - net - pnm"
echo " - http - ftp"
+ if test x"$have_gnutls" = x"yes" && echo " - https"
test x"$have_libssh2" = x"yes" && echo " - sftp - scp"
test x"$have_libnfs" = x"yes" && echo " - nfs"
test x"$enable_mms" != x"no" && echo " - mms"
--git a/src/input/input_http.c b/src/input/input_http.c
--- a/src/input/input_http.c
+++ b/src/input/input_http.c
@@ -50,10 +50,12 @@
#include "group_network.h"
#include "http_helper.h"
#include "input_helper.h"
+#include "xine_tls.h"
#define BUFSIZE 1024
#define DEFAULT_HTTP_PORT 80
+#define DEFAULT_HTTPS_PORT 443
#define TAG_ICY_NAME "icy-name:"
#define TAG_ICY_GENRE "icy-genre:"
@@ -79,7 +81,7 @@
const char *user_agent;
xine_url_t url;
- int fh;
+ xine_tls_t *tls;
/** Set to 1 if the stream is a NSV stream. */
unsigned int is_nsv:1;
@@ -242,13 +244,13 @@
xine_ui_data_t data;
/* get the length of the metadata */
- if (_x_io_tcp_read (this->stream, this->fh, (char*)&len, 1) != 1)
+ if (_x_tls_read (this->tls, (char*)&len, 1) != 1)
return 0;
lprintf ("http_plugin_read_metainf: len=%d\n", len);
if (len > 0) {
- if (_x_io_tcp_read (this->stream, this->fh, metadata_buf, len * 16) != (len * 16))
+ if (_x_tls_read (this->tls, metadata_buf, len * 16) != (len * 16))
return 0;
metadata_buf[len * 16] = '\0';
@@ -315,7 +317,7 @@
((this->shoutcast_pos + nlen) >= this->shoutcast_metaint)) {
nlen = this->shoutcast_metaint - this->shoutcast_pos;
- nlen = _x_io_tcp_read (this->stream, this->fh, &buf[read_bytes], nlen);
+ nlen = _x_tls_read (this->tls, &buf[read_bytes], nlen);
if (nlen < 0)
goto error;
@@ -324,7 +326,7 @@
this->shoutcast_pos = 0;
} else {
- nlen = _x_io_tcp_read (this->stream, this->fh, &buf[read_bytes], nlen);
+ nlen = _x_tls_read (this->tls, &buf[read_bytes], nlen);
if (nlen < 0)
goto error;
@@ -482,52 +484,49 @@
static void http_close(http_input_plugin_t * this)
{
- if (this->fh != -1) {
- _x_io_tcp_close(this->stream, this->fh);
- this->fh = -1;
- }
-
+ _x_tls_close(&this->tls);
_x_url_cleanup(&this->url);
}
static int http_restart(http_input_plugin_t * this, off_t abs_offset)
{
/* save old stream */
- int old_fh = this->fh;
+ xine_tls_t *old_tls = this->tls;
off_t old_pos = this->curpos;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "input_http: seek to %" PRId64 ": reconnecting ...\n",
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": "
+ "seek to %" PRId64 ": reconnecting ...\n",
(int64_t)abs_offset);
- this->fh = -1;
+ this->tls = NULL;
http_close(this);
this->curpos = abs_offset;
if (this->input_plugin.open(&this->input_plugin) != 1) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "input_http: seek to %" PRId64 " failed (http request failed)\n",
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "seek to %" PRId64 " failed (http request failed)\n",
(int64_t)abs_offset);
+ _x_tls_close(&this->tls);
goto fail;
}
if (this->curpos != abs_offset) {
/* something went wrong ... */
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "input_http: seek to %" PRId64 " failed (server returned invalid range)\n",
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": "
+ "seek to %" PRId64 " failed (server returned invalid range)\n",
(int64_t)abs_offset);
- _x_io_tcp_close(this->stream, this->fh);
+ _x_tls_close(&this->tls);
goto fail;
}
/* close old connection */
- _x_io_tcp_close(this->stream, old_fh);
+ _x_tls_close(&old_tls);
return 0;
fail:
/* restore old stream */
- this->fh = old_fh;
+ this->tls = old_tls;
this->curpos = old_pos;
return -1;
}
@@ -625,6 +624,7 @@
int mpegurl_redirect = 0;
char mime_type[256];
[... 32 lines omitted ...]
- if (use_proxy)
- this->fh = _x_io_tcp_connect (this->stream, this_class->proxyhost, proxyport);
- else
- this->fh = _x_io_tcp_connect (this->stream, this->url.host, this->url.port);
-
- if (this->fh == -1)
+ if (fh == -1)
return -2;
{
@@ -683,16 +687,44 @@
progress = 0;
do {
report_progress(this->stream, progress);
- res = _x_io_select (this->stream, this->fh, XIO_WRITE_READY, 500);
+ res = _x_io_select (this->stream, fh, XIO_WRITE_READY, 500);
progress += (500*100000)/timeout;
- } while ((res == XIO_TIMEOUT) && (progress <= 100000));
+ } while ((res == XIO_TIMEOUT) && (progress <= 100000) && !_x_action_pending(this->stream));
if (res != XIO_READY) {
_x_message(this->stream, XINE_MSG_NETWORK_UNREACHABLE, this->mrl, NULL);
+ _x_io_tcp_close(this->stream, fh);
return -3;
}
}
+ /*
+ * TLS
+ */
+
+ _x_assert(this->tls == NULL);
+
+ this->tls = _x_tls_init(this->stream, fh);
+ if (!this->tls) {
+ _x_io_tcp_close(this->stream, fh);
+ return -2;
+ }
+ fh = -1;
+
+ if (use_tls) {
+ int r = _x_tls_handshake(this->tls, this->url.host, -1);
+ if (r < 0) {
+ _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "TLS handshake failed", NULL);
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": TLS handshake failed\n");
+ return -4;
+ }
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": TLS handshake succeed, connection is encrypted\n");
+ }
+
+ /*
+ * Request
+ */
+
if (use_proxy) {
if (this->url.port != DEFAULT_HTTP_PORT) {
snprintf (buf, sizeof(buf), "GET http://%s:%d%s HTTP/1.0\015\012",
@@ -752,14 +784,19 @@
this->user_agent ? " " : "",
VERSION);
buflen = strlen(buf);
- if (_x_io_tcp_write (this->stream, this->fh, buf, buflen) != buflen) {
+
+ if (_x_tls_write(this->tls, buf, buflen) != buflen) {
_x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "couldn't send request", NULL);
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_http: couldn't send request\n");
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": couldn't send request\n");
return -4;
}
lprintf ("request sent: >%s<\n", buf);
+ /*
+ * Response
+ */
+
/* read and parse reply */
done = 0; len = 0; linenum = 0;
this->contentlength = 0;
@@ -768,7 +805,7 @@
while (!done) {
/* fprintf (stderr, "input_http: read...\n"); */
- if (_x_io_tcp_read (this->stream, this->fh, &buf[len], 1) <= 0) {
+ if (_x_tls_read (this->tls, &buf[len], 1) <= 0) {
return -5;
}
@@ -1042,6 +1079,10 @@
http_input_plugin_t *this;
if (strncasecmp (mrl, "http://", 7) &&
+#ifdef HAVE_TLS
+ /* do not accept https:// unless TLS support was built in */
+ strncasecmp (mrl, "https://", 8) &&
+#endif
strncasecmp (mrl, "unsv://", 7) &&
strncasecmp (mrl, "peercast://pls/", 15) &&
!_x_url_user_agent (mrl) /* user agent hacks */) {
@@ -1056,7 +1097,7 @@
}
this->stream = stream;
- this->fh = -1;
+ this->tls = NULL;
this->nbc = nbc_init (this->stream);
this->input_plugin.open = http_plugin_open;
@@ -1102,7 +1143,7 @@
this->input_class.get_instance = http_class_get_instance;
this->input_class.identifier = "http";
- this->input_class.description = N_("http input plugin");
+ this->input_class.description = N_("http/https input plugin");
this->input_class.get_dir = NULL;
this->input_class.get_autoplay_list = NULL;
this->input_class.dispose = http_class_dispose;
@@ -1157,6 +1198,10 @@
_("A comma-separated list of domain names for which the proxy is to be ignored.\nIf a domain name is prefixed with '=' then it is treated as a host name only (full match required)."), 10,
no_proxy_list_change_cb, (void *) this);
+#ifdef HAVE_TLS
+ _x_tls_register_config_keys(config);
+#endif
+
return this;
}
|
|
From: Petri H. <phi...@us...> - 2018-05-09 16:20:54
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525780914 -10800
# Node ID 6e4f0b9c5406e5c9df2f1858ab44d13dde69113b
# Branch default
# Parent 9f55ef73ef80ef0c6aaa028d05970e864ce5fdee
configure: check for gnutls
diff --git a/m4/input.m4 b/m4/input.m4
--- a/m4/input.m4
+++ b/m4/input.m4
@@ -24,6 +24,7 @@
default_enable_avformat=yes
default_enable_sftp=yes
default_enable_nfs=yes
+ default_enable_tls=yes
default_with_external_dvdnav=yes
case "$host_os" in
@@ -249,4 +250,19 @@
fi
AM_CONDITIONAL(ENABLE_NFS, test "x$have_libnfs" = "xyes")
+ dnl TLS support (ftps, https)
+ XINE_ARG_ENABLE([tls], [Enable TLS support using gnutls (enables secure http (https) and ftp (ftps)])
+ if test "x$enable_tls" != "xno"; then
+ PKG_CHECK_MODULES([GNUTLS], [gnutls >= 3.3.0], [have_gnutls=yes], [have_gnutls=no])
+ if test x"$hard_enable_tls" = x"yes" && test x"$have_gnutls" != x"yes"; then
+ AC_MSG_ERROR([TLS support requested, but gnutls not found])
+ fi
+ AC_SUBST(GNUTLS_CFLAGS)
+ AC_SUBST(GNUTLS_LIBS)
+ fi
+ if test x"$have_gnutls" = x"yes"; then
+ AC_DEFINE([HAVE_GNUTLS], 1, [Define this if you have gnutls installed])
+ dnl prepare for other TLS implementations ...
+ AC_DEFINE([HAVE_TLS], 1, [Define this if you have tls support compiled in])
+ fi
])
|
|
From: Petri H. <phi...@us...> - 2018-05-09 16:20:53
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525760431 -10800
# Node ID 9f55ef73ef80ef0c6aaa028d05970e864ce5fdee
# Branch default
# Parent c2300d104f3ba8b0e2e0f2f76bf58626c614051b
Add configure option to disable mms
diff --git a/m4/input.m4 b/m4/input.m4
--- a/m4/input.m4
+++ b/m4/input.m4
@@ -12,6 +12,7 @@
default_enable_dvb=no
default_enable_dvd=yes
default_enable_gnomevfs=yes
+ default_enable_mms=yes
default_enable_samba=yes
default_enable_v4l=no
default_enable_v4l2=no
@@ -132,7 +133,11 @@
dnl dvdnav
XINE_ARG_ENABLE([dvd], [Disable DVD support])
AM_CONDITIONAL([ENABLE_DVD], [test x"$enable_dvd" != x"no"])
-
+
+ dnl mms
+ XINE_ARG_ENABLE([mms], [Disable MMS support])
+ AM_CONDITIONAL([ENABLE_MMS], [test x"$enable_mms" != x"no"])
+
dnl XXX: This could be cleaned up so that code does not have to ifdef so much
XINE_ARG_WITH([external-dvdnav], [Use external dvdnav library])
if test x"$with_external_dvdnav" != x"no"; then
--git a/m4/summary.m4 b/m4/summary.m4
--- a/m4/summary.m4
+++ b/m4/summary.m4
@@ -13,9 +13,9 @@
echo " - rtsp - rtp"
echo " - net - pnm"
echo " - http - ftp"
- echo " - mms"
test x"$have_libssh2" = x"yes" && echo " - sftp - scp"
test x"$have_libnfs" = x"yes" && echo " - nfs"
+ test x"$enable_mms" != x"no" && echo " - mms"
test x"$have_samba" = x"yes" && echo " - smb"
dnl optical discs
echo " - cdda"
--git a/src/input/Makefile.am b/src/input/Makefile.am
--- a/src/input/Makefile.am
+++ b/src/input/Makefile.am
@@ -122,6 +122,10 @@
in_dvd = xineplug_inp_dvd.la
endif
+if ENABLE_MMS
+in_mms = xineplug_inp_mms.la
+endif
+
if WITH_EXTERNAL_DVDNAV
DVD_CFLAGS = $(DVDNAV_CFLAGS) $(DVDREAD_CFLAGS)
link_dvdnav = $(DVDNAV_LIBS) $(DVDREAD_LIBS)
@@ -153,7 +157,7 @@
$(in_nfs) \
$(in_smb) \
$(in_ssh) \
- xineplug_inp_mms.la \
+ $(in_mms) \
$(in_rtp) \
xineplug_inp_network.la \
$(in_pvr) \
|
|
From: Petri H. <phi...@us...> - 2018-05-09 12:20:18
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525768264 -10800
# Node ID c2300d104f3ba8b0e2e0f2f76bf58626c614051b
# Branch default
# Parent 84fa5a6272bb44c493f00b2a8188cdad7d0db512
input: reduce code duplication
diff --git a/src/input/Makefile.am b/src/input/Makefile.am
--- a/src/input/Makefile.am
+++ b/src/input/Makefile.am
@@ -162,10 +162,10 @@
xineplug_inp_cdda.la
xineplug_inp_file_la_SOURCES = input_file.c
-xineplug_inp_file_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
+xineplug_inp_file_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) input_helper.la
xineplug_inp_test_la_SOURCES = input_test.c
-xineplug_inp_test_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
+xineplug_inp_test_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) input_helper.la
xineplug_inp_dvd_la_SOURCES = input_dvd.c
xineplug_inp_dvd_la_LIBADD = $(XINE_LIB) $(link_dvdnav) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) media_helper.la
@@ -199,7 +199,7 @@
xineplug_inp_vcdo_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) media_helper.la
xineplug_inp_stdin_fifo_la_SOURCES = input_stdin_fifo.c
-xineplug_inp_stdin_fifo_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) net_buf_ctrl.la
+xineplug_inp_stdin_fifo_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) net_buf_ctrl.la input_helper.la
xineplug_inp_dvb_la_SOURCES = input_dvb.c
xineplug_inp_dvb_la_DEPS = $(XDG_BASEDIR_DEPS)
--git a/src/input/input_file.c b/src/input/input_file.c
--- a/src/input/input_file.c
+++ b/src/input/input_file.c
@@ -49,6 +49,8 @@
#include <xine/compat.h>
#include <xine/input_plugin.h>
+#include "input_helper.h"
+
#define MAXFILES 65535
#ifndef WIN32
@@ -64,7 +66,6 @@
xine_t *xine;
const char *origin_path;
- int show_hidden_files;
int mrls_allocated_entries;
xine_mrl_t **mrls;
@@ -165,22 +166,21 @@
static buf_element_t *file_input_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) {
- file_input_plugin_t *this = (file_input_plugin_t *) this_gen;
- buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
-
- if (todo > buf->max_size)
- todo = buf->max_size;
- if (todo < 0) {
- buf->free_buffer (buf);
- return NULL;
- }
-
- buf->type = BUF_DEMUX_BLOCK;
-
#ifdef HAVE_MMAP
if ( file_input_check_mmap(this) ) {
+ file_input_plugin_t *this = (file_input_plugin_t *) this_gen;
+ buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
off_t len = todo;
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
+
+ buf->type = BUF_DEMUX_BLOCK;
+
if ( (this->mmap_curr + len) > (this->mmap_base + this->mmap_len) )
len = (this->mmap_base + this->mmap_len) - this->mmap_curr;
@@ -195,34 +195,12 @@
/* free(buf->mem); buf->mem = NULL; */
this->mmap_curr += len;
- } else
+
+ return buf;
+ }
#endif
- {
- off_t num_bytes, total_bytes = 0;
- buf->content = buf->mem;
-
- while (total_bytes < todo) {
- num_bytes = read (this->fh, buf->mem + total_bytes, todo-total_bytes);
- if (num_bytes <= 0) {
- if (num_bytes < 0) {
- xine_log (this->stream->xine, XINE_LOG_MSG,
- _("input_file: read error (%s)\n"), strerror(errno));
- _x_message(this->stream, XINE_MSG_READ_ERROR,
- this->mrl, NULL);
- }
- buf->free_buffer (buf);
- buf = NULL;
- break;
- }
- total_bytes += num_bytes;
- }
-
- if( buf != NULL )
- buf->size = total_bytes;
- }
-
- return buf;
+ return _x_input_default_read_block(this_gen, fifo, todo);
}
static off_t file_input_seek (input_plugin_t *this_gen, off_t offset, int origin) {
@@ -286,10 +264,6 @@
return 0;
}
-static uint32_t file_input_get_blocksize (input_plugin_t *this_gen) {
- return 0;
-}
-
/*
* Return 1 if filepathname is a directory, otherwise 0
*/
@@ -439,7 +413,7 @@
this->input_plugin.seek = file_input_seek;
this->input_plugin.get_current_pos = file_input_get_current_pos;
this->input_plugin.get_length = file_input_get_length;
- this->input_plugin.get_blocksize = file_input_get_blocksize;
+ this->input_plugin.get_blocksize = _x_input_default_get_blocksize;
this->input_plugin.get_mrl = file_input_get_mrl;
this->input_plugin.get_optional_data = file_input_get_optional_data;
this->input_plugin.dispose = file_input_dispose;
@@ -495,11 +469,7 @@
/*
* Callback for config changes.
*/
-static void file_input_hidden_bool_cb (void *data, xine_cfg_entry_t *cfg) {
- file_input_class_t *this = (file_input_class_t *) data;
- this->show_hidden_files = cfg->num_value;
-}
static void file_input_origin_change_cb (void *data, xine_cfg_entry_t *cfg) {
file_input_class_t *this = (file_input_class_t *) data;
@@ -660,10 +630,13 @@
int num_files = -1;
int (*func) () = file_input_sortfiles_default;
int already_tried = 0;
+ int show_hidden_files;
*nFiles = 0;
memset(current_dir, 0, sizeof(current_dir));
+ show_hidden_files = _x_input_get_show_hidden_files(this->xine->config);
+
/*
* No origin location, so got the content of the current directory
*/
@@ -715,7 +688,7 @@
if(file_input_is_dir(fullfilename)) {
/* if user don't want to see hidden files, ignore them */
- if(this->show_hidden_files == 0 &&
+ if (show_hidden_files == 0 &&
((strlen(pdirent->d_name) > 1)
&& (pdirent->d_name[0] == '.' && pdirent->d_name[1] != '.'))) {
;
@@ -755,7 +728,7 @@
&& (pdirent->d_name[0] == '.' && pdirent->d_name[1] != '.')) {
/* if user don't want to see hidden files, ignore them */
- if(this->show_hidden_files) {
+ if (show_hidden_files) {
hide_files[num_hide_files].origin = strdup(current_dir);
hide_files[num_hide_files].mrl = _x_asprintf("%s%s", current_dir_slashed, pdirent->d_name);
@@ -948,7 +921,6 @@
config_values_t *config = this->xine->config;
config->unregister_callback(config, "media.files.origin_path");
- config->unregister_callback(config, "media.files.show_hidden_files");
while(this->mrls_allocated_entries) {
this->mrls_allocated_entries--;
@@ -995,12 +967,7 @@
0, file_input_origin_change_cb, (void *) this);
}
- this->show_hidden_files = config->register_bool(config,
- "media.files.show_hidden_files",
- 0, _("list hidden files"),
- _("If enabled, the browser to select the file to "
- "play will also show hidden files."),
- 10, file_input_hidden_bool_cb, (void *) this);
+ _x_input_register_show_hidden_files(config);
return this;
}
--git a/src/input/input_stdin_fifo.c b/src/input/input_stdin_fifo.c
--- a/src/input/input_stdin_fifo.c
+++ b/src/input/input_stdin_fifo.c
@@ -176,35 +176,6 @@
return done;
}
-static buf_element_t *stdin_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo,
- off_t todo) {
-
- off_t total_bytes;
- /* stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; */
- buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
-
- if (todo > buf->max_size)
- todo = buf->max_size;
- if (todo < 0) {
- buf->free_buffer (buf);
- return NULL;
- }
-
- buf->content = buf->mem;
- buf->type = BUF_DEMUX_BLOCK;
-
- total_bytes = stdin_plugin_read (this_gen, (char*)buf->content, todo);
-
- if (total_bytes != todo) {
- buf->free_buffer (buf);
- return NULL;
- }
-
- buf->size = total_bytes;
-
- return buf;
-}
-
/* forward reference */
static off_t stdin_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) {
@@ -366,7 +337,7 @@
this->input_plugin.open = stdin_plugin_open;
this->input_plugin.get_capabilities = _x_input_get_capabilities_preview;
this->input_plugin.read = stdin_plugin_read;
- this->input_plugin.read_block = stdin_plugin_read_block;
+ this->input_plugin.read_block = _x_input_default_read_block;
this->input_plugin.seek = stdin_plugin_seek;
this->input_plugin.get_current_pos = stdin_plugin_get_current_pos;
this->input_plugin.get_length = stdin_plugin_get_length;
--git a/src/input/input_test.c b/src/input/input_test.c
--- a/src/input/input_test.c
+++ b/src/input/input_test.c
@@ -45,6 +45,8 @@
#include <xine/input_plugin.h>
#include <xine/video_out.h>
+#include "input_helper.h"
+
/* describe tests here */
static const char * const test_names[] = {
"test://",
@@ -558,10 +560,6 @@
/* instance functions */
-static uint32_t test_plugin_get_capabilities (input_plugin_t *this_gen) {
- return INPUT_CAP_SEEKABLE;
-}
-
static off_t test_plugin_read (input_plugin_t *this_gen, void *buf, off_t len) {
test_input_plugin_t *this = (test_input_plugin_t *) this_gen;
@@ -599,39 +597,16 @@
return len;
}
-static buf_element_t *test_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo,
- off_t todo) {
- test_input_plugin_t *this = (test_input_plugin_t *) this_gen;
- buf_element_t *buf;
-
- if (!this->buf || (todo < 0)) return NULL;
-
- buf = fifo->buffer_pool_alloc (fifo);
- if (todo > buf->max_size) todo = buf->max_size;
- buf->type = BUF_DEMUX_BLOCK;
- test_plugin_read (this_gen, buf->content, todo);
-
- return buf;
-}
-
static off_t test_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) {
test_input_plugin_t *this = (test_input_plugin_t *) this_gen;
- off_t newpos = offset;
- switch (origin) {
- case SEEK_SET: break;
- case SEEK_CUR: newpos += this->filepos; break;
- case SEEK_END: newpos += this->filesize; break;
- default: newpos = -1;
+ offset = _x_input_translate_seek(offset, origin, this->filepos, this->filesize);
+
+ if (offset >= 0) {
+ this->filepos = offset;
}
- if ((newpos < 0) || (newpos > this->filesize)) {
- errno = EINVAL;
- return (off_t)-1;
- }
-
- this->filepos = newpos;
- return newpos;
+ return offset;
}
static off_t test_plugin_get_current_pos (input_plugin_t *this_gen) {
@@ -646,22 +621,12 @@
return this->filesize;
}
-static uint32_t test_plugin_get_blocksize (input_plugin_t *this_gen) {
- return 0;
-}
-
static const char *test_plugin_get_mrl (input_plugin_t *this_gen) {
test_input_plugin_t *this = (test_input_plugin_t *) this_gen;
return test_names[this->index];
}
-static int test_plugin_get_optional_data (input_plugin_t *this_gen, void *data,
- int data_type) {
-
- return INPUT_OPTIONAL_UNSUPPORTED;
-}
-
static void test_plugin_dispose (input_plugin_t *this_gen ) {
test_input_plugin_t *this = (test_input_plugin_t *) this_gen;
@@ -690,15 +655,15 @@
this->index = i;
this->input_plugin.open = test_plugin_open;
- this->input_plugin.get_capabilities = test_plugin_get_capabilities;
+ this->input_plugin.get_capabilities = _x_input_get_capabilities_seekable;
this->input_plugin.read = test_plugin_read;
- this->input_plugin.read_block = test_plugin_read_block;
+ this->input_plugin.read_block = _x_input_default_read_block;
this->input_plugin.seek = test_plugin_seek;
this->input_plugin.get_current_pos = test_plugin_get_current_pos;
this->input_plugin.get_length = test_plugin_get_length;
- this->input_plugin.get_blocksize = test_plugin_get_blocksize;
+ this->input_plugin.get_blocksize = _x_input_default_get_blocksize;
this->input_plugin.get_mrl = test_plugin_get_mrl;
- this->input_plugin.get_optional_data = test_plugin_get_optional_data;
+ this->input_plugin.get_optional_data = _x_input_default_get_optional_data;
this->input_plugin.dispose = test_plugin_dispose;
this->input_plugin.input_class = cls_gen;
--git a/src/xine-engine/builtins.c b/src/xine-engine/builtins.c
--- a/src/xine-engine/builtins.c
+++ b/src/xine-engine/builtins.c
@@ -38,6 +38,8 @@
#undef LOG_MODULE
#include "../input/net_buf_ctrl.c"
#undef LOG_MODULE
+#include "../input/input_helper.c"
+#undef LOG_MODULE
#include "../input/input_file.c"
#undef LOG_MODULE
#include "../input/input_stdin_fifo.c"
|
|
From: Petri H. <phi...@us...> - 2018-05-09 12:17:49
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525759937 -10800
# Node ID 84fa5a6272bb44c493f00b2a8188cdad7d0db512
# Branch default
# Parent 0e5501b39a697f46a6dc7530fe3a2919db115ee7
Cosmetics (reorder input plugin summary)
diff --git a/m4/summary.m4 b/m4/summary.m4
--- a/m4/summary.m4
+++ b/m4/summary.m4
@@ -8,10 +8,17 @@
dnl Input
echo " * input plugins:"
- echo " - file - net"
- echo " - stdin_fifo - rtp"
- echo " - http - mms"
- echo " - pnm - rtsp"
+ echo " - file - stdin_fifo"
+ dnl network
+ echo " - rtsp - rtp"
+ echo " - net - pnm"
+ echo " - http - ftp"
+ echo " - mms"
+ test x"$have_libssh2" = x"yes" && echo " - sftp - scp"
+ test x"$have_libnfs" = x"yes" && echo " - nfs"
+ test x"$have_samba" = x"yes" && echo " - smb"
+ dnl optical discs
+ echo " - cdda"
if test x"$enable_vcd" != x"no"; then
if test x"$enable_vcdo" != x"no"; then
echo " - vcdo - vcd"
@@ -19,7 +26,6 @@
echo " - vcd"
fi
fi
- echo " - ftp"
if test x"$enable_dvd" != x"no"; then
if test x"$with_external_dvdnav" != x"no"; then
echo " - dvd (external libs)"
@@ -27,17 +33,13 @@
echo " - dvd (*INTERNAL* libs)"
fi
fi
- test x"$enable_vdr" != x"no" && echo " - vdr"
- test x"$have_dvb" = x"yes" && echo " - dvb"
- test x"$have_gnomevfs" = x"yes" && echo " - gnome-vfs"
- test x"$have_samba" = x"yes" && echo " - smb"
- test x"$have_v4l" = x"yes" && echo " - v4l"
- test x"$have_v4l2" = x"yes" && echo " - v4l2"
- echo " - cdda"
test x"$have_libbluray" = x"yes" && echo " - bluray"
- test x"$have_libssh2" = x"yes" && echo " - sftp"
- test x"$have_libssh2" = x"yes" && echo " - scp"
- test x"$have_libnfs" = x"yes" && echo " - nfs"
+ dnl misc
+ test x"$have_dvb" = x"yes" && echo " - dvb"
+ test x"$have_v4l" = x"yes" && echo " - v4l"
+ test x"$have_v4l2" = x"yes" && echo " - v4l2"
+ test x"$enable_vdr" != x"no" && echo " - vdr"
+ test x"$have_gnomevfs" = x"yes" && echo " - gnome-vfs"
test x"$enable_ffmpeg" != x"no" -a x"$have_avformat" = x"yes" && echo " - avio (libavformat)"
echo " - test"
echo ""
|
|
From: Petri H. <phi...@us...> - 2018-05-09 11:58:39
|
# HG changeset patch # User Petri Hintukainen <phi...@us...> # Date 1525758863 -10800 # Node ID 0e5501b39a697f46a6dc7530fe3a2919db115ee7 # Branch default # Parent 1791383e3ad1504bef60a38c1efb438652bdbec0 Cosmetics diff --git a/src/input/Makefile.am b/src/input/Makefile.am --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -171,7 +171,16 @@ xineplug_inp_dvd_la_LIBADD = $(XINE_LIB) $(link_dvdnav) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) media_helper.la xineplug_inp_dvd_la_CFLAGS = $(AM_CFLAGS) $(DVD_CFLAGS) -xineplug_inp_network_la_SOURCES = group_network.c group_network.h input_net.c input_http.c input_pnm.c pnm.c pnm.h input_rtsp.c input_ftp.c +xineplug_inp_network_la_SOURCES = \ + group_network.c \ + group_network.h \ + input_ftp.c \ + input_http.c \ + input_net.c \ + input_pnm.c \ + input_rtsp.c \ + pnm.c \ + pnm.h xineplug_inp_network_la_LIBADD = $(XINE_LIB) $(NET_LIBS) $(LTLIBINTL) \ libreal.la librtsp.la http_helper.la input_helper.la net_buf_ctrl.la |
|
From: Torsten J. <t....@gm...> - 2018-05-07 17:29:40
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1525714145 -7200
# Node ID 1791383e3ad1504bef60a38c1efb438652bdbec0
# Branch default
# Parent 83664037d4393a4c2bdbd1154a3c144e3a1c2544
demux_qt update 6.
- Fast ms time and normpos calculation.
- Time based normpos, independent of file chunk structure.
- Fix keyframe report normpos (was all 0 due to yet unset data size).
- Simplify.
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.c
@@ -374,6 +374,9 @@
unsigned int modification_time;
unsigned int timescale; /* base clock frequency is Hz */
unsigned int duration;
+ int32_t msecs;
+ uint32_t normpos_mul;
+ uint32_t normpos_shift;
int64_t moov_first_offset;
@@ -662,6 +665,8 @@
info->creation_time = 0;
info->modification_time = 0;
info->duration = 0;
+ info->normpos_mul = 0;
+ info->normpos_shift = 0;
info->trak_count = 0;
info->traks = NULL;
info->artist = NULL;
@@ -680,6 +685,7 @@
info->last_error = QT_OK;
info->demux = demux;
info->timescale = 1;
+ info->msecs = 1;
info->video_trak = -1;
info->audio_trak = -1;
info->chosen_reference = -1;
@@ -1708,6 +1714,36 @@
return QT_OK;
}
+static void qt_normpos_init (qt_info *info) {
+ uint32_t n = info->msecs, dbits = 32, sbits;
+ while (!(n & 0x80000000))
+ dbits--, n <<= 1;
+ /* _mul setup limit: sbits <= 64 - 16
+ * mbits = 16 + sbits - dbits;
+ * _mul usage limit: mbits <= 64 - dbits
+ * 16 + sbits - dbits <= 64 - dbits
+ * sbits <= 48
+ * usage simplifiction: mbits <= 32
+ * 16 + sbits - dbits <= 32
+ * sbits <= 16 + dbits
+ */
+ sbits = 16 + dbits - 1; /* safety */
+ info->normpos_shift = sbits;
+ info->normpos_mul = ((uint64_t)0xffff << sbits) / (uint32_t)info->msecs;
+}
+
+static int32_t qt_msec_2_normpos (qt_info *info, int32_t msec) {
+ return ((uint64_t)msec * info->normpos_mul) >> info->normpos_shift;
+}
+
+static int32_t qt_pts_2_msecs (int64_t pts) {
+#ifdef ARCH_X86_32
+ return (pts * (int32_t)((((uint32_t)1 << 31) + 22) / 45)) >> 32;
+#else
+ return pts / 90;
+#endif
+}
+
#define KEYFRAMES_SIZE 1024
static void qt_keyframes_add (qt_trak *trak, qt_frame *f) {
xine_keyframes_entry_t *e = trak->keyframes_list;
@@ -1719,8 +1755,7 @@
trak->keyframes_size += KEYFRAMES_SIZE;
}
e += trak->keyframes_used++;
- e->msecs = f->pts / 90;
- e->normpos = (trak->info->demux->data_size > 0) ? QTF_OFFSET(f[0]) * 65335 / trak->info->demux->data_size : 0;
+ e->msecs = qt_pts_2_msecs (f->pts);
}
static void qt_keyframes_size (qt_trak *trak, uint32_t n) {
@@ -1738,8 +1773,7 @@
static void qt_keyframes_simple_add (qt_trak *trak, qt_frame *f) {
xine_keyframes_entry_t *e = trak->keyframes_list;
e += trak->keyframes_used++;
- e->msecs = f->pts / 90;
- e->normpos = (trak->info->demux->data_size > 0) ? QTF_OFFSET(f[0]) * 65335 / trak->info->demux->data_size : 0;
+ e->msecs = qt_pts_2_msecs (f->pts);
}
static qt_error build_frame_table (qt_trak *trak, unsigned int global_timescale) {
@@ -2722,39 +2756,62 @@
fragment_scan (info, input);
}
+ /* get real duration */
+ {
+ qt_trak *trak = info->traks;
+ uint32_t n;
+ for (n = info->trak_count; n; n--) {
+ if (trak->frame_count) {
+ int32_t msecs = qt_pts_2_msecs (trak->frames[trak->frame_count].pts);
+ if (msecs > info->msecs)
+ info->msecs = msecs;
+ }
+ trak++;
+ }
+ }
+ qt_normpos_init (info);
+
for (i = 0; i < info->trak_count; i++) {
+ qt_trak *trak = info->traks + i;
#if DEBUG_DUMP_MOOV
unsigned int j;
/* dump the frame table in debug mode */
- for (j = 0; j < info->traks[i].frame_count; j++)
+ for (j = 0; j < trak->frame_count; j++)
debug_frame_table(" %d: %8X bytes @ %"PRIX64", %"PRId64" pts, media id %d%s\n",
j,
- info->traks[i].frames[j].size,
- QTF_OFFSET(info->traks[i].frames[j]),
- info->traks[i].frames[j].pts,
- (int)QTF_MEDIA_ID(info->traks[i].frames[j]),
- (QTF_KEYFRAME(info->traks[i].frames[j])) ? " (keyframe)" : "");
+ trak->frames[j].size,
+ QTF_OFFSET(trak[0].frames[j]),
+ trak->frames[j].pts,
+ (int)QTF_MEDIA_ID(trak[0].frames[j]),
+ (QTF_KEYFRAME(trak[0].frames[j])) ? " (keyframe)" : "");
#endif
/* decide which audio trak and which video trak has the most frames */
- if ((info->traks[i].type == MEDIA_VIDEO) &&
[... 12 lines omitted ...]
+ max_video_frames = trak->frame_count;
+
+ if (trak->keyframes_list) {
+ xine_keyframes_entry_t *e = trak->keyframes_list;
+ uint32_t n = trak->keyframes_used;
+ while (n--) {
+ e->normpos = qt_msec_2_normpos (info, e->msecs);
+ e++;
+ }
+ _x_keyframes_set (info->demux->stream, trak->keyframes_list, trak->keyframes_used);
+ }
+
+ } else if ((trak->type == MEDIA_AUDIO) &&
+ (trak->frame_count > max_audio_frames)) {
info->audio_trak = i;
- max_audio_frames = info->traks[i].frame_count;
+ max_audio_frames = trak->frame_count;
}
- free (info->traks[i].keyframes_list);
- info->traks[i].keyframes_list = NULL;
- info->traks[i].keyframes_size = 0;
+ free (trak->keyframes_list);
+ trak->keyframes_list = NULL;
+ trak->keyframes_size = 0;
}
/* check for references */
@@ -3091,10 +3148,8 @@
while (remaining_sample_bytes) {
buf = this->video_fifo->buffer_pool_size_alloc (this->video_fifo, remaining_sample_bytes);
buf->type = trak->properties->codec_buftype;
- if( this->data_size )
- buf->extra_info->input_normpos = (int)((double)(QTF_OFFSET(trak->frames[i]) - this->data_start)
- * 65535 / this->data_size);
- buf->extra_info->input_time = trak->frames[i].pts / 90;
+ buf->extra_info->input_time = qt_pts_2_msecs (trak->frames[i].pts);
+ buf->extra_info->input_normpos = qt_msec_2_normpos (&this->qt, buf->extra_info->input_time);
buf->pts = trak->frames[i].pts + (int64_t)trak->frames[i].ptsoffs;
buf->decoder_flags |= BUF_FLAG_FRAMERATE;
@@ -3154,9 +3209,8 @@
while (remaining_sample_bytes) {
buf = this->audio_fifo->buffer_pool_size_alloc (this->audio_fifo, remaining_sample_bytes);
buf->type = trak->properties->codec_buftype;
- if( this->data_size )
- buf->extra_info->input_normpos = (int)((double)(QTF_OFFSET(trak->frames[i]) - this->data_start)
- * 65535 / this->data_size);
+ buf->extra_info->input_time = qt_pts_2_msecs (trak->frames[i].pts);
+ buf->extra_info->input_normpos = qt_msec_2_normpos (&this->qt, buf->extra_info->input_time);
/* The audio chunk is often broken up into multiple 8K buffers when
* it is sent to the audio decoder. Only attach the proper timestamp
* to the first buffer. This is for the linear PCM decoder which
@@ -3166,7 +3220,6 @@
if ((buf->type == BUF_AUDIO_LPCM_BE) ||
(buf->type == BUF_AUDIO_LPCM_LE)) {
if (first_buf) {
- buf->extra_info->input_time = trak->frames[i].pts / 90;
buf->pts = trak->frames[i].pts;
first_buf = 0;
} else {
@@ -3174,7 +3227,6 @@
buf->pts = 0;
}
} else {
- buf->extra_info->input_time = trak->frames[i].pts / 90;
buf->pts = trak->frames[i].pts;
}
@@ -3495,11 +3547,14 @@
int best_index;
int left, middle, right;
+#ifdef QT_OFFSET_SEEK
int found;
+#endif
if (!trak->frame_count)
return QT_OK;
+#ifdef QT_OFFSET_SEEK
/* perform a binary search on the trak, testing the offset
* boundaries first; offset request has precedent over time request */
if (start_pos) {
@@ -3526,8 +3581,14 @@
best_index = middle;
}
- } else {
- int64_t pts = 90 * start_time;
+ } else
+#else
+ if (start_pos) {
+ start_time = (uint64_t)(start_pos & 0xffff) * (uint32_t)trak->info->msecs / 0xffff;
+ }
+#endif
+ {
+ int64_t pts = (int64_t)90 * start_time;
if (pts <= trak->frames[0].pts)
best_index = 0;
@@ -3562,8 +3623,10 @@
int i;
int64_t keyframe_pts = -1;
+#ifdef QT_OFFSET_SEEK
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
+#endif
/* short-circuit any attempts to seek in a non-seekable stream, including
* seeking in the forward direction; this may change later */
@@ -3642,13 +3705,8 @@
}
static int demux_qt_get_stream_length (demux_plugin_t *this_gen) {
-
demux_qt_t *this = (demux_qt_t *) this_gen;
-
- if (this->qt.timescale == 0)
- return 0;
-
- return (int)((int64_t) 1000 * this->qt.duration / this->qt.timescale);
+ return this->qt.msecs;
}
static uint32_t demux_qt_get_capabilities(demux_plugin_t *this_gen) {
|
|
From: Petri H. <phi...@us...> - 2018-05-07 10:05:24
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525687504 -10800
# Node ID 83664037d4393a4c2bdbd1154a3c144e3a1c2544
# Branch default
# Parent 366b2f964ecac310965014a8ef9c128bbeb8dfd0
ipmovie: check seek result
diff --git a/src/demuxers/demux_ipmovie.c b/src/demuxers/demux_ipmovie.c
--- a/src/demuxers/demux_ipmovie.c
+++ b/src/demuxers/demux_ipmovie.c
@@ -203,12 +203,14 @@
case OPCODE_END_OF_STREAM:
lprintf("end of stream\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_END_OF_CHUNK:
lprintf("end of chunk\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_CREATE_TIMER:
@@ -261,7 +263,8 @@
case OPCODE_START_STOP_AUDIO:
lprintf("start/stop audio\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_INIT_VIDEO_BUFFERS:
@@ -296,12 +299,14 @@
case OPCODE_UNKNOWN_14:
case OPCODE_UNKNOWN_15:
lprintf("unknown (but documented) opcode %02X\n", opcode_type);
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_SEND_BUFFER:
lprintf("send buffer\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_AUDIO_FRAME:
@@ -314,7 +319,8 @@
opcode_size -= 6;
this->audio_frame_count +=
(opcode_size / this->wave.nChannels / (this->wave.wBitsPerSample / 8));
- this->input->seek(this->input, 6, SEEK_CUR);
+ if (this->input->seek(this->input, 6, SEEK_CUR) < 0)
+ return CHUNK_BAD;
} else
this->audio_frame_count +=
(opcode_size - 6) / this->wave.nChannels;
@@ -353,23 +359,27 @@
this->audio_fifo->put (this->audio_fifo, buf);
}
}else{
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
}
break;
case OPCODE_SILENCE_FRAME:
lprintf("silence frame\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_INIT_VIDEO_MODE:
lprintf("initialize video mode\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_CREATE_GRADIENT:
lprintf("create gradient\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_SET_PALETTE:
@@ -408,7 +418,8 @@
case OPCODE_SET_PALETTE_COMPRESSED:
lprintf("set palette compressed\n");
- this->input->seek(this->input, opcode_size, SEEK_CUR);
+ if (this->input->seek(this->input, opcode_size, SEEK_CUR) < 0)
+ return CHUNK_BAD;
break;
case OPCODE_SET_DECODING_MAP:
@@ -533,7 +544,8 @@
return 0;
/* file is qualified; skip over the signature bytes (+ 6 unknown) in the stream */
- this->input->seek(this->input, IPMOVIE_SIGNATURE_SIZE+6, SEEK_SET);
+ if (this->input->seek(this->input, IPMOVIE_SIGNATURE_SIZE+6, SEEK_SET) < 0)
+ return 0;
/* process the first chunk which should be CHUNK_INIT_VIDEO */
if (process_ipmovie_chunk(this) != CHUNK_INIT_VIDEO)
|
|
From: Petri H. <phi...@us...> - 2018-05-07 10:04:02
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525686086 -10800
# Node ID 366b2f964ecac310965014a8ef9c128bbeb8dfd0
# Branch default
# Parent fe5e00ae4659a2d271cc9fbb4a977c90e91b4299
demux_ts: enable seeking when input supports slow seek
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -2499,7 +2499,7 @@
start_pos = (off_t) ( (double) start_pos / 65535 *
this->input->get_length (this->input) );
- if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) {
+ if (this->input->get_capabilities(this->input) & (INPUT_CAP_SEEKABLE | INPUT_CAP_SLOW_SEEKABLE)) {
if ((!start_pos) && (start_time)) {
|
|
From: Petri H. <phi...@us...> - 2018-05-07 10:04:02
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1523815790 -10800
# Node ID fe5e00ae4659a2d271cc9fbb4a977c90e91b4299
# Branch default
# Parent 538f7599aa30c41fdebf756d3a97581775a4336b
http: support (slow) seeking
diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+ * Add seeking support to http input plugin.
+
xine-lib (1.2.9) 2018-01-11
* Add LIBXINE_VERBOSITY environment var override.
* Add auto gapless switch.
--git a/src/input/input_http.c b/src/input/input_http.c
--- a/src/input/input_http.c
+++ b/src/input/input_http.c
@@ -88,6 +88,9 @@
/** Set to 1 if the stream is ShoutCast. */
unsigned int shoutcast_mode:1;
+ /* set to 1 if server replied with Accept-Ranges: bytes */
+ unsigned int accept_range:1;
+
/* ShoutCast */
int shoutcast_metaint;
off_t shoutcast_pos;
@@ -465,6 +468,9 @@
!strncmp(this->url.uri + strlen(this->url.uri) - 4, ".nsv", 4))
caps |= INPUT_CAP_RIP_FORBIDDEN;
+ if (this->accept_range) {
+ caps |= INPUT_CAP_SLOW_SEEKABLE;
+ }
return caps;
}
@@ -484,11 +490,70 @@
_x_url_cleanup(&this->url);
}
+static int http_restart(http_input_plugin_t * this, off_t abs_offset)
+{
+ /* save old stream */
+ int old_fh = this->fh;
+ off_t old_pos = this->curpos;
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "input_http: seek to %" PRId64 ": reconnecting ...\n",
+ (int64_t)abs_offset);
+
+ this->fh = -1;
+ http_close(this);
+
+ this->curpos = abs_offset;
+ if (this->input_plugin.open(&this->input_plugin) != 1) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "input_http: seek to %" PRId64 " failed (http request failed)\n",
+ (int64_t)abs_offset);
+ goto fail;
+ }
+
+ if (this->curpos != abs_offset) {
+ /* something went wrong ... */
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "input_http: seek to %" PRId64 " failed (server returned invalid range)\n",
+ (int64_t)abs_offset);
+ _x_io_tcp_close(this->stream, this->fh);
+ goto fail;
+ }
+
+ /* close old connection */
+ _x_io_tcp_close(this->stream, old_fh);
+
+ return 0;
+
+ fail:
+ /* restore old stream */
+ this->fh = old_fh;
+ this->curpos = old_pos;
+ return -1;
+}
+
static off_t http_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin) {
http_input_plugin_t *this = (http_input_plugin_t *) this_gen;
+ off_t abs_offset;
- return _x_input_seek_preview(this_gen, offset, origin,
- &this->curpos, this->contentlength, this->preview_size);
+ abs_offset = _x_input_seek_preview(this_gen, offset, origin,
+ &this->curpos, this->contentlength, this->preview_size);
+
+ if (abs_offset < 0 && this->accept_range) {
+
+ abs_offset = _x_input_translate_seek(offset, origin, this->curpos, this->contentlength);
+ if (abs_offset < 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "input_http: invalid seek request (%d, %" PRId64 ")\n",
+ origin, (int64_t)offset);
+ return -1;
+ }
+
+ if (http_restart(this, abs_offset) < 0)
+ return -1;
+ }
+
+ return abs_offset;
}
static const char* http_plugin_get_mrl (input_plugin_t *this_gen) {
@@ -603,8 +668,6 @@
else
this->fh = _x_io_tcp_connect (this->stream, this->url.host, this->url.port);
- this->curpos = 0;
-
if (this->fh == -1)
return -2;
@@ -650,6 +713,15 @@
snprintf (buf + buflen, sizeof(buf) - buflen, "Host: %s\015\012",
this->url.host);
+ if (this->curpos > 0) {
+ /* restart from offset */
+ buflen = strlen(buf);
+ snprintf (buf + buflen, sizeof(buf) - buflen, "Range: bytes=%" PRId64 "-\015\012",
+ (int64_t)this->curpos/*, (int64_t)this->contentlength - 1*/);
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_http: requesting restart from offset %" PRId64 "\n",
+ (int64_t)this->curpos);
+ }
+
buflen = strlen(buf);
if (use_proxy && this_class->proxyuser && strlen(this_class->proxyuser)) {
char *proxyauth;
@@ -691,6 +763,7 @@
/* read and parse reply */
done = 0; len = 0; linenum = 0;
this->contentlength = 0;
+ this->curpos = 0;
while (!done) {
/* fprintf (stderr, "input_http: read...\n"); */
@@ -772,6 +845,39 @@
}
}
+ if (!strncasecmp(buf, "Content-Range", 13)) {
+ intmax_t contentlength, range_start, range_end;
+ if (sscanf(buf, "Content-Range: bytes %" SCNdMAX "-%" SCNdMAX "/%" SCNdMAX,
+ &range_start, &range_end, &contentlength) == 3) {
+ this->curpos = range_start;
+ this->contentlength = contentlength;
+ if (contentlength != range_end + 1) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "input_http: Reveived invalid content range: \'%s\'\n", buf);
+ /* truncate - there won't be more data anyway */
+ this->contentlength = range_end + 1;
+ } else {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "input_http: Stream starting at offset %" PRIdMAX "\n", range_start);
+ }
+ } else {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "input_http: Error parsing \'%s\'\n", buf);
+ }
+ }
+
+ if (!strncasecmp(buf, "Accept-Ranges", 13)) {
+ if (strstr(buf + 14, "bytes")) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "input_http: Server supports request ranges. Enabling seeking support.\n");
+ this->accept_range = 1;
+ } else {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "input_http: Unknown value in header \'%s\'\n", buf + 14);
+ this->accept_range = 0;
+ }
+ }
+
if (!strncasecmp(buf, "Location: ", 10)) {
char *href = (buf + 10);
@@ -892,6 +998,12 @@
}
}
+ if (this->curpos > 0) {
+ /* restarting after seek */
+ this->preview_size = 0;
+ return 1;
+ }
+
/*
* fill preview buffer
*/
|
|
From: Petri H. <phi...@us...> - 2018-05-07 05:33:04
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1525077943 -10800
# Node ID 538f7599aa30c41fdebf756d3a97581775a4336b
# Branch default
# Parent c29602c42c5461773552bc3a378bc944435a8abb
vo_none: drop unused variables
diff --git a/src/video_out/video_out_none.c b/src/video_out/video_out_none.c
--- a/src/video_out/video_out_none.c
+++ b/src/video_out/video_out_none.c
@@ -44,19 +44,16 @@
int height;
double ratio;
int format;
- xine_t *xine;
} vo_none_frame_t;
typedef struct {
vo_driver_t vo_driver;
- config_values_t *config;
int ratio;
xine_t *xine;
} vo_none_driver_t;
typedef struct {
video_driver_class_t driver_class;
- config_values_t *config;
xine_t *xine;
} vo_none_class_t;
@@ -253,7 +250,6 @@
driver = calloc(1, sizeof(vo_none_driver_t));
- driver->config = class->config;
driver->xine = class->xine;
driver->ratio = XINE_VO_ASPECT_AUTO;
@@ -287,7 +283,6 @@
this->driver_class.description = N_("xine video output plugin which displays nothing");
this->driver_class.dispose = default_video_driver_class_dispose;
- this->config = xine->config;
this->xine = xine;
return this;
|
|
From: Torsten J. <t....@gm...> - 2018-05-05 15:00:02
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1525532370 -7200
# Node ID c29602c42c5461773552bc3a378bc944435a8abb
# Branch default
# Parent 9276a5491faf3a25385ea1074517d84de6a515aa
demux_qt update 5.
- Embed qt_info.
- More frame builder optimization.
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.c
@@ -169,8 +169,10 @@
/**
* @brief Network bandwidth, cribbed from src/input/input_mms.c
*/
-static const int64_t bandwidths[]={14400,19200,28800,33600,34430,57600,
- 115200,262200,393216,524300,1544000,10485800};
+static const uint32_t bandwidths[] = {
+ 14400, 19200, 28800, 33600, 34430, 57600,
+ 115200, 262200, 393216, 524300, 1544000, 10485800
+};
/* these are things that can go wrong */
typedef enum {
@@ -320,7 +322,8 @@
unsigned int samples;
unsigned int sample_size;
unsigned int sample_size_count;
- unsigned int sample_size_bits;
+ unsigned int sample_size_bytes;
+ unsigned int sample_size_shift;
unsigned char *sample_size_table;
/* sync samples, a.k.a., keyframes */
@@ -425,7 +428,7 @@
int status;
- qt_info *qt;
+ qt_info qt;
xine_bmiheader bih;
unsigned int current_frame;
unsigned int last_frame;
@@ -652,11 +655,7 @@
/* create a qt_info structure or return NULL if no memory */
static qt_info *create_qt_info (demux_qt_t *demux) {
- qt_info *info;
-
- info = calloc (1, sizeof (*info));
- if (!info)
- return NULL;
+ qt_info *info = &demux->qt;
#ifndef HAVE_ZERO_SAFE_MEM
info->compressed_header = 0;
@@ -723,8 +722,7 @@
free(info->comment);
free(info->composer);
free(info->year);
- free(info);
- info = NULL;
+ memset (info, 0, sizeof (*info));
}
}
@@ -811,7 +809,14 @@
return numBytes;
}
-#define WRITE_BE_32(v,p) { \
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+# define WRITE_BE_32(v,p) { \
+ uint8_t *wp = (uint8_t *)(p); \
+ int32_t n = __builtin_bswap32 ((int32_t)(v)); \
+ __builtin_memcpy (wp, &n, 4); \
+}
+#else
+# define WRITE_BE_32(v,p) { \
unsigned char *wp = (unsigned char *)(p); \
uint32_t wv = (v); \
wp[0] = wv >> 24; \
@@ -819,6 +824,7 @@
wp[2] = wv >> 8; \
wp[3] = wv; \
}
+#endif
/* find sub atoms somewhere inside this atom */
static void find_embedded_atoms (uint8_t *atom,
@@ -875,8 +881,8 @@
"edtsmdiaminfdinfstbl"
/* look into these from "moov" (intentionally hide "trak"). */
"udtametailstiprosinfrmrarmdardrfrmvc";
- unsigned int atomtype, atomsize, subtype = 0, subsize = 0;
- unsigned int i = 8, j, n, left;
+ unsigned int atomtype, atomsize, subsize = 0;
+ unsigned int i = 8, n, left;
if (!atom || !types || !found)
return 0;
@@ -902,8 +908,9 @@
}
for (; i + 8 <= atomsize; i += subsize) {
- subsize = _X_BE_32 (&atom[i]);
- subtype = _X_BE_32 (&atom[i + 4]);
+ unsigned int j;
+ uint32_t subtype = _X_BE_32 (&atom[i + 4]);
+ subsize = _X_BE_32 (&atom[i]);
if (subsize == 0) {
subsize = atomsize - i;
WRITE_BE_32 (subsize, &atom[i]);
@@ -973,7 +980,8 @@
trak->samples = 0;
trak->sample_size = 0;
trak->sample_size_count = 0;
- trak->sample_size_bits = 0;
+ trak->sample_size_bytes = 0;
+ trak->sample_size_shift = 0;
trak->sample_size_table = NULL;
trak->sync_sample_count = 0;
trak->sync_sample_table = NULL;
@@ -1319,6 +1327,10 @@
else if (trak->type == MEDIA_AUDIO) do {
+#ifndef HAVE_ZERO_SAFE_MEM
+ p->s.audio.wave_size = 0;
+ p->s.audio.wave = NULL;
+#endif
if (isize < 0x22)
break;
@@ -1440,11 +1452,11 @@
p->s.audio.samples_per_packet;
[... 722 lines omitted ...]
/* seek all supported audio traks */
- for (i = 0; i < this->qt->audio_trak_count; i++) {
- audio_trak = &this->qt->traks[this->qt->audio_traks[i]];
+ for (i = 0; i < this->qt.audio_trak_count; i++) {
+ audio_trak = &this->qt.traks[this->qt.audio_traks[i]];
this->status = binary_seek(audio_trak, start_pos, start_time);
if (this->status != DEMUX_OK)
return this->status;
@@ -3561,8 +3602,8 @@
* back to the first audio frame that has a pts less than or equal to
* that of the keyframe; do not go through with this process there is
* no video trak */
- if (keyframe_pts >= 0) for (i = 0; i < this->qt->audio_trak_count; i++) {
- audio_trak = &this->qt->traks[this->qt->audio_traks[i]];
+ if (keyframe_pts >= 0) for (i = 0; i < this->qt.audio_trak_count; i++) {
+ audio_trak = &this->qt.traks[this->qt.audio_traks[i]];
if (keyframe_pts > audio_trak->frames[audio_trak->frame_count - 1].pts) {
/* whoops, this trak is too short, mark it finished */
audio_trak->current_frame = audio_trak->frame_count;
@@ -3574,7 +3615,7 @@
}
}
- this->qt->seek_flag = 1;
+ this->qt.seek_flag = 1;
this->status = DEMUX_OK;
/*
@@ -3590,7 +3631,7 @@
static void demux_qt_dispose (demux_plugin_t *this_gen) {
demux_qt_t *this = (demux_qt_t *) this_gen;
- free_qt_info(this->qt);
+ free_qt_info (&this->qt);
free(this);
}
@@ -3604,10 +3645,10 @@
demux_qt_t *this = (demux_qt_t *) this_gen;
- if (this->qt->timescale == 0)
+ if (this->qt.timescale == 0)
return 0;
- return (int)((int64_t) 1000 * this->qt->duration / this->qt->timescale);
+ return (int)((int64_t) 1000 * this->qt.duration / this->qt.timescale);
}
static uint32_t demux_qt_get_capabilities(demux_plugin_t *this_gen) {
@@ -3627,10 +3668,10 @@
case DEMUX_OPTIONAL_DATA_AUDIOLANG: {
char *str = data;
int channel = *((int *)data);
- if ((channel < 0) || (channel >= this->qt->audio_trak_count)) {
+ if ((channel < 0) || (channel >= this->qt.audio_trak_count)) {
strcpy (str, "none");
} else {
- int lang = this->qt->traks[this->qt->audio_traks[channel]].lang;
+ int lang = this->qt.traks[this->qt.audio_traks[channel]].lang;
if ((lang < 0x400) || (lang == 0x7fff)) {
sprintf (str, "%d", channel);
} else {
@@ -3670,7 +3711,9 @@
return NULL;
}
- this = calloc(1, sizeof(demux_qt_t));
+ this = calloc (1, sizeof (demux_qt_t));
+ if (!this)
+ return NULL;
this->stream = stream;
this->input = input;
@@ -3694,26 +3737,23 @@
this->status = DEMUX_FINISHED;
- if ((this->qt = create_qt_info (this)) == NULL) {
- free (this);
- return NULL;
- }
+ create_qt_info (this);
switch (stream->content_detection_method) {
case METHOD_BY_CONTENT:
- last_error = open_qt_file(this->qt, this->input, this->bandwidth);
+ last_error = open_qt_file (&this->qt, this->input, this->bandwidth);
if (last_error == QT_DRM_NOT_SUPPORTED) {
/* special consideration for DRM-protected files */
- if (this->qt->last_error == QT_DRM_NOT_SUPPORTED)
+ if (this->qt.last_error == QT_DRM_NOT_SUPPORTED)
_x_message (this->stream, XINE_MSG_ENCRYPTED_SOURCE,
"DRM-protected Quicktime file", NULL);
} else if (last_error != QT_OK) {
- free_qt_info (this->qt);
+ free_qt_info (&this->qt);
free (this);
return NULL;
}
@@ -3721,8 +3761,8 @@
break;
default:
- if (open_qt_file(this->qt, this->input, this->bandwidth) != QT_OK) {
- free_qt_info (this->qt);
+ if (open_qt_file (&this->qt, this->input, this->bandwidth) != QT_OK) {
+ free_qt_info (&this->qt);
free (this);
return NULL;
}
@@ -3730,9 +3770,9 @@
break;
}
- if (this->qt->fragment_count > 0)
+ if (this->qt.fragment_count > 0)
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- _("demux_qt: added %d fragments\n"), this->qt->fragment_count);
+ _("demux_qt: added %d fragments\n"), this->qt.fragment_count);
return &this->demux_plugin;
}
|
|
From: Torsten J. <t....@gm...> - 2018-04-30 14:21:09
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1525098030 -7200
# Node ID c4384d89b26eef080af83284298089a71ef36201
# Branch default
# Parent cc309b867ac2d46366485be2de2c3bbcbad0a09f
demux_qt update 4.
- Fix little endian 24bit audio regression from update 3.
- Minor audio param parser optimization.
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.c
@@ -1142,6 +1142,10 @@
isize = atomsize;
p->properties_atom = item;
p->properties_atom_size = isize;
+#ifndef HAVE_ZERO_SAFE_MEM
+ p->decoder_config_len = 0;
+ p->decoder_config = NULL;
+#endif
p->media_id = k + 1;
p->codec_fourcc = _X_ME_32 (item + 4);
_x_tag32_me2str (p->codec_str, p->codec_fourcc);
@@ -1318,15 +1322,30 @@
if (isize < 0x22)
break;
- /* fetch audio parameters */
- p->s.audio.sample_rate = _X_BE_16 (item + 0x20);
- p->s.audio.channels = item[0x19];
- p->s.audio.bits = item[0x1b];
-
+ /* fetch audio parameters, assume uncompressed */
+ p->s.audio.sample_rate = _X_BE_16 (item + 0x20);
+ p->s.audio.channels =
+ p->s.audio.samples_per_frame =
+ p->s.audio.samples_per_packet = item[0x19];
+ p->s.audio.bits = item[0x1b];
+ p->s.audio.bytes_per_sample =
+ p->s.audio.bytes_per_packet = p->s.audio.bits / 8;
+ p->s.audio.bytes_per_frame = p->s.audio.bytes_per_sample * p->s.audio.samples_per_frame;
+
+ /* 24-bit audio doesn't always declare itself properly, and can be big- or little-endian */
+ if ((p->codec_fourcc == IN24_FOURCC) && (isize >= 0x52)) {
+ p->s.audio.bits = 24;
+ if (_X_BE_32 (item + 0x4c) == ENDA_ATOM && item[0x51])
+ p->codec_fourcc = NI42_FOURCC;
+ }
p->codec_buftype = _x_formattag_to_buf_audio (p->codec_fourcc);
+
+ /* see if the trak deserves a promotion to VBR */
+ p->s.audio.vbr = (_X_BE_16 (item + 0x1c) == 0xFFFE) ? 1 : 0;
/* in mp4 files the audio fourcc is always 'mp4a' - the codec is
* specified by the object type id field in the esds atom */
if (p->codec_fourcc == MP4A_FOURCC) {
+ p->s.audio.vbr = 1;
if (p->object_type_id == 221) {
p->codec_buftype = BUF_AUDIO_VORBIS;
memcpy (p->codec_str, "vorbis", 7);
@@ -1335,24 +1354,26 @@
memcpy (p->codec_str, "mp3", 4);
}
}
-
- /* 24-bit audio doesn't always declare itself properly, and can be big- or little-endian */
- if ((p->codec_fourcc == IN24_FOURCC) && (isize >= 0x52)) {
- p->s.audio.bits = 24;
- if (_X_BE_32 (item + 0x4c) == ENDA_ATOM && item[0x51])
- p->codec_fourcc = NI42_FOURCC;
+ /* if this is MP4 audio, mark the trak as VBR */
+ else if ((p->codec_fourcc == SAMR_FOURCC) ||
+ (p->codec_fourcc == AC_3_FOURCC) ||
+ (p->codec_fourcc == EAC3_FOURCC) ||
+ (p->codec_fourcc == QCLP_FOURCC)) {
+ p->s.audio.vbr = 1;
}
- /* assume uncompressed audio parameters */
- p->s.audio.bytes_per_sample = p->s.audio.bits / 8;
- p->s.audio.samples_per_frame = p->s.audio.channels;
- p->s.audio.bytes_per_frame = p->s.audio.bytes_per_sample * p->s.audio.samples_per_frame;
- p->s.audio.samples_per_packet = p->s.audio.samples_per_frame;
- p->s.audio.bytes_per_packet = p->s.audio.bytes_per_sample;
+ else if (p->codec_fourcc == ALAC_FOURCC) {
+ p->s.audio.vbr = 1;
+ if (isize >= 0x24 + 36) {
+ /* further, FFmpeg's ALAC decoder requires 36 out-of-band bytes */
+ p->decoder_config_len = 36;
+ p->decoder_config = item + 0x24;
+ }
+ }
/* special case time: A lot of CBR audio codecs stored in the
* early days lacked the extra header; compensate */
- if (p->codec_fourcc == IMA4_FOURCC) {
+ else if (p->codec_fourcc == IMA4_FOURCC) {
p->s.audio.samples_per_packet = 64;
p->s.audio.bytes_per_packet = 34;
p->s.audio.bytes_per_frame = 34 * p->s.audio.channels;
@@ -1384,6 +1405,11 @@
p->s.audio.samples_per_frame = 2 * p->s.audio.channels;
}
+ else if (p->codec_fourcc == DRMS_FOURCC) {
+ last_error = QT_DRM_NOT_SUPPORTED;
+ goto free_trak;
+ }
+
/* it's time to dig a little deeper to determine the real audio
* properties; if a the stsd compressor atom has 0x24 bytes, it
* appears to be a handler for uncompressed data; if there are an
@@ -1414,30 +1440,11 @@
p->s.audio.samples_per_packet;
}
- /* see if the trak deserves a promotion to VBR */
- p->s.audio.vbr = (_X_BE_16 (item + 0x1c) == 0xFFFE) ? 1 : 0;
-
- /* if this is MP4 audio, mark the trak as VBR */
- if ((p->codec_fourcc == MP4A_FOURCC) ||
- (p->codec_fourcc == SAMR_FOURCC) ||
- (p->codec_fourcc == AC_3_FOURCC) ||
- (p->codec_fourcc == EAC3_FOURCC) ||
- (p->codec_fourcc == QCLP_FOURCC))
- p->s.audio.vbr = 1;
-
- else if ((p->codec_fourcc == ALAC_FOURCC) && (isize >= 0x24 + 36)) {
- p->s.audio.vbr = 1;
- /* further, FFmpeg's ALAC decoder requires 36 out-of-band bytes */
- p->decoder_config_len = 36;
- p->decoder_config = item + 0x24;
- }
-
- else if (p->codec_fourcc == DRMS_FOURCC) {
- last_error = QT_DRM_NOT_SUPPORTED;
- goto free_trak;
- }
-
/* check for a MS-style WAVE format header */
+#ifndef HAVE_ZERO_SAFE_MEM
+ p->s.audio.wave_size = 0;
+ p->s.audio.wave = NULL;
+#endif
if ((isize >= 0x50) &&
(_X_BE_32 (item + 0x38) == WAVE_ATOM) &&
(_X_BE_32 (item + 0x40) == FRMA_ATOM) &&
@@ -1455,13 +1462,7 @@
}
memcpy (p->s.audio.wave, item + 0x50, wave_size);
_x_waveformatex_le2me (p->s.audio.wave);
- } else {
- p->s.audio.wave_size = 0;
- p->s.audio.wave = NULL;
}
- } else {
- p->s.audio.wave_size = 0;
- p->s.audio.wave = NULL;
}
k++;
|
|
From: Torsten J. <t....@gm...> - 2018-04-30 14:21:06
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1525098035 -7200
# Node ID 9276a5491faf3a25385ea1074517d84de6a515aa
# Branch default
# Parent c4384d89b26eef080af83284298089a71ef36201
Fix keyframes log.
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -3091,15 +3091,17 @@
int _x_keyframes_set (xine_stream_t *stream, xine_keyframes_entry_t *list, int size) {
int n = (size + KF_MASK) & ~KF_MASK;
pthread_mutex_lock (&stream->index_mutex);
- free (stream->index_array);
+ if (stream->index_array) {
+ xprintf (stream->xine, XINE_VERBOSITY_DEBUG,
+ "keyframes: deleting index.\n");
+ free (stream->index_array);
+ }
stream->index_lastadd = 0;
stream->index_array = (list && (n > 0)) ? malloc (n * sizeof (xine_keyframes_entry_t)) : NULL;
if (!stream->index_array) {
stream->index_used = 0;
stream->index_size = 0;
pthread_mutex_unlock (&stream->index_mutex);
- xprintf (stream->xine, XINE_VERBOSITY_DEBUG,
- "keyframes: deleting index.\n");
return 1;
}
memcpy (stream->index_array, list, size * sizeof (xine_keyframes_entry_t));
|
|
From: Petri H. <phi...@us...> - 2018-04-29 10:06:34
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1524900325 -10800
# Node ID cc309b867ac2d46366485be2de2c3bbcbad0a09f
# Branch default
# Parent 724dfa67b6778c39470185e41377b9a4e700e4d9
Fix leaks
diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c
--- a/src/demuxers/demux_avi.c
+++ b/src/demuxers/demux_avi.c
@@ -693,6 +693,13 @@
return &(AVI_A->audio_idx.aindex[AVI_A->audio_posc]);
}
+static void free_superindex(avisuperindex_chunk **p) {
+ if (*p) {
+ _x_freep(&(*p)->aIndex);
+ }
+ _x_freep(p);
+}
+
static void AVI_close(avi_t *AVI){
int i;
@@ -700,7 +707,10 @@
_x_freep(&AVI->video_idx.vindex);
_x_freep(&AVI->bih);
+ free_superindex(&AVI->video_superindex);
+
for(i=0; i<AVI->n_audio; i++) {
+ free_superindex(&AVI->audio[i]->audio_superindex);
_x_freep(&AVI->audio[i]->audio_idx.aindex);
_x_freep(&AVI->audio[i]->wavex);
_x_freep(&AVI->audio[i]);
--git a/src/demuxers/demux_vc1es.c b/src/demuxers/demux_vc1es.c
--- a/src/demuxers/demux_vc1es.c
+++ b/src/demuxers/demux_vc1es.c
@@ -330,6 +330,9 @@
return NULL;
}
+ if ( input->seek( input, SCRATCH_SIZE, SEEK_SET ) != SCRATCH_SIZE )
+ return NULL;
+
this = calloc(1, sizeof(demux_vc1_es_t));
if (!this)
return NULL;
@@ -356,9 +359,6 @@
this->status = DEMUX_FINISHED;
- if ( input->seek( input, SCRATCH_SIZE, SEEK_SET ) != SCRATCH_SIZE )
- return NULL;
-
return &this->demux_plugin;
}
|
|
From: Torsten J. <t....@gm...> - 2018-04-28 14:00:18
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1524923995 -7200
# Node ID 724dfa67b6778c39470185e41377b9a4e700e4d9
# Branch default
# Parent 64c6af122269a86cc0e21c22393595cd1791fe57
demux_qt update 3.
- Save 25% on frame lists (~1Mb per 1 hour trak).
- Fix standard edit list last frame.
- Optimize standard edit list parser.
- Fix fragment edit list initial delay.
- Enable edit lists for legacy audio.
- Remove unreachable code.
- Debug list traks.
- Fix typo.
- Simplify trak properties parser.
- Prepare for multi media_id mode.
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.c
@@ -194,8 +194,13 @@
} media_type;
+/* TJ. Cinematic movies reach > 200000 frames easily, so we better save space here.
+ * offset / file size should well fit into 48 bits :-) */
typedef struct {
- int64_t offset;
+ union {
+ int64_t offset;
+ uint8_t bytes[8];
+ } _ffs;
unsigned int size;
/* pts actually is dts for reordered video. Edit list and frame
duration code relies on that, so keep the offset separately
@@ -203,9 +208,15 @@
Value is small enough for plain int. */
int ptsoffs;
int64_t pts;
- int keyframe;
- unsigned int media_id;
} qt_frame;
+#define QTF_OFFSET(f) ((f)._ffs.offset & ~((uint64_t)0xffff << 48))
+#ifdef WORDS_BIGENDIAN
+# define QTF_KEYFRAME(f) ((f)._ffs.bytes[0])
+# define QTF_MEDIA_ID(f) ((f)._ffs.bytes[1])
+#else
+# define QTF_KEYFRAME(f) ((f)._ffs.bytes[7])
+# define QTF_MEDIA_ID(f) ((f)._ffs.bytes[6])
+#endif
typedef struct {
int64_t track_duration;
@@ -224,55 +235,44 @@
int qtim_version;
} reference_t;
-typedef union {
-
- struct {
- /* the media id that corresponds to this trak */
- unsigned int media_id;
-
- /* offset into the stsd atom of the properties atom */
- unsigned int properties_offset;
-
- unsigned int codec_fourcc;
- unsigned int codec_buftype;
- unsigned int width;
- unsigned int height;
- int palette_count;
- palette_entry_t palette[PALETTE_COUNT];
- int depth;
- int edit_list_compensation; /* special trick for edit lists */
-
- unsigned char *properties_atom;
- unsigned int properties_atom_size;
- } video;
-
- struct {
- /* the media id that corresponds to this trak */
- unsigned int media_id;
-
- /* offset into the stsd atom of the properties atom */
- unsigned int properties_offset;
-
- unsigned int codec_fourcc;
- unsigned int codec_buftype;
- unsigned int sample_rate;
- unsigned int channels;
- unsigned int bits;
- unsigned int vbr;
- unsigned int wave_size;
- xine_waveformatex *wave;
-
- /* special audio parameters */
- unsigned int samples_per_packet;
- unsigned int bytes_per_packet;
- unsigned int bytes_per_frame;
- unsigned int bytes_per_sample;
- unsigned int samples_per_frame;
-
- unsigned char *properties_atom;
- unsigned int properties_atom_size;
- } audio;
-
+typedef struct {
+ /* the media id that corresponds to this trak */
+ unsigned int media_id;
+ unsigned int codec_fourcc;
+ unsigned int codec_buftype;
+ unsigned char *properties_atom;
+ unsigned char *decoder_config;
+ unsigned int properties_atom_size;
+ unsigned int decoder_config_len;
+ char codec_str[20];
+ /* formattag-like field that specifies codec in mp4 files */
+ int object_type_id;
+ union {
+ struct {
+ unsigned int width;
+ unsigned int height;
+ int depth;
+ int edit_list_compensation; /* special trick for edit lists */
+
+ int palette_count;
+ palette_entry_t palette[PALETTE_COUNT];
+ } video;
+ struct {
+ unsigned int sample_rate;
+ unsigned int channels;
+ unsigned int bits;
+ unsigned int vbr;
+
+ unsigned int wave_size;
+ xine_waveformatex *wave;
+ /* special audio parameters */
+ unsigned int samples_per_packet;
+ unsigned int bytes_per_packet;
+ unsigned int bytes_per_frame;
+ unsigned int bytes_per_sample;
+ unsigned int samples_per_frame;
+ } audio;
+ } s;
} properties_t;
[... 1847 lines omitted ...]
}
- if (!audio_trak->properties->audio.codec_buftype &&
- audio_trak->properties->audio.codec_fourcc) {
- audio_trak->properties->audio.codec_buftype = BUF_AUDIO_UNKNOWN;
- _x_report_audio_format_tag (this->stream->xine, LOG_MODULE,
- audio_trak->properties->audio.codec_fourcc);
- }
-
- if ((audio_trak->properties->audio.codec_buftype == 0) ||
+ if ((audio_trak->properties->codec_buftype == 0) ||
(audio_index >= MAX_AUDIO_TRAKS) ||
(this->audio_fifo == NULL))
continue;
@@ -3364,31 +3390,31 @@
audio_trak->audio_index = audio_index;
/* set the audio bitrate field (only for CBR audio) */
- if (!audio_trak->properties->audio.vbr) {
+ if (!audio_trak->properties->s.audio.vbr) {
audio_bitrate =
- audio_trak->properties->audio.sample_rate /
- audio_trak->properties->audio.samples_per_frame *
- audio_trak->properties->audio.bytes_per_frame *
- audio_trak->properties->audio.channels *
+ audio_trak->properties->s.audio.sample_rate /
+ audio_trak->properties->s.audio.samples_per_frame *
+ audio_trak->properties->s.audio.bytes_per_frame *
+ audio_trak->properties->s.audio.channels *
8;
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE,
audio_bitrate);
}
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- buf->type = audio_trak->properties->audio.codec_buftype | audio_index;
+ buf->type = audio_trak->properties->codec_buftype | audio_index;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
buf->decoder_info[0] = 0;
- buf->decoder_info[1] = audio_trak->properties->audio.sample_rate;
- buf->decoder_info[2] = audio_trak->properties->audio.bits;
- buf->decoder_info[3] = audio_trak->properties->audio.channels;
-
- if( audio_trak->properties->audio.wave_size ) {
- if (audio_trak->properties->audio.wave_size > (unsigned int)buf->max_size)
+ buf->decoder_info[1] = audio_trak->properties->s.audio.sample_rate;
+ buf->decoder_info[2] = audio_trak->properties->s.audio.bits;
+ buf->decoder_info[3] = audio_trak->properties->s.audio.channels;
+
+ if( audio_trak->properties->s.audio.wave_size ) {
+ if (audio_trak->properties->s.audio.wave_size > (unsigned int)buf->max_size)
buf->size = buf->max_size;
else
- buf->size = audio_trak->properties->audio.wave_size;
- memcpy(buf->content, audio_trak->properties->audio.wave, buf->size);
+ buf->size = audio_trak->properties->s.audio.wave_size;
+ memcpy (buf->content, audio_trak->properties->s.audio.wave, buf->size);
} else {
buf->size = 0;
buf->content = NULL;
@@ -3396,14 +3422,14 @@
this->audio_fifo->put (this->audio_fifo, buf);
- if( audio_trak->decoder_config ) {
+ if (audio_trak->properties->decoder_config) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- buf->type = audio_trak->properties->audio.codec_buftype | audio_index;
+ buf->type = audio_trak->properties->codec_buftype | audio_index;
buf->size = 0;
buf->decoder_flags = BUF_FLAG_SPECIAL|BUF_FLAG_HEADER;
buf->decoder_info[1] = BUF_SPECIAL_DECODER_CONFIG;
- buf->decoder_info[2] = audio_trak->decoder_config_len;
- buf->decoder_info_ptr[2] = audio_trak->decoder_config;
+ buf->decoder_info[2] = audio_trak->properties->decoder_config_len;
+ buf->decoder_info_ptr[2] = audio_trak->properties->decoder_config;
this->audio_fifo->put (this->audio_fifo, buf);
}
@@ -3411,10 +3437,10 @@
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->decoder_flags = BUF_FLAG_SPECIAL|BUF_FLAG_HEADER;
buf->decoder_info[1] = BUF_SPECIAL_STSD_ATOM;
- buf->decoder_info[2] = audio_trak->properties->audio.properties_atom_size;
- buf->decoder_info_ptr[2] = audio_trak->properties->audio.properties_atom;
+ buf->decoder_info[2] = audio_trak->properties->properties_atom_size - 4;
+ buf->decoder_info_ptr[2] = audio_trak->properties->properties_atom + 4;
buf->size = 0;
- buf->type = audio_trak->properties->audio.codec_buftype | audio_index;
+ buf->type = audio_trak->properties->codec_buftype | audio_index;
this->audio_fifo->put (this->audio_fifo, buf);
this->qt->audio_trak_count = ++audio_index;
@@ -3435,9 +3461,9 @@
/* perform a binary search on the trak, testing the offset
* boundaries first; offset request has precedent over time request */
if (start_pos) {
- if (start_pos <= trak->frames[0].offset)
+ if (start_pos <= (off_t)QTF_OFFSET(trak->frames[0]))
best_index = 0;
- else if (start_pos >= trak->frames[trak->frame_count - 1].offset)
+ else if (start_pos >= (off_t)QTF_OFFSET(trak->frames[trak->frame_count - 1]))
best_index = trak->frame_count - 1;
else {
left = 0;
@@ -3446,10 +3472,10 @@
while (!found) {
middle = (left + right + 1) / 2;
- if ((start_pos >= trak->frames[middle].offset) &&
- (start_pos < trak->frames[middle + 1].offset)) {
+ if ((start_pos >= (off_t)QTF_OFFSET(trak->frames[middle])) &&
+ (start_pos < (off_t)QTF_OFFSET(trak->frames[middle + 1]))) {
found = 1;
- } else if (start_pos < trak->frames[middle].offset) {
+ } else if (start_pos < (off_t)QTF_OFFSET(trak->frames[middle])) {
right = middle - 1;
} else {
left = middle;
@@ -3514,7 +3540,7 @@
return this->status;
/* search back in the video trak for the nearest keyframe */
while (video_trak->current_frame) {
- if (video_trak->frames[video_trak->current_frame].keyframe) {
+ if (QTF_KEYFRAME(video_trak->frames[video_trak->current_frame])) {
break;
}
video_trak->current_frame--;
|
|
From: Torsten J. <t....@gm...> - 2018-04-28 14:00:17
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1524923990 -7200
# Node ID 64c6af122269a86cc0e21c22393595cd1791fe57
# Branch default
# Parent 5abd264ec8fe3d1634602478cde435054b04ace1
Add fast x86 _X_?E_16 ().
Partial register write is not optimal,
but the alternative is an extra temp register...
diff --git a/src/xine-engine/bswap.h b/src/xine-engine/bswap.h
--- a/src/xine-engine/bswap.h
+++ b/src/xine-engine/bswap.h
@@ -96,6 +96,22 @@
# define _X_LE_32(x) ({ uint32_t tempi; __builtin_memcpy (&tempi, (x), 4); tempi; })
# define _X_LE_64(x) ({ uint64_t tempi; __builtin_memcpy (&tempi, (x), 8); tempi; })
# endif
+# if defined(ARCH_X86)
+ /* These machines have true (u)int16_t. */
+# undef _X_BE_16
+# undef _X_LE_16
+# define _X_BE_16(x) ({ \
+ uint16_t tempi; \
+ __builtin_memcpy (&tempi, (x), 2); \
+ __asm__ __volatile__ ( \
+ "rolw\t$8, %0" \
+ : "=r" (tempi) \
+ : "0" (tempi) \
+ : "cc" \
+ ); \
+ tempi; })
+# define _X_LE_16(x) ({ uint16_t tempi; __builtin_memcpy (&tempi, (x), 2); tempi; })
+# endif
#endif
#ifdef WORDS_BIGENDIAN
|
|
From: Torsten J. <t....@gm...> - 2018-04-28 14:00:17
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1524923985 -7200
# Node ID 5abd264ec8fe3d1634602478cde435054b04ace1
# Branch default
# Parent 455aca0352dd4e638c9f351339c46e1f42847e79
asfheader: silence warnings.
diff --git a/src/demuxers/asfheader.c b/src/demuxers/asfheader.c
--- a/src/demuxers/asfheader.c
+++ b/src/demuxers/asfheader.c
@@ -566,6 +566,10 @@
data_type = _X_LE_16 (p); p += 2;
data_len = _X_LE_32 (p); p += 4;
+ /* not used yet */
+ (void)index;
+ (void)data_type;
+
stream_id = asf_header_get_stream_id (&header->pub, stream);
if (data_len >= 4) {
@@ -611,6 +615,8 @@
return 0;
data_length = _X_LE_32 (p + 16 + 2);
lprintf("parse_asf_header_extension: length: %"PRIu32"\n", data_length);
+ /* used in LOG mode only */
+ (void)data_length;
while (!asf_reader_eos(&reader)) {
@@ -747,6 +753,8 @@
asf_reader_init (&reader, buffer, buffer_len);
p = asf_reader_get_block (&reader, 4 + 2);
object_count = _X_LE_32 (p);
+ /* not used yet */
+ (void)object_count;
while (!asf_reader_eos(&reader)) {
|
|
From: Petri H. <phi...@us...> - 2018-04-27 10:08:40
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1524823672 -10800
# Node ID 455aca0352dd4e638c9f351339c46e1f42847e79
# Branch default
# Parent ec800689d8cceeb84a1ed6bd571fad68c93ecdf9
Fix implicit conversion error when comparing negative int and size_t
diff --git a/src/input/input_http.c b/src/input/input_http.c
--- a/src/input/input_http.c
+++ b/src/input/input_http.c
@@ -850,11 +850,10 @@
if (len == -1)
done = 1;
- else
- len = 0;
+ len = 0;
} else
len ++;
- if ( len >= sizeof(buf) ) {
+ if ( len >= (int)sizeof(buf) ) {
_x_message(this->stream, XINE_MSG_PERMISSION_ERROR, this->mrl, NULL);
xine_log (this->stream->xine, XINE_LOG_MSG,
_("input_http: buffer exhausted after %zu bytes."), sizeof(buf));
|
|
From: Petri H. <phi...@us...> - 2018-04-27 10:08:39
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1524823528 -10800
# Node ID ec800689d8cceeb84a1ed6bd571fad68c93ecdf9
# Branch default
# Parent e77333b063d5930776223f4f46a429445b507fe6
Fix possible leak
diff --git a/src/input/input_http.c b/src/input/input_http.c
--- a/src/input/input_http.c
+++ b/src/input/input_http.c
@@ -914,8 +914,10 @@
lprintf("preview_size=%"PRId64"\n", this->preview_size);
this->curpos = 0;
- if (*mime_type)
+ if (*mime_type) {
+ free(this->mime_type);
this->mime_type = strdup (mime_type);
+ }
return 1;
}
|
|
From: Petri H. <phi...@us...> - 2018-04-27 10:02:06
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1524823109 -10800
# Node ID e77333b063d5930776223f4f46a429445b507fe6
# Branch default
# Parent 07a9496c3af481e372ad5fbf20115501165ff44a
ftp: set INPUT_CAP_SLOW_SEEKABLE when server supports restarting from file offset
diff --git a/src/input/input_ftp.c b/src/input/input_ftp.c
--- a/src/input/input_ftp.c
+++ b/src/input/input_ftp.c
@@ -643,6 +643,13 @@
return result;
}
+static uint32_t _ftp_get_capabilities (input_plugin_t *this_gen)
+{
+ ftp_input_plugin_t *this = (ftp_input_plugin_t *)this_gen;
+
+ return INPUT_CAP_PREVIEW | (this->cap_rest ? INPUT_CAP_SLOW_SEEKABLE : 0);
+}
+
static input_plugin_t *_get_instance (input_class_t *cls_gen, xine_stream_t *stream, const char *mrl)
{
ftp_input_class_t *class = (ftp_input_class_t *)cls_gen;
@@ -666,7 +673,7 @@
this->fd_data = -1;
this->input_plugin.open = _ftp_open;
- this->input_plugin.get_capabilities = _x_input_get_capabilities_preview;
+ this->input_plugin.get_capabilities = _ftp_get_capabilities;
this->input_plugin.read = _ftp_read;
this->input_plugin.read_block = _x_input_default_read_block;
this->input_plugin.seek = _ftp_seek;
|
|
From: Petri H. <phi...@us...> - 2018-04-27 10:02:03
|
# HG changeset patch
# User Petri Hintukainen <phi...@us...>
# Date 1524822998 -10800
# Node ID 07a9496c3af481e372ad5fbf20115501165ff44a
# Branch default
# Parent 42d000904c70a2f883d78abfdc43e30462e96d4c
Set XINE_STREAM_INFO_SEEKABLE for GUI when input announces INPUT_CAP_SLOW_SEEKABLE
diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c
--- a/src/xine-engine/xine_interface.c
+++ b/src/xine-engine/xine_interface.c
@@ -721,7 +721,7 @@
case XINE_STREAM_INFO_SEEKABLE:
if (stream->input_plugin)
- return stream->input_plugin->get_capabilities (stream->input_plugin) & INPUT_CAP_SEEKABLE;
+ return stream->input_plugin->get_capabilities (stream->input_plugin) & (INPUT_CAP_SEEKABLE | INPUT_CAP_SLOW_SEEKABLE);
return 0;
case XINE_STREAM_INFO_HAS_CHAPTERS:
|