Mercurial > mplayer.hg
comparison stream/stream_dvdnav.c @ 25824:eb338d06c638
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://
author | ben |
---|---|
date | Sat, 26 Jan 2008 11:51:34 +0000 |
parents | b43eaaa94dd3 |
children | 4c17a62383a4 |
comparison
equal
deleted
inserted
replaced
25823:60fda6c0c7dc | 25824:eb338d06c638 |
---|---|
16 #include "libavutil/common.h" | 16 #include "libavutil/common.h" |
17 #include "spudec.h" | 17 #include "spudec.h" |
18 #include "m_option.h" | 18 #include "m_option.h" |
19 #include "m_struct.h" | 19 #include "m_struct.h" |
20 #include "help_mp.h" | 20 #include "help_mp.h" |
21 #include "stream_dvd_common.h" | |
22 | |
23 /* state flags */ | |
24 typedef enum { | |
25 NAV_FLAG_EOF = 1 << 0, /* end of stream has been reached */ | |
26 NAV_FLAG_WAIT = 1 << 1, /* wait event */ | |
27 NAV_FLAG_WAIT_SKIP = 1 << 2, /* wait skip disable */ | |
28 NAV_FLAG_CELL_CHANGED = 1 << 3, /* cell change event */ | |
29 NAV_FLAG_WAIT_READ_AUTO = 1 << 4, /* wait read auto mode */ | |
30 NAV_FLAG_WAIT_READ = 1 << 5, /* suspend read from stream */ | |
31 NAV_FLAG_VTS_DOMAIN = 1 << 6, /* vts domain */ | |
32 } dvdnav_state_t; | |
21 | 33 |
22 typedef struct { | 34 typedef struct { |
23 dvdnav_t * dvdnav; /* handle to libdvdnav stuff */ | 35 dvdnav_t * dvdnav; /* handle to libdvdnav stuff */ |
24 char * filename; /* path */ | 36 char * filename; /* path */ |
25 unsigned int duration; /* in milliseconds */ | 37 unsigned int duration; /* in milliseconds */ |
26 int mousex, mousey; | 38 int mousex, mousey; |
27 int title; | 39 int title; |
28 unsigned int spu_clut[16], spu_set; | 40 unsigned int spu_clut[16], spu_set; |
29 dvdnav_highlight_event_t hlev; | 41 dvdnav_highlight_event_t hlev; |
42 int still_length; /* still frame duration */ | |
43 unsigned int state; | |
30 } dvdnav_priv_t; | 44 } dvdnav_priv_t; |
31 | 45 |
32 extern char *dvd_device; | 46 extern char *dvd_device; |
33 extern char *audio_lang, *dvdsub_lang; | 47 extern char *audio_lang, *dvdsub_lang; |
34 extern char *dvd_audio_stream_channels[6], *dvd_audio_stream_types[8]; | 48 extern char *dvd_audio_stream_channels[6], *dvd_audio_stream_types[8]; |
144 hlev->sy = hlev->ey = 0; | 158 hlev->sy = hlev->ey = 0; |
145 hlev->palette = hlev->buttonN = 0; | 159 hlev->palette = hlev->buttonN = 0; |
146 } | 160 } |
147 } | 161 } |
148 | 162 |
163 static inline int dvdnav_get_duration (int length) { | |
164 return (length == 255) ? 0 : length * 1000; | |
165 } | |
166 | |
149 static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len) { | 167 static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len) { |
150 int event = DVDNAV_NOP; | 168 int event = DVDNAV_NOP; |
151 | 169 |
152 *len=-1; | 170 *len=-1; |
153 if (dvdnav_get_next_block(priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) { | 171 if (dvdnav_get_next_block(priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) { |
158 // need to handle certain events internally (like skipping stills) | 176 // need to handle certain events internally (like skipping stills) |
159 switch (event) { | 177 switch (event) { |
160 case DVDNAV_NAV_PACKET: | 178 case DVDNAV_NAV_PACKET: |
161 return event; | 179 return event; |
162 case DVDNAV_STILL_FRAME: { | 180 case DVDNAV_STILL_FRAME: { |
163 dvdnav_still_skip(priv->dvdnav); // don't let dvdnav stall on this image | 181 dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf; |
182 priv->still_length = still_event->length; | |
183 /* set still frame duration */ | |
184 priv->duration = dvdnav_get_duration (priv->still_length); | |
185 if (priv->still_length <= 1) { | |
186 pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav); | |
187 priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm); | |
188 } | |
164 break; | 189 break; |
165 } | 190 } |
166 case DVDNAV_HIGHLIGHT: { | 191 case DVDNAV_HIGHLIGHT: { |
167 dvdnav_get_highlight (priv, 1); | 192 dvdnav_get_highlight (priv, 1); |
168 break; | 193 break; |
169 } | 194 } |
170 case DVDNAV_CELL_CHANGE: { | 195 case DVDNAV_CELL_CHANGE: { |
171 dvdnav_cell_change_event_t *ev = (dvdnav_cell_change_event_t*)buf; | 196 dvdnav_cell_change_event_t *ev = (dvdnav_cell_change_event_t*)buf; |
197 uint32_t nextstill; | |
198 | |
199 priv->state &= ~NAV_FLAG_WAIT_SKIP; | |
172 if(ev->pgc_length) | 200 if(ev->pgc_length) |
173 priv->duration = ev->pgc_length/90; | 201 priv->duration = ev->pgc_length/90; |
202 | |
203 if (dvdnav_is_domain_vts(priv->dvdnav)) | |
204 priv->state &= ~NAV_FLAG_VTS_DOMAIN; | |
205 else | |
206 priv->state |= NAV_FLAG_VTS_DOMAIN; | |
207 | |
208 nextstill = dvdnav_get_next_still_flag (priv->dvdnav); | |
209 if (nextstill) { | |
210 priv->duration = dvdnav_get_duration (nextstill); | |
211 priv->still_length = nextstill; | |
212 if (priv->still_length <= 1) { | |
213 pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav); | |
214 priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm); | |
215 } | |
216 } | |
217 | |
174 break; | 218 break; |
175 } | 219 } |
176 case DVDNAV_SPU_CLUT_CHANGE: { | 220 case DVDNAV_SPU_CLUT_CHANGE: { |
177 memcpy(priv->spu_clut, buf, 16*sizeof(unsigned int)); | 221 memcpy(priv->spu_clut, buf, 16*sizeof(unsigned int)); |
178 priv->spu_set = 1; | 222 priv->spu_set = 1; |
179 break; | 223 break; |
180 } | 224 } |
181 case DVDNAV_WAIT: | 225 case DVDNAV_WAIT: { |
182 dvdnav_wait_skip(priv->dvdnav); | 226 if ((priv->state & NAV_FLAG_WAIT_SKIP) && |
183 break; | 227 !(priv->state & NAV_FLAG_WAIT)) |
228 dvdnav_wait_skip (priv->dvdnav); | |
229 else | |
230 priv->state |= NAV_FLAG_WAIT; | |
231 break; | |
232 } | |
233 case DVDNAV_VTS_CHANGE: { | |
234 priv->state &= ~NAV_FLAG_WAIT_SKIP; | |
235 break; | |
236 } | |
184 } | 237 } |
185 | 238 |
186 *len=0; | 239 *len=0; |
187 } | 240 } |
188 return event; | 241 return event; |
235 static int fill_buffer(stream_t *s, char *but, int len) | 288 static int fill_buffer(stream_t *s, char *but, int len) |
236 { | 289 { |
237 int event; | 290 int event; |
238 | 291 |
239 dvdnav_priv_t* priv=s->priv; | 292 dvdnav_priv_t* priv=s->priv; |
293 if (priv->state & NAV_FLAG_WAIT_READ) /* read is suspended */ | |
294 return -1; | |
240 len=0; | 295 len=0; |
241 if(!s->end_pos) | 296 if(!s->end_pos) |
242 update_title_len(s); | 297 update_title_len(s); |
243 while(!len) /* grab all event until DVDNAV_BLOCK_OK (len=2048), DVDNAV_STOP or DVDNAV_STILL_FRAME */ | 298 while(!len) /* grab all event until DVDNAV_BLOCK_OK (len=2048), DVDNAV_STOP or DVDNAV_STILL_FRAME */ |
244 { | 299 { |
247 { | 302 { |
248 mp_msg(MSGT_CPLAYER,MSGL_ERR, "DVDNAV stream read error!\n"); | 303 mp_msg(MSGT_CPLAYER,MSGL_ERR, "DVDNAV stream read error!\n"); |
249 return 0; | 304 return 0; |
250 } | 305 } |
251 switch (event) { | 306 switch (event) { |
252 case DVDNAV_STOP: | 307 case DVDNAV_STOP: { |
308 priv->state |= NAV_FLAG_EOF; | |
309 return len; | |
310 } | |
253 case DVDNAV_BLOCK_OK: | 311 case DVDNAV_BLOCK_OK: |
254 case DVDNAV_NAV_PACKET: | 312 case DVDNAV_NAV_PACKET: |
313 case DVDNAV_STILL_FRAME: | |
255 return len; | 314 return len; |
315 case DVDNAV_WAIT: { | |
316 if (priv->state & NAV_FLAG_WAIT) | |
317 return len; | |
318 break; | |
319 } | |
256 case DVDNAV_VTS_CHANGE: { | 320 case DVDNAV_VTS_CHANGE: { |
257 int tit = 0, part = 0; | 321 int tit = 0, part = 0; |
258 dvdnav_vts_change_event_t *vts_event = (dvdnav_vts_change_event_t *)s->buffer; | 322 dvdnav_vts_change_event_t *vts_event = (dvdnav_vts_change_event_t *)s->buffer; |
259 mp_msg(MSGT_CPLAYER,MSGL_INFO, "DVDNAV, switched to title: %d\r\n", vts_event->new_vtsN); | 323 mp_msg(MSGT_CPLAYER,MSGL_INFO, "DVDNAV, switched to title: %d\r\n", vts_event->new_vtsN); |
324 priv->state |= NAV_FLAG_CELL_CHANGED; | |
325 priv->state &= ~NAV_FLAG_WAIT_SKIP; | |
326 priv->state &= ~NAV_FLAG_WAIT; | |
260 s->end_pos = 0; | 327 s->end_pos = 0; |
261 update_title_len(s); | 328 update_title_len(s); |
329 if (priv->state & NAV_FLAG_WAIT_READ_AUTO) | |
330 priv->state |= NAV_FLAG_WAIT_READ; | |
262 if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK) { | 331 if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK) { |
263 mp_msg(MSGT_CPLAYER,MSGL_V, "\r\nDVDNAV, NEW TITLE %d\r\n", tit); | 332 mp_msg(MSGT_CPLAYER,MSGL_V, "\r\nDVDNAV, NEW TITLE %d\r\n", tit); |
264 dvdnav_get_highlight (priv, 0); | 333 dvdnav_get_highlight (priv, 0); |
265 if(priv->title > 0 && tit != priv->title) | 334 if(priv->title > 0 && tit != priv->title) |
266 return 0; | 335 return 0; |
267 } | 336 } |
268 break; | 337 break; |
269 } | 338 } |
270 case DVDNAV_CELL_CHANGE: { | 339 case DVDNAV_CELL_CHANGE: { |
340 priv->state |= NAV_FLAG_CELL_CHANGED; | |
341 priv->state &= ~NAV_FLAG_WAIT_SKIP; | |
342 priv->state &= ~NAV_FLAG_WAIT; | |
343 if (priv->state & NAV_FLAG_WAIT_READ_AUTO) | |
344 priv->state |= NAV_FLAG_WAIT_READ; | |
271 if(priv->title > 0 && dvd_last_chapter > 0) { | 345 if(priv->title > 0 && dvd_last_chapter > 0) { |
272 int tit=0, part=0; | 346 int tit=0, part=0; |
273 if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK && part > dvd_last_chapter) | 347 if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK && part > dvd_last_chapter) |
274 return 0; | 348 return 0; |
275 } | 349 } |
315 *((unsigned int *)arg) = part - 1; | 389 *((unsigned int *)arg) = part - 1; |
316 return 1; | 390 return 1; |
317 } | 391 } |
318 case STREAM_CTRL_GET_TIME_LENGTH: | 392 case STREAM_CTRL_GET_TIME_LENGTH: |
319 { | 393 { |
320 if(priv->duration) | 394 if(priv->duration || priv->still_length) |
321 { | 395 { |
322 *((double *)arg) = (double)priv->duration / 1000.0; | 396 *((double *)arg) = (double)priv->duration / 1000.0; |
323 return 1; | 397 return 1; |
324 } | 398 } |
325 break; | 399 break; |
482 mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(priv->dvdnav)); | 556 mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(priv->dvdnav)); |
483 return STREAM_UNSUPPORTED; | 557 return STREAM_UNSUPPORTED; |
484 } | 558 } |
485 if(dvd_chapter > 0) | 559 if(dvd_chapter > 0) |
486 dvdnav_part_play(priv->dvdnav, p->track, dvd_chapter); | 560 dvdnav_part_play(priv->dvdnav, p->track, dvd_chapter); |
487 } else if(p->track == -1) | 561 } else if (p->track == 0) { |
488 dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root); | 562 if(dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root) != DVDNAV_STATUS_OK) |
489 else { | 563 dvdnav_menu_call(priv->dvdnav, DVD_MENU_Title); |
490 mp_msg(MSGT_OPEN,MSGL_INFO,"dvdnav_stream, you didn't specify a track number (as in dvdnav://1), playing whole disc\n"); | |
491 dvdnav_menu_call(priv->dvdnav, DVD_MENU_Title); | |
492 } | 564 } |
493 if(mp_msg_test(MSGT_IDENTIFY, MSGL_INFO)) | 565 if(mp_msg_test(MSGT_IDENTIFY, MSGL_INFO)) |
494 identify(priv, p); | 566 identify(priv, p); |
495 if(p->track > 0) | 567 if(p->track > 0) |
496 show_audio_subs_languages(priv->dvdnav); | 568 show_audio_subs_languages(priv->dvdnav); |
506 stream->type = STREAMTYPE_DVDNAV; | 578 stream->type = STREAMTYPE_DVDNAV; |
507 stream->priv=(void*)priv; | 579 stream->priv=(void*)priv; |
508 *file_format = DEMUXER_TYPE_MPEG_PS; | 580 *file_format = DEMUXER_TYPE_MPEG_PS; |
509 | 581 |
510 update_title_len(stream); | 582 update_title_len(stream); |
511 if(!stream->pos) | 583 if(!stream->pos && p->track > 0) |
512 mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: couldn't get init pos %s\r\n", dvdnav_err_to_string(priv->dvdnav)); | 584 mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: couldn't get init pos %s\r\n", dvdnav_err_to_string(priv->dvdnav)); |
513 | 585 |
514 mp_msg(MSGT_OPEN,MSGL_INFO, "Remember to disable MPlayer's cache when playing dvdnav:// streams (adding -nocache to your command line)\r\n"); | 586 mp_msg(MSGT_OPEN,MSGL_INFO, "Remember to disable MPlayer's cache when playing dvdnav:// streams (adding -nocache to your command line)\r\n"); |
515 | 587 |
516 return STREAM_OK; | 588 return STREAM_OK; |
517 } | 589 } |
518 | 590 |
519 | 591 |
520 int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) { | 592 void mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) { |
521 dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; | 593 dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; |
522 dvdnav_t *nav = priv->dvdnav; | 594 dvdnav_t *nav = priv->dvdnav; |
523 dvdnav_status_t status=DVDNAV_STATUS_ERR; | 595 dvdnav_status_t status=DVDNAV_STATUS_ERR; |
524 pci_t *pci = dvdnav_get_current_nav_pci(nav); | 596 pci_t *pci = dvdnav_get_current_nav_pci(nav); |
525 int reset = 0; | |
526 | 597 |
527 if(cmd != MP_CMD_DVDNAV_SELECT && !pci) | 598 if(cmd != MP_CMD_DVDNAV_SELECT && !pci) |
528 return 0; | 599 return; |
529 | 600 |
530 switch(cmd) { | 601 switch(cmd) { |
531 case MP_CMD_DVDNAV_UP: | 602 case MP_CMD_DVDNAV_UP: |
532 status = dvdnav_upper_button_select(nav, pci); | 603 status = dvdnav_upper_button_select(nav, pci); |
533 break; | 604 break; |
540 case MP_CMD_DVDNAV_RIGHT: | 611 case MP_CMD_DVDNAV_RIGHT: |
541 status = dvdnav_right_button_select(nav, pci); | 612 status = dvdnav_right_button_select(nav, pci); |
542 break; | 613 break; |
543 case MP_CMD_DVDNAV_MENU: | 614 case MP_CMD_DVDNAV_MENU: |
544 status = dvdnav_menu_call(nav,DVD_MENU_Root); | 615 status = dvdnav_menu_call(nav,DVD_MENU_Root); |
545 reset = 1; | |
546 break; | 616 break; |
547 case MP_CMD_DVDNAV_PREVMENU: { | 617 case MP_CMD_DVDNAV_PREVMENU: { |
548 int title=0, part=0; | 618 int title=0, part=0; |
549 | 619 |
550 dvdnav_current_title_info(nav, &title, &part); | 620 dvdnav_current_title_info(nav, &title, &part); |
551 if(title) { | 621 if(title) { |
552 if(dvdnav_menu_call(nav, DVD_MENU_Part) == DVDNAV_STATUS_OK | 622 if((status=dvdnav_menu_call(nav, DVD_MENU_Part)) == DVDNAV_STATUS_OK) |
553 || dvdnav_menu_call(nav, DVD_MENU_Title) == DVDNAV_STATUS_OK) { | |
554 reset = 1; | |
555 break; | 623 break; |
556 } | 624 } |
557 } | 625 if((status=dvdnav_menu_call(nav, DVD_MENU_Title)) == DVDNAV_STATUS_OK) |
558 if(dvdnav_menu_call(nav, DVD_MENU_Root) == DVDNAV_STATUS_OK) | 626 break; |
559 reset = 1; | 627 status=dvdnav_menu_call(nav, DVD_MENU_Root); |
560 } | 628 } |
561 break; | 629 break; |
562 case MP_CMD_DVDNAV_SELECT: | 630 case MP_CMD_DVDNAV_SELECT: |
563 status = dvdnav_button_activate(nav, pci); | 631 status = dvdnav_button_activate(nav, pci); |
564 if(status == DVDNAV_STATUS_OK) reset = 1; | |
565 break; | 632 break; |
566 case MP_CMD_DVDNAV_MOUSECLICK: | 633 case MP_CMD_DVDNAV_MOUSECLICK: |
567 /* | 634 /* |
568 this is a workaround: in theory the simple dvdnav_lower_button_select()+dvdnav_button_activate() | 635 this is a workaround: in theory the simple dvdnav_lower_button_select()+dvdnav_button_activate() |
569 should be enough (and generally it is), but there are cases when the calls to dvdnav_lower_button_select() | 636 should be enough (and generally it is), but there are cases when the calls to dvdnav_lower_button_select() |
570 and friends fail! Hence we have to call dvdnav_mouse_activate(priv->mousex, priv->mousey) with | 637 and friends fail! Hence we have to call dvdnav_mouse_activate(priv->mousex, priv->mousey) with |
571 the coodinates saved by mp_dvdnav_update_mouse_pos(). | 638 the coodinates saved by mp_dvdnav_update_mouse_pos(). |
572 This last call always works well | 639 This last call always works well |
573 */ | 640 */ |
574 status = dvdnav_mouse_activate(nav, pci, priv->mousex, priv->mousey); | 641 status = dvdnav_mouse_activate(nav, pci, priv->mousex, priv->mousey); |
575 if(status == DVDNAV_STATUS_OK) reset = 1; | |
576 break; | 642 break; |
577 default: | 643 default: |
578 mp_msg(MSGT_CPLAYER, MSGL_V, "Unknown DVDNAV cmd %d\n", cmd); | 644 mp_msg(MSGT_CPLAYER, MSGL_V, "Unknown DVDNAV cmd %d\n", cmd); |
579 break; | 645 break; |
580 } | 646 } |
581 | 647 |
582 if(status == DVDNAV_STATUS_OK) | 648 if(status == DVDNAV_STATUS_OK) |
583 dvdnav_get_current_highlight(nav, button); | 649 dvdnav_get_current_highlight(nav, button); |
584 | |
585 return reset; | |
586 } | 650 } |
587 | 651 |
588 void mp_dvdnav_update_mouse_pos(stream_t *stream, int32_t x, int32_t y, int* button) { | 652 void mp_dvdnav_update_mouse_pos(stream_t *stream, int32_t x, int32_t y, int* button) { |
589 dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; | 653 dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; |
590 dvdnav_t *nav = priv->dvdnav; | 654 dvdnav_t *nav = priv->dvdnav; |
720 */ | 784 */ |
721 int dvdnav_number_of_subs(stream_t *stream) { | 785 int dvdnav_number_of_subs(stream_t *stream) { |
722 dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; | 786 dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; |
723 uint8_t lg, k, n=0; | 787 uint8_t lg, k, n=0; |
724 | 788 |
789 if (priv->state & NAV_FLAG_VTS_DOMAIN) return 0; | |
725 for(k=0; k<32; k++) { | 790 for(k=0; k<32; k++) { |
726 lg = dvdnav_get_spu_logical_stream(priv->dvdnav, k); | 791 lg = dvdnav_get_spu_logical_stream(priv->dvdnav, k); |
727 if(lg == 0xff) continue; | 792 if(lg == 0xff) continue; |
728 n++; | 793 n++; |
729 } | 794 } |
762 | 827 |
763 dvdnav_get_number_of_titles (priv->dvdnav, &titles); | 828 dvdnav_get_number_of_titles (priv->dvdnav, &titles); |
764 if (title > 0 && title <= titles) | 829 if (title > 0 && title <= titles) |
765 dvdnav_title_play (priv->dvdnav, title); | 830 dvdnav_title_play (priv->dvdnav, title); |
766 } | 831 } |
832 | |
833 /** | |
834 * \brief Check if end of stream has been reached | |
835 * \param stream: - stream pointer | |
836 * \return 1 on really eof | |
837 */ | |
838 int mp_dvdnav_is_eof (stream_t *stream) { | |
839 return ((dvdnav_priv_t *) stream->priv)->state & NAV_FLAG_EOF; | |
840 } | |
841 | |
842 /** | |
843 * \brief Skip still frame | |
844 * \param stream: - stream pointer | |
845 * \return 0 on success | |
846 */ | |
847 int mp_dvdnav_skip_still (stream_t *stream) { | |
848 dvdnav_priv_t *priv = stream->priv; | |
849 if (priv->still_length == 0xff) | |
850 return 1; | |
851 dvdnav_still_skip(priv->dvdnav); | |
852 return 0; | |
853 } | |
854 | |
855 /** | |
856 * \brief Skip wait event | |
857 * \param stream: - stream pointer | |
858 * \return 0 on success | |
859 */ | |
860 int mp_dvdnav_skip_wait (stream_t *stream) { | |
861 dvdnav_priv_t *priv = stream->priv; | |
862 if (!(priv->state & NAV_FLAG_WAIT)) | |
863 return 1; | |
864 priv->state &= ~NAV_FLAG_WAIT; | |
865 dvdnav_wait_skip(priv->dvdnav); | |
866 return 0; | |
867 } | |
868 | |
869 /** | |
870 * \brief Set wait mode | |
871 * \param stream : - stream pointer | |
872 * \param mode : - if true, then suspend block read | |
873 * \param automode: - if true, then VTS or cell change set wait mode | |
874 */ | |
875 void mp_dvdnav_read_wait (stream_t *stream, int mode, int automode) { | |
876 dvdnav_priv_t *priv = stream->priv; | |
877 if (mode == 0) | |
878 priv->state &= ~NAV_FLAG_WAIT_READ; | |
879 if (mode > 0) | |
880 priv->state |= NAV_FLAG_WAIT_READ; | |
881 if (automode == 0) | |
882 priv->state &= ~NAV_FLAG_WAIT_READ_AUTO; | |
883 if (automode > 0) | |
884 priv->state |= NAV_FLAG_WAIT_READ_AUTO; | |
885 } | |
886 | |
887 /** | |
888 * \brief Check if cell has changed | |
889 * \param stream: - stream pointer | |
890 * \param clear : - if true, then clear cell change flag | |
891 * \return 1 if cell has changed | |
892 */ | |
893 int mp_dvdnav_cell_has_changed (stream_t *stream, int clear) { | |
894 dvdnav_priv_t *priv = stream->priv; | |
895 if (!(priv->state & NAV_FLAG_CELL_CHANGED)) | |
896 return 0; | |
897 if (clear) | |
898 priv->state &= ~NAV_FLAG_CELL_CHANGED; | |
899 return 1; | |
900 } | |
901 | |
767 | 902 |
768 const stream_info_t stream_info_dvdnav = { | 903 const stream_info_t stream_info_dvdnav = { |
769 "DVDNAV stream", | 904 "DVDNAV stream", |
770 "null", | 905 "null", |
771 "", | 906 "", |