You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k9copy/k9decmpeg/k9plaympeg2.cpp

278 lines
7.7 KiB

//
// C++ Implementation: k9plaympeg2
//
// Description:
//
//
// Author: Jean-Michel PETIT <k9copy@free.fr>, (C) 2006
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "k9plaympeg2.h"
#include "kdecmpeg2.h"
#include "dvdnav.h"
#include <klocale.h>
#include <tqapplication.h>
k9PlayMPEG2::k9PlayMPEG2()
{
m_title=NULL;
}
k9PlayMPEG2::~k9PlayMPEG2()
{
stop();
}
void k9PlayMPEG2::updatePos( uint32_t _position) {
m_idxLect=_position;
m_decoder.clear();
m_decoder.getDecoder()->restart();
}
#define DVD_LANGUAGE "en"
#define DVD_READ_CACHE 1
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(TQString("ERR:Error on dvdnav_set_readahead_flag: %1\n").tqarg(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(TQString("ERR:Error on setting languages: %1\n").tqarg(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(TQString("ERR:Error on dvdnav_set_PGC_positioning_flag: %1\n").tqarg(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 && tqApp!=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(TQString("ERR:Error getting next block: %1\n").tqarg(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 (tqApp->tryLock()) {
emit setPosition( pos);
tqApp->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);
}
void k9PlayMPEG2::run() {
m_stopped=false;
m_idxLect=m_startSector;
playTitle();
}
void k9PlayMPEG2::stop() {
m_stopped=TRUE;
m_decoder.setNoData();
m_decoder.clear();
m_decoder.wait();
wait();
}
void k9PlayMPEG2::play() {
if (m_stopped && m_title!=NULL)
open(m_dvd,m_device,m_title,m_chapter);
}
kDecMPEG2 *k9PlayMPEG2::getDecoder() {
return m_decoder.getDecoder() ;
}
void k9PlayMPEG2::open (dvd_reader_t *dvd,const TQString & device,k9DVDTitle * title,int chapter=0) {
m_dvd=dvd;
m_chapter=chapter;
int ret = 0;
struct stat dvd_stat;
TQString c;
m_idxLect=0xFFFFFFFF;
stop();
m_title=title;
m_device=device;
m_startSector=0;
m_lastSector=0;
ret = stat(device.utf8(), &dvd_stat);
/* if ( ret < 0 ) {
c=i18n("Can't find device %1\n").tqarg(device.latin1());
setError(c);
return;
}
*/
m_title=title;
m_startSector=m_title->getChapter( 0)->getstartSector();
m_lastSector= m_startSector + m_title->getsectors(); //m_title->getChapter(m_title->getchapterCount()-1)->getendSector();
emit setPosition( m_startSector);
emit setMax( m_lastSector);
emit setMin( m_startSector);
m_decoder.start(TQThread::LowPriority);
start();
}
#include "k9plaympeg2.moc"