diff options
Diffstat (limited to 'stream')
-rw-r--r-- | stream/stream.c | 8 | ||||
-rw-r--r-- | stream/stream.h | 1 | ||||
-rw-r--r-- | stream/stream_dvdnav.c | 1027 | ||||
-rw-r--r-- | stream/stream_dvdnav.h | 49 |
4 files changed, 0 insertions, 1085 deletions
diff --git a/stream/stream.c b/stream/stream.c index d4f0c8ae97..d04b7fb8d8 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -71,7 +71,6 @@ extern const stream_info_t stream_info_radio; extern const stream_info_t stream_info_pvr; extern const stream_info_t stream_info_ftp; extern const stream_info_t stream_info_vstream; -extern const stream_info_t stream_info_dvdnav; extern const stream_info_t stream_info_smb; extern const stream_info_t stream_info_sdp; extern const stream_info_t stream_info_rtsp_sip; @@ -130,9 +129,6 @@ static const stream_info_t* const auto_open_streams[] = { &stream_info_ifo, &stream_info_dvd, #endif -#ifdef CONFIG_DVDNAV - &stream_info_dvdnav, -#endif #ifdef CONFIG_LIBBLURAY &stream_info_bluray, #endif @@ -313,10 +309,6 @@ int stream_read_internal(stream_t *s, void *buf, int len) // do not retry if this looks like proper eof if (s->eof || (s->end_pos && s->pos == s->end_pos)) goto eof_out; - // dvdnav has some horrible hacks to "suspend" reads, - // we need to skip this code or seeks will hang. - if (s->type == STREAMTYPE_DVDNAV) - goto eof_out; // just in case this is an error e.g. due to network // timeout reset and retry diff --git a/stream/stream.h b/stream/stream.h index df1f15c0b0..7df09490d1 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -42,7 +42,6 @@ #define STREAMTYPE_MEMORY 4 // read data from memory area #define STREAMTYPE_PLAYLIST 6 // FIXME!!! same as STREAMTYPE_FILE now #define STREAMTYPE_DS 8 // read from a demuxer stream -#define STREAMTYPE_DVDNAV 9 // we cannot safely "seek" in this... #define STREAMTYPE_CDDA 10 // raw audio CD reader #define STREAMTYPE_SMB 11 // smb:// url, using libsmbclient (samba) #define STREAMTYPE_VCDBINCUE 12 // vcd directly from bin/cue files diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c deleted file mode 100644 index d0e29446d3..0000000000 --- a/stream/stream_dvdnav.c +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer 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. - * - * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include "options.h" -#include "mp_msg.h" -#include "osdep/timer.h" -#include "input/input.h" -#include "stream.h" -#include "libmpdemux/demuxer.h" -#include <dvdnav/dvdnav.h> -#include "stream_dvdnav.h" -#include "libvo/video_out.h" -#include "libavutil/common.h" -#include "sub/spudec.h" -#include "m_option.h" -#include "m_struct.h" -#include "stream_dvd_common.h" - -/* state flags */ -typedef enum { - NAV_FLAG_EOF = 1 << 0, /* end of stream has been reached */ - NAV_FLAG_WAIT = 1 << 1, /* wait event */ - NAV_FLAG_WAIT_SKIP = 1 << 2, /* wait skip disable */ - NAV_FLAG_CELL_CHANGE = 1 << 3, /* cell change event */ - NAV_FLAG_WAIT_READ_AUTO = 1 << 4, /* wait read auto mode */ - NAV_FLAG_WAIT_READ = 1 << 5, /* suspend read from stream */ - NAV_FLAG_VTS_DOMAIN = 1 << 6, /* vts domain */ - NAV_FLAG_SPU_SET = 1 << 7, /* spu_clut is valid */ - NAV_FLAG_STREAM_CHANGE = 1 << 8, /* title, chapter, audio or SPU */ - NAV_FLAG_AUDIO_CHANGE = 1 << 9, /* audio stream change event */ - NAV_FLAG_SPU_CHANGE = 1 << 10, /* spu stream change event */ -} dvdnav_state_t; - -typedef struct { - dvdnav_t * dvdnav; /* handle to libdvdnav stuff */ - char * filename; /* path */ - unsigned int duration; /* in milliseconds */ - int mousex, mousey; - int title; - unsigned int spu_clut[16]; - dvdnav_highlight_event_t hlev; - int still_length; /* still frame duration */ - unsigned int state; -} dvdnav_priv_t; - -static struct stream_priv_s { - int track; - char* device; -} stream_priv_dflts = { - 0, - NULL -}; - -#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) -/// URL definition -static const m_option_t stream_opts_fields[] = { - {"filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL }, - {"hostname", ST_OFF(track), CONF_TYPE_INT, M_OPT_RANGE, 1, 99, NULL}, - { NULL, NULL, 0, 0, 0, 0, NULL } -}; -static const struct m_struct_st stream_opts = { - "dvd", - sizeof(struct stream_priv_s), - &stream_priv_dflts, - stream_opts_fields -}; - -static int seek(stream_t *s, off_t newpos); -static void show_audio_subs_languages(dvdnav_t *nav); - -static dvdnav_priv_t * new_dvdnav_stream(char * filename) { - const char * title_str; - dvdnav_priv_t *priv; - - if (!filename) - return NULL; - - if (!(priv=calloc(1,sizeof(dvdnav_priv_t)))) - return NULL; - - if (!(priv->filename=strdup(filename))) { - free(priv); - return NULL; - } - - dvd_set_speed(priv->filename, dvd_speed); - - if(dvdnav_open(&(priv->dvdnav),priv->filename)!=DVDNAV_STATUS_OK) - { - free(priv->filename); - free(priv); - return NULL; - } - - if (!priv->dvdnav) { - free(priv); - return NULL; - } - - if(1) //from vlc: if not used dvdnav from cvs will fail - { - int len, event; - char buf[2048]; - - dvdnav_get_next_block(priv->dvdnav,buf,&event,&len); - dvdnav_sector_search(priv->dvdnav, 0, SEEK_SET); - } - - /* turn off dvdnav caching */ - dvdnav_set_readahead_flag(priv->dvdnav, 0); - if(dvdnav_set_PGC_positioning_flag(priv->dvdnav, 1) != DVDNAV_STATUS_OK) - mp_msg(MSGT_OPEN,MSGL_ERR,"stream_dvdnav, failed to set PGC positioning\n"); - /* report the title?! */ - if (dvdnav_get_title_string(priv->dvdnav,&title_str)==DVDNAV_STATUS_OK) { - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_VOLUME_ID=%s\n", title_str); - } - - //dvdnav_event_clear(priv); - - return priv; -} - -static void dvdnav_get_highlight (dvdnav_priv_t *priv, int display_mode) { - pci_t *pnavpci = NULL; - dvdnav_highlight_event_t *hlev = &(priv->hlev); - int btnum; - - if (!priv || !priv->dvdnav) - return; - - pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav); - if (!pnavpci) - return; - - dvdnav_get_current_highlight (priv->dvdnav, &(hlev->buttonN)); - hlev->display = display_mode; /* show */ - - if (hlev->buttonN > 0 && pnavpci->hli.hl_gi.btn_ns > 0 && hlev->display) { - for (btnum = 0; btnum < pnavpci->hli.hl_gi.btn_ns; btnum++) { - btni_t *btni = &(pnavpci->hli.btnit[btnum]); - - if (hlev->buttonN == btnum + 1) { - hlev->sx = FFMIN (btni->x_start, btni->x_end); - hlev->ex = FFMAX (btni->x_start, btni->x_end); - hlev->sy = FFMIN (btni->y_start, btni->y_end); - hlev->ey = FFMAX (btni->y_start, btni->y_end); - - hlev->palette = (btni->btn_coln == 0) ? 0 : - pnavpci->hli.btn_colit.btn_coli[btni->btn_coln - 1][0]; - break; - } - } - } else { /* hide button or no button */ - hlev->sx = hlev->ex = 0; - hlev->sy = hlev->ey = 0; - hlev->palette = hlev->buttonN = 0; - } -} - -static inline int dvdnav_get_duration (int length) { - return (length == 255) ? 0 : length * 1000; -} - -static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len) { - int event = DVDNAV_NOP; - - *len=-1; - if (dvdnav_get_next_block(priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) { - mp_msg(MSGT_OPEN,MSGL_V, "Error getting next block from DVD %d (%s)\n",event, dvdnav_err_to_string(priv->dvdnav) ); - *len=-1; - } - else if (event!=DVDNAV_BLOCK_OK) { - // need to handle certain events internally (like skipping stills) - switch (event) { - case DVDNAV_NAV_PACKET: - return event; - case DVDNAV_STILL_FRAME: { - dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf; - priv->still_length = still_event->length; - /* set still frame duration */ - priv->duration = dvdnav_get_duration (priv->still_length); - if (priv->still_length <= 1) { - pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav); - priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm); - } - break; - } - case DVDNAV_HIGHLIGHT: { - dvdnav_get_highlight (priv, 1); - break; - } - case DVDNAV_CELL_CHANGE: { - dvdnav_cell_change_event_t *ev = (dvdnav_cell_change_event_t*)buf; - uint32_t nextstill; - - priv->state &= ~NAV_FLAG_WAIT_SKIP; - priv->state |= NAV_FLAG_STREAM_CHANGE; - if(ev->pgc_length) - priv->duration = ev->pgc_length/90; - - if (dvdnav_is_domain_vts(priv->dvdnav)) { - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "DVDNAV_TITLE_IS_MOVIE\n"); - priv->state &= ~NAV_FLAG_VTS_DOMAIN; - } else { - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "DVDNAV_TITLE_IS_MENU\n"); - priv->state |= NAV_FLAG_VTS_DOMAIN; - } - - nextstill = dvdnav_get_next_still_flag (priv->dvdnav); - if (nextstill) { - priv->duration = dvdnav_get_duration (nextstill); - priv->still_length = nextstill; - if (priv->still_length <= 1) { - pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav); - priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm); - } - } - - break; - } - case DVDNAV_SPU_CLUT_CHANGE: { - memcpy(priv->spu_clut, buf, 16*sizeof(unsigned int)); - priv->state |= NAV_FLAG_SPU_SET; - break; - } - case DVDNAV_WAIT: { - if ((priv->state & NAV_FLAG_WAIT_SKIP) && - !(priv->state & NAV_FLAG_WAIT)) - dvdnav_wait_skip (priv->dvdnav); - else - priv->state |= NAV_FLAG_WAIT; - break; - } - case DVDNAV_VTS_CHANGE: { - priv->state &= ~NAV_FLAG_WAIT_SKIP; - priv->state |= NAV_FLAG_STREAM_CHANGE; - break; - } - case DVDNAV_SPU_STREAM_CHANGE: { - priv->state |= NAV_FLAG_STREAM_CHANGE; - break; - } - } - - *len=0; - } - return event; -} - -static void update_title_len(stream_t *stream) { - dvdnav_priv_t *priv = stream->priv; - dvdnav_status_t status; - uint32_t pos = 0, len = 0; - - status = dvdnav_get_position(priv->dvdnav, &pos, &len); - if(status == DVDNAV_STATUS_OK && len) { - stream->end_pos = (off_t) len * 2048; - stream->seek = seek; - } else { - stream->seek = NULL; - stream->end_pos = 0; - } -} - - -static int seek(stream_t *s, off_t newpos) { - uint32_t sector = 0; - dvdnav_priv_t *priv = s->priv; - - if(s->end_pos && newpos > s->end_pos) - newpos = s->end_pos; - sector = newpos / 2048ULL; - if(dvdnav_sector_search(priv->dvdnav, (uint64_t) sector, SEEK_SET) != DVDNAV_STATUS_OK) - goto fail; - - s->pos = newpos; - - return 1; - -fail: - mp_msg(MSGT_STREAM,MSGL_INFO,"dvdnav_stream, seeking to %"PRIu64" failed: %s\n", newpos, dvdnav_err_to_string(priv->dvdnav)); - - return 1; -} - -static void stream_dvdnav_close(stream_t *s) { - dvdnav_priv_t *priv = s->priv; - dvdnav_close(priv->dvdnav); - priv->dvdnav = NULL; - dvd_set_speed(priv->filename, -1); - free(priv); -} - - -static int fill_buffer(stream_t *s, char *but, int len) -{ - int event; - - dvdnav_priv_t* priv=s->priv; - if (priv->state & NAV_FLAG_WAIT_READ) /* read is suspended */ - return -1; - len=0; - if(!s->end_pos) - update_title_len(s); - while(!len) /* grab all event until DVDNAV_BLOCK_OK (len=2048), DVDNAV_STOP or DVDNAV_STILL_FRAME */ - { - event=dvdnav_stream_read(priv, s->buffer, &len); - if(event==-1 || len==-1) - { - mp_msg(MSGT_CPLAYER,MSGL_ERR, "DVDNAV stream read error!\n"); - return 0; - } - if (event != DVDNAV_BLOCK_OK) - dvdnav_get_highlight (priv, 1); - switch (event) { - case DVDNAV_STOP: { - priv->state |= NAV_FLAG_EOF; - return len; - } - case DVDNAV_BLOCK_OK: - case DVDNAV_NAV_PACKET: - case DVDNAV_STILL_FRAME: - return len; - case DVDNAV_WAIT: { - if (priv->state & NAV_FLAG_WAIT) - return len; - break; - } - case DVDNAV_VTS_CHANGE: { - int tit = 0, part = 0; - dvdnav_vts_change_event_t *vts_event = (dvdnav_vts_change_event_t *)s->buffer; - mp_msg(MSGT_CPLAYER,MSGL_INFO, "DVDNAV, switched to title: %d\r\n", vts_event->new_vtsN); - priv->state |= NAV_FLAG_CELL_CHANGE; - priv->state |= NAV_FLAG_AUDIO_CHANGE; - priv->state |= NAV_FLAG_SPU_CHANGE; - priv->state &= ~NAV_FLAG_WAIT_SKIP; - priv->state &= ~NAV_FLAG_WAIT; - s->end_pos = 0; - update_title_len(s); - show_audio_subs_languages(priv->dvdnav); - if (priv->state & NAV_FLAG_WAIT_READ_AUTO) - priv->state |= NAV_FLAG_WAIT_READ; - if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK) { - mp_msg(MSGT_CPLAYER,MSGL_V, "\r\nDVDNAV, NEW TITLE %d\r\n", tit); - dvdnav_get_highlight (priv, 0); - if(priv->title > 0 && tit != priv->title) { - priv->state |= NAV_FLAG_EOF; - return 0; - } - } - break; - } - case DVDNAV_CELL_CHANGE: { - priv->state |= NAV_FLAG_CELL_CHANGE; - priv->state |= NAV_FLAG_AUDIO_CHANGE; - priv->state |= NAV_FLAG_SPU_CHANGE; - priv->state &= ~NAV_FLAG_WAIT_SKIP; - priv->state &= ~NAV_FLAG_WAIT; - if (priv->state & NAV_FLAG_WAIT_READ_AUTO) - priv->state |= NAV_FLAG_WAIT_READ; - if(priv->title > 0 && s->opts->chapterrange[1] > 0) { - int tit=0, part=0; - if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK && part > s->opts->chapterrange[1]) { - priv->state |= NAV_FLAG_EOF; - return 0; - } - } - dvdnav_get_highlight (priv, 1); - } - break; - case DVDNAV_AUDIO_STREAM_CHANGE: - priv->state |= NAV_FLAG_AUDIO_CHANGE; - break; - case DVDNAV_SPU_STREAM_CHANGE: - priv->state |= NAV_FLAG_SPU_CHANGE; - break; - } - } - mp_msg(MSGT_STREAM,MSGL_DBG2,"DVDNAV fill_buffer len: %d\n",len); - return len; -} - -static int mp_dvdnav_lang_from_sid(stream_t *stream, int sid); -static int mp_dvdnav_lang_from_aid(stream_t *stream, int sid); - -static int control(stream_t *stream, int cmd, void* arg) { - dvdnav_priv_t* priv=stream->priv; - int tit, part; - - switch(cmd) - { - case STREAM_CTRL_SEEK_TO_CHAPTER: - { - int chap = *(unsigned int *)arg+1; - - if(chap < 1 || dvdnav_current_title_info(priv->dvdnav, &tit, &part) != DVDNAV_STATUS_OK) - break; - if(dvdnav_part_play(priv->dvdnav, tit, chap) != DVDNAV_STATUS_OK) - break; - return 1; - } - case STREAM_CTRL_GET_NUM_CHAPTERS: - { - if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) != DVDNAV_STATUS_OK) - break; - if(dvdnav_get_number_of_parts(priv->dvdnav, tit, &part) != DVDNAV_STATUS_OK) - break; - if(!part) - break; - *(unsigned int *)arg = part; - return 1; - } - case STREAM_CTRL_GET_CURRENT_CHAPTER: - { - if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) != DVDNAV_STATUS_OK) - break; - *(unsigned int *)arg = part - 1; - return 1; - } - case STREAM_CTRL_GET_TIME_LENGTH: - { - if(priv->duration || priv->still_length) - { - *(double *)arg = (double)priv->duration / 1000.0; - return 1; - } - break; - } - case STREAM_CTRL_GET_ASPECT_RATIO: - { - uint8_t ar = dvdnav_get_video_aspect(priv->dvdnav); - *(double *)arg = !ar ? 4.0/3.0 : 16.0/9.0; - return 1; - } - case STREAM_CTRL_GET_CURRENT_TIME: - { - double tm; - tm = dvdnav_get_current_time(priv->dvdnav)/90000.0f; - if(tm != -1) - { - *(double *)arg = tm; - return 1; - } - break; - } - case STREAM_CTRL_SEEK_TO_TIME: - { - uint64_t tm = (uint64_t) (*((double*)arg) * 90000); - if(dvdnav_time_search(priv->dvdnav, tm) == DVDNAV_STATUS_OK) - return 1; - break; - } - case STREAM_CTRL_GET_NUM_ANGLES: - { - uint32_t curr, angles; - if(dvdnav_get_angle_info(priv->dvdnav, &curr, &angles) != DVDNAV_STATUS_OK) - break; - *(int *)arg = angles; - return 1; - } - case STREAM_CTRL_GET_ANGLE: - { - uint32_t curr, angles; - if(dvdnav_get_angle_info(priv->dvdnav, &curr, &angles) != DVDNAV_STATUS_OK) - break; - *(int *)arg = curr; - return 1; - } - case STREAM_CTRL_SET_ANGLE: - { - uint32_t curr, angles; - int new_angle = *(int *)arg; - if(dvdnav_get_angle_info(priv->dvdnav, &curr, &angles) != DVDNAV_STATUS_OK) - break; - if(new_angle>angles || new_angle<1) - break; - if(dvdnav_angle_change(priv->dvdnav, new_angle) != DVDNAV_STATUS_OK) - return 1; - } - case STREAM_CTRL_GET_LANG: - { - struct stream_lang_req *req = arg; - int lang = 0; - switch(req->type) { - case stream_ctrl_audio: - lang = mp_dvdnav_lang_from_aid(stream, req->id); - break; - case stream_ctrl_sub: - lang = mp_dvdnav_lang_from_sid(stream, req->id); - break; - } - if (!lang) - break; - req->name = talloc_strdup(NULL, (char[]) {lang >> 8, lang, 0}); - return STREAM_OK; - } - } - - return STREAM_UNSUPPORTED; -} - -static void identify_chapters(dvdnav_t *nav, uint32_t title) -{ - uint64_t *parts=NULL, duration=0; - uint32_t n, i, t; - n = dvdnav_describe_title_chapters(nav, title, &parts, &duration); - if(parts) { - t = duration / 90; - mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_TITLE_%d_LENGTH=%d.%03d\n", title, t / 1000, t % 1000); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_CHAPTERS=%d\n", title, n); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "TITLE %u, CHAPTERS: ", title); - - for(i=0; i<n; i++) { - t = parts[i] / 90000; - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "%02d:%02d:%02d,", t/3600, (t/60)%60, t%60); - } - free(parts); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "\n"); - } -} - -static void identify(dvdnav_priv_t *priv, struct stream_priv_s *p) -{ - uint32_t titles=0, i; - if(p->track <= 0) { - dvdnav_get_number_of_titles(priv->dvdnav, &titles); - for(i=1; i<=titles; i++) - identify_chapters(priv->dvdnav, i); - } - else - identify_chapters(priv->dvdnav, p->track); -} - -static void show_audio_subs_languages(dvdnav_t *nav) -{ - uint8_t lg; - uint16_t i, lang, format, id, channels; - int base[7] = {128, 0, 0, 0, 160, 136, 0}; - for(i=0; i<8; i++) - { - char tmp[] = "unknown"; - lg = dvdnav_get_audio_logical_stream(nav, i); - if(lg == 0xff) continue; - channels = dvdnav_audio_stream_channels(nav, lg); - if(channels == 0xFFFF) - channels = 2; //unknown - else - channels--; - lang = dvdnav_audio_stream_to_lang(nav, lg); - if(lang != 0xFFFF) - { - tmp[0] = lang >> 8; - tmp[1] = lang & 0xFF; - tmp[2] = 0; - } - format = dvdnav_audio_stream_format(nav, lg); - if(format == 0xFFFF || format > 6) - format = 1; //unknown - id = i + base[format]; - mp_tmsg(MSGT_OPEN,MSGL_STATUS,"audio stream: %d format: %s (%s) language: %s aid: %d.\n", i, - dvd_audio_stream_types[format], dvd_audio_stream_channels[channels], tmp, id); - if (lang != 0xFFFF && lang && tmp[0]) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", id, tmp); - } - - for(i=0; i<32; i++) - { - char tmp[] = "unknown"; - lg = dvdnav_get_spu_logical_stream(nav, i); - if(lg == 0xff) continue; - lang = dvdnav_spu_stream_to_lang(nav, i); - if(lang != 0xFFFF) - { - tmp[0] = lang >> 8; - tmp[1] = lang & 0xFF; - tmp[2] = 0; - } - mp_msg(MSGT_OPEN,MSGL_STATUS,"subtitle ( sid ): %d language: %s\n", lg, tmp); - if (lang != 0xFFFF && lang && tmp[0]) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", lg, tmp); - } -} - -static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { - struct stream_priv_s* p = (struct stream_priv_s*)opts; - char *filename; - dvdnav_priv_t *priv; - - if(p->device) filename = p->device; - else if(dvd_device) filename= dvd_device; - else filename = DEFAULT_DVD_DEVICE; - if(!(priv=new_dvdnav_stream(filename))) { - mp_tmsg(MSGT_OPEN,MSGL_ERR,"Couldn't open DVD device: %s (%s)\n",filename, strerror(errno)); - return STREAM_UNSUPPORTED; - } - - if(p->track > 0) { - priv->title = p->track; - if(dvdnav_title_play(priv->dvdnav, p->track) != DVDNAV_STATUS_OK) { - mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(priv->dvdnav)); - return STREAM_UNSUPPORTED; - } - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_CURRENT_TITLE=%d\n", p->track); - } else if (p->track == 0) { - if(dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root) != DVDNAV_STATUS_OK) - dvdnav_menu_call(priv->dvdnav, DVD_MENU_Title); - } - if(mp_msg_test(MSGT_IDENTIFY, MSGL_INFO)) - identify(priv, p); - if(p->track > 0) - show_audio_subs_languages(priv->dvdnav); - if(dvd_angle > 1) - dvdnav_angle_change(priv->dvdnav, dvd_angle); - - stream->sector_size = 2048; - stream->flags = STREAM_READ | MP_STREAM_SEEK; - stream->fill_buffer = fill_buffer; - stream->seek = seek; - stream->control = control; - stream->close = stream_dvdnav_close; - stream->type = STREAMTYPE_DVDNAV; - stream->priv=(void*)priv; - *file_format = DEMUXER_TYPE_MPEG_PS; - - update_title_len(stream); - if(!stream->pos && p->track > 0) - mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: couldn't get init pos %s\r\n", dvdnav_err_to_string(priv->dvdnav)); - - mp_msg(MSGT_OPEN,MSGL_INFO, "Remember to disable MPlayer's cache when playing dvdnav:// streams (adding -nocache to your command line)\r\n"); - - return STREAM_OK; -} - - -void mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) { - dvdnav_priv_t * priv = stream->priv; - dvdnav_t *nav = priv->dvdnav; - dvdnav_status_t status=DVDNAV_STATUS_ERR; - pci_t *pci = dvdnav_get_current_nav_pci(nav); - - if(cmd != MP_CMD_DVDNAV_SELECT && !pci) - return; - - switch(cmd) { - case MP_CMD_DVDNAV_UP: - status = dvdnav_upper_button_select(nav, pci); - break; - case MP_CMD_DVDNAV_DOWN: - status = dvdnav_lower_button_select(nav, pci); - break; - case MP_CMD_DVDNAV_LEFT: - status = dvdnav_left_button_select(nav, pci); - break; - case MP_CMD_DVDNAV_RIGHT: - status = dvdnav_right_button_select(nav, pci); - break; - case MP_CMD_DVDNAV_MENU: - status = dvdnav_menu_call(nav,DVD_MENU_Root); - break; - case MP_CMD_DVDNAV_PREVMENU: { - int title=0, part=0; - - dvdnav_current_title_info(nav, &title, &part); - if(title) { - if((status=dvdnav_menu_call(nav, DVD_MENU_Part)) == DVDNAV_STATUS_OK) - break; - } - if((status=dvdnav_menu_call(nav, DVD_MENU_Title)) == DVDNAV_STATUS_OK) - break; - status=dvdnav_menu_call(nav, DVD_MENU_Root); - } - break; - case MP_CMD_DVDNAV_SELECT: - status = dvdnav_button_activate(nav, pci); - break; - case MP_CMD_DVDNAV_MOUSECLICK: - /* - this is a workaround: in theory the simple dvdnav_lower_button_select()+dvdnav_button_activate() - should be enough (and generally it is), but there are cases when the calls to dvdnav_lower_button_select() - and friends fail! Hence we have to call dvdnav_mouse_activate(priv->mousex, priv->mousey) with - the coodinates saved by mp_dvdnav_update_mouse_pos(). - This last call always works well - */ - status = dvdnav_mouse_activate(nav, pci, priv->mousex, priv->mousey); - break; - default: - mp_msg(MSGT_CPLAYER, MSGL_V, "Unknown DVDNAV cmd %d\n", cmd); - break; - } - - if(status == DVDNAV_STATUS_OK) - dvdnav_get_current_highlight(nav, button); -} - -void mp_dvdnav_update_mouse_pos(stream_t *stream, int32_t x, int32_t y, int* button) { - dvdnav_priv_t * priv = stream->priv; - dvdnav_t *nav = priv->dvdnav; - dvdnav_status_t status; - pci_t *pci = dvdnav_get_current_nav_pci(nav); - - if(!pci) return; - - status = dvdnav_mouse_select(nav, pci, x, y); - if(status == DVDNAV_STATUS_OK) dvdnav_get_current_highlight(nav, button); - else *button = -1; - priv->mousex = x; - priv->mousey = y; -} - -static int mp_dvdnav_get_aid_from_format (stream_t *stream, int index, uint8_t lg) { - dvdnav_priv_t * priv = stream->priv; - uint8_t format; - - format = dvdnav_audio_stream_format(priv->dvdnav, lg); - switch(format) { - case DVDNAV_FORMAT_AC3: - return index + 128; - case DVDNAV_FORMAT_DTS: - return index + 136; - case DVDNAV_FORMAT_LPCM: - return index + 160; - case DVDNAV_FORMAT_MPEGAUDIO: - return index; - default: - return -1; - } - - return -1; -} - -/** - * \brief mp_dvdnav_aid_from_lang() returns the audio id corresponding to the language code 'lang' - * \param stream: - stream pointer - * \param lang: 2-characters language code[s], eventually separated by spaces of commas - * \return -1 on error, current subtitle id if successful - */ -int mp_dvdnav_aid_from_lang(stream_t *stream, char **language) { - dvdnav_priv_t * priv = stream->priv; - int k; - uint8_t lg; - uint16_t lang, lcode; - - for (int i = 0; language[i]; i++) { - lcode = (language[i][0] << 8) | (language[i][1]); - for(k=0; k<32; k++) { - lg = dvdnav_get_audio_logical_stream(priv->dvdnav, k); - if(lg == 0xff) continue; - lang = dvdnav_audio_stream_to_lang(priv->dvdnav, lg); - if(lang != 0xFFFF && lang == lcode) - return mp_dvdnav_get_aid_from_format (stream, k, lg); - } - } - return -1; -} - -/** - * \brief mp_dvdnav_lang_from_aid() returns the language corresponding to audio id 'aid' - * \param stream: - stream pointer - * \param sid: physical subtitle id - * \return 0 on error, otherwise language id - */ -static int mp_dvdnav_lang_from_aid(stream_t *stream, int aid) { - uint8_t lg; - uint16_t lang; - dvdnav_priv_t * priv = stream->priv; - - if(aid < 0) - return 0; - lg = dvdnav_get_audio_logical_stream(priv->dvdnav, aid & 0x7); - if(lg == 0xff) return 0; - lang = dvdnav_audio_stream_to_lang(priv->dvdnav, lg); - if(lang == 0xffff) return 0; - return lang; -} - - -/** - * \brief mp_dvdnav_sid_from_lang() returns the subtitle id corresponding to the language code 'lang' - * \param stream: - stream pointer - * \param lang: 2-characters language code[s], eventually separated by spaces of commas - * \return -1 on error, current subtitle id if successful - */ -int mp_dvdnav_sid_from_lang(stream_t *stream, char **language) { - dvdnav_priv_t * priv = stream->priv; - uint8_t lg, k; - uint16_t lang, lcode; - - for (int i = 0; language[i]; i++) { - lcode = (language[i][0] << 8) | (language[i][1]); - for(k=0; k<32; k++) { - lg = dvdnav_get_spu_logical_stream(priv->dvdnav, k); - if(lg == 0xff) continue; - lang = dvdnav_spu_stream_to_lang(priv->dvdnav, k); - if(lang != 0xFFFF && lang == lcode) { - return lg; - } - } - } - return -1; -} - -/** - * \brief mp_dvdnav_lang_from_sid() returns the language corresponding to subtitle id 'sid' - * \param stream: - stream pointer - * \param sid: physical subtitle id - * \return 0 on error, otherwise language id - */ -static int mp_dvdnav_lang_from_sid(stream_t *stream, int sid) { - uint8_t k; - uint16_t lang; - dvdnav_priv_t *priv = stream->priv; - if(sid < 0) return 0; - for (k=0; k<32; k++) - if (dvdnav_get_spu_logical_stream(priv->dvdnav, k) == sid) - break; - if (k == 32) - return 0; - lang = dvdnav_spu_stream_to_lang(priv->dvdnav, k); - if(lang == 0xffff) return 0; - return lang; -} - -/** - * \brief mp_dvdnav_number_of_subs() returns the count of available subtitles - * \param stream: - stream pointer - * \return 0 on error, something meaningful otherwise - */ -int mp_dvdnav_number_of_subs(stream_t *stream) { - dvdnav_priv_t * priv = stream->priv; - uint8_t lg, k, n=0; - - if (priv->state & NAV_FLAG_VTS_DOMAIN) return 0; - for(k=0; k<32; k++) { - lg = dvdnav_get_spu_logical_stream(priv->dvdnav, k); - if(lg == 0xff) continue; - if(lg >= n) n = lg + 1; - } - return n; -} - -/** - * \brief mp_dvdnav_get_spu_clut() returns the spu clut - * \param stream: - stream pointer - * \return spu clut pointer - */ -unsigned int *mp_dvdnav_get_spu_clut(stream_t *stream) { - dvdnav_priv_t *priv = stream->priv; - return (priv->state & NAV_FLAG_SPU_SET) ? priv->spu_clut : NULL; -} - -/** - * \brief mp_dvdnav_get_highlight() get dvdnav highlight struct - * \param stream: - stream pointer - * \param hl : - highlight struct pointer - */ -void mp_dvdnav_get_highlight (stream_t *stream, nav_highlight_t *hl) { - dvdnav_priv_t *priv = stream->priv; - dvdnav_highlight_event_t hlev = priv->hlev; - - hl->sx = hlev.sx; - hl->sy = hlev.sy; - hl->ex = hlev.ex; - hl->ey = hlev.ey; - hl->palette = hlev.palette; -} - -void mp_dvdnav_switch_title (stream_t *stream, int title) { - dvdnav_priv_t *priv = stream->priv; - uint32_t titles; - - dvdnav_get_number_of_titles (priv->dvdnav, &titles); - if (title > 0 && title <= titles) - dvdnav_title_play (priv->dvdnav, title); -} - -/** - * \brief Check if end of stream has been reached - * \param stream: - stream pointer - * \return 1 on really eof - */ -int mp_dvdnav_is_eof (stream_t *stream) { - return ((dvdnav_priv_t *) stream->priv)->state & NAV_FLAG_EOF; -} - -/** - * \brief Skip still frame - * \param stream: - stream pointer - * \return 0 on success - */ -int mp_dvdnav_skip_still (stream_t *stream) { - dvdnav_priv_t *priv = stream->priv; - if (priv->still_length == 0xff) - return 1; - dvdnav_still_skip(priv->dvdnav); - return 0; -} - -/** - * \brief Skip wait event - * \param stream: - stream pointer - * \return 0 on success - */ -int mp_dvdnav_skip_wait (stream_t *stream) { - dvdnav_priv_t *priv = stream->priv; - if (!(priv->state & NAV_FLAG_WAIT)) - return 1; - priv->state &= ~NAV_FLAG_WAIT; - dvdnav_wait_skip(priv->dvdnav); - return 0; -} - -/** - * \brief Set wait mode - * \param stream : - stream pointer - * \param mode : - if true, then suspend block read - * \param automode: - if true, then VTS or cell change set wait mode - */ -void mp_dvdnav_read_wait (stream_t *stream, int mode, int automode) { - dvdnav_priv_t *priv = stream->priv; - if (mode == 0) - priv->state &= ~NAV_FLAG_WAIT_READ; - if (mode > 0) - priv->state |= NAV_FLAG_WAIT_READ; - if (automode == 0) - priv->state &= ~NAV_FLAG_WAIT_READ_AUTO; - if (automode > 0) - priv->state |= NAV_FLAG_WAIT_READ_AUTO; -} - -/** - * \brief Check if cell has changed - * \param stream: - stream pointer - * \param clear : - if true, then clear cell change flag - * \return 1 if cell has changed - */ -int mp_dvdnav_cell_has_changed (stream_t *stream, int clear) { - dvdnav_priv_t *priv = stream->priv; - if (!(priv->state & NAV_FLAG_CELL_CHANGE)) - return 0; - if (clear) { - priv->state &= ~NAV_FLAG_CELL_CHANGE; - priv->state |= NAV_FLAG_STREAM_CHANGE; - } - return 1; -} - -/** - * \brief Check if audio has changed - * \param stream: - stream pointer - * \param clear : - if true, then clear audio change flag - * \return 1 if audio has changed - */ -int mp_dvdnav_audio_has_changed (stream_t *stream, int clear) { - dvdnav_priv_t *priv = s |