[vdr-plugin-xineliboutput] 01/03: Imported Upstream version 1.1.0
Tobias Grimm
tiber-guest at alioth.debian.org
Sat Sep 14 19:35:35 UTC 2013
This is an automated email from the git hooks/post-receive script.
tiber-guest pushed a commit to branch master
in repository vdr-plugin-xineliboutput.
commit 9b7ab6b29a23263c45405c94ab61de64d84426c8
Author: etobi <git at e-tobi.net>
Date: Sat Sep 14 21:16:45 2013 +0200
Imported Upstream version 1.1.0
---
HISTORY | 3 +-
configure | 6 +-
device.c | 12 +-
frontend_local.c | 4 +-
tools/gnome_screensaver.c | 62 +
xine/BluRay/Makefile | 166 --
xine/BluRay/decode_spuhdmv.c | 1103 --------
xine/BluRay/demux_ts.c | 2783 --------------------
xine/BluRay/input_bluray.c | 1980 --------------
.../xine-lib-1.1.16.3-ffmpeg-vc1-extradata.diff | 62 -
.../xine-lib-1.1.16.3-ffmpeg-vc1-reopen.diff | 25 -
xine/BluRay/xine_lpcm_decoder.c | 424 ---
xine/vo_osdscaler.c | 14 +-
xine_fbfe_frontend.c | 4 +-
xine_frontend.h | 4 +-
xine_frontend_main.c | 16 +-
xine_sxfe_frontend.c | 39 +-
xineliboutput.c | 16 +-
18 files changed, 154 insertions(+), 6569 deletions(-)
diff --git a/HISTORY b/HISTORY
index 77f26eb..00f38c9 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,8 +1,9 @@
VDR Plugin 'xineliboutput' Revision History
-------------------------------------------
-????-??-??: Version 1.1.0
+2013-08-20: Version 1.1.0
+- Added simple touchscreen remote controller to vdr-sxfe
- Added XShape support for HUD OSD: opaque HUD OSD when no compositing manager
(Thanks to grueni75)
- Added support for background image streams (display images or videos while playing music)
diff --git a/configure b/configure
index 7bc0587..f94bfb8 100755
--- a/configure
+++ b/configure
@@ -7,7 +7,7 @@
# See the main source file 'xineliboutput.c' for copyright information and
# how to reach the author.
#
-# * $Id: configure,v 1.42 2012/08/30 06:44:20 phintuka Exp $
+# * $Id: configure,v 1.43 2013/08/15 10:12:27 phintuka Exp $
#
PKG_CONFIG="pkg-config"
@@ -240,6 +240,7 @@ FEATURES="
i18n
libcap
libbluray
+ mce-dbus-names
"
# set defaults
@@ -382,7 +383,8 @@ if enabled libxine; then
"dbus/dbus-glib.h" \
"-ldbus-glib-1 -lgobject-2.0 -lglib-2.0" \
"dbus_g_bus_get(0,0)" \
- "-I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include"
+ "-I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/lib/glib-2.0/include"
+ enabled dbus-glib-1 && test_library X11 mce-dbus-names "mce/dbus-names.h" "" ""
fi
fi
diff --git a/device.c b/device.c
index f0ad9d3..c182ce9 100644
--- a/device.c
+++ b/device.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: device.c,v 1.122 2012/12/09 21:37:53 rofafor Exp $
+ * $Id: device.c,v 1.125 2013/08/20 09:33:43 phintuka Exp $
*
*/
@@ -781,7 +781,6 @@ void cXinelibDevice::TrickSpeed(int Speed)
m_TrickSpeedMode |= trs_I_frames | trs_Backward | trs_NoAudio;
ForEach(m_clients, &cXinelibThread::TrickSpeed, -RealSpeed, true);
- ForEach(m_clients, &cXinelibThread::Sync);
} else {
@@ -824,6 +823,8 @@ void cXinelibDevice::TrickSpeed(int Speed)
ForEach(m_clients, &cXinelibThread::TrickSpeed, -1);
}
+
+ ForEach(m_clients, &cXinelibThread::Sync);
}
}
@@ -1387,6 +1388,8 @@ void cXinelibDevice::StillPicture(const uchar *Data, int Length)
skipped = 0;
}
+ // Data type
+
bool isPes = DATA_IS_PES(Data) && ((Data[3] & 0xF0) == 0xE0);
bool isMpeg1 = isPes && ((Data[6] & 0xC0) != 0x80);
bool isH264 = isPes && pes_is_frame_h264(Data, Length);
@@ -1411,7 +1414,7 @@ void cXinelibDevice::StillPicture(const uchar *Data, int Length)
m_TrickSpeed = -1; // to make Poll work ...
m_SkipAudio = 1; // enables audio and pts stripping
- for(i=0; i<STILLPICTURE_REPEAT_COUNT; i++)
+ for (i = 0; i < STILLPICTURE_REPEAT_COUNT; i++) {
if(isMpeg1) {
ForEach(m_clients, &cXinelibThread::Play_Mpeg1_PES, Data, Length,
&mmin<int>, Length);
@@ -1434,6 +1437,7 @@ void cXinelibDevice::StillPicture(const uchar *Data, int Length)
Data, Length, VIDEO_STREAM, isH264,
&mand<bool>, true);
}
+ }
TsBufferFlush();
@@ -1446,7 +1450,7 @@ void cXinelibDevice::StillPicture(const uchar *Data, int Length)
ForEach(m_clients, &cXinelibThread::Flush, 60, &mand<bool>, true);
- m_TrickSpeed = 0;
+ m_TrickSpeed = 0; // --> Play() triggers TrickSpeed change and resets still mode
m_SkipAudio = 0;
}
diff --git a/frontend_local.c b/frontend_local.c
index 433b58f..665772d 100644
--- a/frontend_local.c
+++ b/frontend_local.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: frontend_local.c,v 1.60 2012/03/19 11:57:18 phintuka Exp $
+ * $Id: frontend_local.c,v 1.61 2013/08/18 07:58:29 phintuka Exp $
*
*/
@@ -354,7 +354,7 @@ void cXinelibLocal::Action(void)
xc.hud_osd,
xc.opengl,
xc.modeswitch, xc.modeline, xc.display_aspect,
- 0/*no_x_kbd*/, 0/*gui_hotkeys*/,
+ 0/*no_x_kbd*/, 0/*gui_hotkeys*/, 0/*touchscreen*/,
xc.video_port,
xc.scale_video,
NULL,
diff --git a/tools/gnome_screensaver.c b/tools/gnome_screensaver.c
index d9dba27..8168510 100644
--- a/tools/gnome_screensaver.c
+++ b/tools/gnome_screensaver.c
@@ -26,6 +26,11 @@
#include <stdarg.h>
#include <string.h>
+#include "../features.h"
+#ifdef HAVE_MCE_DBUS_NAMES
+# include <mce/dbus-names.h>
+#endif
+
#define LOG_MODULENAME "[scrnsaver] "
#include "../logdefs.h"
@@ -49,6 +54,8 @@
#define MSG_GError "Error: %s"
#define MSG_GNOMEScreensaverEnabled "GNOME screensaver enabled"
#define MSG_GNOMEScreensaverDisabled "GNOME screensaver disabled"
+#define MSG_MCEScreensaverEnabled "MCE screensaver enabled"
+#define MSG_MCEScreensaverDisabled "MCE screensaver disabled"
static guint32 cookie;
@@ -101,6 +108,50 @@ static int gnome_sessionmanager_control(DBusGConnection *connection, int enable)
return 1;
}
+#ifdef HAVE_MCE_DBUS_NAMES
+static int mce_control(DBusGConnection *connection, int enable)
+{
+ GError *error;
+ DBusGProxy *proxy;
+ gboolean ret = 1;
+
+ /* Create a proxy object */
+ proxy = dbus_g_proxy_new_for_name(connection,
+ MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF);
+ if (!proxy) {
+ LOGDBG("Failed to get a proxy for " SM_SERVICE);
+ return 0;
+ }
+
+ error = NULL;
+ if (enable) {
+ ret = dbus_g_proxy_call(proxy, MCE_CANCEL_PREVENT_BLANK_REQ, &error,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ } else {
+ ret = dbus_g_proxy_call(proxy, MCE_PREVENT_BLANK_REQ, &error,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ }
+
+ g_object_unref(proxy);
+
+ if (!ret) {
+ /* Check if it's a remote exception or a regular GError */
+ if (error->domain == DBUS_GERROR &&
+ error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+ LOGMSG(MSG_RemoteMethodException, dbus_g_error_get_name(error), error->message);
+ } else {
+ LOGMSG(MSG_GError, error->message);
+ }
+ g_error_free(error);
+
+ return 0;
+ }
+
+ LOGMSG(enable ? MSG_MCEScreensaverEnabled : MSG_MCEScreensaverDisabled);
+ return 1;
+}
+#endif
+
void gnome_screensaver_control(int enable)
{
DBusGConnection *connection;
@@ -110,6 +161,17 @@ void gnome_screensaver_control(int enable)
g_type_init();
+#ifdef HAVE_MCE_DBUS_NAMES
+ error = NULL;
+ connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (!connection) {
+ LOGMSG(MSG_OpenBusConnectionError, error ? error->message : "<null>");
+ g_error_free(error);
+ } else if (mce_control(connection, enable)) {
+ return;
+ }
+#endif
+
/* Get a connection to the session bus */
error = NULL;
connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
diff --git a/xine/BluRay/Makefile b/xine/BluRay/Makefile
deleted file mode 100644
index b442500..0000000
--- a/xine/BluRay/Makefile
+++ /dev/null
@@ -1,166 +0,0 @@
-#
-# select plugins
-#
-
-ifeq ($(shell pkg-config libxine --atleast-version=1.1.21 || echo "yes"), yes)
- ENABLE_DEMUX_PLUGIN ?= yes
-else
- ENABLE_DEMUX_PLUGIN ?= no
- $(warning demux plugin is included in xine-lib 1.1.21+)
-endif
-
-ifeq ($(shell pkg-config libbluray && echo yes), yes)
- ifeq ($(shell pkg-config libxine --atleast-version=1.1.21 || echo "yes"), yes)
- ENABLE_INPUT_PLUGIN ?= yes
- CFLAGS_BD ?= $(shell pkg-config libbluray --cflags)
- LIBS_BD ?= $(shell pkg-config libbluray --libs)
- else
- ENABLE_DEMUX_PLUGIN ?= no
- $(warning input plugin is included in xine-lib 1.1.21+)
- endif
-else
- ENABLE_INPUT_PLUGIN ?= no
- $(warning libbluray not found)
-endif
-
-ifeq ($(shell pkg-config libxine --atleast-version=1.1.19.1 || echo "yes"), yes)
- ENABLE_SPU_PLUGIN ?= yes
-else
- ENABLE_SPU_PLUGIN ?= no
- $(warning SPU plugin is included in xine-lib 1.1.19+)
-endif
-
-ifeq ($(shell pkg-config libxine --atleast-version=1.1.19.1 || echo "yes"), yes)
- ENABLE_PCM_PLUGIN ?= yes
-else
- ENABLE_PCM_PLUGIN ?= no
- $(warning PCM plugin is included in xine-lib 1.1.19+)
-endif
-
-#
-# compiler options
-#
-
-CFLAGS += -O2 -fPIC -ggdb
-CFLAGS += -Wall -Wextra -Wno-unused-parameter
-CFLAGS += -D_REENTRANT -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-CFLAGS += $(shell pkg-config libxine --cflags)
-CFLAGS += $(CFLAGS_BD)
-INSTALL = install
-
-
-#
-# linker options
-#
-
-LIBS_XINE = $(shell pkg-config libxine --libs)
-LDFLAGS += -shared -fvisibility=hidden
-
-#
-# targets
-#
-
-DESTDIR ?= /
-XINEPLUGINDIR = $(shell pkg-config libxine --variable=plugindir)
-
-ifeq ($(ENABLE_DEMUX_PLUGIN), yes)
- XINEDMXPLUGIN = xineplug_dmx_mpeg_ts_hdmv.so
-else
- $(warning Not building HDMV MPEG-TS demuxer plugin)
-endif
-
-ifeq ($(ENABLE_SPU_PLUGIN), yes)
- XINESPUPLUGIN = xineplug_decode_spuhdmv.so
-else
- $(warning Not building HDMV SPU plugin)
-endif
-
-ifeq ($(ENABLE_INPUT_PLUGIN), yes)
- XINEINPUTPLUGIN= xineplug_inp_bluray.so
-else
- $(warning Not building BluRay input plugin)
-endif
-
-ifeq ($(ENABLE_PCM_PLUGIN), yes)
- XINELPCMPLUGIN = xineplug_decode_lpcm_hdmv.so
-else
- $(warning Not building BluRay PCM plugin)
-endif
-
-#
-# object files
-#
-
-OBJS_XINEDMXPLUGIN = demux_ts.o
-OBJS_XINESPUPLUGIN = decode_spuhdmv.o
-OBJS_XINEINPUTPLUGIN = input_bluray.o
-OBJS_XINELPCMPLUGIN = xine_lpcm_decoder.o
-
-#
-# rules
-#
-
-all: $(XINEDMXPLUGIN) $(XINESPUPLUGIN) $(XINEINPUTPLUGIN) $(XINELPCMPLUGIN)
-
-ifeq ($(ENABLE_DEMUX_PLUGIN), yes)
-$(XINEDMXPLUGIN): $(OBJS_XINEDMXPLUGIN)
- $(CC) $(LDFLAGS) $(LIBS_XINE) -o $@ $(OBJS_XINEDMXPLUGIN)
-endif
-
-ifeq ($(ENABLE_SPU_PLUGIN), yes)
-$(XINESPUPLUGIN): $(OBJS_XINESPUPLUGIN)
- $(CC) $(LDFLAGS) $(LIBS_XINE) -o $@ $(OBJS_XINESPUPLUGIN)
-endif
-
-ifeq ($(ENABLE_INPUT_PLUGIN), yes)
-$(XINEINPUTPLUGIN): $(OBJS_XINEINPUTPLUGIN)
- $(CC) $(LDFLAGS) $(LIBS_XINE) $(LIBS_BD) -o $@ $(OBJS_XINEINPUTPLUGIN)
-endif
-
-ifeq ($(ENABLE_PCM_PLUGIN), yes)
-$(XINELPCMPLUGIN): $(OBJS_XINELPCMPLUGIN)
- $(CC) $(LDFLAGS) $(LIBS_XINE) -o $@ $(OBJS_XINELPCMPLUGIN)
-endif
-
-#
-# targets
-#
-
-clean:
- @rm -rf *.o *.so *~
-
-install: all uninstall
-ifeq ($(ENABLE_DEMUX_PLUGIN), yes)
- @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEDMXPLUGIN)
- @$(INSTALL) -D -m 0644 $(XINEDMXPLUGIN) $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEDMXPLUGIN)
-endif
-ifeq ($(ENABLE_SPU_PLUGIN), yes)
- @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINESPUPLUGIN)
- @$(INSTALL) -D -m 0644 $(XINESPUPLUGIN) $(DESTDIR)/$(XINEPLUGINDIR)/$(XINESPUPLUGIN)
-endif
-ifeq ($(ENABLE_INPUT_PLUGIN), yes)
- @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTPLUGIN)
- @$(INSTALL) -D -m 0644 $(XINEINPUTPLUGIN) $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTPLUGIN)
-endif
-ifeq ($(ENABLE_PCM_PLUGIN), yes)
- @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINELPCMPLUGIN)
- @$(INSTALL) -D -m 0644 $(XINELPCMPLUGIN) $(DESTDIR)/$(XINEPLUGINDIR)/$(XINELPCMPLUGIN)
-endif
-
-uninstall:
-ifeq ($(ENABLE_DEMUX_PLUGIN), yes)
- @echo Removing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEDMXPLUGIN)
- @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEDMXPLUGIN)
-endif
-ifeq ($(ENABLE_SPU_PLUGIN), yes)
- @echo Removing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINESPUPLUGIN)
- @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/$(XINESPUPLUGIN)
-endif
-ifeq ($(ENABLE_INPUT_PLUGIN), yes)
- @echo Removing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTPLUGIN)
- @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTPLUGIN)
-endif
-ifeq ($(ENABLE_PCM_PLUGIN), yes)
- @echo Removing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINELPCMPLUGIN)
- @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/$(XINELPCMPLUGIN)
-endif
diff --git a/xine/BluRay/decode_spuhdmv.c b/xine/BluRay/decode_spuhdmv.c
deleted file mode 100644
index b210f02..0000000
--- a/xine/BluRay/decode_spuhdmv.c
+++ /dev/null
@@ -1,1103 +0,0 @@
-/*
- * Copyright (C) 2000-2009 the xine project
- *
- * Copyright (C) 2009 Petri Hintukainen <phintuka at users.sourceforge.net>
- *
- * This file is part of xine, a unix 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
- *
- * Decoder for HDMV/BluRay bitmap subtitles
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#ifdef HAVE_CONFIG_H
-# include "xine_internal.h"
-# include "buffer.h"
-# include "xineutils.h"
-# include "video_out.h"
-# include "video_overlay.h"
-#else
-# include <xine/xine_internal.h>
-# include <xine/buffer.h>
-# include <xine/xineutils.h>
-# include <xine/video_out.h>
-# include <xine/video_overlay.h>
-#endif
-
-#define XINE_HDMV_TRACE(x...) printf(x)
-/*#define XINE_HDMV_TRACE(x...) */
-#define XINE_HDMV_ERROR(x...) fprintf(stderr, "spuhdmv: " x)
-/*#define XINE_HDMV_ERROR(x...) lprintf(x) */
-
-#ifndef EXPORTED
-# define EXPORTED __attribute__((visibility("default")))
-#endif
-
-#ifndef BUF_SPU_HDMV
-# define BUF_SPU_HDMV 0x04080000
-#endif
-
-#ifndef MAX
-# define MAX(a,b) (a>b)?(a):(b)
-#endif
-
-enum {
- SEGTYPE_PALETTE = 0x14,
- SEGTYPE_OBJECT = 0x15,
- SEGTYPE_PRESENTATION_SEGMENT = 0x16,
- SEGTYPE_WINDOW_DEFINITION = 0x17,
- SEGTYPE_INTERACTIVE = 0x18,
- SEGTYPE_END_OF_DISPLAY = 0x80,
-} eSegmentType;
-
-/*
- * cached palette (xine-lib format)
- */
-typedef struct subtitle_clut_s subtitle_clut_t;
-struct subtitle_clut_s {
- uint8_t id;
- uint32_t color[256];
- uint8_t trans[256];
- subtitle_clut_t *next;
-
- int shown;
-};
-
-/*
- * cached RLE image (xine-lib format)
- */
-typedef struct subtitle_object_s subtitle_object_t;
-struct subtitle_object_s {
- uint16_t id;
- uint16_t xpos, ypos;
- uint16_t width, height;
-
- /* xine format */
- rle_elem_t *rle;
- unsigned int num_rle;
- size_t data_size;
-
- /* HDMV format (used when object does not fit to single segment) */
- uint32_t data_len; /* size of complete object */
- uint8_t *raw_data; /* partial RLE data in HDMV format */
- size_t raw_data_len; /* bytes buffered */
- size_t raw_data_size; /* allocated size */
-
- subtitle_object_t *next;
-
- int shown;
-};
-
-/*
- * Window definition
- */
-typedef struct window_def_s window_def_t;
-struct window_def_s {
- uint8_t id;
- uint16_t xpos, ypos;
- uint16_t width, height;
-
- window_def_t *next;
-
- int shown;
-};
-
-
-/*
- * decoded SPU
- */
-typedef struct composition_object_s composition_object_t;
-struct composition_object_s {
- uint8_t window_id_ref;
- uint16_t object_id_ref;
-
- uint16_t xpos, ypos;
-
- uint8_t forced_flag;
- uint8_t cropped_flag;
- uint16_t crop_horiz_pos, crop_vert_pos;
- uint16_t crop_width, crop_height;
-
- composition_object_t *next;
-
- int shown;
-};
-
-typedef struct composition_descriptor_s composition_descriptor_t;
-struct composition_descriptor_s {
- uint16_t number;
- uint8_t state;
-};
-
-typedef struct presentation_segment_s presentation_segment_t;
-struct presentation_segment_s {
- composition_descriptor_t comp_descr;
-
- uint8_t palette_update_flag;
- uint8_t palette_id_ref;
- uint8_t object_number;
-
- composition_object_t *comp_objs;
-
- presentation_segment_t *next;
-
- int64_t pts;
- int shown;
-};
-
-/*
- * list handling
- */
-
-#define LIST_REPLACE(list, obj, FREE_FUNC) \
- do { \
- unsigned int id = obj->id; \
- \
- /* insert to list */ \
- obj->next = list; \
- list = obj; \
- \
- /* remove old */ \
- while (obj->next && obj->next->id != id) \
- obj = obj->next; \
- if (obj->next) { \
- void *tmp = (void*)obj->next; \
- obj->next = obj->next->next; \
- FREE_FUNC(tmp); \
- } \
- } while (0);
-
-#define LIST_DESTROY(list, FREE_FUNC) \
- while (list) { \
- void *tmp = (void*)list; \
- list = list->next; \
- FREE_FUNC(tmp); \
- }
-
-static void free_subtitle_object(void *ptr)
-{
- if (ptr) {
- free(((subtitle_object_t*)ptr)->rle);
- free(((subtitle_object_t*)ptr)->raw_data);
- free(ptr);
- }
-}
-static void free_presentation_segment(void *ptr)
-{
- if (ptr) {
- presentation_segment_t *seg = (presentation_segment_t*)ptr;
- LIST_DESTROY(seg->comp_objs, free);
- free(ptr);
- }
-}
-
-
-/*
- * segment_buffer_t
- *
- * assemble and decode segments
- */
-
-typedef struct {
- /* current segment */
- int segment_len; /* length of current segment (without 3-byte header) */
- uint8_t segment_type; /* current segment type */
- uint8_t *segment_data; /* pointer to current segment payload */
- uint8_t *segment_end; /* pointer to last byte + 1 of current segment */
- uint8_t error; /* boolean: buffer overflow etc. */
-
- /* accumulated data */
- uint8_t *buf; /* */
- size_t len; /* count of unprocessed bytes */
- size_t data_size; /* allocated buffer size */
-} segment_buffer_t;
-
-/*
- * mgmt
- */
-
-static segment_buffer_t *segbuf_init(void)
-{
- segment_buffer_t *buf = calloc(1, sizeof(segment_buffer_t));
- return buf;
-}
-
-static void segbuf_dispose(segment_buffer_t *buf)
-{
- if (buf->buf)
- free (buf->buf);
- free (buf);
-}
-
-static void segbuf_reset(segment_buffer_t *buf)
-{
- buf->segment_end = buf->segment_data = buf->buf;
- buf->len = 0;
- buf->segment_len = -1;
- buf->segment_type = 0;
- buf->error = 0;
-}
-
-/*
- * assemble, parse
- */
-
-static void segbuf_parse_segment_header(segment_buffer_t *buf)
-{
- if (buf->len > 2) {
- buf->segment_type = buf->buf[0];
- buf->segment_len = (buf->buf[1] << 8) | buf->buf[2];
- buf->segment_data = buf->buf + 3;
- buf->segment_end = buf->segment_data + buf->segment_len;
- buf->error = 0;
-
- if ( buf->segment_type < 0x14 ||
- ( buf->segment_type > 0x18 &&
- buf->segment_type != 0x80)) {
- XINE_HDMV_ERROR("unknown segment type, resetting\n");
- segbuf_reset(buf);
- }
- } else {
- buf->segment_len = -1;
- buf->error = 1;
- }
-}
-
-static void segbuf_fill(segment_buffer_t *buf, uint8_t *data, size_t len)
-{
- if (buf->len + len > buf->data_size) {
- buf->data_size = buf->len + len;
- if (buf->buf)
- buf->buf = realloc(buf->buf, buf->data_size);
- else
- buf->buf = malloc(buf->data_size);
- }
-
- memcpy(buf->buf + buf->len, data, len);
- buf->len += len;
-
- segbuf_parse_segment_header(buf);
-}
-
-static int segbuf_segment_complete(segment_buffer_t *buf)
-{
- return (buf->segment_len >= 0) && (buf->len >= (unsigned)buf->segment_len + 3);
-}
-
-static void segbuf_skip_segment(segment_buffer_t *buf)
-{
- if (segbuf_segment_complete (buf)) {
- buf->len -= buf->segment_len + 3;
- if (buf->len > 0)
- memmove(buf->buf, buf->buf + buf->segment_len + 3, buf->len);
-
- segbuf_parse_segment_header(buf);
-
- XINE_HDMV_TRACE(" skip_segment: %zd bytes left\n", buf->len);
- } else {
- XINE_HDMV_ERROR(" skip_segment: ERROR - %zd bytes queued, %d required\n",
- buf->len, buf->segment_len);
- segbuf_reset (buf);
- }
-}
-
-/*
- * access segment data
- */
-
-static uint8_t segbuf_segment_type(segment_buffer_t *buf)
-{
- return buf->segment_type;
-}
-
-static size_t segbuf_data_length(segment_buffer_t *buf)
-{
- ssize_t val = buf->segment_end - buf->segment_data;
- if (val < 0) val = 0;
- return (size_t)val;
-}
-
-static uint8_t segbuf_get_u8(segment_buffer_t *buf)
-{
- if (!(buf->error = ++buf->segment_data > buf->segment_end))
- return buf->segment_data[-1];
- XINE_HDMV_ERROR("segbuf_get_u8: read failed (end of segment reached) !\n");
- return 0;
-}
-
-static uint16_t segbuf_get_u16(segment_buffer_t *buf)
-{
- return (segbuf_get_u8(buf) << 8) | segbuf_get_u8(buf);
-}
-
-static uint32_t segbuf_get_u24(segment_buffer_t *buf)
-{
- return (segbuf_get_u8(buf) << 16) | (segbuf_get_u8(buf) << 8) | segbuf_get_u8(buf);
-}
-
-/*
- * decode segments
- */
-
-static subtitle_clut_t *segbuf_decode_palette(segment_buffer_t *buf)
-{
- uint8_t palette_id = segbuf_get_u8 (buf);
- uint8_t palette_version_number = segbuf_get_u8 (buf);
-
- size_t len = segbuf_data_length(buf);
- size_t entries = len / 5;
- size_t i;
-
- if (buf->error)
- return NULL;
-
- if (len % 5) {
- XINE_HDMV_ERROR(" decode_palette: segment size error (%zd ; expected %zd for %zd entries)\n",
- len, (5 * entries), entries);
- return NULL;
- }
- XINE_HDMV_TRACE("decode_palette: %zd items (id %d, version %d)\n",
- entries, palette_id, palette_version_number);
-
- /* convert to xine-lib clut */
- subtitle_clut_t *clut = calloc(1, sizeof(subtitle_clut_t));
- clut->id = palette_id;
-
- for (i = 0; i < entries; i++) {
- uint8_t index = segbuf_get_u8 (buf);
- uint8_t Y = segbuf_get_u8 (buf);
- uint8_t Cr = segbuf_get_u8 (buf);
- uint8_t Cb = segbuf_get_u8 (buf);
- uint8_t alpha = segbuf_get_u8 (buf);
- clut->color[index] = (Y << 16) | (Cr << 8) | Cb;
- clut->trans[index] = alpha >> 4;
- }
-
- return clut;
-}
-
-static int segbuf_decode_rle(segment_buffer_t *buf, subtitle_object_t *obj)
-{
- int x = 0, y = 0;
- int rle_size = sizeof(rle_elem_t) * obj->width / 16 * obj->height + 1;
- rle_elem_t *rlep = malloc(rle_size);
-
- free (obj->rle);
- obj->rle = rlep;
- obj->data_size = rle_size;
- obj->num_rle = 0;
-
- /* convert to xine-lib rle format */
- while (y < obj->height && !buf->error) {
-
- /* decode RLE element */
- uint8_t byte = segbuf_get_u8 (buf);
- if (byte != 0) {
- rlep->color = byte;
- rlep->len = 1;
- } else {
- byte = segbuf_get_u8 (buf);
- if (!(byte & 0x80)) {
- rlep->color = 0;
- if (!(byte & 0x40))
- rlep->len = byte & 0x3f;
- else
- rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf);
- } else {
- if (!(byte & 0x40))
- rlep->len = byte & 0x3f;
- else
- rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf);
- rlep->color = segbuf_get_u8 (buf);
- }
- }
-
- /* move to next element */
- if (rlep->len > 0) {
- x += rlep->len;
- rlep++;
- obj->num_rle ++;
- } else {
- /* end of line marker (00 00) */
- if (x < obj->width) {
- rlep->len = obj->width - x;
- rlep->color = 0xff;
- rlep++;
- obj->num_rle ++;
- }
- x = 0;
- y++;
- }
-
- /* grow allocated RLE data size ? */
- if (obj->data_size <= (obj->num_rle + 1) * sizeof(rle_elem_t)) {
- obj->data_size *= 2;
- obj->rle = realloc(obj->rle, obj->data_size);
- rlep = obj->rle + obj->num_rle;
- }
- }
-
- return buf->error;
-}
-
-static subtitle_object_t *segbuf_decode_object(segment_buffer_t *buf, subtitle_object_t *objects)
-{
- uint16_t object_id = segbuf_get_u16(buf);
- uint8_t version = segbuf_get_u8 (buf);
- uint8_t seq_desc = segbuf_get_u8 (buf);
-
- XINE_HDMV_TRACE(" decode_object: object_id %d, version %d, seq 0x%x\n",
- object_id, version, seq_desc);
-
- if (seq_desc & 0x80) {
- /* new object (first-in-sequence flag set) */
-
- subtitle_object_t *obj = calloc(1, sizeof(subtitle_object_t));
-
- obj->id = object_id;
- obj->data_len = segbuf_get_u24(buf);
- obj->width = segbuf_get_u16(buf);
- obj->height = segbuf_get_u16(buf);
-
- if (buf->error) {
- XINE_HDMV_TRACE(" decode error at object header\n");
- free_subtitle_object(obj);
- return NULL;
- }
-
- obj->data_len -= 4; /* width, height parsed */
-
- XINE_HDMV_TRACE(" object length %d bytes, size %dx%d\n", obj->data_len, obj->width, obj->height);
-
- if (obj->data_len > segbuf_data_length(buf)) {
- XINE_HDMV_TRACE(" object length %d bytes, have only %zd bytes -> missing %d bytes\n",
- obj->data_len, segbuf_data_length(buf), obj->data_len - (int)segbuf_data_length(buf));
-
- if (obj->raw_data)
- free(obj->raw_data);
-
- /* store partial RLE data in HDMV format */
- obj->raw_data_len = segbuf_data_length(buf);
- obj->raw_data_size = MAX(obj->data_len, obj->raw_data_len);
- obj->raw_data = malloc(obj->raw_data_size);
- memcpy(obj->raw_data, buf->segment_data, obj->raw_data_len);
-
- return obj;
- }
-
- segbuf_decode_rle (buf, obj);
-
- if (buf->error) {
- XINE_HDMV_TRACE(" decode error at RLE data\n");
- free_subtitle_object(obj);
- return NULL;
- }
-
- return obj;
- }
-
- /* not first-of-sequence --> append data to already existing objct */
-
- /* search for object */
- while (objects && objects->id != object_id)
- objects = objects->next;
-
- if (!objects) {
- XINE_HDMV_TRACE(" object not found from list, discarding segment\n");
- return NULL;
- }
-
- /* store partial RLE data in HDMV format */
- if (objects->raw_data_size < objects->raw_data_len + segbuf_data_length(buf)) {
- XINE_HDMV_ERROR("object larger than object size !\n");
- return NULL;
- }
- memcpy(objects->raw_data + objects->raw_data_len, buf->segment_data, segbuf_data_length(buf));
- objects->raw_data_len += segbuf_data_length(buf);
-
- /* if complete, decode RLE data */
- if (objects->raw_data_len >= objects->data_len) {
- /* create dummy buffer for segbuf_decode_rle */
- segment_buffer_t tmpbuf = {
- .segment_data = objects->raw_data,
- .segment_end = objects->raw_data + objects->raw_data_len,
- };
-
- /* decode RLE data */
- segbuf_decode_rle (&tmpbuf, objects);
-
- if (tmpbuf.error) {
- XINE_HDMV_TRACE(" error decoding multi-segment object\n");
- }
-
- /* free decode buffer */
- free(objects->raw_data);
- objects->raw_data = NULL;
- objects->raw_data_len = 0;
- objects->raw_data_size = 0;
- }
-
- return NULL;
-}
-
-static window_def_t *segbuf_decode_window_definition(segment_buffer_t *buf)
-{
- window_def_t *wnd = calloc(1, sizeof(window_def_t));
-
- uint8_t a = segbuf_get_u8 (buf);
- wnd->id = segbuf_get_u8 (buf);
- wnd->xpos = segbuf_get_u16 (buf);
- wnd->ypos = segbuf_get_u16 (buf);
- wnd->width = segbuf_get_u16 (buf);
- wnd->height = segbuf_get_u16 (buf);
-
- XINE_HDMV_TRACE(" window: [%02x %d] %d,%d %dx%d\n", a,
- wnd->id, wnd->xpos, wnd->ypos, wnd->width, wnd->height);
-
- if (buf->error) {
- free(wnd);
- return NULL;
- }
-
- return wnd;
-}
-
-static int segbuf_decode_video_descriptor(segment_buffer_t *buf)
-{
- uint16_t width = segbuf_get_u16(buf);
- uint16_t height = segbuf_get_u16(buf);
- uint8_t frame_rate = segbuf_get_u8 (buf);
-
- XINE_HDMV_TRACE(" video_descriptor: %dx%d fps %d\n", width, height, frame_rate);
-
- return buf->error;
-}
-
-static int segbuf_decode_composition_descriptor(segment_buffer_t *buf, composition_descriptor_t *descr)
-{
- descr->number = segbuf_get_u16(buf);
- descr->state = segbuf_get_u8 (buf) & 0xc0;
-
- XINE_HDMV_TRACE(" composition_descriptor: number %d, state %d\n", descr->number, descr->state);
- return buf->error;
-}
-
-static composition_object_t *segbuf_decode_composition_object(segment_buffer_t *buf)
-{
- composition_object_t *cobj = calloc(1, sizeof(composition_object_t));
-
- cobj->object_id_ref = segbuf_get_u16 (buf);
- cobj->window_id_ref = segbuf_get_u8 (buf);
- uint8_t tmp = segbuf_get_u8 (buf);
- cobj->cropped_flag = !!(tmp & 0x80);
- cobj->forced_flag = !!(tmp & 0x40);
- cobj->xpos = segbuf_get_u16 (buf);
- cobj->ypos = segbuf_get_u16 (buf);
- if (cobj->cropped_flag) {
- /* x,y where to take the image from */
- cobj->crop_horiz_pos = segbuf_get_u8 (buf);
- cobj->crop_vert_pos = segbuf_get_u8 (buf);
- /* size of the cropped image */
- cobj->crop_width = segbuf_get_u8 (buf);
- cobj->crop_height = segbuf_get_u8 (buf);
- }
-
- if (buf->error) {
- free(cobj);
- return NULL;
- }
-
- XINE_HDMV_TRACE(" composition_object: id: %d, win: %d, position %d,%d crop %d forced %d\n",
- cobj->object_id_ref, cobj->window_id_ref, cobj->xpos, cobj->ypos,
- cobj->cropped_flag, cobj->forced_flag);
-
- return cobj;
-}
-
-static presentation_segment_t *segbuf_decode_presentation_segment(segment_buffer_t *buf)
-{
- presentation_segment_t *seg = calloc(1, sizeof(presentation_segment_t));
- int index;
-
- segbuf_decode_video_descriptor (buf);
- segbuf_decode_composition_descriptor (buf, &seg->comp_descr);
-
- seg->palette_update_flag = !!((segbuf_get_u8(buf)) & 0x80);
- seg->palette_id_ref = segbuf_get_u8 (buf);
- seg->object_number = segbuf_get_u8 (buf);
-
- XINE_HDMV_TRACE(" presentation_segment: object_number %d, palette %d\n",
- seg->object_number, seg->palette_id_ref);
-
- for (index = 0; index < seg->object_number; index++) {
- composition_object_t *cobj = segbuf_decode_composition_object (buf);
- cobj->next = seg->comp_objs;
- seg->comp_objs = cobj;
- }
-
- if (buf->error) {
- free_presentation_segment(seg);
- return NULL;
- }
-
- return seg;
-}
-
-static rle_elem_t *copy_crop_rle(subtitle_object_t *obj, composition_object_t *cobj)
-{
- /* TODO: cropping (w,h sized image from pos x,y) */
-
- rle_elem_t *rle = calloc (obj->num_rle, sizeof(rle_elem_t));
- memcpy (rle, obj->rle, obj->num_rle * sizeof(rle_elem_t));
- return rle;
-}
-
-
-/*
- * xine plugin
- */
-
-typedef struct {
- spu_decoder_class_t decoder_class;
-} spuhdmv_class_t;
-
-typedef struct spuhdmv_decoder_s {
- spu_decoder_t spu_decoder;
-
- spuhdmv_class_t *class;
- xine_stream_t *stream;
-
- segment_buffer_t *buf;
-
- subtitle_clut_t *cluts;
- subtitle_object_t *objects;
- window_def_t *windows;
- presentation_segment_t *segments;
-
- int overlay_handles[MAX_OBJECTS];
-
- int64_t pts;
-
-} spuhdmv_decoder_t;
-
-static void free_objs(spuhdmv_decoder_t *this)
-{
- LIST_DESTROY (this->cluts, free);
- LIST_DESTROY (this->objects, free_subtitle_object);
- LIST_DESTROY (this->windows, free);
- LIST_DESTROY (this->segments, free_presentation_segment);
-}
-
-static int decode_palette(spuhdmv_decoder_t *this)
-{
- /* decode */
- subtitle_clut_t *clut = segbuf_decode_palette(this->buf);
- if (!clut)
- return 1;
-
- LIST_REPLACE (this->cluts, clut, free);
-
- return 0;
-}
-
-static int decode_object(spuhdmv_decoder_t *this)
-{
- /* decode */
- subtitle_object_t *obj = segbuf_decode_object(this->buf, this->objects);
- if (!obj)
- return 1;
-
- LIST_REPLACE (this->objects, obj, free_subtitle_object);
-
- return 0;
-}
-
-static int decode_window_definition(spuhdmv_decoder_t *this)
-{
- /* decode */
- window_def_t *wnd = segbuf_decode_window_definition (this->buf);
- if (!wnd)
- return 1;
-
- LIST_REPLACE (this->windows, wnd, free);
-
- return 0;
-}
-
-static int decode_presentation_segment(spuhdmv_decoder_t *this)
-{
- /* decode */
- presentation_segment_t *seg = segbuf_decode_presentation_segment(this->buf);
- if (!seg)
- return 1;
-
- seg->pts = this->pts;
-
- /* epoch start or acquistion point -> drop cached objects */
- if (seg->comp_descr.state) {
- free_objs(this);
- }
-
- /* replace */
- if (this->segments)
- LIST_DESTROY(this->segments, free_presentation_segment);
- this->segments = seg;
-
- return 0;
-}
-
-static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, unsigned int palette_id_ref,
- int overlay_index, int64_t pts, int force_update)
-{
- video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out);
- metronom_t *metronom = this->stream->metronom;
- video_overlay_event_t event = {.vpts = 0};
- vo_overlay_t overlay = {.data_size = 0};
-
- /* find palette */
- subtitle_clut_t *clut = this->cluts;
- while (clut && clut->id != palette_id_ref)
- clut = clut->next;
- if (!clut) {
- XINE_HDMV_TRACE(" show_overlay: clut %d not found !\n", palette_id_ref);
- return -1;
- }
-
- /* find RLE image */
- subtitle_object_t *obj = this->objects;
- while (obj && obj->id != cobj->object_id_ref)
- obj = obj->next;
- if (!obj) {
- XINE_HDMV_TRACE(" show_overlay: object %d not found !\n", cobj->object_id_ref);
- return -1;
- }
- if (!obj->rle) {
- XINE_HDMV_TRACE(" show_overlay: object %d RLE data not decoded !\n", cobj->object_id_ref);
- return -1;
- }
-
- /* find window */
- window_def_t *wnd = this->windows;
- while (wnd && wnd->id != cobj->window_id_ref)
- wnd = wnd->next;
- if (!wnd) {
- XINE_HDMV_TRACE(" show_overlay: window %d not found !\n", cobj->window_id_ref);
- return -1;
- }
-
- /* do not show again if all elements are unchanged */
- if (!force_update && clut->shown && obj->shown && wnd->shown && cobj->shown)
- return 0;
- clut->shown = obj->shown = wnd->shown = cobj->shown = 1;
-
- /* copy palette to xine overlay */
- overlay.rgb_clut = 0;
- memcpy(overlay.color, clut->color, sizeof(uint32_t) * 256);
- memcpy(overlay.trans, clut->trans, sizeof(uint8_t) * 256);
-
- /* copy and crop RLE image to xine overlay */
- overlay.width = obj->width;
- overlay.height = obj->height;
-
- overlay.rle = copy_crop_rle (obj, cobj);
- overlay.num_rle = obj->num_rle;
- overlay.data_size = obj->num_rle * sizeof(rle_elem_t);
-
- /* */
-
- overlay.x = /*wnd->xpos +*/ cobj->xpos;
- overlay.y = /*wnd->ypos +*/ cobj->ypos;
-
- overlay.unscaled = 0;
- overlay.hili_top = -1;
- overlay.hili_bottom = -1;
- overlay.hili_left = -1;
- overlay.hili_right = -1;
-
- XINE_HDMV_TRACE(" -> overlay: %d,%d %dx%d\n",
- overlay.x, overlay.y, overlay.width, overlay.height);
-
-
- /* set timings */
-
- if (pts > 0)
- event.vpts = metronom->got_spu_packet (metronom, pts);
- else
- event.vpts = 0;
-
-
- /* generate SHOW event */
-
- this->stream->video_out->enable_ovl(this->stream->video_out, 1);
-
- if (this->overlay_handles[overlay_index] < 0)
- this->overlay_handles[overlay_index] = ovl_manager->get_handle(ovl_manager, 0);
-
- event.event_type = OVERLAY_EVENT_SHOW;
- event.object.handle = this->overlay_handles[overlay_index];
- event.object.overlay = &overlay;
- event.object.object_type = 0; /* subtitle */
-
- ovl_manager->add_event (ovl_manager, (void *)&event);
-
- return 0;
-}
-
-static void hide_overlays(spuhdmv_decoder_t *this, int64_t pts)
-{
- video_overlay_event_t event = {.vpts = 0};
- int i = 0;
-
- while (this->overlay_handles[i] >= 0) {
- XINE_HDMV_TRACE(" -> HIDE %d\n", i);
-
- video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out);
- metronom_t *metronom = this->stream->metronom;
-
- event.object.handle = this->overlay_handles[i];
- if (this)
- event.vpts = metronom->got_spu_packet (metronom, pts);
- else
- event.vpts = 0;
- event.event_type = OVERLAY_EVENT_HIDE;
- event.object.overlay = NULL;
- ovl_manager->add_event (ovl_manager, (void *)&event);
-
- //this->overlay_handles[i] = -1;
- i++;
- }
-}
-
-static void update_overlays(spuhdmv_decoder_t *this)
-{
- presentation_segment_t *pseg = this->segments;
-
- while (pseg) {
-
- if (!pseg->object_number) {
-
- /* HIDE */
- if (!pseg->shown)
- hide_overlays (this, pseg->pts);
-
- } else {
-
- /* SHOW */
- composition_object_t *cobj = pseg->comp_objs;
- int i;
-
- for (i = 0; i < pseg->object_number; i++) {
- if (!cobj) {
- XINE_HDMV_ERROR("show_overlays: composition object %d missing !\n", i);
- } else {
- show_overlay(this, cobj, pseg->palette_id_ref, i, pseg->pts, !pseg->shown);
- cobj = cobj->next;
- }
- }
- }
-
- pseg->shown = 1;
-
- pseg = pseg->next;
- }
-}
-
-static void decode_segment(spuhdmv_decoder_t *this)
-{
- XINE_HDMV_TRACE("*** new segment, pts %010"PRId64": 0x%02x (%8d bytes)\n",
- this->pts, this->buf->segment_type, this->buf->segment_len);
-
- switch (segbuf_segment_type(this->buf)) {
- case SEGTYPE_PALETTE:
- XINE_HDMV_TRACE(" segment: PALETTE\n");
- decode_palette(this);
- break;
- case SEGTYPE_OBJECT:
- XINE_HDMV_TRACE(" segment: OBJECT\n");
- decode_object(this);
- break;
- case SEGTYPE_PRESENTATION_SEGMENT:
- XINE_HDMV_TRACE(" segment: PRESENTATION SEGMENT\n");
- decode_presentation_segment(this);
- break;
- case SEGTYPE_WINDOW_DEFINITION:
- XINE_HDMV_TRACE(" segment: WINDOW DEFINITION\n");
- decode_window_definition(this);
- break;
- case SEGTYPE_INTERACTIVE:
- XINE_HDMV_TRACE(" segment: INTERACTIVE\n");
- break;
- case SEGTYPE_END_OF_DISPLAY:
- XINE_HDMV_TRACE(" segment: END OF DISPLAY\n");
-#if 0
- /* drop all cached objects */
- free_objs(this);
-#endif
- break;
- default:
- XINE_HDMV_ERROR(" segment type 0x%x unknown, skipping\n", segbuf_segment_type(this->buf));
- break;
- }
- if (this->buf->error) {
- XINE_HDMV_ERROR("*** DECODE ERROR ***\n");
- }
-
- update_overlays (this);
-}
-
-static void close_osd(spuhdmv_decoder_t *this)
-{
- video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager (this->stream->video_out);
-
- int i = 0;
- while (this->overlay_handles[i] >= 0) {
- ovl_manager->free_handle(ovl_manager, this->overlay_handles[i]);
- this->overlay_handles[i] = -1;
- i++;
- }
-}
-
-static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf)
-{
- spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen;
-
- if ((buf->type & 0xffff0000) != BUF_SPU_HDMV)
- return;
-
- if (buf->size < 1)
- return;
-
- if (buf->pts)
- this->pts = buf->pts;
-
-#ifdef DUMP_SPU_DATA
- int i;
- for(i = 0; i < buf->size; i++)
- printf(" %02x", buf->content[i]);
- printf("\n");
-#endif
-
- segbuf_fill(this->buf, buf->content, buf->size);
-
- while (segbuf_segment_complete(this->buf)) {
- decode_segment(this);
- segbuf_skip_segment(this->buf);
- }
-}
-
-static void spudec_reset (spu_decoder_t * this_gen)
-{
- spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen;
-
- if (this->buf)
- segbuf_reset(this->buf);
-
- free_objs(this);
-
- close_osd(this);
-}
-
-static void spudec_discontinuity (spu_decoder_t *this_gen)
-{
- spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen;
-
- close_osd(this);
-}
-
-static void spudec_dispose (spu_decoder_t *this_gen)
-{
- spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen;
-
- close_osd (this);
- segbuf_dispose (this->buf);
-
- free_objs(this);
-
- free (this);
-}
-
-static spu_decoder_t *open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream)
-{
- spuhdmv_decoder_t *this;
-
- this = (spuhdmv_decoder_t *) calloc(1, sizeof (spuhdmv_decoder_t));
-
- this->spu_decoder.decode_data = spudec_decode_data;
- this->spu_decoder.reset = spudec_reset;
- this->spu_decoder.discontinuity = spudec_discontinuity;
- this->spu_decoder.dispose = spudec_dispose;
- this->spu_decoder.get_interact_info = NULL;
- this->spu_decoder.set_button = NULL;
- this->stream = stream;
- this->class = (spuhdmv_class_t *) class_gen;
-
- this->buf = segbuf_init();
-
- memset(this->overlay_handles, 0xff, sizeof(this->overlay_handles)); /* --> -1 */
-
- return &this->spu_decoder;
-}
-
-static char *get_identifier (spu_decoder_class_t *this)
-{
- return "spuhdmv";
-}
-
-static char *get_description (spu_decoder_class_t *this)
-{
- return "HDMV/BluRay bitmap SPU decoder plugin";
-}
-
-static void dispose_class (spu_decoder_class_t *this)
-{
- free (this);
-}
-
-static void *init_plugin (xine_t *xine, void *data)
-{
- spuhdmv_class_t *this;
-
- this = calloc(1, sizeof (spuhdmv_class_t));
-
- this->decoder_class.open_plugin = open_plugin;
- this->decoder_class.get_identifier = get_identifier;
- this->decoder_class.get_description = get_description;
- this->decoder_class.dispose = dispose_class;
-
- return this;
-}
-
-/* plugin catalog information */
-static uint32_t supported_types[] = { BUF_SPU_HDMV, 0 };
-
-static const decoder_info_t dec_info_data = {
- supported_types, /* supported types */
- 5 /* priority */
-};
-
-const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
- { PLUGIN_SPU_DECODER, 16, "spuhdmv", XINE_VERSION_CODE, &dec_info_data, &init_plugin },
- { PLUGIN_NONE, 0, "", 0, NULL, NULL }
-};
diff --git a/xine/BluRay/demux_ts.c b/xine/BluRay/demux_ts.c
deleted file mode 100644
index 9b78005..0000000
--- a/xine/BluRay/demux_ts.c
+++ /dev/null
@@ -1,2783 +0,0 @@
-
-/*
- * Copyright (C) 2000-2003 the xine project
- *
- * 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
- *
- * Demultiplexer for MPEG2 Transport Streams.
- *
- * For the purposes of playing video, we make some assumptions about the
- * kinds of TS we have to process. The most important simplification is to
- * assume that the TS contains a single program (SPTS) because this then
- * allows significant simplifications to be made in processing PATs.
- *
- * The next simplification is to assume that the program has a reasonable
- * number of video, audio and other streams. This allows PMT processing to
- * be simplified.
- *
- * MODIFICATION HISTORY
- *
- * Date Author
- * ---- ------
- *
- * 8-Apr-2009 Petri Hintukainen <phi at sdf-eu.org>
- * - support for 192-byte packets (HDMV/BluRay)
- * - support for audio inside PES PID 0xfd (HDMV/BluRay)
- * - demux HDMV/BluRay bitmap subtitles
- *
- * 28-Nov-2004 Mike Lampard <mlampard>
- * - Added support for PMT sections larger than 1 ts packet
- *
- * 28-Aug-2004 James Courtier-Dutton <jcdutton>
- * - Improve PAT and PMT handling. Added some FIXME comments.
- *
- * 9-Aug-2003 James Courtier-Dutton <jcdutton>
- * - Improve readability of code. Added some FIXME comments.
- *
- * 25-Nov-2002 Peter Liljenberg
- * - Added DVBSUB support
- *
- * 07-Nov-2992 Howdy Pierce
- * - various bugfixes
- *
- * 30-May-2002 Mauro Borghi
- * - dynamic allocation leaks fixes
- *
- * 27-May-2002 Giovanni Baronetti and Mauro Borghi <mauro.borghi at tilab.com>
- * - fill buffers before putting them in fifos
- * - force PMT reparsing when PMT PID changes
- * - accept non seekable input plugins -- FIX?
- * - accept dvb as input plugin
- * - optimised read operations
- * - modified resync code
- *
- * 16-May-2002 Thibaut Mattern <tmattern at noos.fr>
- * - fix demux loop
- *
- * 07-Jan-2002 Andr Draszik <andid at gmx.net>
- * - added support for single-section PMTs
- * spanning multiple TS packets
- *
- * 10-Sep-2001 James Courtier-Dutton <jcdutton>
- * - re-wrote sync code so that it now does not loose any data
- *
- * 27-Aug-2001 Hubert Matthews Reviewed by: n/a
- * - added in synchronisation code
- *
- * 1-Aug-2001 James Courtier-Dutton <jcdutton> Reviewed by: n/a
- * - TS Streams with zero PES length should now work
- *
- * 30-Jul-2001 shaheedhaque Reviewed by: n/a
- * - PATs and PMTs seem to work
- *
- * 29-Jul-2001 shaheedhaque Reviewed by: n/a
- * - Compiles!
- *
- *
- * TODO: do without memcpys, preview buffers
- */
-
-
-/** HOW TO IMPLEMENT A DVBSUB DECODER.
- *
- * The DVBSUB protocol is specified in ETSI EN 300 743. It can be
- * downloaded for free (registration required, though) from
- * www.etsi.org.
- *
- * The spu_decoder should handle the packet type BUF_SPU_DVB.
- *
- * BUF_SPU_DVBSUB packets without the flag BUF_FLAG_SPECIAL contain
- * the payload of the PES packets carrying DVBSUB data. Since the
- * payload can be broken up over several buf_element_t and the DVBSUB
- * is PES oriented, the decoder_info[2] field (low 16 bits) is used to convey the
- * packet boundaries to the decoder:
- *
- * + For the first buffer of a packet, buf->content points to the
- * first byte of the PES payload. decoder_info[2] is set to the length of the
- * payload. The decoder can use this value to determine when a
- * complete PES packet has been collected.
- *
- * + For the following buffers of the PES packet, decoder_info[2] is 0.
- *
- * The decoder can either use this information to reconstruct the PES
- * payload, or ignore it and implement a parser that handles the
- * irregularites at the start and end of PES packets.
- *
- * In any case buf->pts is always set to the PTS of the PES packet.
- *
- *
- * BUF_SPU_DVB with BUF_FLAG_SPECIAL set contains no payload, and is
- * used to pass control information to the decoder.
- *
- * If decoder_info[1] == BUF_SPECIAL_SPU_DVB_DESCRIPTOR then
- * decoder_info_ptr[2] either points to a spu_dvb_descriptor_t or is NULL.
- *
- * If it is 0, the user has disabled the subtitling, or has selected a
- * channel that is not present in the stream. The decoder should
- * remove any visible subtitling.
- *
- * If it is a pointer, the decoder should reset itself and start
- * extracting the subtitle service identified by comp_page_id and
- * aux_page_id in the spu_dvb_descriptor_t, (the composition and
- * auxilliary page ids, respectively).
- **/
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-#define LOG_MODULE "demux_ts"
-#define LOG_VERBOSE
-/*
-#define LOG
-*/
-
-#include <xine/xine_internal.h>
-#include <xine/xineutils.h>
-#include <xine/demux.h>
-
-//#define TS_PMT_LOG
-//#define TS_PAT_LOG
-
-#ifndef EXPORTED
-# define EXPORTED __attribute__((visibility("default")))
-#endif
-
-#ifndef BUF_SPU_HDMV
-# define BUF_SPU_HDMV 0x04080000
-#endif
-#ifndef BUF_AUDIO_AAC_LATM
-# define BUF_AUDIO_AAC_LATM 0x03420000
-#endif
-#ifndef XINE_EVENT_END_OF_CLIP
-# define XINE_EVENT_END_OF_CLIP 0x80000001
-#endif
-
-/*
- #define TS_LOG
- #define TS_PMT_LOG
- #define TS_PAT_LOG
-
- #define TS_READ_STATS // activates read statistics generation
- #define TS_HEADER_LOG // prints out the Transport packet header.
-*/
-
-/*
- * The maximum number of PIDs we are prepared to handle in a single program
- * is the number that fits in a single-packet PMT.
- */
-#define PKT_SIZE 188
-#define BODY_SIZE (188 - 4)
-/* more PIDS are needed due "auto-detection". 40 spare media entries */
-#define MAX_PIDS ((BODY_SIZE - 1 - 13) / 4) + 40
-#define MAX_PMTS ((BODY_SIZE - 1 - 13) / 4) + 10
-#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))
-
-#define MAX_PES_BUF_SIZE 2048
-
-#define CORRUPT_PES_THRESHOLD 10
-
-#define NULL_PID 0x1fff
-#define INVALID_PID ((unsigned int)(-1))
-#define INVALID_PROGRAM ((unsigned int)(-1))
-#define INVALID_CC ((unsigned int)(-1))
-
-#define PROG_STREAM_MAP 0xBC
-#define PRIVATE_STREAM1 0xBD
-#define PADDING_STREAM 0xBE
-#define PRIVATE_STREAM2 0xBF
-#define AUDIO_STREAM_S 0xC0
-#define AUDIO_STREAM_E 0xDF
-#define VIDEO_STREAM_S 0xE0
-#define VIDEO_STREAM_E 0xEF
-#define ECM_STREAM 0xF0
-#define EMM_STREAM 0xF1
-#define DSM_CC_STREAM 0xF2
-#define ISO13522_STREAM 0xF3
-#define PROG_STREAM_DIR 0xFF
-
-/* descriptors in PMT stream info */
-#define DESCRIPTOR_REG_FORMAT 0x05
-#define DESCRIPTOR_LANG 0x0a
-#define DESCRIPTOR_TELETEXT 0x56
-#define DESCRIPTOR_DVBSUB 0x59
-#define DESCRIPTOR_AC3 0x6a
-#define DESCRIPTOR_EAC3 0x7a
-#define DESCRIPTOR_DTS 0x7b
-#define DESCRIPTOR_AAC 0x7c
-
- typedef enum
- {
- ISO_11172_VIDEO = 0x01, /* ISO/IEC 11172 Video */
- ISO_13818_VIDEO = 0x02, /* ISO/IEC 13818-2 Video */
- ISO_11172_AUDIO = 0x03, /* ISO/IEC 11172 Audio */
- ISO_13818_AUDIO = 0x04, /* ISO/IEC 13818-3 Audi */
- ISO_13818_PRIVATE = 0x05, /* ISO/IEC 13818-1 private sections */
- ISO_13818_PES_PRIVATE = 0x06, /* ISO/IEC 13818-1 PES packets containing private data */
- ISO_13522_MHEG = 0x07, /* ISO/IEC 13512 MHEG */
- ISO_13818_DSMCC = 0x08, /* ISO/IEC 13818-1 Annex A DSM CC */
- ISO_13818_TYPE_A = 0x0a, /* ISO/IEC 13818-6 Multiprotocol encapsulation */
- ISO_13818_TYPE_B = 0x0b, /* ISO/IEC 13818-6 DSM-CC U-N Messages */
- ISO_13818_TYPE_C = 0x0c, /* ISO/IEC 13818-6 Stream Descriptors */
- ISO_13818_TYPE_D = 0x0d, /* ISO/IEC 13818-6 Sections (any type, including private data) */
- ISO_13818_AUX = 0x0e, /* ISO/IEC 13818-1 auxiliary */
- ISO_13818_PART7_AUDIO = 0x0f, /* ISO/IEC 13818-7 Audio with ADTS transport sytax */
- ISO_14496_PART2_VIDEO = 0x10, /* ISO/IEC 14496-2 Visual (MPEG-4) */
- ISO_14496_PART3_AUDIO = 0x11, /* ISO/IEC 14496-3 Audio with LATM transport syntax */
- ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */
- STREAM_VIDEO_MPEG = 0x80,
- STREAM_AUDIO_AC3 = 0x81,
-
- STREAM_VIDEO_VC1 = 0xea, /* VC-1 Video */
- STREAM_VIDEO_SMTPE_VC1 = 0xeb, /* SMTPE VC-1 */
-
- HDMV_AUDIO_80_PCM = 0x80, /* BluRay PCM */
- HDMV_AUDIO_82_DTS = 0x82, /* DTS */
- HDMV_AUDIO_83_TRUEHD = 0x83, /* Dolby TrueHD, primary audio */
- HDMV_AUDIO_84_EAC3 = 0x84, /* Dolby Digital plus, primary audio */
- HDMV_AUDIO_85_DTS_HRA = 0x85, /* DTS-HRA */
- HDMV_AUDIO_86_DTS_HD_MA = 0x86, /* DTS-HD Master audio */
-
- HDMV_SPU_BITMAP = 0x90,
- HDMV_SPU_INTERACTIVE = 0x91,
- HDMV_SPU_TEXT = 0x92,
-
- } streamType;
-
-#define WRAP_THRESHOLD 270000
-
-#define PTS_AUDIO 0
-#define PTS_VIDEO 1
-
-/* bitrate estimation */
-#define TBRE_MIN_TIME ( 2 * 90000)
-#define TBRE_TIME (480 * 90000)
-
-#define TBRE_MODE_PROBE 0
-#define TBRE_MODE_AUDIO_PTS 1
-#define TBRE_MODE_AUDIO_PCR 2
-#define TBRE_MODE_PCR 3
-#define TBRE_MODE_DONE 4
-
-
-#undef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
-#undef MAX
-#define MAX(a,b) ((a)>(b)?(a):(b))
-
-/*
-**
-** DATA STRUCTURES
-**
-*/
-
-/*
- * Describe a single elementary stream.
- */
-typedef struct {
- unsigned int pid;
- fifo_buffer_t *fifo;
- uint8_t *content;
- uint32_t size;
- uint32_t type;
- int64_t pts;
- buf_element_t *buf;
- unsigned int counter;
- uint16_t descriptor_tag; /* +0x100 for PES stream IDs (no available TS descriptor tag?) */
- int corrupted_pes;
-
- int input_normpos;
- int input_time;
-} demux_ts_media;
-
-/* DVBSUB */
-#define MAX_SPU_LANGS 32
-
-typedef struct {
- spu_dvb_descriptor_t desc;
- unsigned int pid;
- int media_index;
-} demux_ts_spu_lang;
-
-/* Audio Channels */
-#define MAX_AUDIO_TRACKS 32
-
-typedef struct {
- unsigned int pid;
- int media_index;
- char lang[4];
-} demux_ts_audio_track;
-
-typedef struct {
- /*
- * The first field must be the "base class" for the plugin!
- */
- demux_plugin_t demux_plugin;
-
- xine_stream_t *stream;
-
- config_values_t *config;
-
- fifo_buffer_t *audio_fifo;
- fifo_buffer_t *video_fifo;
-
- input_plugin_t *input;
-
- int status;
-
- int hdmv; /* -1 = unknown, 0 = mpeg-ts, 1 = hdmv/m2ts */
- int pkt_size; /* TS packet size */
- int pkt_offset; /* TS packet offset */
-
- int rate;
- unsigned int media_num;
- demux_ts_media media[MAX_PIDS];
-
- /* PAT */
- uint32_t last_pat_crc;
- uint32_t transport_stream_id;
- /* programs */
- uint32_t program_number[MAX_PMTS];
- uint32_t pmt_pid[MAX_PMTS];
- uint8_t *pmt[MAX_PMTS];
- uint8_t *pmt_write_ptr[MAX_PMTS];
- uint32_t crc32_table[256];
- uint32_t last_pmt_crc;
- /*
- * Stuff to do with the transport header. As well as the video
- * and audio PIDs, we keep the index of the corresponding entry
- * inthe media[] array.
- */
- unsigned int pcr_pid;
- unsigned int videoPid;
- unsigned int videoMedia;
-
- demux_ts_audio_track audio_tracks[MAX_AUDIO_TRACKS];
- int audio_tracks_count;
-
- int64_t last_pts[2];
- int send_newpts;
- int buf_flag_seek;
-
- unsigned int scrambled_pids[MAX_PIDS];
- unsigned int scrambled_npids;
-
-#ifdef TS_READ_STATS
- uint32_t rstat[NPKT_PER_READ + 1];
-#endif
-
- /* DVBSUB */
- unsigned int spu_pid;
- unsigned int spu_media;
- demux_ts_spu_lang spu_langs[MAX_SPU_LANGS];
- int spu_langs_count;
- int current_spu_channel;
-
- /* dvb */
- xine_event_queue_t *event_queue;
- /* 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 */
-
- off_t frame_pos; /* current ts packet position in input stream (bytes from beginning) */
-
- /* bitrate estimation */
- off_t tbre_bytes, tbre_lastpos;
- int64_t tbre_time, tbre_lasttime;
- unsigned int tbre_mode, tbre_pid;
-
-} demux_ts_t;
-
-typedef struct {
-
- demux_class_t demux_class;
-
- /* class-wide, global variables here */
-
- xine_t *xine;
- config_values_t *config;
-} demux_ts_class_t;
-
-static void demux_ts_tbre_reset (demux_ts_t *this) {
- if (this->tbre_time <= TBRE_TIME) {
- this->tbre_pid = INVALID_PID;
- this->tbre_mode = TBRE_MODE_PROBE;
- }
-}
-
-static void demux_ts_tbre_update (demux_ts_t *this, unsigned int mode, int64_t now) {
- /* select best available timesource on the fly */
- if ((mode < this->tbre_mode) || (now <= 0))
- return;
-
- if (mode == this->tbre_mode) {
- /* skip discontinuities */
- int64_t diff = now - this->tbre_lasttime;
- if ((diff < 0 ? -diff : diff) < 220000) {
- /* add this step */
- this->tbre_bytes += this->frame_pos - this->tbre_lastpos;
- this->tbre_time += diff;
- /* update bitrate */
- if (this->tbre_time > TBRE_MIN_TIME)
- this->rate = this->tbre_bytes * 90000 / this->tbre_time;
- /* stop analyzing */
- if (this->tbre_time > TBRE_TIME)
- this->tbre_mode = TBRE_MODE_DONE;
- }
- } else {
- /* upgrade timesource */
- this->tbre_mode = mode;
- }
-
- /* remember where and when */
- this->tbre_lastpos = this->frame_pos;
- this->tbre_lasttime = now;
-}
-
-static void demux_ts_build_crc32_table(demux_ts_t*this) {
- uint32_t i, j, k;
-
- for( i = 0 ; i < 256 ; i++ ) {
- k = 0;
- for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1) {
- k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
- }
- this->crc32_table[i] = k;
- }
-}
-
-static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data,
- int32_t length, uint32_t crc32) {
- int32_t i;
-
- for(i = 0; i < length; i++) {
- crc32 = (crc32 << 8) ^ this->crc32_table[(crc32 >> 24) ^ data[i]];
- }
- return crc32;
-}
-
-/* redefine abs as macro to handle 64-bit diffs.
- i guess llabs may not be available everywhere */
-#define abs(x) ( ((x)<0) ? -(x) : (x) )
-
-static void check_newpts( demux_ts_t *this, int64_t pts, int video )
-{
- int64_t diff;
-
-#ifdef TS_LOG
- printf ("demux_ts: check_newpts %lld, send_newpts %d, buf_flag_seek %d\n",
- pts, this->send_newpts, this->buf_flag_seek);
-#endif
-
- diff = pts - this->last_pts[video];
-
- if( pts &&
- (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) {
-
- if (this->buf_flag_seek) {
- _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK);
- this->buf_flag_seek = 0;
- } else {
- _x_demux_control_newpts(this->stream, pts, 0);
- }
- this->send_newpts = 0;
- this->last_pts[1-video] = 0;
- }
-
- if( pts )
- {
- /* don't detect a discontinuity only for video respectively audio. It's also a discontinuity
- indication when audio and video pts differ to much e. g. when a pts wrap happens.
- The original code worked well when the wrap happend like this:
-
- V7 A7 V8 V9 A9 Dv V0 V1 da A1 V2 V3 A3 V4
-
- Legend:
- Vn = video packet with timestamp n
- An = audio packet with timestamp n
- Dv = discontinuity detected on following video packet
- Da = discontinuity detected on following audio packet
- dv = discontinuity detected on following video packet but ignored
- da = discontinuity detected on following audio packet but ignored
-
- But with a certain delay between audio and video packets (e. g. the way DVB-S broadcasts
- the packets) the code didn't work:
-
- V7 V8 A7 V9 Dv V0 _A9_ V1 V2 Da _A1_ V3 V4 A3
-
- Packet A9 caused audio to jump forward and A1 caused it to jump backward with inserting
- a delay of almoust 26.5 hours!
-
- The new code gives the following sequences for the above examples:
-
- V7 A7 V8 V9 A9 Dv V0 V1 A1 V2 V3 A3 V4
-
- V7 V8 A7 V9 Dv V0 Da A9 Dv V1 V2 A1 V3 V4 A3
-
- After proving this code it should be cleaned up to use just a single variable "last_pts". */
-
-/*
- this->last_pts[video] = pts;
-*/
- this->last_pts[video] = this->last_pts[1-video] = pts;
- }
-}
-
-/* Send a BUF_SPU_DVB to let xine know of that channel. */
-static void demux_send_special_spu_buf( demux_ts_t *this, uint32_t spu_type, int spu_channel )
-{
- buf_element_t *buf;
-
- buf = this->video_fifo->buffer_pool_alloc( this->video_fifo );
- buf->type = spu_type|spu_channel;
- buf->content = buf->mem;
- buf->size = 0;
- this->video_fifo->put( this->video_fifo, buf );
-}
-
-static void demux_send_special_audio_buf( demux_ts_t *this, uint16_t stream_type, int audio_channel )
-{
- uint32_t type = 0;
-
- switch(stream_type) {
- case ISO_11172_AUDIO:
- case ISO_13818_AUDIO: type = BUF_AUDIO_MPEG; break;
- case ISO_13818_PART7_AUDIO:
- case ISO_14496_PART3_AUDIO: type = BUF_AUDIO_AAC; break;
- default:
- case STREAM_AUDIO_AC3: type = BUF_AUDIO_A52; break;
- }
-
- if (this->hdmv > 0) {
- switch(stream_type) {
- case HDMV_AUDIO_80_PCM: type = BUF_AUDIO_LPCM_BE; break;
- case HDMV_AUDIO_83_TRUEHD:
- case STREAM_AUDIO_AC3: type = BUF_AUDIO_A52; break;
- case HDMV_AUDIO_82_DTS:
- case HDMV_AUDIO_85_DTS_HRA:
- case HDMV_AUDIO_86_DTS_HD_MA: type = BUF_AUDIO_DTS; break;
- }
- }
-
- if (type && this->audio_fifo) {
- buf_element_t *buf = this->audio_fifo->buffer_pool_alloc( this->audio_fifo );
- buf->type = type | audio_channel;
- buf->decoder_flags = BUF_FLAG_PREVIEW;
- buf->content = buf->mem;
- buf->size = 0;
- this->audio_fifo->put( this->audio_fifo, buf );
- }
-}
-
-/*
- * demux_ts_update_spu_channel
- *
- * Send a BUF_SPU_DVB with BUF_SPECIAL_SPU_DVB_DESCRIPTOR to tell
- * the decoder to reset itself on the new channel.
- */
-static void demux_ts_update_spu_channel(demux_ts_t *this)
-{
- buf_element_t *buf;
-
- this->current_spu_channel = this->stream->spu_channel;
-
- buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
- buf->type = BUF_SPU_DVB;
- buf->content = buf->mem;
- buf->decoder_flags = BUF_FLAG_SPECIAL;
- buf->decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR;
- buf->size = 0;
-
- if (this->current_spu_channel >= 0
- && this->current_spu_channel < this->spu_langs_count)
- {
- demux_ts_spu_lang *lang = &this->spu_langs[this->current_spu_channel];
-
- buf->decoder_info[2] = sizeof(lang->desc);
- buf->decoder_info_ptr[2] = &(lang->desc);
- buf->type |= this->current_spu_channel;
-
- this->spu_pid = lang->pid;
- this->spu_media = lang->media_index;
-
-#ifdef TS_LOG
- printf("demux_ts: DVBSUB: selecting lang: %s page %ld %ld\n",
- lang->desc.lang, lang->desc.comp_page_id, lang->desc.aux_page_id);
-#endif
- }
- else
- {
- buf->decoder_info_ptr[2] = NULL;
-
- this->spu_pid = INVALID_PID;
-
-#ifdef TS_LOG
- printf("demux_ts: DVBSUB: deselecting lang\n");
-#endif
- }
-
- if ((this->media[this->spu_media].type & BUF_MAJOR_MASK) == BUF_SPU_HDMV) {
- buf->type = BUF_SPU_HDMV;
- }
-
- this->video_fifo->put(this->video_fifo, buf);
-}
-
-static void demux_ts_send_buffer(demux_ts_media *m, int flags)
-{
- if (m->buf) {
- m->buf->content = m->buf->mem;
- m->buf->type = m->type;
- m->buf->decoder_flags |= flags;
- m->buf->pts = m->pts;
- m->buf->decoder_info[0] = 1;
- m->buf->extra_info->input_normpos = m->input_normpos;
- m->buf->extra_info->input_time = m->input_time;
-
- m->fifo->put(m->fifo, m->buf);
- m->buf = NULL;
-
-#ifdef TS_LOG
- printf ("demux_ts: produced buffer, pts=%lld\n", m->pts);
-#endif
- }
-}
-
-static void demux_ts_flush_media(demux_ts_media *m)
-{
- demux_ts_send_buffer(m, BUF_FLAG_FRAME_END);
-}
-
-static void demux_ts_flush(demux_ts_t *this)
-{
- unsigned int i;
- for (i = 0; i < this->media_num; ++i) {
- demux_ts_flush_media(&this->media[i]);
- }
-}
-
-/*
- * demux_ts_parse_pat
- *
- * Parse a program association table (PAT).
- * The PAT is expected to be exactly one section long,
- * and that section is expected to be contained in a single TS packet.
- *
- * The PAT is assumed to contain a single program definition, though
- * we can cope with the stupidity of SPTSs which contain NITs.
- */
-static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
- unsigned char *pkt, unsigned int pusi) {
- uint32_t table_id;
- uint32_t section_syntax_indicator;
- int32_t section_length;
- uint32_t transport_stream_id;
- uint32_t version_number;
- uint32_t current_next_indicator;
- uint32_t section_number;
- uint32_t last_section_number;
- uint32_t crc32;
- uint32_t calc_crc32;
-
- unsigned char *program;
- unsigned int program_number;
- unsigned int pmt_pid;
- unsigned int program_count;
-
- /*
- * A PAT in a single section should start with a payload unit start
- * indicator set.
- */
- if (!pusi) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: demux error! PAT without payload unit start indicator\n");
- return;
- }
-
- /*
- * sections start with a pointer. Skip it!
- */
- pkt += pkt[4];
- if (pkt - original_pkt > PKT_SIZE) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: demux error! PAT with invalid pointer\n");
- return;
- }
- table_id = (unsigned int)pkt[5] ;
- section_syntax_indicator = (((unsigned int)pkt[6] >> 7) & 1) ;
- section_length = (((unsigned int)pkt[6] & 0x03) << 8) | pkt[7];
- transport_stream_id = ((uint32_t)pkt[8] << 8) | pkt[9];
- version_number = ((uint32_t)pkt[10] >> 1) & 0x1f;
- current_next_indicator = ((uint32_t)pkt[10] & 0x01);
- section_number = (uint32_t)pkt[11];
- last_section_number = (uint32_t)pkt[12];
- crc32 = (uint32_t)pkt[4+section_length] << 24;
- crc32 |= (uint32_t)pkt[5+section_length] << 16;
- crc32 |= (uint32_t)pkt[6+section_length] << 8;
- crc32 |= (uint32_t)pkt[7+section_length] ;
-
-#ifdef TS_PAT_LOG
- printf ("demux_ts: PAT table_id: %.2x\n", table_id);
- printf (" section_syntax: %d\n", section_syntax_indicator);
- printf (" section_length: %d (%#.3x)\n",
- section_length, section_length);
- printf (" transport_stream_id: %#.4x\n", transport_stream_id);
- printf (" version_number: %d\n", version_number);
- printf (" c/n indicator: %d\n", current_next_indicator);
- printf (" section_number: %d\n", section_number);
- printf (" last_section_number: %d\n", last_section_number);
-#endif
-
- if ((section_syntax_indicator != 1) || !(current_next_indicator)) {
- return;
- }
-
- if (pkt - original_pkt > BODY_SIZE - 1 - 3 - section_length) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: FIXME: (unsupported )PAT spans multiple TS packets\n");
- return;
- }
-
- if ((section_number != 0) || (last_section_number != 0)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: FIXME: (unsupported) PAT consists of multiple (%d) sections\n", last_section_number);
- return;
- }
-
- /* Check CRC. */
- calc_crc32 = demux_ts_compute_crc32 (this, pkt+5, section_length+3-4,
- 0xffffffff);
- if (crc32 != calc_crc32) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: demux error! PAT with invalid CRC32: packet_crc32: %.8x calc_crc32: %.8x\n",
- crc32,calc_crc32);
- return;
- }
-#ifdef TS_PAT_LOG
- else {
- printf ("demux_ts: PAT CRC32 ok.\n");
- }
-#endif
-
- if (crc32 == this->last_pat_crc &&
- this->transport_stream_id == transport_stream_id) {
- lprintf("demux_ts: PAT CRC unchanged\n");
- return;
- }
-
- if (this->transport_stream_id != transport_stream_id) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: PAT transport_stream_id changed\n");
- }
-
- this->last_pat_crc = crc32;
- this->transport_stream_id = transport_stream_id;
-
- /*
- * Process all programs in the program loop.
- */
- program_count = 0;
- for (program = pkt + 13;
- (program < pkt + 13 + section_length - 9) && (program_count < MAX_PMTS);
- program += 4) {
- program_number = ((unsigned int)program[0] << 8) | program[1];
- pmt_pid = (((unsigned int)program[2] & 0x1f) << 8) | program[3];
-
- /*
- * completely skip NIT pids.
- */
- if (program_number == 0x0000)
- continue;
-
- /*
- * Add the program number to the table if we haven't already
- * seen it. The order of the program numbers is assumed not
- * to change between otherwise identical PATs.
- */
- if (this->program_number[program_count] != program_number) {
- this->program_number[program_count] = program_number;
- this->pmt_pid[program_count] = INVALID_PID;
- }
-
- /* force PMT reparsing when pmt_pid changes */
- if (this->pmt_pid[program_count] != pmt_pid) {
- this->pmt_pid[program_count] = pmt_pid;
- this->audio_tracks_count = 0;
- this->last_pmt_crc = 0;
- this->videoPid = INVALID_PID;
- this->spu_pid = INVALID_PID;
- this->pcr_pid = INVALID_PID;
-
- if (this->pmt[program_count] != NULL) {
- free(this->pmt[program_count]);
- this->pmt[program_count] = NULL;
- this->pmt_write_ptr[program_count] = NULL;
- }
- }
-#ifdef TS_PAT_LOG
- if (this->program_number[program_count] != INVALID_PROGRAM)
- printf ("demux_ts: PAT acquired count=%d programNumber=0x%04x "
- "pmtPid=0x%04x\n",
- program_count,
- this->program_number[program_count],
- this->pmt_pid[program_count]);
-#endif
-
- ++program_count;
- }
-
- /* Add "end of table" markers. */
- if (program_count < MAX_PMTS) {
- this->program_number[program_count] = INVALID_PROGRAM;
- this->pmt_pid[program_count] = INVALID_PID;
- }
-}
-
-static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
- uint8_t *buf, int packet_len) {
-
- unsigned char *p;
- int header_len;
- int64_t pts;
- uint32_t stream_id;
-
- if (packet_len < 9) {
- xprintf (xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: too short PES packet header (%d bytes)\n", packet_len);
- return 0;
- }
-
- p = buf;
-
- /* we should have a PES packet here */
-
- if (p[0] || p[1] || (p[2] != 1)) {
- xprintf (xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: error %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]);
- return 0 ;
- }
-
- /* packet_len = p[4] << 8 | p[5]; */
- stream_id = p[3];
- header_len = p[8];
-
- /* sometimes corruption on header_len causes segfault in memcpy below */
- if (header_len + 9 > packet_len) {
- xprintf (xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: illegal value for PES_header_data_length (0x%x)\n", header_len);
- return 0;
- }
-
-#ifdef TS_LOG
- printf ("demux_ts: packet stream id: %.2x len: %d (%x)\n",
- stream_id, packet_len, packet_len);
-#endif
-
- if (p[7] & 0x80) { /* pts avail */
-
- if (header_len < 5) {
- return 0;
- }
-
- pts = (int64_t)(p[ 9] & 0x0E) << 29 ;
- pts |= p[10] << 22 ;
- pts |= (p[11] & 0xFE) << 14 ;
- pts |= p[12] << 7 ;
- pts |= (p[13] & 0xFE) >> 1 ;
-
- } else
- pts = 0;
-
- /* code works but not used in xine
- if (p[7] & 0x40) {
-
- DTS = (p[14] & 0x0E) << 29 ;
- DTS |= p[15] << 22 ;
- DTS |= (p[16] & 0xFE) << 14 ;
- DTS |= p[17] << 7 ;
- DTS |= (p[18] & 0xFE) >> 1 ;
-
- } else
- DTS = 0;
- */
-
- m->pts = pts;
-
- p += header_len + 9;
- packet_len -= header_len + 9;
-
- if (m->descriptor_tag == STREAM_VIDEO_VC1) {
- m->content = p;
- m->size = packet_len;
- m->type = BUF_VIDEO_VC1;
- return 1;
- }
-
- if (m->descriptor_tag == HDMV_SPU_BITMAP) {
- long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3;
-
- m->content = p;
- m->size = packet_len;
- m->type |= BUF_SPU_HDMV;
- m->buf->decoder_info[2] = payload_len;
- return 1;
-
- } else
-
- if (stream_id == 0xbd || stream_id == 0xfd /* HDMV */) {
-
- int spu_id;
-
- lprintf ("audio buf = %02X %02X %02X %02X %02X %02X %02X %02X\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-
- /*
- * we check the descriptor tag first because some stations
- * do not include any of the ac3 header info in their audio tracks
- * these "raw" streams may begin with a byte that looks like a stream type.
- * For audio streams, m->type already contains the stream no.
- */
- if(m->descriptor_tag == HDMV_AUDIO_84_EAC3) {
- m->content = p;
- m->size = packet_len;
- m->type |= BUF_AUDIO_EAC3;
- return 1;
-
- } else if (m->descriptor_tag == STREAM_AUDIO_AC3) { /* ac3 - raw */
- m->content = p;
- m->size = packet_len;
- m->type |= BUF_AUDIO_A52;
- return 1;
-
- } else if (m->descriptor_tag == HDMV_AUDIO_83_TRUEHD) {
- /* TODO: separate AC3 and TrueHD streams ... */
- m->content = p;
- m->size = packet_len;
- m->type |= BUF_AUDIO_A52;
- return 1;
-
- } else if (m->descriptor_tag == HDMV_AUDIO_82_DTS ||
- m->descriptor_tag == HDMV_AUDIO_85_DTS_HRA ||
- m->descriptor_tag == HDMV_AUDIO_86_DTS_HD_MA ) {
- m->content = p;
- m->size = packet_len;
- m->type |= BUF_AUDIO_DTS;
- return 1;
-
- } else if (packet_len < 2) {
- return 0;
-
- } else if (m->descriptor_tag == HDMV_AUDIO_80_PCM) {
-
- if (packet_len < 4) {
- return 0;
- }
-
- m->content = p + 4;
- m->size = packet_len - 4;
- m->type |= BUF_AUDIO_LPCM_BE;
-
- m->buf->decoder_flags |= BUF_FLAG_SPECIAL;
- m->buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG;
- m->buf->decoder_info[2] = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
-
- return 1;
-
- } else if (m->descriptor_tag == ISO_13818_PES_PRIVATE
- && p[0] == 0x20 && p[1] == 0x00) {
- /* DVBSUB */
- long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3;
-
- m->content = p;
- m->size = packet_len;
- m->type |= BUF_SPU_DVB;
- m->buf->decoder_info[2] = payload_len;
- return 1;
-
- } else if (p[0] == 0x0B && p[1] == 0x77) { /* ac3 - syncword */
- m->content = p;
- m->size = packet_len;
- m->type |= BUF_AUDIO_A52;
- return 1;
-
- } else if ((p[0] & 0xE0) == 0x20) {
- spu_id = (p[0] & 0x1f);
-
- m->content = p+1;
- m->size = packet_len-1;
- m->type = BUF_SPU_DVD + spu_id;
- return 1;
- } else if ((p[0] & 0xF0) == 0x80) {
-
- if (packet_len < 4) {
- return 0;
- }
-
- m->content = p+4;
- m->size = packet_len - 4;
- m->type |= BUF_AUDIO_A52;
- return 1;
-
-#if 0
- /* commented out: does not set PCM type. Decoder can't handle raw PCM stream without configuration. */
- } else if ((p[0]&0xf0) == 0xa0) {
-
- unsigned int pcm_offset;
-
- for (pcm_offset=0; ++pcm_offset < packet_len-1 ; ){
- if (p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80 ) { /* START */
- pcm_offset += 2;
- break;
- }
- }
-
- if (packet_len < pcm_offset) {
- return 0;
- }
-
- m->content = p+pcm_offset;
- m->size = packet_len-pcm_offset;
- m->type |= BUF_AUDIO_LPCM_BE;
- return 1;
-#endif
- }
-
- } else if ((stream_id & 0xf0) == 0xe0) {
-
- m->content = p;
- m->size = packet_len;
- switch (m->descriptor_tag) {
- case ISO_11172_VIDEO:
- case ISO_13818_VIDEO:
- case STREAM_VIDEO_MPEG:
- lprintf ("demux_ts: found MPEG video type.\n");
- m->type = BUF_VIDEO_MPEG;
- break;
- case ISO_14496_PART2_VIDEO:
- lprintf ("demux_ts: found MPEG4 video type.\n");
- m->type = BUF_VIDEO_MPEG4;
- break;
- case ISO_14496_PART10_VIDEO:
- lprintf ("demux_ts: found H264 video type.\n");
- m->type = BUF_VIDEO_H264;
- break;
- default:
- lprintf ("demux_ts: unknown video type: %d, defaulting to MPEG.\n", m->descriptor_tag);
- m->type = BUF_VIDEO_MPEG;
- break;
- }
- return 1;
-
- } else if ((stream_id & 0xe0) == 0xc0) {
-
- m->content = p;
- m->size = packet_len;
- switch (m->descriptor_tag) {
- case ISO_11172_AUDIO:
- case ISO_13818_AUDIO:
- lprintf ("demux_ts: found MPEG audio track.\n");
- m->type |= BUF_AUDIO_MPEG;
- break;
- case ISO_13818_PART7_AUDIO:
- lprintf ("demux_ts: found AAC audio track.\n");
- m->type |= BUF_AUDIO_AAC;
- break;
- case ISO_14496_PART3_AUDIO:
- lprintf ("demux_ts: found AAC LATM audio track.\n");
- m->type |= BUF_AUDIO_AAC_LATM;
- break;
- default:
- lprintf ("demux_ts: unknown audio type: %d, defaulting to MPEG.\n", m->descriptor_tag);
- m->type |= BUF_AUDIO_MPEG;
- break;
- }
- return 1;
-
- } else {
-#ifdef TS_LOG
- printf ("demux_ts: unknown packet, id: %x\n", stream_id);
-#endif
- }
-
- return 0 ;
-}
-
-
-static void fill_extra_info(demux_ts_t *this, buf_element_t *buf)
-{
- off_t len = this->input->get_length (this->input);
- off_t pos = this->input->get_current_pos (this->input);
-
- if (len) {
- buf->extra_info->input_normpos = (int)( (double) pos * 65535 / len );
- }
-
- if (this->input->get_current_time)
- buf->extra_info->input_time = this->input->get_current_time(this->input);
-
- if (this->rate) {
- if (buf->extra_info->input_time <= 0)
- buf->extra_info->input_time = (int)((int64_t)pos * 1000 / this->rate);
-
- buf->extra_info->total_time = (int)((int64_t)len * 1000 / this->rate);
- }
-}
-
-/*
- * buffer arriving pes data
- */
-static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
- unsigned int mediaIndex,
- unsigned int pus,
- unsigned int cc,
- unsigned int len) {
-
- demux_ts_media *m = &this->media[mediaIndex];
-
- if (!m->fifo) {
-#ifdef TS_LOG
- printf ("fifo unavailable (%d)\n", mediaIndex);
-#endif
- return; /* To avoid segfault if video out or audio out plugin not loaded */
- }
-
- /* By checking the CC here, we avoid the need to check for the no-payload
- case (i.e. adaptation field only) when it does not get bumped. */
- if (m->counter != INVALID_CC) {
- if ((m->counter & 0x0f) != cc) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: PID 0x%.4x: unexpected cc %d (expected %d)\n", m->pid, cc, m->counter);
- }
- }
- m->counter = cc;
- m->counter++;
-
- if (pus) { /* new PES packet */
-
- demux_ts_flush_media(m);
-
- /* allocate the buffer here, as pes_header needs a valid buf for dvbsubs */
- m->buf = m->fifo->buffer_pool_alloc(m->fifo);
-
- if (!demux_ts_parse_pes_header(this->stream->xine, m, ts, len)) {
- m->buf->free_buffer(m->buf);
- m->buf = NULL;
-
- m->corrupted_pes++;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: PID 0x%.4x: corrupted pes encountered\n", m->pid);
- } else {
-
- m->corrupted_pes = 0;
- memcpy(m->buf->mem, ts+len-m->size, m->size);
- m->buf->size = m->size;
-
- /* cache frame position */
- off_t length = this->input->get_length (this->input);
- if (length > 0) {
- m->input_normpos = (double)this->frame_pos * 65535.0 / length;
- }
- if (this->rate) {
- m->input_time = this->frame_pos * 1000 / this->rate;
- }
-
- /* rate estimation */
- if ((this->tbre_pid == INVALID_PID) && (this->audio_fifo == m->fifo))
- this->tbre_pid = m->pid;
- if (m->pid == this->tbre_pid)
- demux_ts_tbre_update (this, TBRE_MODE_AUDIO_PTS, m->pts);
- }
-
- } else if (!m->corrupted_pes) { /* no pus -- PES packet continuation */
-
- if ((m->buf->size + len) > MAX_PES_BUF_SIZE) {
- demux_ts_send_buffer(m, 0);
- m->buf = m->fifo->buffer_pool_alloc(m->fifo);
- }
- memcpy(m->buf->mem + m->buf->size, ts, len);
- m->buf->size += len;
- }
-}
-
-/*
- * Create a buffer for a PES stream.
- */
-static void demux_ts_pes_new(demux_ts_t*this,
- unsigned int mediaIndex,
- unsigned int pid,
- fifo_buffer_t *fifo,
- uint16_t descriptor) {
-
- demux_ts_media *m = &this->media[mediaIndex];
-
- /* new PID seen - initialise stuff */
- m->pid = pid;
- m->fifo = fifo;
-
- if (m->buf != NULL) m->buf->free_buffer(m->buf);
- m->buf = NULL;
- m->counter = INVALID_CC;
- m->descriptor_tag = descriptor;
- m->corrupted_pes = 1;
-}
-
-
-/* Find the first ISO 639 language descriptor (tag 10) and
- * store the 3-char code in dest, nullterminated. If no
- * code is found, zero out dest.
- **/
-static void demux_ts_get_lang_desc(demux_ts_t *this, char *dest,
- const unsigned char *data, int length)
-{
- const unsigned char *d = data;
-
- while (d < (data + length))
-
- {
- if (d[0] == DESCRIPTOR_LANG && d[1] >= 4)
-
- {
- memcpy(dest, d + 2, 3);
- dest[3] = 0;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: found ISO 639 lang: %s\n", dest);
- return;
- }
- d += 2 + d[1];
- }
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: found no ISO 639 lang\n");
- memset(dest, 0, 4);
-}
-
-/* Find the registration code (tag=5) and return it as a uint32_t
- * This should return "AC-3" or 0x41432d33 for AC3/A52 audio tracks.
- */
-static void demux_ts_get_reg_desc(demux_ts_t *this, uint32_t *dest,
- const unsigned char *data, int length)
-{
- const unsigned char *d = data;
-
- while (d < (data + length))
-
- {
- if (d[0] == DESCRIPTOR_REG_FORMAT && d[1] >= 4)
-
- {
- *dest = (d[2] << 24) | (d[3] << 16) | (d[4] << 8) | d[5];
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: found registration format identifier: 0x%.4x\n", *dest);
- return;
- }
- d += 2 + d[1];
- }
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: found no format id\n");
- *dest = 0;
-}
-
-static inline int ts_payloadsize(unsigned char * tsp)
-{
- if (!(tsp[3] & 0x10))
- return 0;
- if (tsp[3] & 0x20) {
- if (tsp[4] > 183)
- return 0;
- else
- return 183 - tsp[4];
- }
- return 184;
-}
-
-/* check if an apid is in the list of known apids */
-static int apid_check(demux_ts_t*this, unsigned int pid) {
- int i;
- for (i = 0; i < this->audio_tracks_count; i++) {
- if (this->audio_tracks[i].pid == pid)
- return i;
- }
- return -1;
-}
-
-/*
- * NAME demux_ts_parse_pmt
- *
- * Parse a PMT. The PMT is expected to be exactly one section long,
- * and that section is expected to be contained in a single TS packet.
- *
- * In other words, the PMT is assumed to describe a reasonable number of
- * video, audio and other streams (with descriptors).
- * FIXME: Implement support for multi section PMT.
- */
-static void demux_ts_parse_pmt (demux_ts_t *this,
- unsigned char *originalPkt,
- unsigned char *pkt,
- unsigned int pusi,
- uint32_t program_count) {
-
- uint32_t table_id;
- uint32_t section_syntax_indicator;
- uint32_t section_length = 0; /* to calm down gcc */
- uint32_t program_number;
- uint32_t version_number;
- uint32_t current_next_indicator;
- uint32_t section_number;
- uint32_t last_section_number;
- uint32_t program_info_length;
- uint32_t crc32;
- uint32_t calc_crc32;
- uint32_t coded_length;
- unsigned int pid;
- unsigned char *stream;
- unsigned int i;
- int count;
- char *ptr = NULL;
- unsigned char len;
- unsigned int offset=0;
-
- /*
- * A new section should start with the payload unit start
- * indicator set. We allocate some mem (max. allowed for a PM section)
- * to copy the complete section into one chunk.
- */
- if (pusi) {
- pkt+=pkt[4]; /* pointer to start of section */
- offset=1;
-
- free(this->pmt[program_count]);
- this->pmt[program_count] = (uint8_t *) calloc(4096, sizeof(unsigned char));
- this->pmt_write_ptr[program_count] = this->pmt[program_count];
-
- table_id = pkt[5] ;
- section_syntax_indicator = (pkt[6] >> 7) & 0x01;
- section_length = (((uint32_t) pkt[6] << 8) | pkt[7]) & 0x03ff;
- program_number = ((uint32_t) pkt[8] << 8) | pkt[9];
- version_number = (pkt[10] >> 1) & 0x1f;
- current_next_indicator = pkt[10] & 0x01;
- section_number = pkt[11];
- last_section_number = pkt[12];
-
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT table_id: %2x\n", table_id);
- printf (" section_syntax: %d\n", section_syntax_indicator);
- printf (" section_length: %d (%#.3x)\n",
- section_length, section_length);
- printf (" program_number: %#.4x\n", program_number);
- printf (" version_number: %d\n", version_number);
- printf (" c/n indicator: %d\n", current_next_indicator);
- printf (" section_number: %d\n", section_number);
- printf (" last_section_number: %d\n", last_section_number);
-#endif
-
- if ((section_syntax_indicator != 1) || !current_next_indicator) {
-#ifdef TS_PMT_LOG
- printf ("ts_demux: section_syntax_indicator != 1 "
- "|| !current_next_indicator\n");
-#endif
- return;
- }
-
- if (program_number != this->program_number[program_count]) {
- /* several programs can share the same PMT pid */
-#ifdef TS_PMT_LOG
-printf("Program Number is %i, looking for %i\n",program_number,this->program_number[program_count]);
- printf ("ts_demux: waiting for next PMT on this PID...\n");
-#endif
- return;
- }
-
- if ((section_number != 0) || (last_section_number != 0)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: FIXME (unsupported) PMT consists of multiple (%d) sections\n", last_section_number);
- return;
- }
-
- }
-
- if (!this->pmt[program_count]) {
- /* not the first TS packet of a PMT, or the calloc didn't work */
-#ifdef TS_PMT_LOG
- printf ("ts_demux: not the first TS packet of a PMT...\n");
-#endif
- return;
- }
-
- if (!pusi){
- section_length = (this->pmt[program_count][1] << 8
- | this->pmt[program_count][2]) & 0x03ff;
- }
-
- count=ts_payloadsize(originalPkt);
-
- ptr = (char*)originalPkt+offset+(PKT_SIZE-count);
- len = count-offset;
- memcpy (this->pmt_write_ptr[program_count], ptr, len);
- this->pmt_write_ptr[program_count] +=len;
-
-#ifdef TS_PMT_LOG
- printf ("ts_demux: wr_ptr: %p, will be %p when finished\n",
- this->pmt_write_ptr[program_count],
- this->pmt[program_count] + section_length);
-#endif
- if (this->pmt_write_ptr[program_count] < this->pmt[program_count]
- + section_length) {
- /* didn't get all TS packets for this section yet */
-#ifdef TS_PMT_LOG
- printf ("ts_demux: didn't get all PMT TS packets yet...\n");
-#endif
- return;
- }
-
- if (!section_length) {
- free (this->pmt[program_count]);
- this->pmt[program_count] = NULL;
-#ifdef TS_PMT_LOG
- printf ("ts_demux: eek, zero-length section?\n");
-#endif
- return;
- }
-
-#ifdef TS_PMT_LOG
- printf ("ts_demux: have all TS packets for the PMT section\n");
-#endif
-
- crc32 = (uint32_t) this->pmt[program_count][section_length+3-4] << 24;
- crc32 |= (uint32_t) this->pmt[program_count][section_length+3-3] << 16;
- crc32 |= (uint32_t) this->pmt[program_count][section_length+3-2] << 8;
- crc32 |= (uint32_t) this->pmt[program_count][section_length+3-1] ;
-
- /* Check CRC. */
- calc_crc32 = demux_ts_compute_crc32 (this,
- this->pmt[program_count],
- section_length+3-4, 0xffffffff);
- if (crc32 != calc_crc32) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: demux error! PMT with invalid CRC32: packet_crc32: %#.8x calc_crc32: %#.8x\n",
- crc32,calc_crc32);
- return;
- }
- else {
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT CRC32 ok.\n");
-#endif
- if ( crc32==this->last_pmt_crc ) {
-#ifdef TS_PMT_LOG
- printf("demux_ts: PMT with CRC32=%d already parsed. Skipping.\n", crc32);
-#endif
- return;
- }
- else {
-#ifdef TS_PMT_LOG
- printf("demux_ts: new PMT, parsing...\n");
-#endif
- this->last_pmt_crc = crc32;
- }
- }
-
- /*
- * Forget the current video, audio and subtitle PIDs; if the PMT has not
- * changed, we'll pick them up again when we parse this PMT, while if the
- * PMT has changed (e.g. an IPTV streamer that's just changed its source),
- * we'll get new PIDs that we should follow.
- */
- this->audio_tracks_count = 0;
- this->videoPid = INVALID_PID;
- this->spu_pid = INVALID_PID;
-
- /*
- * ES definitions start here...we are going to learn upto one video
- * PID and one audio PID.
- */
- program_info_length = ((this->pmt[program_count][10] << 8)
- | this->pmt[program_count][11]) & 0x0fff;
-
-/* Program info descriptor is currently just ignored.
- * printf ("demux_ts: program_info_desc: ");
- * for (i = 0; i < program_info_length; i++)
- * printf ("%.2x ", this->pmt[program_count][12+i]);
- * printf ("\n");
- */
- stream = &this->pmt[program_count][12] + program_info_length;
- coded_length = 13 + program_info_length;
- if (coded_length > section_length) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux error! PMT with inconsistent progInfo length\n");
- return;
- }
- section_length -= coded_length;
-
- /*
- * Extract the elementary streams.
- */
- this->spu_langs_count = 0;
- while (section_length > 0) {
- unsigned int stream_info_length;
-
- pid = ((stream[1] << 8) | stream[2]) & 0x1fff;
- stream_info_length = ((stream[3] << 8) | stream[4]) & 0x0fff;
- coded_length = 5 + stream_info_length;
- if (coded_length > section_length) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux error! PMT with inconsistent streamInfo length\n");
- return;
- }
-
- /*
- * Squirrel away the first audio and the first video stream. TBD: there
- * should really be a way to select the stream of interest.
- */
- switch (stream[0]) {
- case ISO_11172_VIDEO:
- case ISO_13818_VIDEO:
- case ISO_14496_PART2_VIDEO:
- case ISO_14496_PART10_VIDEO:
- case STREAM_VIDEO_VC1:
- if (this->videoPid == INVALID_PID) {
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT video pid 0x%.4x type %2.2x\n", pid, stream[0]);
-#endif
- demux_ts_pes_new(this, this->media_num, pid, this->video_fifo,stream[0]);
- this->videoMedia = this->media_num;
- this->videoPid = pid;
- }
-
- break;
- case ISO_11172_AUDIO:
- case ISO_13818_AUDIO:
- case ISO_13818_PART7_AUDIO:
- case ISO_14496_PART3_AUDIO:
- if (this->audio_tracks_count < MAX_AUDIO_TRACKS) {
- if (apid_check(this, pid) < 0) {
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT audio pid 0x%.4x type %2.2x\n", pid, stream[0]);
-#endif
- demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo,stream[0]);
- this->audio_tracks[this->audio_tracks_count].pid = pid;
- this->audio_tracks[this->audio_tracks_count].media_index = this->media_num;
- this->media[this->media_num].type = this->audio_tracks_count;
- demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang,
- stream + 5, stream_info_length);
- demux_send_special_audio_buf(this, stream[0], this->audio_tracks_count);
- this->audio_tracks_count++;
- }
- }
- break;
- case ISO_13818_PRIVATE:
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT streamtype 13818_PRIVATE, pid: 0x%.4x type %2.2x\n", pid, stream[0]);
-
- for (i = 5; i < coded_length; i++)
- printf ("%.2x ", stream[i]);
- printf ("\n");
-#endif
- break;
- case ISO_13818_TYPE_C: /* data carousel */
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT streamtype 13818_TYPE_C, pid: 0x%.4x type %2.2x\n", pid, stream[0]);
-#endif
- break;
- case ISO_13818_PES_PRIVATE:
- for (i = 5; i < coded_length; i += stream[i+1] + 2) {
- if (((stream[i] == DESCRIPTOR_AC3) || (stream[i] == DESCRIPTOR_EAC3)) &&
- (this->audio_tracks_count < MAX_AUDIO_TRACKS)) {
- if (apid_check(this, pid) < 0) {
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT AC3 audio pid 0x%.4x type %2.2x\n", pid, stream[0]);
-#endif
- if (stream[i] == DESCRIPTOR_AC3)
- demux_ts_pes_new(this, this->media_num, pid,
- this->audio_fifo, STREAM_AUDIO_AC3);
- else
- demux_ts_pes_new(this, this->media_num, pid,
- this->audio_fifo, HDMV_AUDIO_84_EAC3);
-
- this->audio_tracks[this->audio_tracks_count].pid = pid;
- this->audio_tracks[this->audio_tracks_count].media_index = this->media_num;
- this->media[this->media_num].type = this->audio_tracks_count;
- demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang,
- stream + 5, stream_info_length);
- demux_send_special_audio_buf(this, STREAM_AUDIO_AC3, this->audio_tracks_count);
- this->audio_tracks_count++;
- break;
- }
- }
- /* Teletext */
- else if (stream[i] == DESCRIPTOR_TELETEXT)
- {
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT Teletext, pid: 0x%.4x type %2.2x\n", pid, stream[0]);
-
- for (i = 5; i < coded_length; i++)
- printf ("%.2x ", stream[i]);
- printf ("\n");
-#endif
- break;
- }
-
- /* DVBSUB */
- else if (stream[i] == DESCRIPTOR_DVBSUB)
- {
- unsigned int pos;
- for (pos = i + 2;
- pos + 8 <= i + 2 + stream[i + 1]
- && this->spu_langs_count < MAX_SPU_LANGS;
- pos += 8)
- {
- int no = this->spu_langs_count;
- demux_ts_spu_lang *lang = &this->spu_langs[no];
-
- this->spu_langs_count++;
-
- memcpy(lang->desc.lang, &stream[pos], 3);
- lang->desc.lang[3] = 0;
- lang->desc.comp_page_id =
- (stream[pos + 4] << 8) | stream[pos + 5];
- lang->desc.aux_page_id =
- (stream[pos + 6] << 8) | stream[pos + 7];
- lang->pid = pid;
- lang->media_index = this->media_num;
- this->media[this->media_num].type = no;
- demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]);
- demux_send_special_spu_buf( this, BUF_SPU_DVB, no );
-#ifdef TS_LOG
- printf("demux_ts: DVBSUB: pid 0x%.4x: %s page %ld %ld type %2.2x\n",
- pid, lang->desc.lang,
- lang->desc.comp_page_id,
- lang->desc.aux_page_id,
- stream[0]);
-#endif
- }
- }
- }
- break;
-
- case HDMV_SPU_INTERACTIVE:
- case HDMV_SPU_TEXT:
- if (this->hdmv > 0) {
- printf("demux_ts: Skipping unsupported HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n",
- stream[0], pid);
- break;
- }
- /* fall thru */
-
- case HDMV_SPU_BITMAP:
- if (this->hdmv > 0) {
- if (pid >= 0x1200 && pid < 0x1300) {
- /* HDMV Presentation Graphics / SPU */
-
- if (this->spu_langs_count >= MAX_SPU_LANGS) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: too many SPU tracks! ignoring pid 0x%.4x\n",
- pid);
- break;
- }
-
- demux_ts_spu_lang *lang = &this->spu_langs[this->spu_langs_count];
-
- memset(lang->desc.lang, 0, sizeof(lang->desc.lang));
- /*memcpy(lang->desc.lang, &stream[pos], 3);*/
- /*lang->desc.lang[3] = 0;*/
- lang->pid = pid;
- lang->media_index = this->media_num;
- this->media[this->media_num].type = this->spu_langs_count;
- demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]);
- demux_send_special_spu_buf( this, BUF_SPU_HDMV, this->spu_langs_count );
- this->spu_langs_count++;
-#ifdef TS_PMT_LOG
- printf("demux_ts: HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n",
- stream[0], pid);
-#endif
- break;
- }
- }
- /* fall thru */
- default:
-
-/* This following section handles all the cases where the audio track info is stored in PMT user info with stream id >= 0x80
- * We first check that the stream id >= 0x80, because all values below that are invalid if not handled above,
- * then we check the registration format identifier to see if it holds "AC-3" (0x41432d33) and
- * if is does, we tag this as an audio stream.
- * FIXME: This will need expanding if we ever see a DTS or other media format here.
- */
- if ((this->audio_tracks_count < MAX_AUDIO_TRACKS) && (stream[0] >= 0x80) ) {
- if (apid_check(this,pid) < 0) {
- uint32_t format_identifier=0;
- demux_ts_get_reg_desc(this, &format_identifier,
- stream + 5, stream_info_length);
- /* If no format identifier, assume A52 */
- if (( format_identifier == 0x41432d33) ||
- ( format_identifier == 0) ||
- ((format_identifier == 0x48444d56 || this->hdmv>0) && stream[0] == HDMV_AUDIO_80_PCM) /* BluRay PCM */) {
-
- demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo, stream[0]);
- this->audio_tracks[this->audio_tracks_count].pid = pid;
- this->audio_tracks[this->audio_tracks_count].media_index = this->media_num;
- this->media[this->media_num].type = this->audio_tracks_count;
- demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang,
- stream + 5, stream_info_length);
- demux_send_special_audio_buf(this, stream[0], this->audio_tracks_count);
- this->audio_tracks_count++;
- break;
- }
- }
- } else {
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT unknown stream_type: 0x%.2x pid: 0x%.4x\n",
- stream[0], pid);
-
- for (i = 5; i < coded_length; i++)
- printf ("%.2x ", stream[i]);
- printf ("\n");
-#endif
- }
- break;
- }
- this->media_num++;
- stream += coded_length;
- section_length -= coded_length;
- }
-
- /*
- * Get the current PCR PID.
- */
- pid = ((this->pmt[program_count][8] << 8)
- | this->pmt[program_count][9]) & 0x1fff;
- if (this->pcr_pid != pid) {
-#ifdef TS_PMT_LOG
- if (this->pcr_pid == INVALID_PID) {
- printf ("demux_ts: PMT pcr pid 0x%.4x\n", pid);
- } else {
- printf ("demux_ts: PMT pcr pid changed 0x%.4x\n", pid);
- }
-#endif
- this->pcr_pid = pid;
- }
-
- if ( this->stream->spu_channel>=0 && this->spu_langs_count>0 )
- demux_ts_update_spu_channel( this );
-
- demux_ts_tbre_reset (this);
-
- /* Inform UI of channels changes */
- xine_event_t ui_event;
- ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
- ui_event.data_length = 0;
- xine_event_send( this->stream, &ui_event );
-}
-
-static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) {
-
- int p = 0;
- int n = 0;
- int i = 0;
- int sync_ok = 0;
- int read_length;
-
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: about to resync!\n");
-
- for (p=0; p < npkt_read; p++) {
- for(n=0; n < this->pkt_size; n++) {
- sync_ok = 1;
- for (i=0; i < MIN(MIN_SYNCS, npkt_read - p); i++) {
- if (buf[this->pkt_offset + n + ((i+p) * this->pkt_size)] != SYNC_BYTE) {
- sync_ok = 0;
- break;
- }
- }
- if (sync_ok) break;
- }
- if (sync_ok) break;
- }
-
- if (sync_ok) {
- /* Found sync, fill in */
- memmove(&buf[0], &buf[n + p * this->pkt_size],
- ((this->pkt_size * (npkt_read - p)) - n));
- read_length = this->input->read(this->input,
- (char*)&buf[(this->pkt_size * (npkt_read - p)) - n],
- n + p * this->pkt_size);
- /* FIXME: when read_length is not as required... we now stop demuxing */
- if (read_length != (n + p * this->pkt_size)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts_tsync_correct: sync found, but read failed\n");
- return 0;
- }
- } else {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts_tsync_correct: sync not found! Stop demuxing\n");
- return 0;
- }
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: resync successful!\n");
- return 1;
-}
-
-static int sync_detect(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) {
-
- int i, sync_ok;
-
- sync_ok = 1;
-
- if (this->hdmv) {
- this->pkt_size = PKT_SIZE + 4;
- this->pkt_offset = 4;
- for (i=0; i < MIN(MIN_SYNCS, npkt_read - 3); i++) {
- if (buf[this->pkt_offset + i * this->pkt_size] != SYNC_BYTE) {
- sync_ok = 0;
- break;
- }
- }
- if (sync_ok) {
- if (this->hdmv < 0) {
- /* fix npkt_read (packet size is 192, not 188) */
- this->npkt_read = npkt_read * PKT_SIZE / this->pkt_size;
- }
- this->hdmv = 1;
- return sync_ok;
- }
- if (this->hdmv > 0)
- return sync_correct(this, buf, npkt_read);
-
- /* plain ts */
- this->hdmv = 0;
- this->pkt_size = PKT_SIZE;
- this->pkt_offset = 0;
- }
-
- for (i=0; i < MIN(MIN_SYNCS, npkt_read); i++) {
- if (buf[i * PKT_SIZE] != SYNC_BYTE) {
- sync_ok = 0;
- break;
- }
- }
- if (!sync_ok) return sync_correct(this, buf, npkt_read);
- return sync_ok;
-}
-
-
-/*
- * Main synchronisation routine.
- */
-static unsigned char * demux_synchronise(demux_ts_t* this) {
-
- uint8_t *return_pointer = NULL;
- int32_t read_length;
-
- this->frame_pos += this->pkt_size;
-
- if ( (this->packet_number) >= this->npkt_read) {
-
- /* NEW: handle read returning less packets than NPKT_PER_READ... */
- do {
- this->frame_pos = this->input->get_current_pos (this->input);
-
- read_length = this->input->read(this->input, (char*)this->buf,
- this->pkt_size * NPKT_PER_READ);
- if (read_length < 0 || read_length % this->pkt_size) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: read returned %d bytes (not a multiple of %d!)\n",
- read_length, this->pkt_size);
- this->status = DEMUX_FINISHED;
- return NULL;
- }
- this->npkt_read = read_length / this->pkt_size;
-
-#ifdef TS_READ_STATS
- this->rstat[this->npkt_read]++;
-#endif
- /*
- * what if this->npkt_read < 5 ? --> ok in sync_detect
- *
- * NEW: stop demuxing if read returns 0 a few times... (200)
- */
-
- if (this->npkt_read == 0) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: read 0 packets\n");
- this->status = DEMUX_FINISHED;
- return NULL;
- }
-
- } while (! read_length);
-
- this->packet_number = 0;
-
- if (!sync_detect(this, &(this->buf)[0], this->npkt_read)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: sync error.\n");
- this->status = DEMUX_FINISHED;
- return NULL;
- }
- }
- return_pointer = &(this->buf)[this->pkt_offset + this->pkt_size * this->packet_number];
- this->packet_number++;
- return return_pointer;
-}
-
-
-static int64_t demux_ts_adaptation_field_parse(uint8_t *data,
- uint32_t adaptation_field_length) {
-
-#ifdef TS_LOG
- uint32_t discontinuity_indicator=0;
- uint32_t random_access_indicator=0;
- uint32_t elementary_stream_priority_indicator=0;
-#endif
- uint32_t PCR_flag=0;
- int64_t PCR=-1;
-#ifdef TS_LOG
- uint32_t EPCR=0;
- uint32_t OPCR_flag=0;
- uint32_t OPCR=0;
- uint32_t EOPCR=0;
- uint32_t slicing_point_flag=0;
- uint32_t transport_private_data_flag=0;
- uint32_t adaptation_field_extension_flag=0;
-#endif
- uint32_t offset = 1;
-
-#ifdef TS_LOG
- discontinuity_indicator = ((data[0] >> 7) & 0x01);
- random_access_indicator = ((data[0] >> 6) & 0x01);
- elementary_stream_priority_indicator = ((data[0] >> 5) & 0x01);
-#endif
- PCR_flag = ((data[0] >> 4) & 0x01);
-#ifdef TS_LOG
- OPCR_flag = ((data[0] >> 3) & 0x01);
- slicing_point_flag = ((data[0] >> 2) & 0x01);
- transport_private_data_flag = ((data[0] >> 1) & 0x01);
- adaptation_field_extension_flag = (data[0] & 0x01);
-#endif
-
-#ifdef TS_LOG
- printf ("demux_ts: ADAPTATION FIELD length: %d (%x)\n",
- adaptation_field_length, adaptation_field_length);
- if(discontinuity_indicator) {
- printf (" Discontinuity indicator: %d\n",
- discontinuity_indicator);
- }
- if(random_access_indicator) {
- printf (" Random_access indicator: %d\n",
- random_access_indicator);
- }
- if(elementary_stream_priority_indicator) {
- printf (" Elementary_stream_priority_indicator: %d\n",
- elementary_stream_priority_indicator);
- }
-#endif
-
- if(PCR_flag) {
- if (adaptation_field_length < offset + 6)
- return -1;
-
- PCR = (((int64_t) data[offset]) & 0xFF) << 25;
- PCR += (int64_t) ((data[offset+1] & 0xFF) << 17);
- PCR += (int64_t) ((data[offset+2] & 0xFF) << 9);
- PCR += (int64_t) ((data[offset+3] & 0xFF) << 1);
- PCR += (int64_t) ((data[offset+4] & 0x80) >> 7);
-
-#ifdef TS_LOG
- EPCR = ((data[offset+4] & 0x1) << 8) | data[offset+5];
- printf ("demux_ts: PCR: %lld, EPCR: %u\n",
- PCR, EPCR);
-#endif
- offset+=6;
- }
-
-#ifdef TS_LOG
- if(OPCR_flag) {
- if (adaptation_field_length < offset + 6)
- return PCR;
-
- OPCR = data[offset] << 25;
- OPCR |= data[offset+1] << 17;
- OPCR |= data[offset+2] << 9;
- OPCR |= data[offset+3] << 1;
- OPCR |= (data[offset+4] >> 7) & 0x01;
- EOPCR = ((data[offset+4] & 0x1) << 8) | data[offset+5];
-
- printf ("demux_ts: OPCR: %u, EOPCR: %u\n",
- OPCR,EOPCR);
-
- offset+=6;
- }
-
- if(slicing_point_flag) {
- printf ("demux_ts: slicing_point_flag: %d\n",
- slicing_point_flag);
- }
- if(transport_private_data_flag) {
- printf ("demux_ts: transport_private_data_flag: %d\n",
- transport_private_data_flag);
- }
- if(adaptation_field_extension_flag) {
- printf ("demux_ts: adaptation_field_extension_flag: %d\n",
- adaptation_field_extension_flag);
- }
-#endif /* TS_LOG */
-
- return PCR;
-}
-
-/* transport stream packet layer */
-static void demux_ts_parse_packet (demux_ts_t*this) {
-
- unsigned char *originalPkt;
- unsigned int sync_byte;
- unsigned int transport_error_indicator;
- unsigned int payload_unit_start_indicator;
- unsigned int transport_priority;
- unsigned int pid;
- unsigned int transport_scrambling_control;
- unsigned int adaptation_field_control;
- unsigned int continuity_counter;
- unsigned int data_offset;
- unsigned int data_len;
- uint32_t program_count;
- unsigned int i;
-
- /* get next synchronised packet, or NULL */
- originalPkt = demux_synchronise(this);
- if (originalPkt == NULL)
- return;
-
- sync_byte = originalPkt[0];
- transport_error_indicator = (originalPkt[1] >> 7) & 0x01;
- payload_unit_start_indicator = (originalPkt[1] >> 6) & 0x01;
- transport_priority = (originalPkt[1] >> 5) & 0x01;
- pid = ((originalPkt[1] << 8) |
- originalPkt[2]) & 0x1fff;
- transport_scrambling_control = (originalPkt[3] >> 6) & 0x03;
- adaptation_field_control = (originalPkt[3] >> 4) & 0x03;
- continuity_counter = originalPkt[3] & 0x0f;
-
-
-#ifdef TS_HEADER_LOG
- printf("demux_ts:ts_header:sync_byte=0x%.2x\n",sync_byte);
- printf("demux_ts:ts_header:transport_error_indicator=%d\n", transport_error_indicator);
- printf("demux_ts:ts_header:payload_unit_start_indicator=%d\n", payload_unit_start_indicator);
- printf("demux_ts:ts_header:transport_priority=%d\n", transport_priority);
- printf("demux_ts:ts_header:pid=0x%.4x\n", pid);
- printf("demux_ts:ts_header:transport_scrambling_control=0x%.1x\n", transport_scrambling_control);
- printf("demux_ts:ts_header:adaptation_field_control=0x%.1x\n", adaptation_field_control);
- printf("demux_ts:ts_header:continuity_counter=0x%.1x\n", continuity_counter);
-#endif
- /*
- * Discard packets that are obviously bad.
- */
- if (sync_byte != SYNC_BYTE) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux error! invalid ts sync byte %.2x\n", sync_byte);
- return;
- }
- if (transport_error_indicator) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux error! transport error\n");
- return;
- }
- if (pid == 0x1ffb) {
- /* printf ("demux_ts: PSIP table. Program Guide etc....not supported yet. PID = 0x1ffb\n"); */
- return;
- }
-
- if (transport_scrambling_control) {
- if (this->videoPid == pid) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: selected videoPid is scrambled; skipping...\n");
- }
- for (i=0; i < this->scrambled_npids; i++) {
- if (this->scrambled_pids[i] == pid) return;
- }
- if (this->scrambled_npids < MAX_PIDS) {
- this->scrambled_pids[this->scrambled_npids] = pid;
- this->scrambled_npids++;
- }
-
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: PID 0x%.4x is scrambled!\n", pid);
- return;
- }
-
- data_offset = 4;
-
- if( adaptation_field_control & 0x2 ){
- uint32_t adaptation_field_length = originalPkt[4];
- if (adaptation_field_length > 0) {
- int64_t pcr = demux_ts_adaptation_field_parse (originalPkt+5, adaptation_field_length);
- if (pid == this->pcr_pid)
- demux_ts_tbre_update (this, TBRE_MODE_PCR, pcr);
- else if (pid == this->tbre_pid)
- demux_ts_tbre_update (this, TBRE_MODE_AUDIO_PCR, pcr);
- }
- /*
- * Skip adaptation header.
- */
- data_offset += adaptation_field_length + 1;
- }
-
- if (! (adaptation_field_control & 0x1)) {
- return;
- }
-
- /* PAT */
- if (pid == 0) {
- demux_ts_parse_pat(this, originalPkt, originalPkt+data_offset-4,
- payload_unit_start_indicator);
- return;
- }
-
- /* PMT */
- program_count=0;
- while ((this->program_number[program_count] != INVALID_PROGRAM) &&
- (program_count < MAX_PMTS)) {
- if (pid == this->pmt_pid[program_count]) {
-
-#ifdef TS_LOG
- printf ("demux_ts: PMT prog: 0x%.4x pid: 0x%.4x\n",
- this->program_number[program_count],
- this->pmt_pid[program_count]);
-#endif
- demux_ts_parse_pmt (this, originalPkt, originalPkt+data_offset-4,
- payload_unit_start_indicator,
- program_count);
- return;
- }
- program_count++;
- }
-
- data_len = PKT_SIZE - data_offset;
-
- if (data_len > PKT_SIZE) {
-
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: demux error! invalid payload size %d\n", data_len);
-
- } else {
-
- /*
- * Do the demuxing in descending order of packet frequency!
- */
- int index;
- if (pid == this->videoPid) {
-#ifdef TS_LOG
- printf ("demux_ts: Video pid: 0x%.4x\n", pid);
-#endif
- check_newpts(this, this->media[this->videoMedia].pts, PTS_VIDEO);
- demux_ts_buffer_pes (this, originalPkt+data_offset, this->videoMedia,
- payload_unit_start_indicator, continuity_counter,
- data_len);
- return;
- }
- else if ((index = apid_check(this, pid)) > -1) {
-#ifdef TS_LOG
- printf ("demux_ts: Audio pid: 0x%.4x\n", pid);
-#endif
- check_newpts(this, this->media[this->audio_tracks[index].media_index].pts, PTS_AUDIO);
- demux_ts_buffer_pes (this, originalPkt+data_offset,
- this->audio_tracks[index].media_index,
- payload_unit_start_indicator, continuity_counter,
- data_len);
- return;
- }
- else if (pid == NULL_PID) {
-#ifdef TS_LOG
- printf ("demux_ts: Null Packet\n");
-#endif
- return;
- }
- /* 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;
- }
- }
-}
-
-/*
- * check for pids change events
- */
-
-static void demux_ts_event_handler (demux_ts_t *this) {
-
- xine_event_t *event;
-
- while ((event = xine_event_get (this->event_queue))) {
-
-
- switch (event->type) {
-
- case XINE_EVENT_END_OF_CLIP:
- /* flush all streams */
- demux_ts_flush(this);
- /* fall thru */
-
- case XINE_EVENT_PIDS_CHANGE:
-
- this->videoPid = INVALID_PID;
- this->pcr_pid = INVALID_PID;
- this->audio_tracks_count = 0;
- this->media_num = 0;
- this->send_newpts = 1;
- this->spu_pid = INVALID_PID;
- this->spu_media = 0;
- this->spu_langs_count= 0;
- this->last_pmt_crc = 0;
- _x_demux_control_start (this->stream);
- break;
-
- }
-
- xine_event_free (event);
- }
-}
-
-/*
- * send a piece of data down the fifos
- */
-
-static int demux_ts_send_chunk (demux_plugin_t *this_gen) {
-
- demux_ts_t*this = (demux_ts_t*)this_gen;
-
- demux_ts_event_handler (this);
-
- demux_ts_parse_packet(this);
-
- /* DVBSUB: check if channel has changed. Dunno if I should, or
- * even could, lock the xine object. */
- if (this->stream->spu_channel != this->current_spu_channel) {
- demux_ts_update_spu_channel(this);
- }
-
- return this->status;
-}
-
-static void demux_ts_dispose (demux_plugin_t *this_gen) {
- int i;
- demux_ts_t*this = (demux_ts_t*)this_gen;
-
- for (i=0; i < MAX_PMTS; i++) {
- if (this->pmt[i] != NULL) {
- free(this->pmt[i]);
- this->pmt[i] = NULL;
- }
- }
- for (i=0; i < MAX_PIDS; i++) {
- if (this->media[i].buf != NULL) {
- this->media[i].buf->free_buffer(this->media[i].buf);
- this->media[i].buf = NULL;
- }
- }
-
- xine_event_dispose_queue (this->event_queue);
-
- free(this_gen);
-}
-
-static int demux_ts_get_status(demux_plugin_t *this_gen) {
-
- demux_ts_t*this = (demux_ts_t*)this_gen;
-
- return this->status;
-}
-
-static void demux_ts_send_headers (demux_plugin_t *this_gen) {
-
- demux_ts_t *this = (demux_ts_t *) this_gen;
-
- this->video_fifo = this->stream->video_fifo;
- this->audio_fifo = this->stream->audio_fifo;
-
- this->status = DEMUX_OK;
-
- /*
- * send start buffers
- */
-
- this->videoPid = INVALID_PID;
- this->pcr_pid = INVALID_PID;
- this->audio_tracks_count = 0;
- this->media_num= 0;
- this->last_pmt_crc = 0;
-
- _x_demux_control_start (this->stream);
-
- this->input->seek (this->input, 0, SEEK_SET);
-
- this->send_newpts = 1;
-
- demux_ts_build_crc32_table (this);
-
- this->status = DEMUX_OK ;
-
- this->scrambled_npids = 0;
-
- /* DVBSUB */
- this->spu_pid = INVALID_PID;
- this->spu_langs_count = 0;
- this->current_spu_channel = -1;
-
- /* FIXME ? */
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
-}
-
-static int demux_ts_seek (demux_plugin_t *this_gen,
- off_t start_pos, int start_time, int playing) {
-
- demux_ts_t *this = (demux_ts_t *) this_gen;
- int i;
- 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 ((!start_pos) && (start_time)) {
-
- if (this->input->seek_time) {
- this->input->seek_time(this->input, start_time, SEEK_SET);
- } else {
- start_pos = (int64_t)start_time * this->rate / 1000;
- this->input->seek (this->input, start_pos, SEEK_SET);
- }
-
- } else {
- this->input->seek (this->input, start_pos, SEEK_SET);
- }
- }
-
- this->send_newpts = 1;
-
- for (i=0; i<MAX_PIDS; i++) {
- demux_ts_media *m = &this->media[i];
-
- if (m->buf != NULL)
- m->buf->free_buffer(m->buf);
- m->buf = NULL;
- m->counter = INVALID_CC;
- m->corrupted_pes = 1;
- }
-
- if( !playing ) {
-
- this->status = DEMUX_OK;
- this->buf_flag_seek = 0;
-
- } else {
-
- this->buf_flag_seek = 1;
- _x_demux_flush_engine(this->stream);
-
- }
-
- demux_ts_tbre_reset (this);
-
- return this->status;
-}
-
-static int demux_ts_get_stream_length (demux_plugin_t *this_gen) {
-
- demux_ts_t*this = (demux_ts_t*)this_gen;
-
- if (this->rate)
- return (int)((int64_t) this->input->get_length (this->input)
- * 1000 / this->rate);
- else
- return 0;
-}
-
-
-static uint32_t demux_ts_get_capabilities(demux_plugin_t *this_gen)
-{
- return DEMUX_CAP_AUDIOLANG | DEMUX_CAP_SPULANG;
-}
-
-static void flush_decoders(demux_ts_t *this)
-{
- buf_element_t *buf;
- xine_stream_t *stream = this->stream;
- unsigned int i;
-
- /* flush demuxer caches*/
- for (i = 0; i < MAX_PIDS; i++) {
- demux_ts_flush_media(&this->media[i]);
- }
-
- /* flush decoders */
- buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo);
- buf->type = BUF_CONTROL_FLUSH_DECODER;
- stream->video_fifo->put (stream->video_fifo, buf);
-#if 0
- buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo);
- buf->type = BUF_CONTROL_FLUSH_DECODER;
- stream->audio_fifo->put (stream->audio_fifo, buf);
-#endif
- /* reset decoders */
- buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo);
- buf->type = BUF_CONTROL_RESET_DECODER;
- stream->video_fifo->put (stream->video_fifo, buf);
-
- buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo);
- buf->type = BUF_CONTROL_RESET_DECODER;
- stream->audio_fifo->put (stream->audio_fifo, buf);
-
- /* reset demuxer */
- this->videoPid = INVALID_PID;
- this->audio_tracks_count = 0;
- this->media_num = 0;
- this->send_newpts = 1;
- this->spu_pid = INVALID_PID;
- this->spu_media = 0;
- this->spu_langs_count= 0;
- this->last_pmt_crc = 0;
-
- /* wait until processed */
- _x_demux_control_headers_done (stream);
-
- /* start */
- _x_demux_control_start (stream);
-}
-
-static int demux_ts_get_optional_data(demux_plugin_t *this_gen,
- void *data, int data_type)
-{
- demux_ts_t *this = (demux_ts_t *) this_gen;
- char *str = data;
-
- /* be a bit paranoid */
- if (this == NULL || this->stream == NULL || data == NULL)
- return DEMUX_OPTIONAL_UNSUPPORTED;
-
- int channel = *((int *)data);
-
- switch (data_type)
- {
- case DEMUX_OPTIONAL_DATA_AUDIOLANG:
- if ((channel >= 0) && (channel < this->audio_tracks_count)) {
- if(this->audio_tracks[channel].lang[0])
- strcpy(str, this->audio_tracks[channel].lang);
- else {
- input_plugin_t *input_plugin = this->stream->input_plugin;
- /* Language not known. Use track number. */
- sprintf(str, "%3i", channel);
- /* Ask input plugin */
- if (input_plugin && input_plugin->get_capabilities (input_plugin) & INPUT_CAP_SPULANG)
- return input_plugin->get_optional_data (input_plugin, data, data_type);
- }
- }
- else {
- strcpy(str, "none");
- return DEMUX_OPTIONAL_UNSUPPORTED;
- }
- return DEMUX_OPTIONAL_SUCCESS;
-
- case DEMUX_OPTIONAL_DATA_SPULANG:
- if (channel>=0 && channel<this->spu_langs_count) {
- if (this->spu_langs[channel].desc.lang[0]) {
- memcpy(str, this->spu_langs[channel].desc.lang, 3);
- str[3] = 0;
- } else {
- input_plugin_t *input_plugin = this->stream->input_plugin;
- /* Language not known. Use track number. */
- sprintf(str, "%3i", channel);
- /* Ask input plugin */
- if (input_plugin && input_plugin->get_capabilities (input_plugin) & INPUT_CAP_SPULANG)
- return input_plugin->get_optional_data (input_plugin, data, data_type);
- }
- }
- else {
- strcpy(str, "none");
- return DEMUX_OPTIONAL_UNSUPPORTED;
- }
- return DEMUX_OPTIONAL_SUCCESS;
-
- default:
- return DEMUX_OPTIONAL_UNSUPPORTED;
- }
-}
-
-static int detect_ts(uint8_t *buf, size_t len, unsigned int ts_size)
-{
- unsigned int i, try_again;
- size_t j, packs;
-
- if (len < ts_size * 4) {
- return 0;
- }
-
- packs = len / ts_size - 2;
-
- for (i = 0; i < ts_size; i++) {
- try_again = 0;
- if (buf[i] == SYNC_BYTE) {
- for (j = 1; j < packs; j++) {
- if (buf[i + j*ts_size] != SYNC_BYTE) {
- try_again = 1;
- break;
- }
- }
- if (try_again == 0) {
-#ifdef TS_LOG
- printf ("demux_ts: found 0x47 pattern at offset %d\n", i);
-#endif
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-static demux_plugin_t *open_plugin (demux_class_t *class_gen,
- xine_stream_t *stream,
- input_plugin_t *input) {
-
- demux_ts_t *this;
- int i;
- int hdmv = -1;
- int size;
-
- switch (stream->content_detection_method) {
-
- case METHOD_BY_CONTENT: {
- uint8_t buf[2069];
-
- size = _x_demux_read_header(input, buf, sizeof(buf));
- if (size < 4 * PKT_SIZE)
- return NULL;
-
- if (detect_ts(buf, size, PKT_SIZE))
- hdmv = 0;
- else if (detect_ts(buf, size, PKT_SIZE+4))
- hdmv = 1;
- else
- return NULL;
- }
- break;
-
-#if DEMUXER_PLUGIN_IFACE_VERSION < 27
- case METHOD_BY_EXTENSION:
-#else
- case METHOD_BY_MRL:
-#endif
- {
- const char *const mrl = input->get_mrl (input);
-
- if (_x_demux_check_extension (mrl, "m2ts mts"))
- hdmv = 1;
- else
- hdmv = 0;
-
- /* check extension */
-#if DEMUXER_PLUGIN_IFACE_VERSION < 27
- const char *const extensions = class_gen->get_extensions (class_gen);
-#else
- const char *const extensions = class_gen->extensions;
-#endif
- if (_x_demux_check_extension (mrl, extensions))
- break;
-
- /* accept dvb streams */
- /*
- * Also handle the special dvbs,dvbt and dvbc mrl formats:
- * the content is exactly the same but the input plugin
- * uses a different tuning algorithm [Pragma]
- */
-
- if (!strncasecmp (mrl, "dvb://", 6))
- break;
- if (!strncasecmp (mrl, "dvbs://", 7))
- break;
- if (!strncasecmp (mrl, "dvbc://", 7))
- break;
- if (!strncasecmp (mrl, "dvbt://", 7))
- break;
-
- /* accept BluRay discs */
- if (!strncasecmp (mrl, "bluray:/", 8) ||
- !strncasecmp (mrl, "bd:/", 4)) {
- hdmv = 1;
- break;
- }
-
- return NULL;
- }
-
- case METHOD_EXPLICIT:
- break;
-
- default:
- return NULL;
- }
-
- /*
- * if we reach this point, the input has been accepted.
- */
-
- this = calloc(1, sizeof(*this));
- this->stream = stream;
- this->input = input;
-
- this->demux_plugin.send_headers = demux_ts_send_headers;
- this->demux_plugin.send_chunk = demux_ts_send_chunk;
- this->demux_plugin.seek = demux_ts_seek;
- this->demux_plugin.dispose = demux_ts_dispose;
- this->demux_plugin.get_status = demux_ts_get_status;
- this->demux_plugin.get_stream_length = demux_ts_get_stream_length;
- this->demux_plugin.get_capabilities = demux_ts_get_capabilities;
- this->demux_plugin.get_optional_data = demux_ts_get_optional_data;
- this->demux_plugin.demux_class = class_gen;
-
- /*
- * 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;
- this->media[i].buf = NULL;
- }
-
- 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_ptr[i] = NULL;
- }
-
- this->scrambled_npids = 0;
- this->videoPid = INVALID_PID;
- this->pcr_pid = INVALID_PID;
- this->audio_tracks_count = 0;
- this->last_pmt_crc = 0;
-
- this->rate = xine_get_stream_info(this->stream, XINE_STREAM_INFO_BITRATE);
- if (this->rate > 0 && this->rate < 100000000 )
- this->rate /= 8; /* bits/s -> bytes/s */
- else
- this->rate = 800000; /* FIXME */
- this->tbre_pid = INVALID_PID;
-
- this->status = DEMUX_FINISHED;
-
- /* DVBSUB */
- this->spu_pid = INVALID_PID;
- this->spu_langs_count = 0;
- this->current_spu_channel = -1;
-
- /* dvb */
- this->event_queue = xine_event_new_queue (this->stream);
-
- /* HDMV */
- this->hdmv = hdmv;
- this->pkt_offset = (hdmv > 0) ? 4 : 0;
- this->pkt_size = PKT_SIZE + this->pkt_offset;
-
- return &this->demux_plugin;
-}
-
-/*
- * ts demuxer class
- */
-
-#if DEMUXER_PLUGIN_IFACE_VERSION < 27
-static const char *get_description (demux_class_t *this_gen) {
- return "MPEG Transport Stream demuxer (HDMV)";
-}
-#endif
-
-#if DEMUXER_PLUGIN_IFACE_VERSION < 27
-static const char *get_identifier (demux_class_t *this_gen) {
- return "MPEG_TS_HDMV";
-}
-#endif
-
-#if DEMUXER_PLUGIN_IFACE_VERSION < 27
-static const char *get_extensions (demux_class_t *this_gen) {
- return "m2ts mts";
-}
-#endif
-
-#if DEMUXER_PLUGIN_IFACE_VERSION < 27
-static const char *get_mimetypes (demux_class_t *this_gen) {
- return NULL;
-}
-#endif
-
-static void class_dispose (demux_class_t *this_gen) {
-
- demux_ts_class_t *this = (demux_ts_class_t *) this_gen;
-
- free (this);
-}
-
-static void *init_class (xine_t *xine, void *data) {
-
- demux_ts_class_t *this;
-
- this = calloc(1, sizeof(demux_ts_class_t));
- this->config = xine->config;
- this->xine = xine;
-
- this->demux_class.open_plugin = open_plugin;
-#if DEMUXER_PLUGIN_IFACE_VERSION < 27
- this->demux_class.get_description = get_description;
- this->demux_class.get_identifier = get_identifier;
- this->demux_class.get_mimetypes = get_mimetypes;
- this->demux_class.get_extensions = get_extensions;
-#else
- this->demux_class.description = "MPEG Transport Stream demuxer (HDMV)";
- this->demux_class.identifier = "MPEG_TS_HDMV";
- this->demux_class.mimetypes = NULL;
- this->demux_class.extensions = "m2ts mts";
-#endif
- this->demux_class.dispose = class_dispose;
-
- return this;
-}
-
-
-/*
- * exported plugin catalog entry
- */
-static const demuxer_info_t demux_info_ts = {
- 5 /* priority */
-};
-
-const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
-#if DEMUX_PLUGIN_IFACE_VERSION <= 26
- { PLUGIN_DEMUX, 26, "mpeg-ts-hdmv", XINE_VERSION_CODE, &demux_info_ts, init_class },
-#elif DEMUX_PLUGIN_IFACE_VERSION >= 27
- { PLUGIN_DEMUX, 27, "mpeg-ts-hdmv", XINE_VERSION_CODE, &demux_info_ts, init_class },
-#endif
- { PLUGIN_NONE, 0, "", 0, NULL, NULL }
-};
-
diff --git a/xine/BluRay/input_bluray.c b/xine/BluRay/input_bluray.c
deleted file mode 100644
index 6261eaf..0000000
--- a/xine/BluRay/input_bluray.c
+++ /dev/null
@@ -1,1980 +0,0 @@
-/*
- * Copyright (C) 2000-2011 the xine project
- * Copyright (C) 2009-2011 Petri Hintukainen <phintuka at users.sourceforge.net>
- *
- * 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 for BluRay discs / images
- *
- * Requires libbluray 0.2.1 or later:
- * http://www.videolan.org/developers/libbluray.html
- * git://git.videolan.org/libbluray.git
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* asprintf: */
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <pthread.h>
-
-/* for loop device (used with .iso images) */
-#include <sys/mount.h>
-#include <linux/fs.h>
-#include <linux/loop.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-/* libbluray */
-#include <libbluray/bluray.h>
-#include <libbluray/bluray-version.h>
-#include <libbluray/keys.h>
-#include <libbluray/overlay.h>
-#include <libbluray/meta_data.h>
-
-/* xine */
-
-#define LOG_MODULE "input_bluray"
-#define LOG_VERBOSE
-
-#define LOG
-
-#define LOGMSG(x...) xine_log (this->stream->xine, XINE_LOG_MSG, "input_bluray: " x);
-
-#define XINE_ENGINE_INTERNAL
-
-#ifdef HAVE_CONFIG_H
-# include "xine_internal.h"
-# include "input_plugin.h"
-#else
-# include <xine/xine_internal.h>
-# include <xine/input_plugin.h>
-#endif
-
-#ifndef XINE_VERSION_CODE
-# error XINE_VERSION_CODE undefined !
-#endif
-
-#ifndef EXPORTED
-# define EXPORTED __attribute__((visibility("default")))
-#endif
-
-#ifndef XINE_EVENT_END_OF_CLIP
-# define XINE_EVENT_END_OF_CLIP 0x80000001
-#endif
-
-/* */
-
-#ifndef MIN
-# define MIN(a,b) ((a)<(b)?(a):(b))
-#endif
-#ifndef MAX
-# define MAX(a,b) ((a)>(b)?(a):(b))
-#endif
-
-#define ALIGNED_UNIT_SIZE 6144
-#define PKT_SIZE 192
-#define TICKS_IN_MS 45
-
-#define MIN_TITLE_LENGTH 180
-
-/* */
-
-typedef struct {
-
- input_class_t input_class;
-
- xine_t *xine;
-
- xine_mrl_t **xine_playlist;
- int xine_playlist_size;
-
- /* config */
- char *mountpoint;
- char *device;
- char *language;
- char *country;
- int region;
- int parental;
-} bluray_input_class_t;
-
-typedef struct {
- input_plugin_t input_plugin;
-
- bluray_input_class_t *class;
-
- xine_stream_t *stream;
- xine_event_queue_t *event_queue;
- xine_osd_t *osd[2];
-
- char *mrl;
- char *disc_root;
- char *disc_name;
-
- BLURAY *bdh;
-
- const BLURAY_DISC_INFO *disc_info;
- const META_DL *meta_dl; /* disc library meta data */
-
- int num_title_idx; /* number of relevant playlists */
- int current_title_idx;
- int num_titles; /* navigation mode, number of titles in disc index */
- int current_title; /* navigation mode, title from disc index */
- BLURAY_TITLE_INFO *title_info;
- pthread_mutex_t title_info_mutex; /* lock this when accessing title_info outside of input/demux thread */
- unsigned int current_clip;
- time_t still_end_time;
- int pg_stream;
-
- uint8_t nav_mode : 1;
- uint8_t error : 1;
- uint8_t menu_open : 1;
- uint8_t stream_flushed : 1;
- uint8_t demux_action_req : 1;
- uint8_t end_of_title : 1;
- uint8_t pg_enable : 1;
- int mouse_inside_button;
-
- uint32_t cap_seekable;
-
- /* loop device for .iso image */
- char *iso_image;
- char *loop_dev;
- char mount_point[64];
-
-} bluray_input_plugin_t;
-
-/*
- * Loop device setup stuff, swiped from busybox.
- */
-
-int del_loop(const char *device)
-{
- int fd;
-
- if ((fd = open(device, O_RDONLY)) < 0) {
- perror(device);
- return -1;
- }
- if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
- close(fd);
-/* umm... why? perror("ioctl: LOOP_CLR_FD"); */
- return -1;
- }
- close(fd);
- return 0;
-}
-
-int set_loop(const char *device, const char *file, int offset, int *loopro)
-{
- struct loop_info loopinfo;
- int fd, ffd, mode;
-
- mode = *loopro ? O_RDONLY : O_RDWR;
- if ((ffd = open (file, mode)) < 0 && !*loopro
- && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
- perror (file);
- return 1;
- }
- if ((fd = open (device, mode)) < 0) {
- close(ffd);
- perror(device);
- return 1;
- }
- *loopro = (mode == O_RDONLY);
-
- memset(&loopinfo, 0, sizeof(loopinfo));
- strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
- loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
-
- loopinfo.lo_offset = offset;
-
- loopinfo.lo_encrypt_key_size = 0;
- if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
- perror("ioctl: LOOP_SET_FD");
- close(fd);
- close(ffd);
- return 1;
- }
- if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
- (void) ioctl(fd, LOOP_CLR_FD, 0);
- perror("ioctl: LOOP_SET_STATUS");
- close(fd);
- close(ffd);
- return 1;
- }
- close(fd);
- close(ffd);
- return 0;
-}
-
-char *find_unused_loop_device (void)
-{
- char dev[20];
- int i, fd;
- struct stat statbuf;
- struct loop_info loopinfo;
-
- for(i = 0; i <= 7; i++) {
- sprintf(dev, "/dev/loop%d", i);
- if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
- if ((fd = open (dev, O_RDONLY)) >= 0) {
- if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1) {
- if (errno == ENXIO) { /* probably free */
- close (fd);
- return strdup(dev);
- }
- }
- close (fd);
- }
- }
- }
- return NULL;
-}
-
-/*
- *
- */
-
-static void close_loop_device (bluray_input_plugin_t *this)
-{
- if (this->iso_image) {
- umount(this->mount_point);
- rmdir(this->mount_point);
- free(this->iso_image);
- this->iso_image = NULL;
- }
- if (this->loop_dev) {
- del_loop(this->loop_dev);
- free(this->loop_dev);
- this->loop_dev = NULL;
- }
-}
-
-static int mount_iso_image(bluray_input_plugin_t *this)
-{
- close_loop_device(this);
-
- /* create temporary mount point */
- sprintf(this->mount_point, "/tmp/xine_bd.%d.XXXXXX", (int)getpid());
- if (mktemp(this->mount_point)) {};
- if (mkdir(this->mount_point, S_IRWXU)) {
- LOGMSG("Failed to create temporary mount point %s: %s\n",
- this->mount_point, strerror(errno));
- return 0;
- }
-
- /* find and initialize unused loop device */
-
- this->loop_dev = find_unused_loop_device();
- if (!this->loop_dev) {
- LOGMSG("No free loop device for %s\n", this->disc_root);
- return 0;
- }
-
- int pro = O_RDONLY;
- if (set_loop(this->loop_dev, this->disc_root, 0, &pro)) {
- LOGMSG("Error setting up loop device %s for %s\n", this->loop_dev, this->disc_root);
- return 0;
- }
-
- /* mount .iso image */
- if (mount(this->loop_dev, this->mount_point, "udf",
- MS_NODEV | MS_MGC_VAL | MS_NOSUID | MS_RDONLY, NULL)) {
- LOGMSG("Error mounting loop device %s to %s\n", this->loop_dev, this->mount_point);
- return 0;
- }
-
- this->iso_image = this->disc_root;
- this->disc_root = strdup(this->mount_point);
-
- LOGMSG("Mounted %s to %s using loop device %s\n", this->iso_image, this->mount_point, this->loop_dev);
-
- return 1;
-}
-
-/*
- * overlay
- */
-
-#define PALETTE_INDEX_BACKGROUND 0xff
-
-static void send_num_buttons(bluray_input_plugin_t *this, int n)
-{
- xine_event_t event;
- xine_ui_data_t data;
-
- event.type = XINE_EVENT_UI_NUM_BUTTONS;
- event.data = &data;
- event.data_length = sizeof(data);
- data.num_buttons = n;
-
- xine_event_send(this->stream, &event);
-}
-
-static void clear_overlay(xine_osd_t *osd)
-{
- /* palette entry 0xff is background --> can't use xine_osd_clear(). */
- memset(osd->osd.area, PALETTE_INDEX_BACKGROUND, osd->osd.width * osd->osd.height);
- osd->osd.x1 = osd->osd.width;
- osd->osd.y1 = osd->osd.height;
- osd->osd.x2 = 0;
- osd->osd.y2 = 0;
-}
-
-static xine_osd_t *get_overlay(bluray_input_plugin_t *this, int plane)
-{
- if (!this->osd[plane]) {
- this->osd[plane] = xine_osd_new(this->stream, 0, 0, 1920, 1080);
- clear_overlay(this->osd[plane]);
- }
- if (!this->pg_enable) {
- _x_select_spu_channel(this->stream, -1);
- }
- return this->osd[plane];
-}
-
-static void close_overlay(bluray_input_plugin_t *this, int plane)
-{
- if (plane < 0) {
- close_overlay(this, 0);
- close_overlay(this, 1);
- return;
- }
-
- if (plane < 2 && this->osd[plane]) {
- xine_osd_free(this->osd[plane]);
- this->osd[plane] = NULL;
- if (plane == 1) {
- send_num_buttons(this, 0);
- this->menu_open = 0;
- }
- }
-}
-
-static void open_overlay(bluray_input_plugin_t *this, const BD_OVERLAY * const ov)
-{
- lprintf("open_overlay(%d,%d)\n", ov->w, ov->h);
-
- if (this->osd[ov->plane]) {
- close_overlay(this, ov->plane);
- }
-
- this->osd[ov->plane] = xine_osd_new(this->stream, ov->x, ov->y, ov->w, ov->h);
- clear_overlay(this->osd[ov->plane]);
-}
-
-static void draw_bitmap(xine_osd_t *osd, const BD_OVERLAY * const ov)
-{
- unsigned i;
-
- /* convert and set palette */
- if (ov->palette) {
- uint32_t color[256];
- uint8_t trans[256];
- for(i = 0; i < 256; i++) {
- trans[i] = ov->palette[i].T;
- color[i] = (ov->palette[i].Y << 16) | (ov->palette[i].Cr << 8) | ov->palette[i].Cb;
- }
-
- xine_osd_set_palette(osd, color, trans);
- }
-
- /* uncompress and draw bitmap */
- if (ov->img) {
- const BD_PG_RLE_ELEM *rlep = ov->img;
- uint8_t *img = malloc(ov->w * ov->h);
- unsigned pixels = ov->w * ov->h;
-
- for (i = 0; i < pixels; i += rlep->len, rlep++) {
- memset(img + i, rlep->color, rlep->len);
- }
-
- xine_osd_draw_bitmap(osd, img, ov->x, ov->y, ov->w, ov->h, NULL);
-
- free(img);
- }
-}
-
-static void overlay_proc(void *this_gen, const BD_OVERLAY * const ov)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
- xine_osd_t *osd;
-
- if (!this) {
- return;
- }
-
- if (!ov) {
- /* hide OSD */
- close_overlay(this, -1);
- return;
- }
-
- if (ov->plane > 1) {
- return;
- }
-
- switch (ov->cmd) {
- case BD_OVERLAY_INIT: /* init overlay plane. Size of full plane in x,y,w,h */
- open_overlay(this, ov);
- return;
- case BD_OVERLAY_CLOSE: /* close overlay */
- close_overlay(this, ov->plane);
- return;
- }
-
- osd = get_overlay(this, ov->plane);
-
- switch (ov->cmd) {
- case BD_OVERLAY_DRAW: /* draw bitmap (x,y,w,h,img,palette) */
- draw_bitmap(osd, ov);
- return;
-
- case BD_OVERLAY_WIPE: /* clear area (x,y,w,h) */
- xine_osd_draw_rect(osd, ov->x, ov->y, ov->x + ov->w - 1, ov->y + ov->h - 1, PALETTE_INDEX_BACKGROUND, 1);
- return;
-
- case BD_OVERLAY_CLEAR: /* clear plane */
- xine_osd_hide(osd, 0);
- clear_overlay(osd);
- return;
-
- case BD_OVERLAY_FLUSH: /* all changes have been done, flush overlay to display at given pts */
- xine_osd_show(osd, 0);
-
- if (ov->plane == 1) {
- this->menu_open = 1;
- send_num_buttons(this, 1);
- }
- return;
-
- default:
- LOGMSG("unknown overlay command %d\n", ov->cmd);
- return;
- }
-}
-
-/*
- * stream info
- */
-
-static void update_stream_info(bluray_input_plugin_t *this)
-{
- if (this->title_info) {
- /* set stream info */
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_COUNT, this->title_info->angle_count);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER, bd_get_current_angle(this->bdh));
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_CHAPTERS, this->title_info->chapter_count > 0);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_COUNT, this->title_info->chapter_count);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, bd_get_current_chapter(this->bdh) + 1);
- }
-}
-
-static void update_title_name(bluray_input_plugin_t *this)
-{
- char title_name[64] = "";
- xine_ui_data_t udata;
- xine_event_t uevent = {
- .type = XINE_EVENT_UI_SET_TITLE,
- .stream = this->stream,
- .data = &udata,
- .data_length = sizeof(udata)
- };
-
- /* check disc library metadata */
- if (this->meta_dl) {
- unsigned i;
- for (i = 0; i < this->meta_dl->toc_count; i++)
- if (this->meta_dl->toc_entries[i].title_number == (unsigned)this->current_title)
- if (this->meta_dl->toc_entries[i].title_name)
- if (strlen(this->meta_dl->toc_entries[i].title_name) > 2)
- strncpy(title_name, this->meta_dl->toc_entries[i].title_name, sizeof(title_name));
- }
-
- /* title name */
- if (title_name[0]) {
- } else if (this->current_title == BLURAY_TITLE_TOP_MENU) {
- strcpy(title_name, "Top Menu");
- } else if (this->current_title == BLURAY_TITLE_FIRST_PLAY) {
- strcpy(title_name, "First Play");
- } else if (this->nav_mode) {
- snprintf(title_name, sizeof(title_name), "Title %d/%d (PL %d/%d)",
- this->current_title, this->num_titles,
- this->current_title_idx + 1, this->num_title_idx);
- } else {
- snprintf(title_name, sizeof(title_name), "Title %d/%d",
- this->current_title_idx + 1, this->num_title_idx);
- }
-
- /* disc name */
- if (this->disc_name && this->disc_name[0]) {
- udata.str_len = snprintf(udata.str, sizeof(udata.str), "%s, %s",
- this->disc_name, title_name);
- } else {
- udata.str_len = snprintf(udata.str, sizeof(udata.str), "%s",
- title_name);
- }
-
- _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, udata.str);
-
- xine_event_send(this->stream, &uevent);
-}
-
-static void update_title_info(bluray_input_plugin_t *this, int playlist_id)
-{
- /* update title_info */
-
- pthread_mutex_lock(&this->title_info_mutex);
-
- if (this->title_info)
- bd_free_title_info(this->title_info);
-
- if (playlist_id < 0)
- this->title_info = bd_get_title_info(this->bdh, this->current_title_idx, 0);
- else
- this->title_info = bd_get_playlist_info(this->bdh, playlist_id, 0);
-
- pthread_mutex_unlock(&this->title_info_mutex);
-
- if (!this->title_info) {
- LOGMSG("bd_get_title_info(%d) failed\n", this->current_title_idx);
- return;
- }
-
-#ifdef LOG
- int ms = this->title_info->duration / INT64_C(90);
- lprintf("Opened title %d. Length %"PRId64" bytes / %02d:%02d:%02d.%03d\n",
- this->current_title_idx, bd_get_title_size(this->bdh),
- ms / 3600000, (ms % 3600000 / 60000), (ms % 60000) / 1000, ms % 1000);
-#endif
-
- /* calculate and set stream rate */
-
- uint64_t rate = bd_get_title_size(this->bdh) * UINT64_C(8) // bits
- * INT64_C(90000)
- / (uint64_t)(this->title_info->duration);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, rate);
-
-#ifdef LOG
- int krate = (int)(rate / UINT64_C(1024));
- int s = this->title_info->duration / 90000;
- int h = s / 3600; s -= h*3600;
- int m = s / 60; s -= m*60;
- int f = this->title_info->duration % 90000; f = f * 1000 / 90000;
- LOGMSG("BluRay stream: length: %d:%d:%d.%03d\n"
- " bitrate: %d.%03d Mbps\n\n",
- h, m, s, f, krate/1024, (krate%1024)*1000/1024);
-#endif
-
- /* set stream info */
-
- if (this->nav_mode) {
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_TITLE_COUNT, this->num_titles);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_TITLE_NUMBER, this->current_title);
- } else {
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_TITLE_COUNT, this->num_title_idx);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_TITLE_NUMBER, this->current_title_idx + 1);
- }
-
- update_stream_info(this);
-
- /* set title */
- update_title_name(this);
-}
-
-/*
- * libbluray event handling
- */
-
-static void stream_flush(bluray_input_plugin_t *this)
-{
- if (this->stream_flushed || !this->stream)
- return;
-
- lprintf("Stream flush\n");
-
- this->stream_flushed = 1;
-
- xine_event_t event = {
- .type = XINE_EVENT_END_OF_CLIP,
- .stream = this->stream,
- .data = NULL,
- .data_length = 0,
- };
- xine_event_send (this->stream, &event);
-
- this->demux_action_req = 1;
-}
-
-static void stream_reset(bluray_input_plugin_t *this)
-{
- if (!this || !this->stream || !this->stream->demux_plugin)
- return;
-
- lprintf("Stream reset\n");
-
-#if XINE_VERSION_CODE < 10121
- this->cap_seekable = 0;
-
- _x_set_fine_speed(this->stream, XINE_FINE_SPEED_NORMAL);
- this->stream->demux_plugin->seek(this->stream->demux_plugin, 0, 0, 1);
- _x_demux_control_start(this->stream);
-
- this->cap_seekable = INPUT_CAP_SEEKABLE;
-#else
- xine_event_t event = {
- .type = XINE_EVENT_PIDS_CHANGE,
- .stream = this->stream,
- .data = NULL,
- .data_length = 0,
- };
-
- if (!this->end_of_title) {
- _x_demux_flush_engine(this->stream);
- }
-
- xine_event_send (this->stream, &event);
-
- this->demux_action_req = 1;
-#endif
-}
-
-static void wait_secs(bluray_input_plugin_t *this, unsigned seconds)
-{
- stream_flush(this);
-
- if (this->still_end_time) {
- if (time(NULL) >= this->still_end_time) {
- lprintf("pause end\n");
- this->still_end_time = 0;
- bd_read_skip_still(this->bdh);
- stream_reset(this);
- return;
- }
- }
-
- else if (seconds) {
- if (seconds > 300) {
- seconds = 300;
- }
-
- lprintf("still image, pause for %d seconds\n", seconds);
- this->still_end_time = time(NULL) + seconds;
- }
-
- xine_usec_sleep(40*1000);
-}
-
-static void update_spu_channel(bluray_input_plugin_t *this, int channel)
-{
- if (this->stream->video_fifo) {
- buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo);
- buf->type = BUF_CONTROL_SPU_CHANNEL;
- buf->decoder_info[0] = channel;
- buf->decoder_info[1] = channel;
- buf->decoder_info[2] = channel;
-
- this->stream->video_fifo->put(this->stream->video_fifo, buf);
- }
-}
-
-static void update_audio_channel(bluray_input_plugin_t *this, int channel)
-{
- if (this->stream->audio_fifo) {
- buf_element_t *buf = this->stream->audio_fifo->buffer_pool_alloc(this->stream->audio_fifo);
- buf->type = BUF_CONTROL_AUDIO_CHANNEL;
- buf->decoder_info[0] = channel;
-
- this->stream->audio_fifo->put(this->stream->audio_fifo, buf);
- }
-}
-
-static void handle_libbluray_event(bluray_input_plugin_t *this, BD_EVENT ev)
-{
- switch ((bd_event_e)ev.event) {
-
- case BD_EVENT_NONE:
- break;
-
- case BD_EVENT_ERROR:
- LOGMSG("BD_EVENT_ERROR\n");
- this->error = 1;
- return;
-
- case BD_EVENT_READ_ERROR:
- LOGMSG("BD_EVENT_READ_ERROR\n");
- return;
-
- case BD_EVENT_ENCRYPTED:
- lprintf("BD_EVENT_ENCRYPTED\n");
- _x_message (this->stream, XINE_MSG_ENCRYPTED_SOURCE,
- "Media stream scrambled/encrypted", NULL);
- this->error = 1;
- return;
-
- /* sound effects */
-#if BLURAY_VERSION >= 202
- case BD_EVENT_SOUND_EFFECT:
- lprintf("BD_EVENT_SOUND_EFFECT %d\n", ev.param);
- break;
-#endif
-
- /* playback control */
-
- case BD_EVENT_SEEK:
- lprintf("BD_EVENT_SEEK\n");
- this->still_end_time = 0;
- stream_reset(this);
- break;
-
- case BD_EVENT_STILL_TIME:
- wait_secs(this, ev.param);
- break;
-
- case BD_EVENT_STILL:
- lprintf("BD_EVENT_STILL %d\n", ev.param);
- int paused = _x_get_fine_speed(this->stream) == XINE_SPEED_PAUSE;
- if (paused && !ev.param) {
- _x_set_fine_speed(this->stream, XINE_FINE_SPEED_NORMAL);
- }
- if (!paused && ev.param) {
- _x_set_fine_speed(this->stream, XINE_SPEED_PAUSE);
- }
- break;
-
- /* playback position */
-
- case BD_EVENT_ANGLE:
- lprintf("BD_EVENT_ANGLE_NUMBER %d\n", ev.param);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER, ev.param);
- break;
-
- case BD_EVENT_END_OF_TITLE:
- lprintf("BD_EVENT_END_OF_TITLE\n");
- stream_flush(this);
- this->end_of_title = 1;
- break;
-
- case BD_EVENT_TITLE:
- if (this->nav_mode) {
- lprintf("BD_EVENT_TITLE %d\n", ev.param);
- this->current_title = ev.param;
- }
- break;
-
- case BD_EVENT_PLAYLIST:
- lprintf("BD_EVENT_PLAYLIST %d\n", ev.param);
- this->current_title_idx = bd_get_current_title(this->bdh);
- this->current_clip = 0;
- update_title_info(this, ev.param);
- stream_reset(this);
- this->end_of_title = 0;
- break;
-
- case BD_EVENT_PLAYITEM:
- lprintf("BD_EVENT_PLAYITEM %d\n", ev.param);
- this->current_clip = ev.param;
- this->still_end_time = 0;
- break;
-
- case BD_EVENT_CHAPTER:
- lprintf("BD_EVENT_CHAPTER %d\n", ev.param);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, ev.param);
- break;
-
- /* stream selection */
-
- case BD_EVENT_AUDIO_STREAM:
- lprintf("BD_EVENT_AUDIO_STREAM %d\n", ev.param);
- if (ev.param < 32) {
- update_audio_channel(this, ev.param - 1);
- } else {
- update_audio_channel(this, 0);
- }
- break;
-
- case BD_EVENT_PG_TEXTST:
- lprintf("BD_EVENT_PG_TEXTST %s\n", ev.param ? "ON" : "OFF");
- this->pg_enable = !!ev.param;
- update_spu_channel(this, this->pg_enable ? this->pg_stream : -1);
- break;
-
- case BD_EVENT_PG_TEXTST_STREAM:
- lprintf("BD_EVENT_PG_TEXTST_STREAM %d\n", ev.param);
- if (ev.param < 64) {
- this->pg_stream = ev.param - 1;
- } else {
- this->pg_stream = -1;
- }
- if (this->pg_enable) {
- update_spu_channel(this, this->pg_stream);
- }
- break;
-
- case BD_EVENT_IG_STREAM:
- case BD_EVENT_SECONDARY_AUDIO:
- case BD_EVENT_SECONDARY_AUDIO_STREAM:
- case BD_EVENT_SECONDARY_VIDEO:
- case BD_EVENT_SECONDARY_VIDEO_SIZE:
- case BD_EVENT_SECONDARY_VIDEO_STREAM:
- // TODO
-
- default:
- lprintf("unhandled libbluray event %d [param %d]\n", ev.event, ev.param);
- break;
- }
-}
-
-static void handle_libbluray_events(bluray_input_plugin_t *this)
-{
- BD_EVENT ev;
- while (bd_get_event(this->bdh, &ev)) {
- handle_libbluray_event(this, ev);
- if (this->error || ev.event == BD_EVENT_NONE || ev.event == BD_EVENT_ERROR)
- break;
- }
-}
-
-/*
- * xine event handling
- */
-
-static int open_title (bluray_input_plugin_t *this, int title_idx)
-{
- if (bd_select_title(this->bdh, title_idx) <= 0) {
- LOGMSG("bd_select_title(%d) failed\n", title_idx);
- return 0;
- }
-
- this->current_title_idx = title_idx;
-
- update_title_info(this, -1);
-
- return 1;
-}
-
-static void send_mouse_enter_leave_event(bluray_input_plugin_t *this, int direction)
-{
- if (direction != this->mouse_inside_button) {
- xine_event_t event;
- xine_spu_button_t spu_event;
-
- spu_event.direction = direction;
- spu_event.button = 1;
-
- event.type = XINE_EVENT_SPU_BUTTON;
- event.stream = this->stream;
- event.data = &spu_event;
- event.data_length = sizeof(spu_event);
- xine_event_send(this->stream, &event);
-
- this->mouse_inside_button = direction;
- }
-}
-
-static void handle_events(bluray_input_plugin_t *this)
-{
- if (!this->event_queue)
- return;
-
- xine_event_t *event;
- while (NULL != (event = xine_event_get(this->event_queue))) {
-
- if (!this->bdh || !this->title_info) {
- xine_event_free(event);
- return;
- }
-
- int64_t pts = xine_get_current_vpts(this->stream) -
- this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET);
-
- if (this->menu_open) {
- switch (event->type) {
- case XINE_EVENT_INPUT_LEFT: bd_user_input(this->bdh, pts, BD_VK_LEFT); break;
- case XINE_EVENT_INPUT_RIGHT: bd_user_input(this->bdh, pts, BD_VK_RIGHT); break;
- }
- } else {
- switch (event->type) {
-
- case XINE_EVENT_INPUT_LEFT:
- lprintf("XINE_EVENT_INPUT_LEFT: previous title\n");
- if (!this->nav_mode) {
- open_title(this, MAX(0, this->current_title_idx - 1));
- } else {
- bd_play_title(this->bdh, MAX(1, this->current_title - 1));
- }
- stream_reset(this);
- break;
-
- case XINE_EVENT_INPUT_RIGHT:
- lprintf("XINE_EVENT_INPUT_RIGHT: next title\n");
- if (!this->nav_mode) {
- open_title(this, MIN(this->num_title_idx - 1, this->current_title_idx + 1));
- } else {
- bd_play_title(this->bdh, MIN(this->num_titles, this->current_title + 1));
- }
- stream_reset(this);
- break;
- }
- }
-
- switch (event->type) {
-
- case XINE_EVENT_INPUT_MOUSE_BUTTON: {
- xine_input_data_t *input = event->data;
- lprintf("mouse click: button %d at (%d,%d)\n", input->button, input->x, input->y);
- if (input->button == 1) {
- bd_mouse_select(this->bdh, pts, input->x, input->y);
- bd_user_input(this->bdh, pts, BD_VK_MOUSE_ACTIVATE);
- send_mouse_enter_leave_event(this, 0);
- }
- break;
- }
-
- case XINE_EVENT_INPUT_MOUSE_MOVE: {
- xine_input_data_t *input = event->data;
- if (bd_mouse_select(this->bdh, pts, input->x, input->y) > 0) {
- send_mouse_enter_leave_event(this, 1);
- } else {
- send_mouse_enter_leave_event(this, 0);
- }
- break;
- }
-
- case XINE_EVENT_INPUT_MENU1:
- if (!this->disc_info->top_menu_supported) {
- _x_message (this->stream, XINE_MSG_GENERAL_WARNING,
- "Can't open Top Menu",
- "Top Menu title not supported", NULL);
- }
- bd_menu_call(this->bdh, pts);
- break;
-
- case XINE_EVENT_INPUT_MENU2: bd_user_input(this->bdh, pts, BD_VK_POPUP); break;
- case XINE_EVENT_INPUT_UP: bd_user_input(this->bdh, pts, BD_VK_UP); break;
- case XINE_EVENT_INPUT_DOWN: bd_user_input(this->bdh, pts, BD_VK_DOWN); break;
- case XINE_EVENT_INPUT_SELECT: bd_user_input(this->bdh, pts, BD_VK_ENTER); break;
- case XINE_EVENT_INPUT_NUMBER_0: bd_user_input(this->bdh, pts, BD_VK_0); break;
- case XINE_EVENT_INPUT_NUMBER_1: bd_user_input(this->bdh, pts, BD_VK_1); break;
- case XINE_EVENT_INPUT_NUMBER_2: bd_user_input(this->bdh, pts, BD_VK_2); break;
- case XINE_EVENT_INPUT_NUMBER_3: bd_user_input(this->bdh, pts, BD_VK_3); break;
- case XINE_EVENT_INPUT_NUMBER_4: bd_user_input(this->bdh, pts, BD_VK_4); break;
- case XINE_EVENT_INPUT_NUMBER_5: bd_user_input(this->bdh, pts, BD_VK_5); break;
- case XINE_EVENT_INPUT_NUMBER_6: bd_user_input(this->bdh, pts, BD_VK_6); break;
- case XINE_EVENT_INPUT_NUMBER_7: bd_user_input(this->bdh, pts, BD_VK_7); break;
- case XINE_EVENT_INPUT_NUMBER_8: bd_user_input(this->bdh, pts, BD_VK_8); break;
- case XINE_EVENT_INPUT_NUMBER_9: bd_user_input(this->bdh, pts, BD_VK_9); break;
-
- case XINE_EVENT_INPUT_NEXT: {
- cfg_entry_t* entry = this->class->xine->config->lookup_entry(this->class->xine->config,
- "media.bluray.skip_behaviour");
- switch (entry->num_value) {
- case 0: /* skip by chapter */
- bd_seek_chapter(this->bdh, bd_get_current_chapter(this->bdh) + 1);
- update_stream_info(this);
- break;
- case 1: /* skip by title */
- if (!this->nav_mode) {
- open_title(this, MIN(this->num_title_idx - 1, this->current_title_idx + 1));
- } else {
- bd_play_title(this->bdh, MIN(this->num_titles, this->current_title + 1));
- }
- break;
- }
- stream_reset(this);
- break;
- }
-
- case XINE_EVENT_INPUT_PREVIOUS: {
- cfg_entry_t* entry = this->class->xine->config->lookup_entry(this->class->xine->config,
- "media.bluray.skip_behaviour");
- switch (entry->num_value) {
- case 0: /* skip by chapter */
- bd_seek_chapter(this->bdh, MAX(0, ((int)bd_get_current_chapter(this->bdh)) - 1));
- update_stream_info(this);
- break;
- case 1: /* skip by title */
- if (!this->nav_mode) {
- open_title(this, MAX(0, this->current_title_idx - 1));
- } else {
- bd_play_title(this->bdh, MAX(1, this->current_title - 1));
- }
- break;
- }
- stream_reset(this);
- break;
- }
-
- case XINE_EVENT_INPUT_ANGLE_NEXT: {
- unsigned curr_angle = bd_get_current_angle(this->bdh);
- unsigned angle = MIN(8, curr_angle + 1);
- lprintf("XINE_EVENT_INPUT_ANGLE_NEXT: set angle %d --> %d\n", curr_angle, angle);
- bd_seamless_angle_change(this->bdh, angle);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER, bd_get_current_angle(this->bdh));
- break;
- }
-
- case XINE_EVENT_INPUT_ANGLE_PREVIOUS: {
- unsigned curr_angle = bd_get_current_angle(this->bdh);
- unsigned angle = curr_angle ? curr_angle - 1 : 0;
- lprintf("XINE_EVENT_INPUT_ANGLE_PREVIOUS: set angle %d --> %d\n", curr_angle, angle);
- bd_seamless_angle_change(this->bdh, angle);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER, bd_get_current_angle(this->bdh));
- break;
- }
- }
-
- xine_event_free(event);
- }
-}
-
-/*
- * xine plugin interface
- */
-
-static uint32_t bluray_plugin_get_capabilities (input_plugin_t *this_gen)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
- return this->cap_seekable |
- INPUT_CAP_BLOCK |
- INPUT_CAP_AUDIOLANG |
- INPUT_CAP_SPULANG |
- INPUT_CAP_CHAPTERS;
-}
-
-#if XINE_VERSION_CODE >= 10121
-# define CHECK_READ_INTERRUPT \
- do { \
- if (this->demux_action_req) { \
- this->demux_action_req = 0; \
- errno = EAGAIN; \
- return -1; \
- } \
- } while (0)
-#else
-# define CHECK_READ_INTERRUPT
-#endif
-
-
-#if XINE_VERSION_CODE >= 10190
-static off_t bluray_plugin_read (input_plugin_t *this_gen, void *buf, off_t len)
-#else
-static off_t bluray_plugin_read (input_plugin_t *this_gen, char *buf, off_t len)
-#endif
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
- off_t result;
-
- if (!this || !this->bdh || len < 0 || this->error)
- return -1;
-
- handle_events(this);
- CHECK_READ_INTERRUPT;
-
- if (this->nav_mode) {
- do {
- BD_EVENT ev;
- result = bd_read_ext (this->bdh, (unsigned char *)buf, len, &ev);
- handle_libbluray_event(this, ev);
- CHECK_READ_INTERRUPT;
-
- if (result == 0) {
- handle_events(this);
- CHECK_READ_INTERRUPT;
-
- if (ev.event == BD_EVENT_NONE) {
- if (_x_action_pending(this->stream)) {
- break;
- }
- }
- }
- } while (!this->error && result == 0);
- } else {
- result = bd_read (this->bdh, (unsigned char *)buf, len);
- handle_libbluray_events(this);
- }
-
- if (result < 0)
- LOGMSG("bd_read() failed: %s (%d of %d)\n", strerror(errno), (int)result, (int)len);
-
- if (result > 0)
- this->stream_flushed = 0;
-
- return result;
-}
-
-static buf_element_t *bluray_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo)
-{
- buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
-
- if (todo > (off_t)buf->max_size)
- todo = buf->max_size;
-
- if (todo > ALIGNED_UNIT_SIZE)
- todo = ALIGNED_UNIT_SIZE;
-
- if (todo > 0) {
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- buf->size = bluray_plugin_read(this_gen, (char*)buf->mem, todo);
- buf->type = BUF_DEMUX_BLOCK;
-
- if (buf->size > 0) {
- buf->extra_info->input_time = 0;
- buf->extra_info->total_time = this->title_info->duration / 90000;
- return buf;
- }
- }
-
- buf->free_buffer (buf);
- return NULL;
-}
-
-static off_t bluray_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- if (!this || !this->bdh)
- return -1;
- if (this->still_end_time)
- return offset;
-
- /* convert relative seeks to absolute */
-
- if (origin == SEEK_CUR) {
- offset = bd_tell(this->bdh) + offset;
- }
- else if (origin == SEEK_END) {
- if (offset < (off_t)bd_get_title_size(this->bdh))
- offset = bd_get_title_size(this->bdh) - offset;
- else
- offset = 0;
- }
-
- lprintf("bluray_plugin_seek() seeking to %lld\n", (long long)offset);
-
- return bd_seek (this->bdh, offset);
-}
-
-static off_t bluray_plugin_seek_time (input_plugin_t *this_gen, int time_offset, int origin)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- if (!this || !this->bdh)
- return -1;
-
- if (this->still_end_time)
- return bd_tell(this->bdh);
-
- /* convert relative seeks to absolute */
-
- if (origin == SEEK_CUR) {
- time_offset += this_gen->get_current_time(this_gen);
- }
- else if (origin == SEEK_END) {
-
- pthread_mutex_lock(&this->title_info_mutex);
-
- if (!this->title_info) {
- pthread_mutex_unlock(&this->title_info_mutex);
- return -1;
- }
-
- int duration = this->title_info->duration / 90;
- if (time_offset < duration)
- time_offset = duration - time_offset;
- else
- time_offset = 0;
-
- pthread_mutex_unlock(&this->title_info_mutex);
- }
-
- lprintf("bluray_plugin_seek_time() seeking to %d.%03ds\n", time_offset / 1000, time_offset % 1000);
-
- return bd_seek_time(this->bdh, time_offset * INT64_C(90));
-}
-
-static off_t bluray_plugin_get_current_pos (input_plugin_t *this_gen)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- return this->bdh ? bd_tell(this->bdh) : 0;
-}
-
-static int bluray_plugin_get_current_time (input_plugin_t *this_gen)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- return this->bdh ? (int)(bd_tell_time(this->bdh) / UINT64_C(90)) : -1;
-}
-
-static off_t bluray_plugin_get_length (input_plugin_t *this_gen)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- return this->bdh ? (off_t)bd_get_title_size(this->bdh) : (off_t)-1;
-}
-
-static uint32_t bluray_plugin_get_blocksize (input_plugin_t *this_gen)
-{
- (void)this_gen;
-
- return ALIGNED_UNIT_SIZE;
-}
-
-static const char* bluray_plugin_get_mrl (input_plugin_t *this_gen)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- return this->mrl;
-}
-
-static int get_audio_lang (bluray_input_plugin_t *this, int *data)
-{
- /*
- * audio track language:
- * - channel number can be mpeg-ts PID (0x1100 ... 0x11ff)
- */
-
- unsigned int current_clip = this->current_clip; /* can change any time */
-
- if (this->title_info && current_clip < this->title_info->clip_count) {
- int channel = *data;
- BLURAY_CLIP_INFO *clip = &this->title_info->clips[current_clip];
-
- if (channel >= 0 && channel < clip->audio_stream_count) {
- memcpy(data, clip->audio_streams[channel].lang, 4);
- return INPUT_OPTIONAL_SUCCESS;
- }
-
- /* search by pid */
- int i;
- for (i = 0; i < clip->audio_stream_count; i++) {
- if (channel == clip->audio_streams[i].pid) {
- memcpy(data, clip->audio_streams[i].lang, 4);
- return INPUT_OPTIONAL_SUCCESS;
- }
- }
- }
-
- return INPUT_OPTIONAL_UNSUPPORTED;
-}
-
-static int get_spu_lang (bluray_input_plugin_t *this, int *data)
-{
- /*
- * SPU track language:
- * - channel number can be mpeg-ts PID (0x1200 ... 0x12ff)
- */
-
- unsigned int current_clip = this->current_clip; /* can change any time */
-
- if (this->title_info && current_clip < this->title_info->clip_count) {
- int channel = *data;
- BLURAY_CLIP_INFO *clip = &this->title_info->clips[current_clip];
-
- if (channel >= 0 && channel < clip->pg_stream_count) {
- memcpy(data, clip->pg_streams[channel].lang, 4);
- return INPUT_OPTIONAL_SUCCESS;
- }
-
- /* search by pid */
- int i;
- for (i = 0; i < clip->pg_stream_count; i++) {
- if (channel == clip->pg_streams[i].pid) {
- memcpy(data, clip->pg_streams[i].lang, 4);
- return INPUT_OPTIONAL_SUCCESS;
- }
- }
- }
-
- return INPUT_OPTIONAL_UNSUPPORTED;
-}
-
-static int get_optional_data_impl (bluray_input_plugin_t *this, void *data, int data_type)
-{
- switch (data_type) {
-
- case INPUT_OPTIONAL_DATA_DEMUXER:
-#ifdef HAVE_CONFIG_H
- *(const char **)data = "mpeg-ts";
-#else
- *(const char **)data = "mpeg-ts-hdmv";
-#endif
- return INPUT_OPTIONAL_SUCCESS;
-
- case INPUT_OPTIONAL_DATA_AUDIOLANG:
- return get_audio_lang(this, data);
-
- case INPUT_OPTIONAL_DATA_SPULANG:
- return get_spu_lang(this, data);
-
- default:
- return INPUT_OPTIONAL_UNSUPPORTED;
- }
-
- return INPUT_OPTIONAL_UNSUPPORTED;
-}
-
-static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
- int r = INPUT_OPTIONAL_UNSUPPORTED;
-
- if (this && this->stream && data) {
- pthread_mutex_lock(&this->title_info_mutex);
- r = get_optional_data_impl(this, data, data_type);
- pthread_mutex_unlock(&this->title_info_mutex);
- }
-
- return r;
-}
-
-static void bluray_plugin_dispose (input_plugin_t *this_gen)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
- if (this->bdh)
- bd_register_overlay_proc(this->bdh, NULL, NULL);
-
- close_overlay(this, -1);
-
- if (this->event_queue)
- xine_event_dispose_queue(this->event_queue);
-
- pthread_mutex_lock(&this->title_info_mutex);
- if (this->title_info)
- bd_free_title_info(this->title_info);
- this->title_info = NULL;
- pthread_mutex_unlock(&this->title_info_mutex);
-
- pthread_mutex_destroy(&this->title_info_mutex);
-
- if (this->bdh)
- bd_close(this->bdh);
-
- free (this->mrl);
- free (this->disc_root);
- free (this->disc_name);
-
- close_loop_device(this);
-
- free (this);
-}
-
-static int parse_mrl(const char *mrl_in, char **path, int *title, int *chapter)
-{
- int skip = 0;
-
- if (!strncasecmp(mrl_in, "bluray:", 7))
- skip = 7;
- else if (!strncasecmp(mrl_in, "bd:", 3))
- skip = 3;
- else
- return -1;
-
- char *mrl = strdup(mrl_in + skip);
-
- /* title[.chapter] given ? parse and drop it */
- if (mrl[strlen(mrl)-1] != '/') {
- char *end = strrchr(mrl, '/');
- if (end && end[1]) {
- if (sscanf(end, "/%d.%d", title, chapter) < 1)
- *title = -1;
- else
- *end = 0;
- }
- }
- lprintf(" -> title %d, chapter %d, mrl \'%s\'\n", *title, *chapter, mrl);
-
- if ((mrl[0] == 0) ||
- (mrl[1] == 0 && mrl[0] == '/') ||
- (mrl[2] == 0 && mrl[1] == '/' && mrl[0] == '/') ||
- (mrl[3] == 0 && mrl[2] == '/' && mrl[1] == '/' && mrl[0] == '/')){
-
- /* default device */
- *path = NULL;
-
- } else if (*mrl == '/') {
-
- /* strip extra slashes */
- char *start = mrl;
- while (start[0] == '/' && start[1] == '/')
- start++;
-
- *path = strdup(start);
-
- _x_mrl_unescape(*path);
-
- lprintf("non-defaut mount point \'%s\'\n", *path);
-
- } else {
- lprintf("invalid mrl \'%s\'\n", mrl_in);
- free(mrl);
- return 0;
- }
-
- free(mrl);
-
- return 1;
-}
-
-static int get_disc_info(bluray_input_plugin_t *this)
-{
- const BLURAY_DISC_INFO *disc_info;
-
- disc_info = bd_get_disc_info(this->bdh);
-
- if (!disc_info) {
- LOGMSG("bd_get_disc_info() failed\n");
- return -1;
- }
-
- if (!disc_info->bluray_detected) {
- LOGMSG("bd_get_disc_info(): BluRay not detected\n");
- this->nav_mode = 0;
- return 0;
- }
-
- if (disc_info->aacs_detected && !disc_info->aacs_handled) {
- if (!disc_info->libaacs_detected)
- _x_message (this->stream, XINE_MSG_ENCRYPTED_SOURCE,
- "Media stream scrambled/encrypted with AACS",
- "libaacs not installed", NULL);
- else
- _x_message (this->stream, XINE_MSG_ENCRYPTED_SOURCE,
- "Media stream scrambled/encrypted with AACS", NULL);
- return -1;
- }
-
- if (disc_info->bdplus_detected && !disc_info->bdplus_handled) {
- if (!disc_info->libbdplus_detected)
- _x_message (this->stream, XINE_MSG_ENCRYPTED_SOURCE,
- "Media scrambled/encrypted with BD+",
- "libbdplus not installed.", NULL);
- else
- _x_message (this->stream, XINE_MSG_ENCRYPTED_SOURCE,
- "Media stream scrambled/encrypted with BD+", NULL);
- return -1;
- }
-
- if (this->nav_mode && !disc_info->first_play_supported) {
- _x_message (this->stream, XINE_MSG_GENERAL_WARNING,
- "Can't play disc in HDMV navigation mode",
- "First Play title not supported", NULL);
- this->nav_mode = 0;
- }
-
- if (this->nav_mode && disc_info->num_unsupported_titles > 0) {
- _x_message (this->stream, XINE_MSG_GENERAL_WARNING,
- "Unsupported titles found",
- "Some titles can't be played in navigation mode", NULL);
- }
-
- this->num_titles = disc_info->num_hdmv_titles + disc_info->num_bdj_titles;
- this->disc_info = disc_info;
-
- return 1;
-}
-
-static char *get_file_name(const char *path)
-{
- const char *name_start;
- char *file_name = NULL;
- int len;
-
- name_start = path + strlen(path) - 1;
- /* skip trailing '/' */
- while (name_start > path && name_start[0] == '/')
- name_start--;
- /* find prev '/' */
- while (name_start > path && name_start[-1] != '/')
- name_start--;
-
- file_name = strdup(name_start);
- len = strlen(file_name);
-
- /* trim trailing '/' */
- while (len > 0 && file_name[len - 1] == '/')
- file_name[--len] = 0;
-
- /* trim trailing ".iso" */
- if (len > 3 && !strcasecmp(file_name + len - 4, ".iso"))
- file_name[len - 4] = 0;
-
- /* '_' --> ' ' */
- for (len = 0; file_name[len]; ++len)
- if (file_name[len] == '_')
- file_name[len] = ' ';
-
- lprintf("disc name: %s\n", file_name);
- return file_name;
-}
-
-static int is_iso_image(const char *mrl)
-{
- if (mrl) {
- const char *pos = strrchr(mrl, '.');
- return pos && !strcasecmp(pos + 1, "iso");
- }
- return 0;
-}
-
-static int bluray_plugin_open (input_plugin_t *this_gen)
-{
- bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
- int title = -1;
- int chapter = 0;
-
- lprintf("bluray_plugin_open '%s'\n",this->mrl);
-
- /* validate and parse mrl */
- if (!parse_mrl(this->mrl, &this->disc_root, &title, &chapter))
- return -1;
-
- if (!strncasecmp(this->mrl, "bd:", 3))
- this->nav_mode = 1;
-
- if (!this->disc_root)
- this->disc_root = strdup(this->class->mountpoint);
-
- /* mount .iso image */
- if (is_iso_image(this->disc_root) && !mount_iso_image(this)) {
- _x_message (this->stream, XINE_MSG_GENERAL_WARNING,
- "Can't play BluRay .iso image",
- "Mounting of .iso image using loop device failed.\n"
- "Not enough loop devices or insufficient permissions ?", NULL);
- return -1;
- }
-
- /* open libbluray */
-
- if (! (this->bdh = bd_open (this->disc_root, NULL))) {
- LOGMSG("bd_open(\'%s\') failed: %s\n", this->disc_root, strerror(errno));
- return -1;
- }
- lprintf("bd_open(\'%s\') OK\n", this->disc_root);
-
- if (get_disc_info(this) < 0) {
- return -1;
- }
-
- /* load title list */
-
- this->num_title_idx = bd_get_titles(this->bdh, TITLES_RELEVANT, MIN_TITLE_LENGTH);
- LOGMSG("%d titles\n", this->num_title_idx);
-
- if (this->num_title_idx < 1)
- return -1;
-
- /* select title */
-
- /* if title was not in mrl, find the main title */
- if (title < 0) {
- uint64_t duration = 0;
- int i, playlist = 99999;
- for (i = 0; i < this->num_title_idx; i++) {
- BLURAY_TITLE_INFO *info = bd_get_title_info(this->bdh, i, 0);
- if (info->duration > duration) {
- title = i;
- duration = info->duration;
- playlist = info->playlist;
- }
- bd_free_title_info(info);
- }
- lprintf("main title: %d (%05d.mpls)\n", title, playlist);
- }
-
- /* update player settings */
-
- bd_set_player_setting (this->bdh, BLURAY_PLAYER_SETTING_REGION_CODE, this->class->region);
- bd_set_player_setting (this->bdh, BLURAY_PLAYER_SETTING_PARENTAL, this->class->parental);
- bd_set_player_setting_str(this->bdh, BLURAY_PLAYER_SETTING_AUDIO_LANG, this->class->language);
- bd_set_player_setting_str(this->bdh, BLURAY_PLAYER_SETTING_PG_LANG, this->class->language);
- bd_set_player_setting_str(this->bdh, BLURAY_PLAYER_SETTING_MENU_LANG, this->class->language);
- bd_set_player_setting_str(this->bdh, BLURAY_PLAYER_SETTING_COUNTRY_CODE, this->class->country);
-
- /* init event queue */
- bd_get_event(this->bdh, NULL);
-
- /* get disc name */
-
- this->meta_dl = bd_get_meta(this->bdh);
-
- if (this->meta_dl && this->meta_dl->di_name && strlen(this->meta_dl->di_name) > 1) {
- this->disc_name = strdup(this->meta_dl->di_name);
- }
- else if (strcmp(this->disc_root, this->class->mountpoint)) {
- this->disc_name = get_file_name(this->iso_image ?: this->disc_root);
- }
-
- /* register overlay (graphics) handler */
-
- bd_register_overlay_proc(this->bdh, this, overlay_proc);
-
- /* open */
- this->current_title = -1;
- this->current_title_idx = -1;
-
- if (this->nav_mode) {
- if (bd_play(this->bdh) <= 0) {
- LOGMSG("bd_play() failed\n");
- return -1;
- }
-
- } else {
- if (open_title(this, title) <= 0 &&
- open_title(this, 0) <= 0)
- return -1;
- }
-
- /* jump to chapter */
-
- if (chapter > 0) {
- chapter = MAX(0, MIN((int)this->title_info->chapter_count, chapter) - 1);
- bd_seek_chapter(this->bdh, chapter);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, chapter + 1);
- }
-
- return 1;
-}
-
-static input_plugin_t *bluray_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream,
- const char *mrl)
-{
- bluray_input_plugin_t *this;
-
- lprintf("bluray_class_get_instance\n");
-
- if (strncasecmp(mrl, "bluray:", 7) && strncasecmp(mrl, "bd:", 3))
- return NULL;
-
- this = (bluray_input_plugin_t *) calloc(1, sizeof (bluray_input_plugin_t));
-
- this->stream = stream;
- this->class = (bluray_input_class_t*)cls_gen;
- this->mrl = strdup(mrl);
-
- this->cap_seekable = INPUT_CAP_SEEKABLE;
-
- this->input_plugin.open = bluray_plugin_open;
- this->input_plugin.get_capabilities = bluray_plugin_get_capabilities;
- this->input_plugin.read = bluray_plugin_read;
- this->input_plugin.read_block = bluray_plugin_read_block;
- this->input_plugin.seek = bluray_plugin_seek;
- this->input_plugin.seek_time = bluray_plugin_seek_time;
- this->input_plugin.get_current_pos = bluray_plugin_get_current_pos;
- this->input_plugin.get_current_time = bluray_plugin_get_current_time;
- this->input_plugin.get_length = bluray_plugin_get_length;
- this->input_plugin.get_blocksize = bluray_plugin_get_blocksize;
- this->input_plugin.get_mrl = bluray_plugin_get_mrl;
- this->input_plugin.get_optional_data = bluray_plugin_get_optional_data;
- this->input_plugin.dispose = bluray_plugin_dispose;
- this->input_plugin.input_class = cls_gen;
-
- this->event_queue = xine_event_new_queue (this->stream);
-
- pthread_mutex_init(&this->title_info_mutex, NULL);
-
- this->pg_stream = -1;
-
- return &this->input_plugin;
-}
-
-/*
- * plugin class
- */
-
-static void mountpoint_change_cb(void *data, xine_cfg_entry_t *cfg)
-{
- bluray_input_class_t *this = (bluray_input_class_t *) data;
-
- this->mountpoint = cfg->str_value;
-}
-
-static void device_change_cb(void *data, xine_cfg_entry_t *cfg)
-{
- bluray_input_class_t *this = (bluray_input_class_t *) data;
-
- this->device = cfg->str_value;
-}
-
-static void language_change_cb(void *data, xine_cfg_entry_t *cfg)
-{
- bluray_input_class_t *class = (bluray_input_class_t *) data;
-
- class->language = cfg->str_value;
-#if 0
- if (class->bdh) {
- bd_set_player_setting_str(class->bdh, BLURAY_PLAYER_SETTING_AUDIO_LANG, class->language);
- bd_set_player_setting_str(class->bdh, BLURAY_PLAYER_SETTING_PG_LANG, class->language);
- bd_set_player_setting_str(class->bdh, BLURAY_PLAYER_SETTING_MENU_LANG, class->language);
- }
-#endif
-}
-
-static void country_change_cb(void *data, xine_cfg_entry_t *cfg)
-{
- bluray_input_class_t *this = (bluray_input_class_t *) data;
-
- this->country = cfg->str_value;
-}
-
-static void region_change_cb(void *data, xine_cfg_entry_t *cfg)
-{
- bluray_input_class_t *this = (bluray_input_class_t *) data;
-
- this->region = cfg->num_value;
-}
-
-static void parental_change_cb(void *data, xine_cfg_entry_t *cfg)
-{
- bluray_input_class_t *this = (bluray_input_class_t *) data;
-
- this->parental = cfg->num_value;
-}
-
-static void free_xine_playlist(bluray_input_class_t *this)
-{
- if (this->xine_playlist) {
- int i;
- for (i = 0; i < this->xine_playlist_size; i++) {
- MRL_ZERO(this->xine_playlist[i]);
- free(this->xine_playlist[i]);
- }
- free(this->xine_playlist);
- this->xine_playlist = NULL;
- }
-
- this->xine_playlist_size = 0;
-}
-
-#if INPUT_PLUGIN_IFACE_VERSION < 18
-static const char *bluray_class_get_description (input_class_t *this_gen)
-{
- (void)this_gen;
-
- return _("BluRay input plugin");
-}
-#endif
-
-#if INPUT_PLUGIN_IFACE_VERSION < 18
-static const char *bluray_class_get_identifier (input_class_t *this_gen)
-{
- (void)this_gen;
-
- return "bluray";
-}
-#endif
-
-static char **bluray_class_get_autoplay_list (input_class_t *this_gen, int *num_files)
-{
- (void)this_gen;
-
- static char *autoplay_list[] = { "bluray:/", NULL };
-
- *num_files = 1;
-
- return autoplay_list;
-}
-
-static xine_mrl_t **bluray_class_get_dir(input_class_t *this_gen, const char *filename, int *nFiles)
-{
- bluray_input_class_t *this = (bluray_input_class_t*) this_gen;
- char *path = NULL;
- int title = -1, chapter = -1, i, num_pl;
- BLURAY *bdh;
-
- lprintf("bluray_class_get_dir(%s)\n", filename);
-
- free_xine_playlist(this);
-
- if (filename)
- parse_mrl(filename, &path, &title, &chapter);
-
- bdh = bd_open(path ? path : this->mountpoint, NULL);
-
- if (bdh) {
- num_pl = bd_get_titles(bdh, TITLES_RELEVANT, MIN_TITLE_LENGTH);
-
- if (num_pl > 0) {
-
- this->xine_playlist_size = num_pl;
- this->xine_playlist = calloc(this->xine_playlist_size + 1, sizeof(xine_mrl_t*));
-
- for (i = 0; i < num_pl; i++) {
- //BLURAY_TITLE_INFO *info = bd_get_title_info(bd, title);
-
- this->xine_playlist[i] = calloc(1, sizeof(xine_mrl_t));
-
- if (asprintf(&this->xine_playlist[i]->origin, "bluray:/%s", path?:"") < 0)
- this->xine_playlist[i]->origin = NULL;
- if (asprintf(&this->xine_playlist[i]->mrl, "bluray:/%s/%d", path?:"", i) < 0)
- this->xine_playlist[i]->mrl = NULL;
- this->xine_playlist[i]->type = mrl_dvd;
- //this->xine_playlist[i]->size = info->duration;
-
- //bd_free_title_info(info);
- }
- }
-
- bd_close(bdh);
- }
-
- free(path);
-
- if (nFiles)
- *nFiles = this->xine_playlist_size;
-
- return this->xine_playlist;
-}
-
-static int bluray_class_eject_media (input_class_t *this_gen)
-{
- (void)this_gen;
-#if 0
- bluray_input_class_t *this = (bluray_input_class_t*) this_gen;
-
- return media_eject_media (this->xine, this->device);
-#endif
- return 1;
-}
-
-static void bluray_class_dispose (input_class_t *this_gen)
-{
- bluray_input_class_t *this = (bluray_input_class_t *) this_gen;
- config_values_t *config = this->xine->config;
-
- free_xine_playlist(this);
-
- config->unregister_callback(config, "media.bluray.mountpoint");
- config->unregister_callback(config, "media.bluray.device");
- config->unregister_callback(config, "media.bluray.region");
- config->unregister_callback(config, "media.bluray.language");
- config->unregister_callback(config, "media.bluray.country");
- config->unregister_callback(config, "media.bluray.parental");
-
- free (this);
-}
-
-static void *bluray_init_plugin (xine_t *xine, void *data)
-{
- (void)data;
-
- static char *skip_modes[] = {"skip chapter", "skip title", NULL};
-
- config_values_t *config = xine->config;
- bluray_input_class_t *this = (bluray_input_class_t *) calloc(1, sizeof (bluray_input_class_t));
-
- this->xine = xine;
-
- this->input_class.get_instance = bluray_class_get_instance;
-#if INPUT_PLUGIN_IFACE_VERSION < 18
- this->input_class.get_identifier = bluray_class_get_identifier;
- this->input_class.get_description = bluray_class_get_description;
-#else
- this->input_class.identifier = "bluray";
- this->input_class.description = _("BluRay input plugin");
-#endif
- this->input_class.get_dir = bluray_class_get_dir;
- this->input_class.get_autoplay_list = bluray_class_get_autoplay_list;
- this->input_class.dispose = bluray_class_dispose;
- this->input_class.eject_media = bluray_class_eject_media;
-
- this->mountpoint =
- config->register_filename(config, "media.bluray.mountpoint",
- "/mnt/bluray", XINE_CONFIG_STRING_IS_DIRECTORY_NAME,
- _("BluRay mount point"),
- _("Default mount location for BluRay discs."),
- 0, mountpoint_change_cb, (void *) this);
- this->device =
- config->register_filename(config, "media.bluray.device",
- "/dev/dvd", XINE_CONFIG_STRING_IS_DIRECTORY_NAME,
- _("device used for BluRay playback"),
- _("The path to the device "
- "which you intend to use for playing BluRy discs."),
- 0, device_change_cb, (void *) this);
-
- /* Player settings */
- this->language =
- config->register_string(config, "media.bluray.language",
- "eng",
- _("default language for BluRay playback"),
- _("xine tries to use this language as a default for BluRay playback. "
- "As far as the BluRay supports it, menus and audio tracks will be presented "
- "in this language.\nThe value must be a three character"
- "ISO639-2 language code."),
- 0, language_change_cb, this);
- this->country =
- config->register_string(config, "media.bluray.country",
- "en",
- _("BluRay player country code"),
- _("The value must be a two character ISO3166-1 country code."),
- 0, country_change_cb, this);
- this->region =
- config->register_num(config, "media.bluray.region",
- 7,
- _("BluRay player region code (1=A, 2=B, 4=C)"),
- _("This only needs to be changed if your BluRay jumps to a screen "
- "complaining about a wrong region code. It has nothing to do with "
- "the region code set in BluRay drives, this is purely software."),
- 0, region_change_cb, this);
- this->parental =
- config->register_num(config, "media.bluray.parental",
- 99,
- _("parental control age limit (1-99)"),
- _("Prevents playback of BluRay titles where parental "
- "control age limit is higher than this limit"),
- 0, parental_change_cb, this);
-
- /* */
- config->register_enum(config, "media.bluray.skip_behaviour", 0,
- skip_modes,
- _("unit for the skip action"),
- _("You can configure the behaviour when issuing a skip command (using the skip "
- "buttons for example)."),
- 20, NULL, NULL);
-
- return this;
-}
-
-/*
- * exported plugin catalog entry
- */
-
-const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
-#if INPUT_PLUGIN_IFACE_VERSION <= 17
- { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "BLURAY", XINE_VERSION_CODE, NULL, bluray_init_plugin },
- { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "BD", XINE_VERSION_CODE, NULL, bluray_init_plugin },
-#elif INPUT_PLUGIN_IFACE_VERSION >= 18
- { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 18, "BLURAY", XINE_VERSION_CODE, NULL, bluray_init_plugin },
- { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 18, "BD", XINE_VERSION_CODE, NULL, bluray_init_plugin },
-#endif
- { PLUGIN_NONE, 0, "", 0, NULL, NULL }
-};
diff --git a/xine/BluRay/patches/xine-lib-1.1.16.3-ffmpeg-vc1-extradata.diff b/xine/BluRay/patches/xine-lib-1.1.16.3-ffmpeg-vc1-extradata.diff
deleted file mode 100644
index c37c7e2..0000000
--- a/xine/BluRay/patches/xine-lib-1.1.16.3-ffmpeg-vc1-extradata.diff
+++ /dev/null
@@ -1,62 +0,0 @@
---- src/combined/ffmpeg/ff_video_decoder.c 2009-04-16 14:24:20.000000000 +0300
-+++ src/combined/ffmpeg/ff_video_decoder.c 2009-09-24 15:21:25.000000000 +0300
-@@ -1165,6 +1181,49 @@
- }
- }
-
-+static int ff_vc1_find_header(ff_video_decoder_t *this, buf_element_t *buf)
-+{
-+ uint8_t *p = buf->content;
-+
-+ if (!p[0] && !p[1] && p[2] == 1 && p[3] == 0x0f) {
-+ int i;
-+
-+ this->context->extradata = calloc(1, buf->size);
-+ this->context->extradata_size = 0;
-+
-+ for (i = 0; i < buf->size && i < 128; i++) {
-+ if (!p[i] && !p[i+1] && p[i+2]) {
-+ lprintf("00 00 01 %02x at %d\n", p[i+3], i);
-+ if (p[i+3] != 0x0e && p[i+3] != 0x0f)
-+ break;
-+ }
-+ this->context->extradata[i] = p[i];
-+ this->context->extradata_size++;
-+ }
-+
-+ lprintf("ff_video_decoder: found VC1 sequence header\n");
-+ return 1;
-+ }
-+
-+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
-+ "ffmpeg_video_dec: VC1 extradata missing !\n");
-+ return 0;
-+}
-+
-+static int ff_check_extradata(ff_video_decoder_t *this, unsigned int codec_type, buf_element_t *buf)
-+{
-+ if (this->context && this->context->extradata)
-+ return 1;
-+
-+ switch (codec_type) {
-+ case BUF_VIDEO_VC1:
-+ return ff_vc1_find_header(this, buf);
-+ default:;
-+ }
-+
-+ return 1;
-+}
-+
- #endif /* AVCODEC_HAS_REORDERED_OPAQUE */
- static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
- uint8_t *chunk_buf = this->buf;
-@@ -1176,6 +1235,9 @@
- if (this->decoder_init_mode) {
- int codec_type = buf->type & 0xFFFF0000;
-
-+ if (!ff_check_extradata(this, codec_type, buf))
-+ return;
-+
- /* init ffmpeg decoder */
- init_video_codec(this, codec_type);
- init_postprocess(this);
diff --git a/xine/BluRay/patches/xine-lib-1.1.16.3-ffmpeg-vc1-reopen.diff b/xine/BluRay/patches/xine-lib-1.1.16.3-ffmpeg-vc1-reopen.diff
deleted file mode 100644
index 745931b..0000000
--- a/xine/BluRay/patches/xine-lib-1.1.16.3-ffmpeg-vc1-reopen.diff
+++ /dev/null
@@ -1,25 +0,0 @@
---- src/combined/ffmpeg/ff_video_decoder.c 2009-04-16 14:24:20.000000000 +0300
-+++ src/combined/ffmpeg/ff_video_decoder.c 2009-09-24 15:21:25.000000000 +0300
-@@ -340,6 +340,22 @@
- return;
- }
-
-+ if (this->codec->id == CODEC_ID_VC1 &&
-+ (!this->bih.biWidth || !this->bih.biHeight)) {
-+ /* VC1 codec must be re-opened with correct width and height. */
-+ avcodec_close(this->context);
-+
-+ if (avcodec_open (this->context, this->codec) < 0) {
-+ pthread_mutex_unlock(&ffmpeg_lock);
-+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
-+ _("ffmpeg_video_dec: couldn't open decoder (pass 2)\n"));
-+ free(this->context);
-+ this->context = NULL;
-+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
-+ return;
-+ }
-+ }
-+
- if (this->class->thread_count > 1) {
- avcodec_thread_init(this->context, this->class->thread_count);
- this->context->thread_count = this->class->thread_count;
diff --git a/xine/BluRay/xine_lpcm_decoder.c b/xine/BluRay/xine_lpcm_decoder.c
deleted file mode 100644
index 719963f..0000000
--- a/xine/BluRay/xine_lpcm_decoder.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2000-2003 the xine project
- *
- * 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
- *
- * 31-8-2001 Added LPCM rate sensing.
- * (c) 2001 James Courtier-Dutton James at superbug.demon.co.uk
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef __sun
-#define _XOPEN_SOURCE 500
-#endif
-/* avoid compiler warnings */
-#define _BSD_SOURCE 1
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <netinet/in.h> /* ntohs */
-
-#ifdef HAVE_CONFIG_H
-#include "xine_internal.h"
-#include "audio_out.h"
-#include "buffer.h"
-#else
-#include <xine/xine_internal.h>
-#include <xine/audio_out.h>
-#include <xine/buffer.h>
-#endif
-
-#ifdef WIN32
-#include <winsock.h>
-/*#include <Winsock2.h>*/ /* htons */
-#endif
-
-#ifndef EXPORTED
-# define EXPORTED __attribute__((visibility("default")))
-#endif
-
-typedef struct {
- audio_decoder_class_t decoder_class;
-} lpcm_class_t;
-
-typedef struct lpcm_decoder_s {
- audio_decoder_t audio_decoder;
-
- xine_stream_t *stream;
-
- uint32_t rate;
- uint32_t bits_per_sample;
- uint32_t number_of_channels;
- uint32_t ao_cap_mode;
-
- int output_open;
- int cpu_be; /* TRUE, if we're a Big endian CPU */
-
- int64_t pts;
-
- uint8_t *buf;
- size_t buffered_bytes;
- size_t buf_size;
-
-} lpcm_decoder_t;
-
-static void lpcm_reset (audio_decoder_t *this_gen) {
-
- lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen;
-
- free (this->buf);
- this->buf = NULL;
-}
-
-static void lpcm_discontinuity (audio_decoder_t *this_gen) {
-
- lpcm_reset(this_gen);
-}
-
-static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
-
- lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen;
- int16_t *sample_buffer=(int16_t *)buf->content;
- int buf_size = buf->size;
- int stream_be;
- audio_buffer_t *audio_buffer;
- int format_changed = 0;
- int special_dvd_audio = 0;
-
- /* Drop preview data */
- if (buf->decoder_flags & BUF_FLAG_PREVIEW)
- return;
-
- /* get config byte from mpeg2 stream */
- if ( (buf->decoder_flags & BUF_FLAG_SPECIAL) &&
- buf->decoder_info[1] == BUF_SPECIAL_LPCM_CONFIG ) {
- unsigned int bits_per_sample = 16;
- unsigned int sample_rate = 0;
- unsigned int num_channels;
-
- lprintf("lpcm_decoder: config data 0x%x\n", buf->decoder_info[2]);
-
- /* BluRay PCM header is 4 bytes */
- if (buf->decoder_info[2] & 0xffffff00) {
- static const uint8_t channels[16] = {0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0};
-
- num_channels = channels[(buf->decoder_info[2] >> (16+4)) & 0x0f];
- switch ((buf->decoder_info[2] >> (24+6)) & 0x03) {
- case 1: bits_per_sample = 16; break;
- case 2: /*bits_per_sample = 20; break;*/
- /* 20 bits = padded to 24 bits with four zero bits */
- case 3: bits_per_sample = 24; break;
- default: bits_per_sample = 0; break;
- }
- switch ((buf->decoder_info[2] >> 16) & 0x0f) {
- case 1: sample_rate = 48000; break;
- case 4: sample_rate = 96000; break;
- case 5: sample_rate = 192000; break;
- default: sample_rate = 0; break;
- }
-
- if (!num_channels || !sample_rate || !bits_per_sample)
- xine_log (this->stream->xine, XINE_LOG_MSG,
- "lpcm_decoder: unsupported BluRay PCM format: 0x%08x\n", buf->decoder_info[2]);
-
- if (this->buffered_bytes)
- xine_log (this->stream->xine, XINE_LOG_MSG, "lpcm_decoder: %zd bytes lost !\n", this->buffered_bytes);
-
- if (!this->buf) {
- this->buffered_bytes = 0;
- this->buf_size = 8128;
- this->buf = malloc(this->buf_size);
- }
-
- } else {
-
- /* MPEG2/DVD PCM header is one byte */
- num_channels = (buf->decoder_info[2] & 0x7) + 1;
- switch ((buf->decoder_info[2]>>4) & 3) {
- case 0: sample_rate = 48000; break;
- case 1: sample_rate = 96000; break;
- case 2: sample_rate = 44100; break;
- case 3: sample_rate = 32000; break;
- }
- switch ((buf->decoder_info[2]>>6) & 3) {
- case 0: bits_per_sample = 16; break;
- case 1: bits_per_sample = 20; break;
- case 2: bits_per_sample = 24; special_dvd_audio = 1; break;
- }
- }
-
- if( this->bits_per_sample != bits_per_sample ||
- this->number_of_channels != num_channels ||
- this->rate != sample_rate ||
- !this->output_open ) {
- this->bits_per_sample = bits_per_sample;
- this->number_of_channels = num_channels;
- this->rate = sample_rate;
- format_changed++;
-
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "lpcm_decoder: format changed to %d channels, %d bits per sample, %d Hz, %d kbit/s\n",
- num_channels, bits_per_sample, sample_rate, (num_channels * sample_rate * bits_per_sample)/1024);
- }
- }
-
- if( buf->decoder_flags & BUF_FLAG_STDHEADER ) {
- this->rate=buf->decoder_info[1];
- this->bits_per_sample=buf->decoder_info[2];
- this->number_of_channels=buf->decoder_info[3];
- format_changed++;
- }
-
- /*
- * (re-)open output device
- */
- if ( format_changed ) {
- if (this->output_open)
- this->stream->audio_out->close (this->stream->audio_out, this->stream);
-
- this->ao_cap_mode=_x_ao_channels2mode(this->number_of_channels);
-
- /* force 24-bit samples into 16 bits for now */
- if (this->bits_per_sample == 24)
- this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream,
- 16,
- this->rate,
- this->ao_cap_mode) ;
- else
- this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream,
- this->bits_per_sample,
- this->rate,
- this->ao_cap_mode) ;
-
- /* stream/meta info */
- _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Linear PCM");
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE,
- this->bits_per_sample * this->rate * this->number_of_channels);
- }
-
- if (!this->output_open || (buf->decoder_flags & BUF_FLAG_HEADER) )
- return;
-
- if (buf->pts && !this->pts)
- this->pts = buf->pts;
-
- /* data accumulation */
- if (this->buf) {
- int frame_end = buf->decoder_flags & BUF_FLAG_FRAME_END;
- if (this->buffered_bytes || !frame_end) {
- if (this->buf_size < this->buffered_bytes + buf->size) {
- this->buf_size *= 2;
- this->buf = realloc(this->buf, this->buf_size);
- }
-
- memcpy(this->buf + this->buffered_bytes, buf->content, buf->size);
- this->buffered_bytes += buf->size;
-
- if (!frame_end)
- return;
-
- sample_buffer = (int16_t*)this->buf;
- buf_size = this->buffered_bytes;
- this->buffered_bytes = 0;
- }
- }
-
- audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out);
-
- /* Swap LPCM samples into native byte order, if necessary */
- buf->type &= 0xffff0000;
- stream_be = ( buf->type == BUF_AUDIO_LPCM_BE );
-
- if( this->bits_per_sample == 16 ){
- if (stream_be != this->cpu_be)
- swab (sample_buffer, audio_buffer->mem, buf_size);
- else
- memcpy (audio_buffer->mem, sample_buffer, buf_size);
- }
- else if( this->bits_per_sample == 20 ) {
- uint8_t *s = (uint8_t *)sample_buffer;
- uint8_t *d = (uint8_t *)audio_buffer->mem;
- int n = buf_size;
-
- if (stream_be != this->cpu_be) {
- while( n >= 0 ) {
- swab( s, d, 8 );
- s += 10;
- d += 8;
- n -= 10;
- }
- } else {
- while( n >= 0 ) {
- memcpy( d, s, 8 );
- s += 10;
- d += 8;
- n -= 10;
- }
- }
- } else if( this->bits_per_sample == 24 ) {
- uint8_t *s = (uint8_t *)sample_buffer;
- uint8_t *d = (uint8_t *)audio_buffer->mem;
- int n = buf_size;
-
- if ( stream_be ) {
- if (special_dvd_audio)
- while (n >= 12) {
- if ( stream_be == this->cpu_be ) {
- *d++ = s[0];
- *d++ = s[1];
- *d++ = s[2];
- *d++ = s[3];
- *d++ = s[4];
- *d++ = s[5];
- *d++ = s[6];
- *d++ = s[7];
- } else {
- *d++ = s[1];
- *d++ = s[0];
- *d++ = s[3];
- *d++ = s[2];
- *d++ = s[5];
- *d++ = s[4];
- *d++ = s[7];
- *d++ = s[6];
- }
- s += 12;
- n -= 12;
- }
- else
- while (n >= 3) {
- if ( stream_be == this->cpu_be ) {
- *d++ = s[0];
- *d++ = s[1];
- } else {
- *d++ = s[1];
- *d++ = s[0];
- }
- s += 3;
- n -= 3;
- }
- } else {
- while (n >= 3) {
- if ( stream_be == this->cpu_be ) {
- *d++ = s[1];
- *d++ = s[2];
- } else {
- *d++ = s[2];
- *d++ = s[1];
- }
- s += 3;
- n -= 3;
- }
- }
-
- if ( (d - (uint8_t*)audio_buffer->mem)/2*3 < buf_size )
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "lpcm_decoder: lost %i bytes of %i in the buffer\n", (int)(buf_size - (d - (uint8_t*)audio_buffer->mem)/2*3), buf_size);
-
- } else {
- memcpy (audio_buffer->mem, sample_buffer, buf_size);
- }
-
- audio_buffer->vpts = this->pts;
- audio_buffer->num_frames = (((buf_size*8)/this->number_of_channels)/this->bits_per_sample);
-
- this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream);
-
- this->pts = 0;
-}
-
-static void lpcm_dispose (audio_decoder_t *this_gen) {
- lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen;
-
- if (this->output_open)
- this->stream->audio_out->close (this->stream->audio_out, this->stream);
- this->output_open = 0;
-
- free (this->buf);
-
- free (this_gen);
-}
-
-static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) {
-
- lpcm_decoder_t *this ;
-
- this = (lpcm_decoder_t *) calloc(1, sizeof(lpcm_decoder_t));
-
- this->audio_decoder.decode_data = lpcm_decode_data;
- this->audio_decoder.reset = lpcm_reset;
- this->audio_decoder.discontinuity = lpcm_discontinuity;
- this->audio_decoder.dispose = lpcm_dispose;
-
- this->output_open = 0;
- this->rate = 0;
- this->bits_per_sample=0;
- this->number_of_channels=0;
- this->ao_cap_mode=0;
- this->stream = stream;
-
- this->cpu_be = ( htons(1) == 1 );
-
- return &this->audio_decoder;
-}
-
-static char *get_identifier (audio_decoder_class_t *this) {
- return "Linear PCM (BluRay)";
-}
-
-static char *get_description (audio_decoder_class_t *this) {
- return "Linear PCM audio decoder plugin (BluRay)";
-}
-
-static void dispose_class (audio_decoder_class_t *this) {
- free (this);
-}
-
-static void *init_plugin (xine_t *xine, void *data) {
-
- lpcm_class_t *this ;
-
- this = (lpcm_class_t *) calloc(1, sizeof(lpcm_class_t));
-
- this->decoder_class.open_plugin = open_plugin;
- this->decoder_class.get_identifier = get_identifier;
- this->decoder_class.get_description = get_description;
- this->decoder_class.dispose = dispose_class;
-
- return this;
-}
-
-static uint32_t audio_types[] = {
- BUF_AUDIO_LPCM_BE, BUF_AUDIO_LPCM_LE, 0
-};
-
-static const decoder_info_t dec_info_audio = {
- audio_types, /* supported types */
- 10 /* priority */
-};
-
-const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
- { PLUGIN_AUDIO_DECODER, 15, "pcm_bluray", XINE_VERSION_CODE, &dec_info_audio, init_plugin },
- { PLUGIN_NONE, 0, "", 0, NULL, NULL }
-};
diff --git a/xine/vo_osdscaler.c b/xine/vo_osdscaler.c
index 61ea038..a9f5506 100644
--- a/xine/vo_osdscaler.c
+++ b/xine/vo_osdscaler.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: vo_osdscaler.c,v 1.14 2013/01/16 13:25:44 phintuka Exp $
+ * $Id: vo_osdscaler.c,v 1.15 2013/08/19 08:20:30 phintuka Exp $
*
*/
@@ -147,6 +147,18 @@ static osd_data_t *osd_data_init(vo_overlay_t *ovl, osd_data_t *next,
data->ovl.width = x2 - data->ovl.x - 1;
data->ovl.height = y2 - data->ovl.y - 1;
+#ifdef VO_CAP_VIDEO_WINDOW_OVERLAY
+ if (ovl->video_window_x >= 0 &&
+ ovl->video_window_y >= 0 &&
+ ovl->video_window_width > 0 &&
+ ovl->video_window_height > 0) {
+ data->ovl.video_window_x = (ovl->video_window_x * factor_x) >> 16;
+ data->ovl.video_window_y = (ovl->video_window_y * factor_y) >> 16;
+ data->ovl.video_window_width = (ovl->video_window_width * factor_x) >> 16;
+ data->ovl.video_window_height = (ovl->video_window_height * factor_y) >> 16;
+ }
+#endif
+
data->ovl.rle = (rle_elem_t*)
rle_scale_nearest((struct xine_rle_elem_s*)ovl->rle, &num_rle,
ovl->width, ovl->height,
diff --git a/xine_fbfe_frontend.c b/xine_fbfe_frontend.c
index 094b2ac..8cc4ea5 100644
--- a/xine_fbfe_frontend.c
+++ b/xine_fbfe_frontend.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: xine_fbfe_frontend.c,v 1.50 2012/03/19 11:51:22 phintuka Exp $
+ * $Id: xine_fbfe_frontend.c,v 1.51 2013/08/18 07:58:29 phintuka Exp $
*
*/
@@ -120,7 +120,7 @@ static int fbfe_display_open(frontend_t *this_gen,
int xpos, int ypos,
int width, int height, int fullscreen, int hud, int opengl,
int modeswitch, const char *modeline, int aspect,
- int no_x_kbd, int gui_hotkeys,
+ int no_x_kbd, int gui_hotkeys, int touchscreen,
const char *video_port, int scale_video,
const char *aspect_controller, int window_id)
{
diff --git a/xine_frontend.h b/xine_frontend.h
index f10290e..23a5beb 100644
--- a/xine_frontend.h
+++ b/xine_frontend.h
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: xine_frontend.h,v 1.29 2012/03/19 11:53:04 phintuka Exp $
+ * $Id: xine_frontend.h,v 1.30 2013/08/19 08:50:19 phintuka Exp $
*
*/
@@ -79,7 +79,7 @@ struct frontend_s {
int fullscreen, int hud, int opengl,
int modeswitch, const char *modeline,
int aspect,
- int no_x_kbd, int gui_hotkeys,
+ int no_x_kbd, int gui_hotkeys, int touchscreen,
const char *video_port,
int scale_video,
const char *aspect_controller, int window_id);
diff --git a/xine_frontend_main.c b/xine_frontend_main.c
index 1d8ac91..543c139 100644
--- a/xine_frontend_main.c
+++ b/xine_frontend_main.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: xine_frontend_main.c,v 1.103 2012/03/19 11:51:21 phintuka Exp $
+ * $Id: xine_frontend_main.c,v 1.104 2013/08/18 07:58:29 phintuka Exp $
*
*/
@@ -152,6 +152,7 @@ static const char help_str[] =
" -x, --noxkbd Disable X11 keyboard input\n"
#endif
" -o, --hotkeys Enable frontend GUI hotkeys\n"
+ " -U, --touch Enable touch screen remote controller\n"
" -p, --shutdown=MIN[:CMD] Shutdown after MIN minutes of inactivity\n"
" Use CMD to perform shutdown (default: /sbin/shutdown)\n"
" -T, --terminal=dev Controlling TTY\n"
@@ -166,7 +167,7 @@ static const char help_str[] =
" are tried in following order:\n"
" local pipe, rtp, udp, tcp\n\n";
-static const char short_options[] = "HA:V:d:W:a:fg:Dw:h:B:nP:L:C:T:p:vsxlkobSRtur";
+static const char short_options[] = "HA:V:d:W:a:fg:Dw:h:B:nP:L:C:T:p:vsxlkoObSRtuUr";
static const struct option long_options[] = {
{ "help", no_argument, NULL, 'H' },
@@ -204,6 +205,7 @@ static const struct option long_options[] = {
{ "nokbd", no_argument, NULL, 'k' },
{ "noxkbd", no_argument, NULL, 'x' },
{ "hotkeys", no_argument, NULL, 'o' },
+ { "touch", no_argument, NULL, 'U' },
{ "daemon", no_argument, NULL, 'b' },
{ "slave", no_argument, NULL, 'S' },
@@ -225,6 +227,7 @@ int main(int argc, char *argv[])
int scale_video = 1, aspect = 1, modeswitch = 0;
int daemon_mode = 0, nokbd = 0, noxkbd = 0, slave_mode = 0;
int repeat_emu = 0;
+ int touchscreen = 0;
int window_id = WINDOW_ID_NONE;
int xmajor, xminor, xsub;
int c;
@@ -434,6 +437,13 @@ int main(int argc, char *argv[])
" LIRC PowerOff -> power off\n"
" LIRC Quit -> exit\n");
break;
+ case 'U': touchscreen = 1;
+ PRINTF("Touchscreen input enabled\n");
+ PRINTF("Display is divided to 4x3 buttons:\n");
+ PRINTF(" Menu Up Back Ok \n");
+ PRINTF(" Left Down Right \n");
+ PRINTF(" Red Green Yellow Blue\n");
+ break;
case 'b': nokbd = daemon_mode = 1;
PRINTF("Keyboard input disabled\n");
break;
@@ -550,7 +560,7 @@ int main(int argc, char *argv[])
/* Initialize display */
if (!fe->fe_display_open(fe, xpos, ypos, width, height, fullscreen, hud, opengl, modeswitch,
- "", aspect, noxkbd, gui_hotkeys,
+ "", aspect, noxkbd, gui_hotkeys, touchscreen,
video_port, scale_video,
aspect_controller, window_id)) {
fprintf(stderr, "Error opening display\n");
diff --git a/xine_sxfe_frontend.c b/xine_sxfe_frontend.c
index 4f536bb..e525387 100644
--- a/xine_sxfe_frontend.c
+++ b/xine_sxfe_frontend.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: xine_sxfe_frontend.c,v 1.204 2012/03/19 11:51:21 phintuka Exp $
+ * $Id: xine_sxfe_frontend.c,v 1.205 2013/08/18 07:58:29 phintuka Exp $
*
*/
@@ -121,6 +121,9 @@ typedef struct sxfe_s {
#endif
Time prev_click_time; /* time of previous mouse button click (grab double clicks) */
int mousecursor_timeout;
+#ifdef HAVE_MCE_DBUS_NAMES
+ int mce_blank_prevent_timer;
+#endif
#ifdef HAVE_XDPMS
BOOL dpms_state;
#endif
@@ -159,6 +162,7 @@ typedef struct sxfe_s {
uint8_t dragging : 1;
uint8_t gui_hotkeys : 1;
uint8_t no_x_kbd : 1;
+ uint8_t touchscreen : 1;
/* OSD Video Window */
pthread_mutex_t video_win_mutex;
@@ -2238,7 +2242,7 @@ static int sxfe_display_open(frontend_t *this_gen,
int xpos, int ypos,
int width, int height, int fullscreen, int hud, int opengl,
int modeswitch, const char *modeline, int aspect,
- int no_x_kbd, int gui_hotkeys,
+ int no_x_kbd, int gui_hotkeys, int touchscreen,
const char *video_port, int scale_video,
const char *aspect_controller, int window_id)
{
@@ -2321,8 +2325,9 @@ static int sxfe_display_open(frontend_t *this_gen,
this->xinerama_screen = -1;
- this->gui_hotkeys = gui_hotkeys;
- this->no_x_kbd = no_x_kbd ? 1 : 0;
+ this->gui_hotkeys = !!gui_hotkeys;
+ this->no_x_kbd = !!no_x_kbd;
+ this->touchscreen = !!touchscreen;
/*
* init x11 stuff
@@ -2787,6 +2792,22 @@ static void XButtonEvent_handler(sxfe_t *this, XButtonEvent *bev)
{
switch(bev->button) {
case Button1:
+
+ if (this->touchscreen) {
+ int x = bev->x * 4 / this->x.width;
+ int y = bev->y * 3 / this->x.height;
+ static const char * const map[3][4] = {
+ {"Menu", "Up", "Back", "Ok"},
+ {"Left", "Down", "Right", "Ok"},
+ {"Red", "Green", "Yellow", "Blue"}};
+ if (map[y][x]) {
+ char tmp[128];
+ sprintf(tmp, "KEY %s", map[y][x]);
+ this->x.fe.send_event((frontend_t*)this, tmp);
+ }
+ return;
+ }
+
/* Double-click toggles between fullscreen and windowed mode */
if(bev->time - this->prev_click_time < DOUBLECLICK_TIME) {
/* Toggle fullscreen */
@@ -2861,6 +2882,16 @@ static int sxfe_run(frontend_t *this_gen)
poll_time = time_ms();
}
+#ifdef HAVE_MCE_DBUS_NAMES
+# ifdef HAVE_DBUS_GLIB_1
+ /* Disable MCE screensaver */
+ if (++this->mce_blank_prevent_timer > 100) {
+ gnome_screensaver_control(0);
+ this->mce_blank_prevent_timer = 0;
+ }
+# endif
+#endif
+
if (poll(&pfd, 1, poll_timeout) < 1 || !(pfd.revents & POLLIN)) {
if (this->mousecursor_timeout > 0) {
diff --git a/xineliboutput.c b/xineliboutput.c
index 4d15dd0..c285e42 100644
--- a/xineliboutput.c
+++ b/xineliboutput.c
@@ -21,7 +21,7 @@
*
* xineliboutput.c: VDR Plugin interface
*
- * $Id: xineliboutput.c,v 1.56 2012/06/13 07:32:24 phintuka Exp $
+ * $Id: xineliboutput.c,v 1.58 2013/08/20 09:09:33 phintuka Exp $
*
*/
@@ -43,7 +43,7 @@
//---------------------------------plugin-------------------------------------
-static const char *VERSION = "1.0.90-cvs";
+static const char *VERSION = "1.1.0";
static const char *DESCRIPTION = trNOOP("X11/xine-lib output plugin");
static const char *MAINMENUENTRY = trNOOP("Media Player");
@@ -93,7 +93,10 @@ cPluginXinelibOutput::cPluginXinelibOutput(void)
cPluginXinelibOutput::~cPluginXinelibOutput()
{
// Clean up after yourself!
- cXinelibDevice::Dispose();
+
+ if (m_Dev) {
+ cXinelibDevice::Dispose();
+ }
}
@@ -115,9 +118,9 @@ const char cmdLineHelp[] =
" Supported values:\n"
" for sxfe: auto, x11, xshm, xv, xvmc, xxmc,\n"
#ifdef HAVE_VDPAU
- "vdpau, "
+" vdpau, "
#endif
-" vidix, sdl, opengl, none\n"
+" vaapi, vidix, sdl, opengl, none\n"
" for fbfe: auto, fb, DirectFB, vidixfb,\n"
" sdl, dxr3, aadxr3, none\n"
#if 0
@@ -144,6 +147,9 @@ const char cmdLineHelp[] =
" (or framebuffer device name)\n"
" -W ID --wid=ID Use existing X11 window\n"
" Special ID for root window: --wid=root\n"
+#ifdef HAVE_XRANDR
+" -m --modeswitch Enable video mode switching\n"
+#endif
" -P NAME --post=NAME Use xine post plugin NAME\n"
" format: pluginname[:arg=val[,arg=val]][,...]\n"
" example: \n"
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-xineliboutput.git
More information about the pkg-vdr-dvb-changes
mailing list