Mercurial > mplayer.hg
annotate stream/stream_dvdnav.c @ 19382:7c6c205b88b6
trying to fix the reverting paragraph
if you dissagree, dont hesitate to revert this commit or flame, but at least we should not claim that svn cannot revert commits except by recommiting the old version
author | michael |
---|---|
date | Sun, 13 Aug 2006 22:14:32 +0000 |
parents | ab8d6b6deb63 |
children | 6e618d1fbb23 |
rev | line source |
---|---|
19302 | 1 #include "config.h" |
2 | |
3 #include <stdlib.h> | |
4 #include <stdio.h> | |
5 #include <unistd.h> | |
6 #include <string.h> | |
7 #include "mp_msg.h" | |
8 #include "osdep/timer.h" | |
9 #include "input/input.h" | |
10 #include "stream.h" | |
19312
ab8d6b6deb63
proper inclusion of demuxer.h (including libmpdemux in Makefile only was to make previous split easier)
ben
parents:
19302
diff
changeset
|
11 #include "libmpdemux/demuxer.h" |
19302 | 12 #include "stream_dvdnav.h" |
13 #include "libvo/video_out.h" | |
14 #include "spudec.h" | |
15 #include "m_option.h" | |
16 #include "m_struct.h" | |
17 #include "help_mp.h" | |
18 | |
19 extern char *dvd_device; | |
20 extern char *audio_lang, *dvdsub_lang; | |
21 | |
22 static struct stream_priv_s { | |
23 int track; | |
24 char* device; | |
25 } stream_priv_dflts = { | |
26 1, | |
27 NULL | |
28 }; | |
29 | |
30 #define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) | |
31 /// URL definition | |
32 static m_option_t stream_opts_fields[] = { | |
33 {"filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL }, | |
34 {"hostname", ST_OFF(track), CONF_TYPE_INT, 0, 0, 0, NULL}, | |
35 { NULL, NULL, 0, 0, 0, 0, NULL } | |
36 }; | |
37 static struct m_struct_st stream_opts = { | |
38 "dvd", | |
39 sizeof(struct stream_priv_s), | |
40 &stream_priv_dflts, | |
41 stream_opts_fields | |
42 }; | |
43 | |
44 int dvd_nav_skip_opening=0; /* skip opening stalls? */ | |
45 int osd_show_dvd_nav_delay=0; /* count down for dvd nav text on OSD */ | |
46 char dvd_nav_text[50]; /* for reporting stuff to OSD */ | |
47 int osd_show_dvd_nav_highlight; /* show highlight area */ | |
48 int osd_show_dvd_nav_sx; /* start x .... */ | |
49 int osd_show_dvd_nav_ex; | |
50 int osd_show_dvd_nav_sy; | |
51 int osd_show_dvd_nav_ey; | |
52 int dvd_nav_still=0; /* are we on a still picture? */ | |
53 | |
54 dvdnav_priv_t * new_dvdnav_stream(char * filename) { | |
55 char * title_str; | |
56 dvdnav_priv_t *dvdnav_priv; | |
57 | |
58 if (!filename) | |
59 return NULL; | |
60 | |
61 if (!(dvdnav_priv=calloc(1,sizeof(*dvdnav_priv)))) | |
62 return NULL; | |
63 | |
64 if (!(dvdnav_priv->filename=strdup(filename))) { | |
65 free(dvdnav_priv); | |
66 return NULL; | |
67 } | |
68 | |
69 if(dvdnav_open(&(dvdnav_priv->dvdnav),dvdnav_priv->filename)!=DVDNAV_STATUS_OK) | |
70 { | |
71 free(dvdnav_priv->filename); | |
72 free(dvdnav_priv); | |
73 return NULL; | |
74 } | |
75 | |
76 if (!dvdnav_priv->dvdnav) { | |
77 free(dvdnav_priv); | |
78 return NULL; | |
79 } | |
80 | |
81 if(1) //from vlc: if not used dvdnav from cvs will fail | |
82 { | |
83 int len, event; | |
84 char buf[2048]; | |
85 | |
86 dvdnav_get_next_block(dvdnav_priv->dvdnav,buf,&event,&len); | |
87 } | |
88 | |
89 /* turn on dvdnav caching */ | |
90 dvdnav_set_readahead_flag(dvdnav_priv->dvdnav, 0); | |
91 if(dvdnav_set_PGC_positioning_flag(dvdnav_priv->dvdnav, 1) != DVDNAV_STATUS_OK) | |
92 mp_msg(MSGT_OPEN,MSGL_ERR,"stream_dvdnav, failed to set PGC positioning\n"); | |
93 #if 1 | |
94 /* report the title?! */ | |
95 if (dvdnav_get_title_string(dvdnav_priv->dvdnav,&title_str)==DVDNAV_STATUS_OK) { | |
96 mp_msg(MSGT_IDENTIFY, MSGL_INFO,"Title: '%s'\n",title_str); | |
97 } | |
98 #endif | |
99 | |
100 //dvdnav_event_clear(dvdnav_priv); | |
101 | |
102 return dvdnav_priv; | |
103 } | |
104 | |
105 int dvdnav_stream_reset(dvdnav_priv_t * dvdnav_priv) { | |
106 if (!dvdnav_priv) return 0; | |
107 | |
108 // if (dvdnav_reset(dvdnav_priv->dvdnav)!=DVDNAV_STATUS_OK) | |
109 return 0; | |
110 | |
111 dvdnav_priv->started=0; | |
112 | |
113 return 1; | |
114 } | |
115 | |
116 int dvdnav_stream_sleeping(dvdnav_priv_t * dvdnav_priv) { | |
117 unsigned int now; | |
118 | |
119 if (!dvdnav_priv) return 0; | |
120 | |
121 if(dvdnav_priv->sleeping) | |
122 { | |
123 now=GetTimer(); | |
124 while(dvdnav_priv->sleeping>1 || now<dvdnav_priv->sleep_until) { | |
125 // printf("%s %u<%u\n",__FUNCTION__,now,dvdnav_priv->sleep_until); | |
126 // usec_sleep(1000); /* 1ms granularity */ | |
127 return 1; | |
128 } | |
129 dvdnav_still_skip(dvdnav_priv->dvdnav); // continue past... | |
130 dvdnav_priv->sleeping=0; | |
131 mp_msg(MSGT_OPEN,MSGL_V, "%s: woke up!\n",__FUNCTION__); | |
132 } | |
133 dvd_nav_still=0; | |
134 mp_msg(MSGT_OPEN,MSGL_V, "%s: active\n",__FUNCTION__); | |
135 return 0; | |
136 } | |
137 | |
138 void dvdnav_stream_sleep(dvdnav_priv_t * dvdnav_priv, int seconds) { | |
139 if (!dvdnav_priv) return; | |
140 | |
141 if (!dvdnav_priv->started) return; | |
142 | |
143 dvdnav_priv->sleeping=0; | |
144 switch (seconds) { | |
145 case 0: | |
146 return; | |
147 case 0xff: | |
148 mp_msg(MSGT_OPEN,MSGL_V, "Sleeping indefinately\n" ); | |
149 dvdnav_priv->sleeping=2; | |
150 break; | |
151 default: | |
152 mp_msg(MSGT_OPEN,MSGL_V, "Sleeping %d sec(s)\n", seconds ); | |
153 dvdnav_priv->sleep_until = GetTimer();// + seconds*1000000; | |
154 dvdnav_priv->sleeping=1; | |
155 break; | |
156 } | |
157 //if (dvdnav_priv->started) dvd_nav_still=1; | |
158 } | |
159 | |
160 void dvdnav_stream_add_event(dvdnav_priv_t* dvdnav_priv, int event, unsigned char *buf, int len) { | |
161 //printf("%s: %d\n",__FUNCTION__,event); | |
162 | |
163 dvdnav_event_t * dvdnav_event; | |
164 mp_cmd_t * cmd; | |
165 | |
166 if (!dvdnav_priv->started) return; | |
167 | |
168 if (!(dvdnav_event=calloc(1,sizeof(*dvdnav_event)))) { | |
169 mp_msg(MSGT_OPEN,MSGL_V, "%s: dvdnav_event: out of memory!\n",__FUNCTION__); | |
170 return; | |
171 } | |
172 dvdnav_event->event=event; | |
173 dvdnav_event->details=calloc(1,len); | |
174 memcpy(dvdnav_event->details,buf,len); | |
175 dvdnav_event->len=len; | |
176 | |
177 if (!(cmd = calloc(1,sizeof(*cmd)))) { | |
178 mp_msg(MSGT_OPEN,MSGL_V, "%s: mp_cmd_t: out of memory!\n",__FUNCTION__); | |
179 free(dvdnav_event->details); | |
180 free(dvdnav_event); | |
181 return; | |
182 } | |
183 cmd->id=MP_CMD_DVDNAV_EVENT; // S+event; | |
184 cmd->name=strdup("dvdnav_event"); // FIXME: do I really need a 'name'? | |
185 cmd->nargs=1; | |
186 cmd->args[0].v.v=dvdnav_event; | |
187 } | |
188 | |
189 int dvdnav_stream_read(dvdnav_priv_t * dvdnav_priv, unsigned char *buf, int *len) { | |
190 int event = DVDNAV_NOP; | |
191 | |
192 if (!len) return -1; | |
193 *len=-1; | |
194 if (!dvdnav_priv) return -1; | |
195 if (!buf) return -1; | |
196 | |
197 if (dvd_nav_still) { | |
198 mp_msg(MSGT_OPEN,MSGL_V, "%s: got a stream_read while I should be asleep!\n",__FUNCTION__); | |
199 *len=0; | |
200 return -1; | |
201 } | |
202 | |
203 if (dvdnav_get_next_block(dvdnav_priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) { | |
204 mp_msg(MSGT_OPEN,MSGL_V, "Error getting next block from DVD %d (%s)\n",event, dvdnav_err_to_string(dvdnav_priv->dvdnav) ); | |
205 *len=-1; | |
206 } | |
207 else if (event!=DVDNAV_BLOCK_OK) { | |
208 | |
209 // need to handle certain events internally (like skipping stills) | |
210 switch (event) { | |
211 case DVDNAV_STILL_FRAME: { | |
212 dvdnav_still_event_t *still_event = (dvdnav_still_event_t*)(buf); | |
213 //if (dvdnav_priv->started) dvd_nav_still=1; | |
214 //else | |
215 dvdnav_still_skip(dvdnav_priv->dvdnav); // don't let dvdnav stall on this image | |
216 | |
217 break; | |
218 case DVDNAV_WAIT: | |
219 dvdnav_wait_skip(dvdnav_priv->dvdnav); | |
220 break; | |
221 } | |
222 } | |
223 | |
224 // got an event, repeat the read | |
225 dvdnav_stream_add_event(dvdnav_priv,event,buf,*len); | |
226 *len=0; | |
227 } | |
228 // printf("%s: got %d\n",__FUNCTION__,*len); | |
229 return event; | |
230 } | |
231 | |
232 void dvdnav_stream_fullstart(dvdnav_priv_t * dvdnav_priv) { | |
233 if (dvdnav_priv && !dvdnav_priv->started) { | |
234 dvdnav_stream_reset(dvdnav_priv); | |
235 dvdnav_priv->started=1; | |
236 } | |
237 } | |
238 | |
239 unsigned int * dvdnav_stream_get_palette(dvdnav_priv_t * dvdnav_priv) { | |
240 if (!dvdnav_priv) { | |
241 mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv\n",__FUNCTION__); | |
242 return NULL; | |
243 } | |
244 if (!dvdnav_priv->dvdnav) { | |
245 mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv->dvdnav\n",__FUNCTION__); | |
246 return NULL; | |
247 } | |
248 #if 0 | |
249 if (!dvdnav_priv->dvdnav->vm) { | |
250 mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv->dvdnav->vm\n",__FUNCTION__); | |
251 return NULL; | |
252 } | |
253 if (!dvdnav_priv->dvdnav->vm->state.pgc) { | |
254 printf("%s: NULL dvdnav_priv->dvdnav->vm->state.pgc\n",__FUNCTION__); | |
255 return NULL; | |
256 } | |
257 return dvdnav_priv->dvdnav->vm->state.pgc->palette; | |
258 #endif | |
259 } | |
260 | |
261 static void update_title_len(stream_t *stream) { | |
262 dvdnav_priv_t *priv = stream->priv; | |
263 dvdnav_status_t status; | |
264 uint32_t pos = 0, len = 0; | |
265 | |
266 status = dvdnav_get_position(priv->dvdnav, &pos, &len); | |
267 if(status == DVDNAV_STATUS_OK && len) | |
268 stream->end_pos = (off_t) len * 2048; | |
269 } | |
270 | |
271 | |
272 static int seek(stream_t *s, off_t newpos) { | |
273 uint32_t pos = 0, len = 0, sector = 0; | |
274 dvdnav_priv_t *priv = s->priv; | |
275 | |
276 if(newpos==0) { | |
277 if(dvdnav_stream_reset(priv->dvdnav)) | |
278 s->pos=0; | |
279 } | |
280 else { | |
281 if(s->end_pos && newpos > s->end_pos) | |
282 newpos = s->end_pos; | |
283 sector = newpos / 2048ULL; | |
284 if(dvdnav_sector_search(priv->dvdnav, (uint64_t) sector, SEEK_SET) != DVDNAV_STATUS_OK) | |
285 goto fail; | |
286 | |
287 s->pos = newpos; | |
288 } | |
289 | |
290 return 1; | |
291 | |
292 fail: | |
293 mp_msg(MSGT_STREAM,MSGL_INFO,"dvdnav_stream, seeking to %"PRIu64" failed: %s\n", newpos, dvdnav_err_to_string(priv->dvdnav)); | |
294 | |
295 return 1; | |
296 } | |
297 | |
298 static void stream_dvdnav_close(stream_t *s) { | |
299 dvdnav_priv_t *priv = s->priv; | |
300 dvdnav_close(priv->dvdnav); | |
301 priv->dvdnav = NULL; | |
302 free(priv); | |
303 } | |
304 | |
305 | |
306 static int fill_buffer(stream_t *s, char *but, int len) | |
307 { | |
308 int event; | |
309 dvdnav_priv_t* dvdnav_priv=s->priv; | |
310 len=0; | |
311 if(!s->end_pos) | |
312 update_title_len(s); | |
313 while(!len) /* grab all event until DVDNAV_BLOCK_OK (len=2048), DVDNAV_STOP or DVDNAV_STILL_FRAME */ | |
314 { | |
315 if(-1==(event=dvdnav_stream_read(dvdnav_priv, s->buffer, &len)) || len==-1) | |
316 { | |
317 mp_msg(MSGT_CPLAYER,MSGL_ERR, "DVDNAV stream read error!\n"); | |
318 return 0; | |
319 } | |
320 switch (event) { | |
321 case DVDNAV_STOP: return len; | |
322 case DVDNAV_BLOCK_OK: return len; | |
323 #if 0 | |
324 case DVDNAV_STILL_FRAME: { | |
325 if(!dvdnav_priv->stillok) dvdnav_priv->stillcounter++; | |
326 dvdnav_priv->lockstillcounter++; | |
327 return len; | |
328 break; | |
329 } | |
330 | |
331 case DVDNAV_WAIT: { | |
332 if(dvdnav_priv->waitcounter>=DVDNAV_MAX_WAIT_FRAME) return len; | |
333 break; | |
334 } | |
335 #endif | |
336 } | |
337 #if 0 | |
338 if(dvdnav_priv->event.cell_really_change && | |
339 dvdnav_priv->started && | |
340 !dvdnav_priv->vts_domain) | |
341 return len; | |
342 #endif | |
343 } | |
344 mp_msg(MSGT_STREAM,MSGL_DBG2,"DVDNAV fill_buffer len: %d\n",len); | |
345 return len; | |
346 } | |
347 | |
348 static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { | |
349 struct stream_priv_s* p = (struct stream_priv_s*)opts; | |
350 char *filename; | |
351 int event,len,tmplen=0; | |
352 uint32_t pos, l2; | |
353 dvdnav_priv_t *dvdnav_priv; | |
354 dvdnav_status_t status; | |
355 | |
356 //mp_msg(MSGT_OPEN,MSGL_INFO,"URL: %s\n", filename); | |
357 | |
358 if(p->device) filename = p->device; | |
359 else if(dvd_device) filename= dvd_device; | |
360 else filename = DEFAULT_DVD_DEVICE; | |
361 if(!(dvdnav_priv=new_dvdnav_stream(filename))) { | |
362 mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename); | |
363 return STREAM_UNSUPORTED; | |
364 } | |
365 | |
366 if(dvdnav_title_play(dvdnav_priv->dvdnav, p->track) != DVDNAV_STATUS_OK) { | |
367 mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(dvdnav_priv->dvdnav)); | |
368 return STREAM_UNSUPORTED; | |
369 } | |
370 | |
371 stream->sector_size = 2048; | |
372 stream->flags = STREAM_READ | STREAM_SEEK; | |
373 stream->fill_buffer = fill_buffer; | |
374 stream->seek = seek; | |
375 stream->close = stream_dvdnav_close; | |
376 stream->type = STREAMTYPE_DVDNAV; | |
377 stream->priv=(void*)dvdnav_priv; | |
378 *file_format = DEMUXER_TYPE_MPEG_PS; | |
379 | |
380 update_title_len(stream); | |
381 if(!stream->pos) | |
382 mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: %d, couldn't get init pos %s\r\n", status, dvdnav_err_to_string(dvdnav_priv->dvdnav)); | |
383 | |
384 return STREAM_OK; | |
385 } | |
386 | |
387 stream_info_t stream_info_dvdnav = { | |
388 "DVDNAV stream", | |
389 "null", | |
390 "", | |
391 "", | |
392 open_s, | |
393 { "dvdnav", NULL }, | |
394 &stream_opts, | |
395 1 // Urls are an option string | |
396 }; |