summaryrefslogtreecommitdiff
path: root/xine_input_vdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'xine_input_vdr.c')
-rw-r--r--xine_input_vdr.c190
1 files changed, 127 insertions, 63 deletions
diff --git a/xine_input_vdr.c b/xine_input_vdr.c
index 43015253..bdb0cbc6 100644
--- a/xine_input_vdr.c
+++ b/xine_input_vdr.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: xine_input_vdr.c,v 1.138 2008-05-06 23:14:19 phintuka Exp $
+ * $Id: xine_input_vdr.c,v 1.138.2.11 2008-10-04 06:51:35 phintuka Exp $
*
*/
@@ -48,6 +48,13 @@
#include <xine/buffer.h>
#include <xine/post.h>
+#if XINE_VERSION_CODE >= 10190
+# include <libavutil/mem.h>
+#endif
+#ifndef XINE_VERSION_CODE
+# error XINE_VERSION_CODE undefined !
+#endif
+
#include "xine_input_vdr.h"
#include "xine_input_vdr_net.h"
#include "xine_osd_command.h"
@@ -247,6 +254,7 @@ typedef struct vdr_input_plugin_s {
int send_pts;
int padding_cnt;
int loop_play;
+ int dvd_menu;
int hd_stream; /* true if current stream is HD */
int h264; /* -1: unknown, 0: no, 1: yes */
@@ -356,7 +364,7 @@ struct udp_data_s {
static udp_data_t *init_udp_data(void)
{
- udp_data_t *data = (udp_data_t *)xine_xmalloc(sizeof(udp_data_t));
+ udp_data_t *data = calloc(1, sizeof(udp_data_t));
data->received_frames = -1;
@@ -1248,6 +1256,8 @@ static void queue_nosignal(vdr_input_plugin_t *this)
buf->type = BUF_VIDEO_MPEG;
xine_fast_memcpy(buf->content, &data[pos], buf->size);
pos += buf->size;
+ if(pos >= datalen)
+ buf->decoder_flags |= BUF_FLAG_FRAME_END;
this->stream->video_fifo->put(this->stream->video_fifo, buf);
} else {
LOGMSG("Error: queue_nosignal: no buffers !");
@@ -1255,6 +1265,20 @@ static void queue_nosignal(vdr_input_plugin_t *this)
}
}
+ /* sequence end */
+ buf = this->stream->video_fifo->buffer_pool_try_alloc(this->stream->video_fifo);
+ if (buf) {
+ static const uint8_t seq_end[] = {0x00, 0x00, 0x01, 0xb7}; /* mpeg2 */
+ buf->type = BUF_VIDEO_MPEG;
+ buf->size = sizeof(seq_end);
+ buf->decoder_flags = BUF_FLAG_FRAME_END;
+ memcpy(buf->content, seq_end, sizeof(seq_end));
+ this->stream->video_fifo->put(this->stream->video_fifo, buf);
+
+ /*put_control_buf(this->stream->video_fifo, this->stream->video_fifo, BUF_CONTROL_FLUSH_DECODER);*/
+ /*put_control_buf(this->stream->video_fifo, this->stream->video_fifo, BUF_CONTROL_NOP);*/
+ }
+
free(tmp);
}
@@ -1400,11 +1424,10 @@ static fifo_buffer_t *fifo_buffer_new (xine_stream_t *stream, int num_buffers, u
fifo_buffer_t *ref = stream->video_fifo;
fifo_buffer_t *this;
int i;
- int alignment = 2048;
- unsigned char *multi_buffer = NULL;
+ unsigned char *multi_buffer;
LOGDBG("fifo_buffer_new...");
- this = xine_xmalloc (sizeof (fifo_buffer_t));
+ this = calloc(1, sizeof (fifo_buffer_t));
this->first = NULL;
this->last = NULL;
@@ -1430,13 +1453,7 @@ static fifo_buffer_t *fifo_buffer_new (xine_stream_t *stream, int num_buffers, u
* init buffer pool, allocate nNumBuffers of buf_size bytes each
*/
- if (buf_size % alignment != 0)
- buf_size += alignment - (buf_size % alignment);
-
- multi_buffer = xine_xmalloc_aligned (alignment, num_buffers * buf_size,
- &this->buffer_pool_base);
-
- this->buffer_pool_top = NULL;
+ multi_buffer = this->buffer_pool_base = av_mallocz (num_buffers * buf_size);
pthread_mutex_init (&this->buffer_pool_mutex, NULL);
pthread_cond_init (&this->buffer_pool_cond_not_empty, NULL);
@@ -1450,7 +1467,7 @@ static fifo_buffer_t *fifo_buffer_new (xine_stream_t *stream, int num_buffers, u
for (i = 0; i<num_buffers; i++) {
buf_element_t *buf;
- buf = xine_xmalloc (sizeof (buf_element_t));
+ buf = calloc(1, sizeof (buf_element_t));
buf->mem = multi_buffer;
multi_buffer += buf_size;
@@ -1479,22 +1496,8 @@ static buf_element_t *get_buf_element(vdr_input_plugin_t *this, int size, int fo
buf_element_t *buf = NULL;
/* HD buffer */
- if(this->hd_stream) {
- if(!this->hd_buffer)
- this->hd_buffer = fifo_buffer_new(this->stream, HD_BUF_NUM_BUFS, HD_BUF_ELEM_SIZE);
-
- if(size <= HD_BUF_ELEM_SIZE && this->hd_buffer && this->hd_stream)
- buf = this->hd_buffer->buffer_pool_try_alloc(this->hd_buffer);
- } else {
- if(this->hd_buffer) {
- LOGMSG("hd_buffer still exists ...");
- if(this->hd_buffer->num_free(this->hd_buffer) == this->hd_buffer->buffer_pool_capacity) {
- LOGMSG("disposing hd_buffer ...");
- this->hd_buffer->dispose(this->hd_buffer);
- this->hd_buffer = NULL;
- }
- }
- }
+ if(this->hd_stream && size <= HD_BUF_ELEM_SIZE)
+ buf = this->hd_buffer->buffer_pool_try_alloc(this->hd_buffer);
/* limit max. buffered data */
if(!force && !buf) {
@@ -1724,7 +1727,7 @@ static input_plugin_t *fifo_class_get_instance (input_class_t *class_gen,
xine_stream_t *stream,
const char *data)
{
- fifo_input_plugin_t *slave = (fifo_input_plugin_t *) xine_xmalloc (sizeof(fifo_input_plugin_t));
+ fifo_input_plugin_t *slave = calloc(1, sizeof(fifo_input_plugin_t));
unsigned long int imaster;
vdr_input_plugin_t *master;
LOGDBG("fifo_class_get_instance");
@@ -1978,6 +1981,7 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
video_overlay_event_t ov_event;
vo_overlay_t ov_overlay;
video_overlay_manager_t *ovl_manager;
+ xine_stream_t *stream = this->slave_stream ?: this->stream;
int handle = -1, i;
/* Caller must have locked this->osd_lock ! */
@@ -1986,7 +1990,7 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
/* Check parameters */
- if(!cmd || !this || !this->stream) {
+ if(!cmd || !this || !stream) {
LOGMSG("exec_osd_command: Stream not initialized !");
return CONTROL_DISCONNECTED;
}
@@ -2005,7 +2009,7 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
/* we already have port ticket */
ovl_manager =
- this->stream->video_out->get_overlay_manager(this->stream->video_out);
+ stream->video_out->get_overlay_manager(stream->video_out);
if(!ovl_manager) {
LOGMSG("exec_osd_command: Stream has no overlay manager !");
@@ -2016,11 +2020,10 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
/* calculate exec time */
if(cmd->pts || cmd->delay_ms) {
- int64_t vpts = xine_get_current_vpts(this->stream);
+ int64_t vpts = xine_get_current_vpts(stream);
if(cmd->pts) {
ov_event.vpts = cmd->pts +
- this->stream->metronom->get_option(this->stream->metronom,
- METRONOM_VPTS_OFFSET);
+ stream->metronom->get_option(stream->metronom, METRONOM_VPTS_OFFSET);
} else {
if(this->last_changed_vpts[cmd->wnd])
ov_event.vpts = this->last_changed_vpts[cmd->wnd] + cmd->delay_ms*90;
@@ -2040,7 +2043,7 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
this->vdr_osd_height = cmd->h;
} else if(cmd->cmd == OSD_Nop) {
- this->last_changed_vpts[cmd->wnd] = xine_get_current_vpts(this->stream);
+ this->last_changed_vpts[cmd->wnd] = xine_get_current_vpts(stream);
} else if(cmd->cmd == OSD_SetPalette) {
/* TODO */
@@ -2082,6 +2085,8 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
int xmove = 0, ymove = 0;
int unscaled_supported = 1;
+ stream->video_out->enable_ovl(stream->video_out, 1);
+
if(handle < 0)
handle = this->osdhandle[cmd->wnd] =
ovl_manager->get_handle(ovl_manager,0);
@@ -2111,7 +2116,7 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
ov_event.object.overlay->trans[i] = (cmd->palette[i].alpha + 0x7)/0xf;
}
- if(!(this->stream->video_out->get_capabilities(this->stream->video_out) &
+ if(!(stream->video_out->get_capabilities(stream->video_out) &
VO_CAP_UNSCALED_OVERLAY))
unscaled_supported = 0;
else if(cmd->flags & OSDFLAG_UNSCALED)
@@ -2184,10 +2189,10 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
}
if(use_unscaled) {
- int win_width = this->stream->video_out->get_property(this->stream->video_out,
- VO_PROP_WINDOW_WIDTH);
- int win_height = this->stream->video_out->get_property(this->stream->video_out,
- VO_PROP_WINDOW_HEIGHT);
+ int win_width = stream->video_out->get_property(stream->video_out,
+ VO_PROP_WINDOW_WIDTH);
+ int win_height = stream->video_out->get_property(stream->video_out,
+ VO_PROP_WINDOW_HEIGHT);
if(cmd->scaling > 0) {
/* it is not nice to have subs in _middle_ of display when using 1440x900 etc... */
@@ -2250,7 +2255,7 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)
break;
} while(1);
- this->last_changed_vpts[cmd->wnd] = xine_get_current_vpts(this->stream);
+ this->last_changed_vpts[cmd->wnd] = xine_get_current_vpts(stream);
} else {
LOGMSG("Unknown OSD command %d", cmd->cmd);
@@ -2846,6 +2851,19 @@ static void select_spu_channel(xine_stream_t *stream, int channel)
}
}
+static void dvd_menu_domain(vdr_input_plugin_t *this, int value)
+{
+ if (value) {
+ LOGDBG("dvd_menu_domain(1)");
+ this->dvd_menu = 1;
+ this->slave_stream->spu_channel_user = SPU_CHANNEL_AUTO;
+ this->slave_stream->spu_channel = this->slave_stream->spu_channel_auto;
+ } else {
+ LOGDBG("dvd_menu_domain(0)");
+ this->dvd_menu = 0;
+ }
+}
+
static int handle_control_playfile(vdr_input_plugin_t *this, const char *cmd)
{
const char *pt = cmd + 9;
@@ -2954,6 +2972,7 @@ static int handle_control_playfile(vdr_input_plugin_t *this, const char *cmd)
vdr_event_cb, this);
}
select_spu_channel(this->slave_stream, SPU_CHANNEL_AUTO);
+ this->dvd_menu = 0;
errno = 0;
err = !xine_open(this->slave_stream, filename);
@@ -3520,7 +3539,7 @@ static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd)
if(!strcmp(cmd+6, eventmap[i].name)) {
xine_event_t ev;
ev.type = eventmap[i].type;
- ev.stream = this->slave_stream ? this->slave_stream : this->stream;
+ ev.stream = this->slave_stream ?: this->stream;
/* tag event to prevent circular input events
(vdr -> here -> event_listener -> vdr -> ...) */
ev.data = "VDR";
@@ -3545,7 +3564,13 @@ static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd)
} else if(!strncasecmp(cmd, "HDMODE ", 7)) {
if(1 == sscanf(cmd, "HDMODE %d", &tmp32)) {
pthread_mutex_lock(&this->lock);
- this->hd_stream = tmp32 ? 1 : 0;
+ if(tmp32) {
+ if(!this->hd_buffer)
+ this->hd_buffer = fifo_buffer_new(this->stream, HD_BUF_NUM_BUFS, HD_BUF_ELEM_SIZE);
+ this->hd_stream = 1;
+ } else {
+ this->hd_stream = 0;
+ }
pthread_mutex_unlock(&this->lock);
}
@@ -3709,16 +3734,34 @@ static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd)
int old_ch = _x_get_spu_channel (stream);
int max_ch = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
int ch = old_ch;
+ int ch_auto = strstr(cmd+10, "auto") ? 1 : 0;
+
if(strstr(cmd, "NEXT"))
ch = ch < max_ch ? ch+1 : -2;
else if(strstr(cmd, "PREV"))
ch = ch > -2 ? ch-1 : max_ch-1;
else if(1 == sscanf(cmd, "SPUSTREAM %d", &tmp32)) {
ch = tmp32;
+ } else if(cmd[10] && cmd[11] && (cmd[12] < 'a' || cmd[12] > 'z')) {
+ /* ISO 639-1 language code */
+ const char spu_lang[3] = {cmd[10], cmd[11], 0};
+ LOGMSG("Preferred SPU language: %s", spu_lang);
+ this->class->xine->config->update_string(this->class->xine->config,
+ "media.dvd.language", spu_lang);
+ ch = old_ch = 0;
} else
err = CONTROL_PARAM_ERROR;
- if(ch != old_ch) {
- select_spu_channel(stream, ch);
+
+ if (old_ch == SPU_CHANNEL_AUTO)
+ old_ch = stream->spu_channel_auto;
+
+ if (ch != old_ch) {
+ if (ch_auto && stream->spu_channel_user == SPU_CHANNEL_AUTO) {
+ LOGDBG("Automatic SPU channel %d->%d ignored", old_ch, ch);
+ } else {
+ LOGDBG("Forced SPU channel %d->%d", old_ch, ch);
+ select_spu_channel(stream, ch);
+ }
LOGDBG("SPU channel selected: [%d]", _x_get_spu_channel (stream));
}
@@ -3941,8 +3984,24 @@ static void *vdr_control_thread(void *this_gen)
static void slave_track_maps_changed(vdr_input_plugin_t *this)
{
char tracks[1024], lang[128];
- int i, current, n = 0, cnt;
-
+ int i, current, n = 0;
+ size_t cnt;
+
+ /* DVD title and menu domain detection */
+#ifdef XINE_STREAM_INFO_DVD_TITLE_NUMBER
+ i = _x_stream_info_get(this->slave_stream, XINE_STREAM_INFO_DVD_TITLE_NUMBER);
+ if(i >= 0) {
+ if (i == 0)
+ dvd_menu_domain(this, 1);
+ sprintf(tracks, "INFO DVDTITLE %d\r\n", i);
+ if(this->funcs.xine_input_event)
+ this->funcs.xine_input_event(tracks, NULL);
+ else
+ write_control(this, tracks);
+ LOGDBG(tracks);
+ }
+#endif
+
/* Audio tracks */
strcpy(tracks, "INFO TRACKMAP AUDIO ");
@@ -3980,6 +4039,8 @@ static void slave_track_maps_changed(vdr_input_plugin_t *this)
"*%d:%s ", current,
current==SPU_CHANNEL_NONE ? "none" : "auto");
n++;
+ if(current == SPU_CHANNEL_AUTO)
+ current = this->slave_stream->spu_channel_auto;
}
for(i=0; i<32 && cnt<sizeof(tracks)-32; i++)
if(xine_get_spu_lang(this->slave_stream, i, lang)) {
@@ -3998,18 +4059,6 @@ static void slave_track_maps_changed(vdr_input_plugin_t *this)
strcpy(tracks+cnt, "\r\n");
write_control(this, tracks);
}
-
-#ifdef XINE_STREAM_INFO_DVD_TITLE_NUMBER
- i = _x_stream_info_get(this->slave_stream,XINE_STREAM_INFO_DVD_TITLE_NUMBER);
- if(i >= 0) {
- sprintf(tracks, "INFO DVDTITLE %d\r\n", i);
- if(this->funcs.xine_input_event)
- this->funcs.xine_input_event(tracks, NULL);
- else
- write_control(this, tracks);
- LOGDBG(tracks);
- }
-#endif
}
/* Map some xine input events to vdr input (remote key names) */
@@ -4123,6 +4172,8 @@ static void vdr_event_cb (void *user_data, const xine_event_t *event)
#ifdef XINE_STREAM_INFO_DVD_TITLE_NUMBER
int tt = _x_stream_info_get(this->slave_stream,XINE_STREAM_INFO_DVD_TITLE_NUMBER);
snprintf(titlen, sizeof(titlen), "INFO DVDTITLE %d\r\n", tt);
+ if (tt == 0)
+ dvd_menu_domain(this, 1);
#endif
snprintf(msg, sizeof(msg), "INFO TITLE %s\r\n%s", data->str, titlen);
msg[sizeof(msg)-1] = 0;
@@ -4133,6 +4184,20 @@ static void vdr_event_cb (void *user_data, const xine_event_t *event)
break;
}
+ case XINE_EVENT_UI_NUM_BUTTONS:
+ if (event->stream == this->slave_stream) {
+ xine_ui_data_t *data = (xine_ui_data_t*)event->data;
+ char msg[64];
+ dvd_menu_domain(this, data->num_buttons > 0);
+ snprintf(msg, sizeof(msg), "INFO DVDBUTTONS %d\r\n", data->num_buttons);
+ msg[sizeof(msg)-1] = 0;
+ if (this->funcs.xine_input_event)
+ this->funcs.xine_input_event(msg, NULL);
+ else
+ write_control(this, msg);
+ break;
+ }
+
case XINE_EVENT_UI_CHANNELS_CHANGED:
if(event->stream==this->slave_stream)
slave_track_maps_changed(this);
@@ -4953,7 +5018,6 @@ static void post_frame_end(vdr_input_plugin_t *this, int type)
/* Should not be here ...
Failing to send BUF_FLAG_FRAME_END 's freezes the decoder */
LOGERR("get_buf_element() for H.264 BUF_FLAG_FRAME_END failed - aborting");
- abort();
}
}
@@ -6327,7 +6391,7 @@ static input_plugin_t *vdr_class_get_instance (input_class_t *class_gen,
return fifo_class_get_instance(class_gen, stream, data);
}
- this = (vdr_input_plugin_t *) xine_xmalloc (sizeof(vdr_input_plugin_t));
+ this = calloc(1, sizeof(vdr_input_plugin_t));
this->stream = stream;
this->mrl = strdup(mrl);
@@ -6480,7 +6544,7 @@ static void *init_class (xine_t *xine, void *data)
}
}
- this = (vdr_input_class_t *) xine_xmalloc (sizeof (vdr_input_class_t));
+ this = calloc(1, sizeof (vdr_input_class_t));
this->xine = xine;