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; int event,len,tmplen=0; uint32_t pos, l2; dvdnav_priv_t *priv; dvdnav_status_t status; 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_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename); return STREAM_UNSUPORTED; } if(p->track > 0) { if(dvd_chapter > 0 && dvd_last_chapter > 0 && dvd_chapter > dvd_last_chapter) { mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, invalid chapter range: %d > %d\n", dvd_chapter, dvd_last_chapter); return STREAM_UNSUPORTED; } 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_UNSUPORTED; } 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); } if(dvd_angle > 1) dvdnav_angle_change(priv->dvdnav, dvd_angle); stream->sector_size = 2048; stream->flags = STREAM_READ | 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) mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: %d, couldn't get init pos %s\r\n", status, 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; }
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) { *((double *)arg) = (double)priv->duration / 1000.0; return 1; } break; } } return STREAM_UNSUPORTED; }
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 = *(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->buf[0] = lang >> 8; req->buf[1] = lang; req->buf[2] = 0; return STREAM_OK; } } return STREAM_UNSUPPORTED; }
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) { *((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; } } return STREAM_UNSUPPORTED; }
void k9PlayMPEG2::playTitle() { dvdnav_t *dvdnav; uint8_t mem[DVD_VIDEO_LB_LEN]; int finished = 0; int32_t tt = 0,ptt=0; uint32_t pos, lgr; int title=m_title->getnumTitle(); /* open dvdnav handle */ if (dvdnav_open(&dvdnav, m_device,m_dvd) != DVDNAV_STATUS_OK) { setError("ERR:Error on dvdnav_open\n"); return ; } /* set read ahead cache usage */ if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) { setError(QString("ERR:Error on dvdnav_set_readahead_flag: %1\n").arg(dvdnav_err_to_string(dvdnav))); return; } /* set the language */ if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) { setError(QString("ERR:Error on setting languages: %1\n").arg(dvdnav_err_to_string(dvdnav))); return ; } /* set the PGC positioning flag to have position information relatively to the * whole feature instead of just relatively to the current chapter */ if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) { setError(QString("ERR:Error on dvdnav_set_PGC_positioning_flag: %1\n").arg(dvdnav_err_to_string(dvdnav))); return ; } int32_t parts; dvdnav_get_number_of_parts(dvdnav , title, &parts); if (m_chapter==0) dvdnav_title_play(dvdnav , title); else dvdnav_part_play(dvdnav , title,m_chapter); /* the read loop which regularly calls dvdnav_get_next_block * and handles the returned events */ while (!finished && !m_stopped && qApp!=NULL) { int result, event, len; uint8_t *buf = mem; if (m_idxLect !=0xFFFFFFFF) { dvdnav_sector_search(dvdnav, m_idxLect,SEEK_SET); m_idxLect=0xFFFFFFFF; } /* the main reading function */ #ifdef DVD_READ_CACHE result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len); #else result = dvdnav_get_next_block(dvdnav, buf, &event, &len); #endif if (result == DVDNAV_STATUS_ERR) { setError(QString("ERR:Error getting next block: %1\n").arg(dvdnav_err_to_string(dvdnav))); return; } switch (event) { case DVDNAV_NAV_PACKET: { dvdnav_current_title_info(dvdnav, &tt, &ptt); dvdnav_get_position(dvdnav, &pos, &lgr); if (tt != title) finished=1; if (finished==0 && buf[17]==0xE0) { m_decoder.addData( buf,len); } if (qApp->tryLock()) { emit setPosition( pos); qApp->unlock(); } } break; //removed break --> save case DVDNAV_BLOCK_OK: /* We have received a regular block of the currently playing MPEG stream.*/ m_decoder.addData( buf,len); break; case DVDNAV_NOP: /* Nothing to do here. */ break; case DVDNAV_STILL_FRAME: /* We have reached a still frame. A real player application would wait * the amount of time specified by the still's length while still handling * user input to make menus and other interactive stills work. * A length of 0xff means an indefinite still which has to be skipped * indirectly by some user interaction. */ { dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf; dvdnav_still_skip(dvdnav); } break; case DVDNAV_WAIT: /* We have reached a point in DVD playback, where timing is critical. * Player application with internal fifos can introduce state * inconsistencies, because libdvdnav is always the fifo's length * ahead in the stream compared to what the application sees. * Such applications should wait until their fifos are empty * when they receive this type of event. */ dvdnav_wait_skip(dvdnav); break; case DVDNAV_SPU_CLUT_CHANGE: /* Player applications should pass the new colour lookup table to their * SPU decoder */ break; case DVDNAV_SPU_STREAM_CHANGE: /* Player applications should inform their SPU decoder to switch channels */ break; case DVDNAV_AUDIO_STREAM_CHANGE: /* Player applications should inform their audio decoder to switch channels */ break; case DVDNAV_HIGHLIGHT: /* Player applications should inform their overlay engine to highlight the * given button */ { dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf; } break; case DVDNAV_VTS_CHANGE: /* Some status information like video aspect and video scale permissions do * not change inside a VTS. Therefore this event can be used to query such * information only when necessary and update the decoding/displaying * accordingly. */ break; case DVDNAV_CELL_CHANGE: // dvdnav_get_position(dvdnav, &pos, &lgr); break; case DVDNAV_HOP_CHANNEL: /* This event is issued whenever a non-seamless operation has been executed. * Applications with fifos should drop the fifos content to speed up responsiveness. */ break; case DVDNAV_STOP: /* Playback should end here. */ { finished = 1; } break; default: finished = 1; break; } #ifdef DVD_READ_CACHE dvdnav_free_cache_block(dvdnav, buf); #endif } m_decoder.setNoData(); /* destroy dvdnav handle */ dvdnav_close(dvdnav); }