summaryrefslogtreecommitdiffstats
path: root/k9decmpeg/k9plaympeg2.cpp
blob: f5ff3d767d4f4c84754190a41d57931c7e7ea587 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
//
// 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"