mirror of
https://github.com/mpv-player/mpv
synced 2025-03-25 04:38:01 +00:00
Add support for dvdnav still frames playback.
Based on various patches from Otvos Attila and MPlayer'ized by me. N.B. Always use -vc ffmpeg12 with dvdnav:// git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@25852 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
2597f0c3e2
commit
d56fe785be
@ -3124,12 +3124,8 @@ int run_command(MPContext * mpctx, mp_cmd_t * cmd)
|
||||
if (mpctx->stream->type != STREAMTYPE_DVDNAV)
|
||||
break;
|
||||
|
||||
if (mp_dvdnav_handle_input
|
||||
(mpctx->stream, cmd->args[0].v.i, &button)) {
|
||||
uninit_player(INITED_ALL - (INITED_STREAM | INITED_INPUT |
|
||||
(fixed_vo ? INITED_VO : 0)));
|
||||
brk_cmd = 2;
|
||||
} else if (button > 0)
|
||||
mp_dvdnav_handle_input(mpctx->stream,cmd->args[0].v.i,&button);
|
||||
if (button > 0)
|
||||
set_osd_msg(OSD_MSG_TEXT, 1, osd_duration,
|
||||
"Selected button number %d", button);
|
||||
}
|
||||
|
@ -102,6 +102,13 @@ typedef struct MPContext {
|
||||
#endif
|
||||
|
||||
int was_paused;
|
||||
|
||||
#ifdef USE_DVDNAV
|
||||
mp_image_t *nav_smpi; ///< last decoded dvdnav video image
|
||||
unsigned char *nav_buffer; ///< last read dvdnav video frame
|
||||
unsigned char *nav_start; ///< pointer to last read video buffer
|
||||
int nav_in_size; ///< last read size
|
||||
#endif
|
||||
} MPContext;
|
||||
|
||||
|
||||
|
171
mplayer.c
171
mplayer.c
@ -573,6 +573,17 @@ char *get_metadata (metadata_t type) {
|
||||
/// step size of mixer changes
|
||||
int volstep = 3;
|
||||
|
||||
#ifdef USE_DVDNAV
|
||||
static void mp_dvdnav_context_free(MPContext *ctx){
|
||||
if (ctx->nav_smpi) free_mp_image(ctx->nav_smpi);
|
||||
ctx->nav_smpi = NULL;
|
||||
if (ctx->nav_buffer) free(ctx->nav_buffer);
|
||||
ctx->nav_buffer = NULL;
|
||||
ctx->nav_start = NULL;
|
||||
ctx->nav_in_size = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void uninit_player(unsigned int mask){
|
||||
mask=inited_flags&mask;
|
||||
|
||||
@ -622,6 +633,9 @@ void uninit_player(unsigned int mask){
|
||||
current_module="uninit_vo";
|
||||
mpctx->video_out->uninit();
|
||||
mpctx->video_out=NULL;
|
||||
#ifdef USE_DVDNAV
|
||||
mp_dvdnav_context_free(mpctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Must be after libvo uninit, as few vo drivers (svgalib) have tty code.
|
||||
@ -1767,6 +1781,136 @@ static float timing_sleep(float time_frame)
|
||||
return time_frame;
|
||||
}
|
||||
|
||||
#ifdef USE_DVDNAV
|
||||
#ifndef FF_B_TYPE
|
||||
#define FF_B_TYPE 3
|
||||
#endif
|
||||
/// store decoded video image
|
||||
static mp_image_t * mp_dvdnav_copy_mpi(mp_image_t *to_mpi,
|
||||
mp_image_t *from_mpi) {
|
||||
mp_image_t *mpi;
|
||||
|
||||
/// Do not store B-frames
|
||||
if (from_mpi->pict_type == FF_B_TYPE)
|
||||
return to_mpi;
|
||||
|
||||
if (to_mpi &&
|
||||
to_mpi->w == from_mpi->w &&
|
||||
to_mpi->h == from_mpi->h &&
|
||||
to_mpi->imgfmt == from_mpi->imgfmt)
|
||||
mpi = to_mpi;
|
||||
else {
|
||||
if (to_mpi)
|
||||
free_mp_image(to_mpi);
|
||||
if (from_mpi->w == 0 || from_mpi->h == 0)
|
||||
return NULL;
|
||||
mpi = alloc_mpi(from_mpi->w,from_mpi->h,from_mpi->imgfmt);
|
||||
}
|
||||
|
||||
copy_mpi(mpi,from_mpi);
|
||||
return mpi;
|
||||
}
|
||||
|
||||
static void mp_dvdnav_reset_stream (MPContext *ctx) {
|
||||
if (ctx->sh_video) {
|
||||
/// clear video pts
|
||||
ctx->d_video->pts = 0.0f;
|
||||
ctx->sh_video->pts = 0.0f;
|
||||
ctx->sh_video->i_pts = 0.0f;
|
||||
ctx->sh_video->last_pts = 0.0f;
|
||||
ctx->sh_video->num_buffered_pts = 0;
|
||||
ctx->sh_video->num_frames = 0;
|
||||
ctx->sh_video->num_frames_decoded = 0;
|
||||
ctx->sh_video->timer = 0.0f;
|
||||
ctx->sh_video->stream_delay = 0.0f;
|
||||
ctx->sh_video->timer = 0;
|
||||
ctx->demuxer->stream_pts = MP_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
if (ctx->sh_audio) {
|
||||
/// free audio packets and reset
|
||||
ds_free_packs(ctx->d_audio);
|
||||
audio_delay -= ctx->sh_audio->stream_delay;
|
||||
ctx->delay =- audio_delay;
|
||||
ctx->audio_out->reset();
|
||||
resync_audio_stream(ctx->sh_audio);
|
||||
}
|
||||
|
||||
if (ctx->d_sub) dvdsub_id = -2;
|
||||
|
||||
audio_delay = 0.0f;
|
||||
correct_pts = 0;
|
||||
|
||||
/// clear all EOF related flags
|
||||
ctx->d_video->eof = ctx->d_audio->eof = ctx->stream->eof = 0;
|
||||
}
|
||||
|
||||
/// Restore last decoded DVDNAV (still frame)
|
||||
static mp_image_t *mp_dvdnav_restore_smpi(int *in_size,
|
||||
unsigned char **start,
|
||||
mp_image_t *decoded_frame)
|
||||
{
|
||||
if (mpctx->stream->type != STREAMTYPE_DVDNAV)
|
||||
return decoded_frame;
|
||||
|
||||
/// a change occured in dvdnav stream
|
||||
if (mp_dvdnav_cell_has_changed(mpctx->stream,0)) {
|
||||
mp_dvdnav_read_wait(mpctx->stream, 1, 1);
|
||||
mp_dvdnav_context_free(mpctx);
|
||||
mp_dvdnav_reset_stream(mpctx);
|
||||
mp_dvdnav_read_wait(mpctx->stream, 0, 1);
|
||||
mp_dvdnav_cell_has_changed(mpctx->stream,1);
|
||||
}
|
||||
|
||||
if (*in_size < 0) {
|
||||
float len;
|
||||
|
||||
/// Display still frame, if any
|
||||
if (mpctx->nav_smpi && !mpctx->nav_buffer)
|
||||
decoded_frame = mpctx->nav_smpi;
|
||||
|
||||
/// increment video frame : continue playing after still frame
|
||||
len = demuxer_get_time_length(mpctx->demuxer);
|
||||
if (mpctx->sh_video->pts >= len &&
|
||||
mpctx->sh_video->pts > 0.0 && len > 0.0) {
|
||||
mp_dvdnav_skip_still(mpctx->stream);
|
||||
mp_dvdnav_skip_wait(mpctx->stream);
|
||||
}
|
||||
mpctx->sh_video->pts += 1 / mpctx->sh_video->fps;
|
||||
|
||||
if (mpctx->nav_buffer) {
|
||||
*start = mpctx->nav_start;
|
||||
*in_size = mpctx->nav_in_size;
|
||||
if (mpctx->nav_start)
|
||||
memcpy(*start,mpctx->nav_buffer,mpctx->nav_in_size);
|
||||
}
|
||||
}
|
||||
|
||||
return decoded_frame;
|
||||
}
|
||||
|
||||
/// Save last decoded DVDNAV (still frame)
|
||||
static void mp_dvdnav_save_smpi(int in_size,
|
||||
unsigned char *start,
|
||||
mp_image_t *decoded_frame)
|
||||
{
|
||||
if (mpctx->stream->type != STREAMTYPE_DVDNAV)
|
||||
return;
|
||||
|
||||
if (mpctx->nav_buffer)
|
||||
free(mpctx->nav_buffer);
|
||||
|
||||
mpctx->nav_buffer = malloc(in_size);
|
||||
mpctx->nav_start = start;
|
||||
mpctx->nav_in_size = mpctx->nav_buffer ? in_size : -1;
|
||||
if (mpctx->nav_buffer)
|
||||
memcpy(mpctx->nav_buffer,start,in_size);
|
||||
|
||||
if (decoded_frame && mpctx->nav_smpi != decoded_frame)
|
||||
mpctx->nav_smpi = mp_dvdnav_copy_mpi(mpctx->nav_smpi,decoded_frame);
|
||||
}
|
||||
#endif /* USE_DVDNAV */
|
||||
|
||||
static void adjust_sync_and_print_status(int between_frames, float timing_error)
|
||||
{
|
||||
current_module="av_sync";
|
||||
@ -2079,7 +2223,7 @@ static double update_video(int *blit_frame)
|
||||
*blit_frame = 0; // Don't blit if we hit EOF
|
||||
if (!correct_pts) {
|
||||
unsigned char* start=NULL;
|
||||
void *decoded_frame;
|
||||
void *decoded_frame = NULL;
|
||||
int drop_frame=0;
|
||||
int in_size;
|
||||
|
||||
@ -2087,6 +2231,15 @@ static double update_video(int *blit_frame)
|
||||
frame_time = sh_video->next_frame_time;
|
||||
in_size = video_read_frame(sh_video, &sh_video->next_frame_time,
|
||||
&start, force_fps);
|
||||
#ifdef USE_DVDNAV
|
||||
/// wait, still frame or EOF
|
||||
if (mpctx->stream->type == STREAMTYPE_DVDNAV && in_size < 0) {
|
||||
if (mp_dvdnav_is_eof(mpctx->stream)) return -1;
|
||||
if (mpctx->d_video) mpctx->d_video->eof = 0;
|
||||
if (mpctx->d_audio) mpctx->d_audio->eof = 0;
|
||||
mpctx->stream->eof = 0;
|
||||
} else
|
||||
#endif
|
||||
if (in_size < 0)
|
||||
return -1;
|
||||
if (in_size > max_framesize)
|
||||
@ -2117,8 +2270,17 @@ static double update_video(int *blit_frame)
|
||||
update_teletext(sh_video, mpctx->demuxer, 0);
|
||||
update_osd_msg();
|
||||
current_module = "decode_video";
|
||||
#ifdef USE_DVDNAV
|
||||
decoded_frame = mp_dvdnav_restore_smpi(&in_size,&start,decoded_frame);
|
||||
/// still frame has been reached, no need to decode
|
||||
if (in_size > 0 && !decoded_frame)
|
||||
#endif
|
||||
decoded_frame = decode_video(sh_video, start, in_size, drop_frame,
|
||||
sh_video->pts);
|
||||
#ifdef USE_DVDNAV
|
||||
/// save back last still frame for future display
|
||||
mp_dvdnav_save_smpi(in_size,start,decoded_frame);
|
||||
#endif
|
||||
current_module = "filter_video";
|
||||
*blit_frame = (decoded_frame && filter_video(sh_video, decoded_frame,
|
||||
sh_video->pts));
|
||||
@ -3463,6 +3625,13 @@ if (end_at.type == END_AT_SIZE) {
|
||||
end_at.type = END_AT_NONE;
|
||||
}
|
||||
|
||||
#ifdef USE_DVDNAV
|
||||
mp_dvdnav_context_free(mpctx);
|
||||
if (mpctx->stream->type == STREAMTYPE_DVDNAV) {
|
||||
mp_dvdnav_read_wait(mpctx->stream, 0, 1);
|
||||
mp_dvdnav_cell_has_changed(mpctx->stream,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(!mpctx->eof){
|
||||
float aq_sleep_time=0;
|
||||
|
@ -18,6 +18,18 @@
|
||||
#include "m_option.h"
|
||||
#include "m_struct.h"
|
||||
#include "help_mp.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_CHANGED = 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 */
|
||||
} dvdnav_state_t;
|
||||
|
||||
typedef struct {
|
||||
dvdnav_t * dvdnav; /* handle to libdvdnav stuff */
|
||||
@ -27,6 +39,8 @@ typedef struct {
|
||||
int title;
|
||||
unsigned int spu_clut[16], spu_set;
|
||||
dvdnav_highlight_event_t hlev;
|
||||
int still_length; /* still frame duration */
|
||||
unsigned int state;
|
||||
} dvdnav_priv_t;
|
||||
|
||||
extern char *dvd_device;
|
||||
@ -146,6 +160,10 @@ static void dvdnav_get_highlight (dvdnav_priv_t *priv, int display_mode) {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -160,7 +178,14 @@ static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len
|
||||
case DVDNAV_NAV_PACKET:
|
||||
return event;
|
||||
case DVDNAV_STILL_FRAME: {
|
||||
dvdnav_still_skip(priv->dvdnav); // don't let dvdnav stall on this image
|
||||
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: {
|
||||
@ -169,8 +194,27 @@ static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len
|
||||
}
|
||||
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;
|
||||
if(ev->pgc_length)
|
||||
priv->duration = ev->pgc_length/90;
|
||||
|
||||
if (dvdnav_is_domain_vts(priv->dvdnav))
|
||||
priv->state &= ~NAV_FLAG_VTS_DOMAIN;
|
||||
else
|
||||
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: {
|
||||
@ -178,9 +222,18 @@ static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len
|
||||
priv->spu_set = 1;
|
||||
break;
|
||||
}
|
||||
case DVDNAV_WAIT:
|
||||
dvdnav_wait_skip(priv->dvdnav);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*len=0;
|
||||
@ -237,6 +290,8 @@ 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);
|
||||
@ -249,16 +304,30 @@ static int fill_buffer(stream_t *s, char *but, int len)
|
||||
return 0;
|
||||
}
|
||||
switch (event) {
|
||||
case DVDNAV_STOP:
|
||||
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_CHANGED;
|
||||
priv->state &= ~NAV_FLAG_WAIT_SKIP;
|
||||
priv->state &= ~NAV_FLAG_WAIT;
|
||||
s->end_pos = 0;
|
||||
update_title_len(s);
|
||||
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);
|
||||
@ -268,6 +337,11 @@ static int fill_buffer(stream_t *s, char *but, int len)
|
||||
break;
|
||||
}
|
||||
case DVDNAV_CELL_CHANGE: {
|
||||
priv->state |= NAV_FLAG_CELL_CHANGED;
|
||||
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 && dvd_last_chapter > 0) {
|
||||
int tit=0, part=0;
|
||||
if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK && part > dvd_last_chapter)
|
||||
@ -317,7 +391,7 @@ static int control(stream_t *stream, int cmd, void* arg) {
|
||||
}
|
||||
case STREAM_CTRL_GET_TIME_LENGTH:
|
||||
{
|
||||
if(priv->duration)
|
||||
if(priv->duration || priv->still_length)
|
||||
{
|
||||
*((double *)arg) = (double)priv->duration / 1000.0;
|
||||
return 1;
|
||||
@ -484,11 +558,9 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||
}
|
||||
if(dvd_chapter > 0)
|
||||
dvdnav_part_play(priv->dvdnav, p->track, dvd_chapter);
|
||||
} else if(p->track == -1)
|
||||
dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root);
|
||||
else {
|
||||
mp_msg(MSGT_OPEN,MSGL_INFO,"dvdnav_stream, you didn't specify a track number (as in dvdnav://1), playing whole disc\n");
|
||||
dvdnav_menu_call(priv->dvdnav, DVD_MENU_Title);
|
||||
} 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);
|
||||
@ -508,7 +580,7 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||
*file_format = DEMUXER_TYPE_MPEG_PS;
|
||||
|
||||
update_title_len(stream);
|
||||
if(!stream->pos)
|
||||
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");
|
||||
@ -517,15 +589,14 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||
}
|
||||
|
||||
|
||||
int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) {
|
||||
void mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) {
|
||||
dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv;
|
||||
dvdnav_t *nav = priv->dvdnav;
|
||||
dvdnav_status_t status=DVDNAV_STATUS_ERR;
|
||||
pci_t *pci = dvdnav_get_current_nav_pci(nav);
|
||||
int reset = 0;
|
||||
|
||||
if(cmd != MP_CMD_DVDNAV_SELECT && !pci)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
switch(cmd) {
|
||||
case MP_CMD_DVDNAV_UP:
|
||||
@ -542,26 +613,22 @@ int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) {
|
||||
break;
|
||||
case MP_CMD_DVDNAV_MENU:
|
||||
status = dvdnav_menu_call(nav,DVD_MENU_Root);
|
||||
reset = 1;
|
||||
break;
|
||||
case MP_CMD_DVDNAV_PREVMENU: {
|
||||
int title=0, part=0;
|
||||
|
||||
dvdnav_current_title_info(nav, &title, &part);
|
||||
if(title) {
|
||||
if(dvdnav_menu_call(nav, DVD_MENU_Part) == DVDNAV_STATUS_OK
|
||||
|| dvdnav_menu_call(nav, DVD_MENU_Title) == DVDNAV_STATUS_OK) {
|
||||
reset = 1;
|
||||
if((status=dvdnav_menu_call(nav, DVD_MENU_Part)) == DVDNAV_STATUS_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dvdnav_menu_call(nav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
|
||||
reset = 1;
|
||||
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);
|
||||
if(status == DVDNAV_STATUS_OK) reset = 1;
|
||||
break;
|
||||
case MP_CMD_DVDNAV_MOUSECLICK:
|
||||
/*
|
||||
@ -572,7 +639,6 @@ int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) {
|
||||
This last call always works well
|
||||
*/
|
||||
status = dvdnav_mouse_activate(nav, pci, priv->mousex, priv->mousey);
|
||||
if(status == DVDNAV_STATUS_OK) reset = 1;
|
||||
break;
|
||||
default:
|
||||
mp_msg(MSGT_CPLAYER, MSGL_V, "Unknown DVDNAV cmd %d\n", cmd);
|
||||
@ -581,8 +647,6 @@ int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) {
|
||||
|
||||
if(status == DVDNAV_STATUS_OK)
|
||||
dvdnav_get_current_highlight(nav, button);
|
||||
|
||||
return reset;
|
||||
}
|
||||
|
||||
void mp_dvdnav_update_mouse_pos(stream_t *stream, int32_t x, int32_t y, int* button) {
|
||||
@ -722,6 +786,7 @@ int dvdnav_number_of_subs(stream_t *stream) {
|
||||
dvdnav_priv_t * priv=(dvdnav_priv_t*)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;
|
||||
@ -765,6 +830,76 @@ void mp_dvdnav_switch_title (stream_t *stream, int title) {
|
||||
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_CHANGED))
|
||||
return 0;
|
||||
if (clear)
|
||||
priv->state &= ~NAV_FLAG_CELL_CHANGED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const stream_info_t stream_info_dvdnav = {
|
||||
"DVDNAV stream",
|
||||
"null",
|
||||
|
@ -17,10 +17,15 @@ int dvdnav_aid_from_lang(stream_t *stream, unsigned char *language);
|
||||
int dvdnav_lang_from_aid(stream_t *stream, int id, unsigned char *buf);
|
||||
int dvdnav_sid_from_lang(stream_t *stream, unsigned char *language);
|
||||
int dvdnav_lang_from_sid(stream_t *stream, int sid, unsigned char *buf);
|
||||
int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button);
|
||||
void mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button);
|
||||
void mp_dvdnav_update_mouse_pos(stream_t *stream, int32_t x, int32_t y, int* button);
|
||||
void mp_dvdnav_get_highlight (stream_t *stream, nav_highlight_t *hl);
|
||||
unsigned int *mp_dvdnav_get_spu_clut(stream_t *stream);
|
||||
void mp_dvdnav_switch_title(stream_t *stream, int title);
|
||||
int mp_dvdnav_is_eof (stream_t *stream);
|
||||
int mp_dvdnav_skip_still (stream_t *stream);
|
||||
int mp_dvdnav_skip_wait (stream_t *stream);
|
||||
void mp_dvdnav_read_wait (stream_t *stream, int mode, int automode);
|
||||
int mp_dvdnav_cell_has_changed (stream_t *stream, int clear);
|
||||
|
||||
#endif /* MPLAYER_STREAM_DVDNAV_H */
|
||||
|
Loading…
Reference in New Issue
Block a user