summaryrefslogtreecommitdiff
path: root/src/input/input_dvd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/input_dvd.c')
-rw-r--r--src/input/input_dvd.c350
1 files changed, 129 insertions, 221 deletions
diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c
index e8961055e..b5f254621 100644
--- a/src/input/input_dvd.c
+++ b/src/input/input_dvd.c
@@ -18,7 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: input_dvd.c,v 1.128 2003/02/14 18:00:38 heikos Exp $
+ * $Id: input_dvd.c,v 1.129 2003/02/20 16:01:57 mroi Exp $
*
*/
@@ -110,10 +110,6 @@
/* Some misc. defines */
#define DVD_BLOCK_SIZE 2048
-#ifndef BUF_DEMUX_BLOCK
-#define BUF_DEMUX_BLOCK 0x05000000
-#endif
-#define VIDEO_FILL_THROTTLE 5
/* Debugging macros */
#ifdef __GNUC__
@@ -159,8 +155,7 @@ typedef struct {
char *mrl; /* Current MRL */
int mode;
dvdnav_t *dvdnav; /* Handle for libdvdnav */
- char dvd_name[128];
- size_t dvd_name_length;
+ const char *dvd_name;
/*
xine_mrl_t **mrls;
int num_mrls;
@@ -174,6 +169,7 @@ typedef struct {
void (*free_buffer)(buf_element_t *);
int mem_stack;
unsigned char *mem[1024];
+ int freeing;
} dvd_input_plugin_t;
typedef struct {
@@ -198,7 +194,6 @@ typedef struct {
} dvd_input_class_t;
static void dvd_handle_events(dvd_input_plugin_t *this);
-static void flush_buffers(dvd_input_plugin_t *this);
static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode);
/* Callback on device name change */
@@ -300,10 +295,10 @@ void update_title_display(dvd_input_plugin_t *this) {
}
ui_str_length = strlen(this->ui_title);
- if (this->dvd_name[0] != 0 && (ui_str_length + this->dvd_name_length < MAX_STR_LEN)) {
- snprintf(this->ui_title+ui_str_length, MAX_STR_LEN - ui_str_length,
- ", %s",
- &this->dvd_name[0]);
+ if (this->dvd_name && this->dvd_name[0] &&
+ (ui_str_length + strlen(this->dvd_name) < MAX_STR_LEN)) {
+ snprintf(this->ui_title+ui_str_length, MAX_STR_LEN - ui_str_length,
+ ", %s", this->dvd_name);
}
#ifdef INPUT_DEBUG
printf("input_dvd: Changing title to read '%s'\n", this->ui_title);
@@ -330,12 +325,10 @@ static void dvd_plugin_dispose (input_plugin_t *this_gen) {
trace_print("Called\n");
xine_event_dispose_queue (this->event_queue);
- if(this->opened || this->dvdnav)
- dvdnav_close(this->dvdnav);
- this->dvdnav = NULL;
- this->opened = 0;
- this->dvd_name[0] = 0;
- this->dvd_name_length = 0;
+ dvdnav_close(this->dvdnav);
+ /* raise the freeing flag, so that the plugin will be freed as soon
+ * as all buffers have returned to the libdvdnav read ahead cache */
+ this->freeing = 1;
}
@@ -438,6 +431,11 @@ static void dvd_plugin_free_buffer(buf_element_t *buf) {
pthread_mutex_unlock(&this->buf_mutex);
/* give this buffer back to xine's pool */
buf->free_buffer(buf);
+ if (this->freeing && !this->mem_stack) {
+ /* all buffers returned, we can free the plugin now */
+ pthread_mutex_destroy(&this->buf_mutex);
+ free(this);
+ }
}
static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
@@ -476,8 +474,8 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
}
switch(event) {
- case DVDNAV_BLOCK_OK:
- {
+ case DVDNAV_BLOCK_OK:
+ {
buf->content = block;
buf->type = BUF_DEMUX_BLOCK;
@@ -488,64 +486,57 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
this->seekable = 1;
finished = 1;
- }
+ }
break;
- case DVDNAV_NOP:
- {
- /* Nothing */
- }
+ case DVDNAV_NOP:
break;
- case DVDNAV_STILL_FRAME:
- {
-
- /* OK, So xine no-longer accepts BUF_VIDEO_FILLs, find out
- * how else we provide the hint
- */
- dvdnav_still_event_t *still_event =
- (dvdnav_still_event_t*)(block);
- buf->type = BUF_CONTROL_NOP;
- finished = 1;
+ case DVDNAV_STILL_FRAME:
+ {
+ dvdnav_still_event_t *still_event =
+ (dvdnav_still_event_t*)block;
+ buf->type = BUF_CONTROL_NOP;
+ finished = 1;
- /* stills are not seekable */
- this->seekable = 0;
-
- /* Xine's method of doing still-frames */
- if (this->pause_timer == 0) {
+ /* stills are not seekable */
+ this->seekable = 0;
+
+ /* Xine's method of doing still-frames */
+ if (this->pause_timer == 0) {
#ifdef INPUT_DEBUG
- printf("input_dvd: Stillframe! (pause time = 0x%02x)\n",
+ printf("input_dvd: Stillframe! (pause time = 0x%02x)\n",
still_event->length);
#endif
- this->pause_timer = still_event->length;
- this->pause_end_time = time(NULL) + this->pause_timer;
- this->pause_counter = 0;
- break;
- }
-
- if(this->pause_timer == 0xff) {
- this->pause_counter++;
- xine_usec_sleep(100000);
- break;
- }
- if ( (this->pause_timer != 0xFF) &&
- (time(NULL) >= this->pause_end_time) ){
- this->pause_timer = 0;
- this->pause_end_time = 0;
- dvdnav_still_skip(this->dvdnav);
- break;
- }
- if(this->pause_timer) {
- this->pause_counter++;
+ this->pause_timer = still_event->length;
+ this->pause_end_time = time(NULL) + this->pause_timer;
+ this->pause_counter = 0;
+ break;
+ }
+
+ if(this->pause_timer == 0xff) {
+ this->pause_counter++;
+ xine_usec_sleep(50000);
+ break;
+ }
+ if ((this->pause_timer != 0xff) &&
+ (time(NULL) >= this->pause_end_time)) {
+ this->pause_timer = 0;
+ this->pause_end_time = 0;
+ dvdnav_still_skip(this->dvdnav);
+ break;
+ }
+ if(this->pause_timer) {
+ this->pause_counter++;
#ifdef INPUT_DEBUG
- printf("input_dvd: Stillframe! (pause_timer = 0x%02x) counter=%d\n",
+ printf("input_dvd: Stillframe! (pause_timer = 0x%02x) counter=%d\n",
still_event->length, this->pause_counter);
#endif
- xine_usec_sleep(100000);
- break;
- }
- }
- break;
- case DVDNAV_SPU_STREAM_CHANGE:
- {
+ xine_usec_sleep(50000);
+ break;
+ }
+ }
+ break;
+ case DVDNAV_SPU_STREAM_CHANGE:
+ {
dvdnav_spu_stream_change_event_t *stream_event =
(dvdnav_spu_stream_change_event_t*) (block);
buf->content = block;
@@ -560,10 +551,10 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
stream_event->physical_pan_scan);
#endif
finished = 1;
- }
+ }
break;
- case DVDNAV_AUDIO_STREAM_CHANGE:
- {
+ case DVDNAV_AUDIO_STREAM_CHANGE:
+ {
dvdnav_audio_stream_change_event_t *stream_event =
(dvdnav_audio_stream_change_event_t*) (block);
buf->content = block;
@@ -573,15 +564,13 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
printf("input_dvd: AUDIO stream %d\n", stream_event->physical);
#endif
finished = 1;
- }
+ }
break;
- case DVDNAV_HIGHLIGHT:
- {
- xine_dvd_send_button_update(this, 0);
- }
+ case DVDNAV_HIGHLIGHT:
+ xine_dvd_send_button_update(this, 0);
break;
- case DVDNAV_VTS_CHANGE:
- {
+ case DVDNAV_VTS_CHANGE:
+ {
int aspect, permission;
#ifdef INPUT_DEBUG
printf("input_dvd: VTS change\n");
@@ -596,60 +585,50 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
buf->decoder_info[2] = aspect;
buf->decoder_info[3] = permission;
finished = 1;
- }
+ }
break;
- case DVDNAV_CELL_CHANGE:
- {
- xine_event_t event;
-
- /* Tell Xine to update the UI */
- event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
- event.stream = this->stream;
- event.data = NULL;
- event.data_length = 0;
- xine_event_send(this->stream, &event);
-
- update_title_display(this);
- }
+ case DVDNAV_CELL_CHANGE:
+ {
+ xine_event_t event;
+
+ /* Tell Xine to update the UI */
+ event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
+ event.stream = this->stream;
+ event.data = NULL;
+ event.data_length = 0;
+ xine_event_send(this->stream, &event);
+
+ update_title_display(this);
+ }
break;
- case DVDNAV_SEEK_DONE:
- {
-#ifdef INPUT_DEBUG
- printf("input_dvd: Seek done\n");
-#endif
- /* FIXME: This should send a message to clear all currently displaying subtitle. */
- }
+ case DVDNAV_HOP_CHANNEL:
+ xine_demux_flush_engine(this->stream);
break;
- case DVDNAV_HOP_CHANNEL:
- {
- flush_buffers(this);
- break;
- }
- case DVDNAV_NAV_PACKET:
- {
+ case DVDNAV_NAV_PACKET:
+ {
buf->content = block;
buf->type = BUF_DEMUX_BLOCK;
finished = 1;
- }
+ }
break;
- case DVDNAV_SPU_CLUT_CHANGE:
- {
+ case DVDNAV_SPU_CLUT_CHANGE:
+ {
buf->content = block;
buf->type = BUF_SPU_DVD;
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE;
buf->decoder_info[2] = SPU_DVD_SUBTYPE_CLUT;
finished = 1;
- }
+ }
break;
- case DVDNAV_STOP:
- {
+ case DVDNAV_STOP:
+ {
if (buf->mem != block) dvdnav_free_cache_block(this->dvdnav, block);
buf->free_buffer(buf);
/* return NULL to indicate end of stream */
return NULL;
- }
- default:
+ }
+ default:
printf("input_dvd: FIXME: Unknown event (%i)\n", event);
break;
}
@@ -702,8 +681,6 @@ static off_t dvd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin
}
return dvdnav_sector_search(this->dvdnav, offset / DVD_BLOCK_SIZE , origin) * DVD_BLOCK_SIZE;
-
- return -1;
}
static off_t dvd_plugin_get_current_pos (input_plugin_t *this_gen){
@@ -731,7 +708,6 @@ static off_t dvd_plugin_get_length (input_plugin_t *this_gen) {
if(!this || !this->dvdnav) {
return 0;
}
-
result = dvdnav_get_position(this->dvdnav, &pos, &length);
return (off_t)length * (off_t)2048;
}
@@ -778,11 +754,6 @@ static char* dvd_plugin_get_mrl (input_plugin_t *this_gen) {
return this->mrl;
}
-static void flush_buffers(dvd_input_plugin_t *this) {
-
- xine_demux_flush_engine(this->stream);
-}
-
static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode) {
int32_t button;
int32_t show;
@@ -920,8 +891,8 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
return;
}
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
- xine_dvd_send_button_update(this, 1);
- dvdnav_button_activate(this->dvdnav, &nav_pci);
+ if (dvdnav_button_activate(this->dvdnav, &nav_pci) == DVDNAV_STATUS_OK)
+ xine_dvd_send_button_update(this, 1);
}
}
break;
@@ -933,8 +904,8 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
}
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
xine_input_data_t *input = event->data;
- xine_dvd_send_button_update(this, 1);
- dvdnav_mouse_activate(this->dvdnav, &nav_pci, input->x, input->y);
+ if (dvdnav_mouse_activate(this->dvdnav, &nav_pci, input->x, input->y) == DVDNAV_STATUS_OK)
+ xine_dvd_send_button_update(this, 1);
}
}
break;
@@ -950,63 +921,49 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
case XINE_EVENT_INPUT_MOUSE_MOVE:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
xine_input_data_t *input = event->data;
/* printf("input_dvd: Mouse move (x,y) = (%i,%i)\n", input->x, input->y); */
dvdnav_mouse_select(this->dvdnav, &nav_pci, input->x, input->y);
- xine_dvd_send_button_update(this, 0);
}
}
break;
case XINE_EVENT_INPUT_UP:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_upper_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_DOWN:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_lower_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_LEFT:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_left_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_RIGHT:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_right_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_NUMBER_9:
@@ -1030,13 +987,11 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
case XINE_EVENT_INPUT_NUMBER_0:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
- dvdnav_button_select(this->dvdnav, &nav_pci, this->typed_buttonN);
- xine_dvd_send_button_update(this, 1);
- dvdnav_button_activate(this->dvdnav, &nav_pci);
+ if (dvdnav_button_select_and_activate(this->dvdnav, &nav_pci, this->typed_buttonN) == DVDNAV_STATUS_OK)
+ xine_dvd_send_button_update(this, 1);
this->typed_buttonN = 0;
}
break;
@@ -1199,12 +1154,12 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
xine_event_t event;
static char *handled_mrl = "dvd:/";
+ trace_print("Called\n");
+
/* Check we can handle this MRL */
if (strncasecmp (data, handled_mrl, strlen(handled_mrl) ) != 0)
return NULL;
- printf("input_dvd.c: open_plugin called.\n");
-
this = (dvd_input_plugin_t *) xine_xmalloc (sizeof (dvd_input_plugin_t));
if (this == NULL) {
printf("input_dvd.c: xine_xmalloc failed!!!! You have run out of memory\n");
@@ -1231,8 +1186,7 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
this->seekable = 0;
this->buttonN = 0;
this->typed_buttonN = 0;
- this->dvd_name[0] = 0;
- this->dvd_name_length = 0;
+ this->dvd_name = NULL;
this->mrl = NULL;
/*
this->mrls = NULL;
@@ -1241,15 +1195,14 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
pthread_mutex_init(&this->buf_mutex, NULL);
this->mem_stack = 0;
- trace_print("Called\n");
+ this->freeing = 0;
+
this->event_queue = xine_event_new_queue (this->stream);
/* printf("input_dvd: open1: dvdnav=%p opened=%d\n",this->dvdnav, this->opened); */
/* printf("data=%p\n",data);
if (data) printf("data=%s\n",data); */
- this->mrl = strdup(data);
+ this->mrl = strdup(data);
this->pause_timer = 0;
- this->dvd_name[0] = 0;
- this->dvd_name_length = 0;
/* we already checked the "dvd:/" MRL above */
locator = &this->mrl[strlen(handled_mrl)];
@@ -1277,8 +1230,6 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
this->mode = MODE_NAVIGATE;
}
- printf("input_dvd.c:open_plugin:dvd_device=%s\n",class->dvd_device);
-
if(this->opened) {
if ( intended_dvd_device==this->current_dvd_device ) {
/* Already open, so skip opening */
@@ -1304,61 +1255,8 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
this->opened=1;
this->current_dvd_device=intended_dvd_device;
}
- if (1) {
- int fd, i;
- off64_t off;
- uint8_t data[DVD_VIDEO_LB_LEN];
-
- /* Read DVD name */
- fd=open(intended_dvd_device, O_RDONLY);
- if (fd > 0) {
- off = lseek64( fd, 32 * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
- if( off == ( 32 * (int64_t) DVD_VIDEO_LB_LEN ) ) {
- off = read( fd, data, DVD_VIDEO_LB_LEN );
- close(fd);
- if (off == ( (int64_t) DVD_VIDEO_LB_LEN )) {
- printf("input_dvd: DVD Title: ");
- for(i=25; i < 73; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- printf("%c", data[i]);
- } else {
- printf(" ");
- }
- }
- strncpy(&this->dvd_name[0], &data[25], 48);
- /* printf("input_dvd: TITLE:%s\n",&this->dvd_name[0]); */
- this->dvd_name[48]=0;
- this->dvd_name_length=strlen(&this->dvd_name[0]);
- printf("\ninput_dvd: DVD Serial Number: ");
- for(i=73; i < 89; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- printf("%c", data[i]);
- } else {
- printf(" ");
- }
- }
- printf("\ninput_dvd: DVD Title (Alternative): ");
- for(i=89; i < 128; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- printf("%c", data[i]);
- } else {
- printf(" ");
- }
- }
- printf("\n");
- } else {
- printf("input_dvd: Can't read name block. Probably not a DVD-ROM device.\n");
- }
- } else {
- printf("input_dvd: Can't seek to block %u\n", 32 );
- }
- } else {
- printf("input_dvd: NAME OPEN FAILED\n");
- }
- }
+
+ dvdnav_get_title_string(this->dvdnav, &this->dvd_name);
/* config callbacks may react now */
class->ip = this;
@@ -1464,7 +1362,7 @@ static xine_mrl_t **dvd_class_get_dir (input_class_t *this_gen,
}
#endif
-static char ** dvd_class_get_autoplay_list (input_class_t *this_gen,
+static char **dvd_class_get_autoplay_list (input_class_t *this_gen,
int *num_files) {
dvd_input_class_t *this = (dvd_input_class_t *) this_gen;
@@ -1658,6 +1556,16 @@ static void *init_class (xine_t *xine, void *data) {
/*
* $Log: input_dvd.c,v $
+ * Revision 1.129 2003/02/20 16:01:57 mroi
+ * syncing to libdvdnav 0.1.5 and modifying input plugin accordingly
+ * quoting the ChangeLog:
+ * * some bugfixes
+ * * code cleanup
+ * * build process polishing
+ * * more sensible event order in get_next_block to ensure useful event delivery
+ * * VOBU level resume
+ * * fixed: seeking in a multiangle feature briefly showed the wrong angle
+ *
* Revision 1.128 2003/02/14 18:00:38 heikos
* FreeBSD compile fixes
*