source: titan/libdreamdvd/main.c @ 42984

Last change on this file since 42984 was 31353, checked in by obi, 9 years ago

reset

File size: 105.6 KB
Line 
1/*
2 * DreamDVD V0.9 - DVD-Player for Dreambox
3 * Copyright (C) 2007 by Seddi
4 *
5 * This DVD Player is based upon the great work from the libdvdnav project,
6 * a52dec library, ffmpeg and the knowledge from all the people who made
7 * watching DVD within linux possible.
8 *
9 * DreamDVD is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * DreamDVD is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
22 *
23 * part of libdreamdvd
24 */
25
26#include "main.h"
27#include "mpegaudioenc.h"
28#include "a52dec.h"
29#include <asm/types.h>
30
31#ifdef __sh__
32//aktivate LPCM Support
33#define HARDWARE_SUPPORT_LPCM
34#endif
35
36/*
37 * local helper functions
38 */
39static ssize_t safe_write(int fd, const void *buf, size_t count)
40{
41        const uint8_t *ptr = buf;
42        size_t written = 0;
43        ssize_t n;
44
45        while (written < count) {
46                n = write(fd, &ptr[written], count - written);
47#if defined(__sh__)
48                return 0;
49#else           
50                if (n < 0) {
51                        if (errno != EINTR) {
52                                perror("write");
53                                return written ? written : -1;
54                        }
55                } else {
56                        written += n;
57                }
58#endif         
59        }
60
61        return written;
62}
63
64static void write_string(const char *filename, const char *string)
65{
66        FILE *f;
67
68        f = fopen(filename, "w");
69        if (f == NULL) {
70                perror(filename);
71                return;
72        }
73
74        fputs(string, f);
75        fclose(f);
76}
77
78static int open_pipe(int fd[2])
79{
80        int flags;
81
82        fd[0] = fd[1] = -1;
83
84        if (pipe(fd) < 0) {
85                perror("pipe");
86                goto err;
87        }
88
89        flags = fcntl(fd[0], F_GETFL);
90        if (flags < 0) {
91                perror("F_GETFL");
92                goto err;
93        }
94        if (fcntl(fd[0], F_SETFL, flags | O_NONBLOCK) < 0) {
95                perror("F_SETFL");
96                goto err;
97        }
98
99        return 0;
100
101err:
102        if (fd[0] != -1) {
103                close(fd[0]);
104                fd[0] = -1;
105        }
106        if (fd[1] != -1) {
107                close(fd[1]);
108                fd[1] = -1;
109        }
110
111        return -1;
112}
113
114/*
115 * external functions
116 */
117
118// create ddvd handle and set defaults
119struct ddvd *ddvd_create(void)
120{
121        struct ddvd *pconfig;
122
123        pconfig = malloc(sizeof(struct ddvd));
124        if (pconfig == NULL) {
125                perror("malloc");
126                return NULL;
127        }
128
129        memset(pconfig, 0, sizeof(struct ddvd));
130
131        // defaults
132        ddvd_set_ac3thru(pconfig, 0);
133        ddvd_set_language(pconfig, "en");
134#if defined(__sh__)
135        ddvd_set_dvd_path(pconfig, "/dev/sr0");
136#else
137        ddvd_set_dvd_path(pconfig, "/dev/cdroms/cdrom0");
138#endif
139        ddvd_set_video(pconfig, DDVD_4_3, DDVD_LETTERBOX, DDVD_PAL);
140        ddvd_set_lfb(pconfig, NULL, 720, 576, 1, 720);
141        struct ddvd_resume resume_info;
142        resume_info.title=resume_info.chapter=resume_info.block=resume_info.audio_id=resume_info.audio_lock=resume_info.spu_id=resume_info.spu_lock=0;
143        ddvd_set_resume_pos(pconfig, resume_info);
144        pconfig->should_resume = 0;
145        pconfig->next_time_update = 0;
146        strcpy(pconfig->title_string, "");
147
148        // open pipes
149        if (open_pipe(pconfig->key_pipe) < 0) {
150                ddvd_close(pconfig);
151                return NULL;
152        }
153        if (open_pipe(pconfig->message_pipe) < 0) {
154                ddvd_close(pconfig);
155                return NULL;
156        }
157
158        return pconfig;
159}
160
161// destroy ddvd handle
162void ddvd_close(struct ddvd *pconfig)
163{
164        if (pconfig->message_pipe[0] != -1)
165                close(pconfig->message_pipe[0]);
166        if (pconfig->message_pipe[1] != -1)
167                close(pconfig->message_pipe[1]);
168        if (pconfig->key_pipe[0] != -1)
169                close(pconfig->key_pipe[0]);
170        if (pconfig->key_pipe[1] != -1)
171                close(pconfig->key_pipe[1]);
172        if (pconfig->dvd_path != NULL)
173                free(pconfig->dvd_path);
174
175        free(pconfig);
176}
177
178// get message_pipe fd for polling functions in the host app
179int ddvd_get_messagepipe_fd(struct ddvd *pconfig)
180{
181        return pconfig->message_pipe[0];
182}
183
184// set resume postion
185void ddvd_set_resume_pos(struct ddvd *pconfig, struct ddvd_resume resume_info)
186{
187        pconfig->resume_title = resume_info.title;
188        pconfig->resume_chapter = resume_info.chapter;
189        pconfig->resume_block = resume_info.block;
190        pconfig->should_resume = 1;
191        pconfig->resume_audio_id = resume_info.audio_id;
192        pconfig->resume_audio_lock = resume_info.audio_lock;
193        pconfig->resume_spu_id = resume_info.spu_id;
194        pconfig->resume_spu_lock = resume_info.spu_lock;
195}
196
197// set framebuffer options
198void ddvd_set_lfb(struct ddvd *pconfig, unsigned char *lfb, int xres, int yres, int bypp, int stride)
199{
200        return ddvd_set_lfb_ex(pconfig, lfb, xres, yres, bypp, stride, 0);
201}
202
203void ddvd_set_lfb_ex(struct ddvd *pconfig, unsigned char *lfb, int xres, int yres, int bypp, int stride, int canscale)
204{
205        pconfig->lfb = lfb;
206        pconfig->xres = xres;
207        pconfig->yres = yres;
208        pconfig->stride = stride;
209        pconfig->bypp = bypp;
210        pconfig->canscale = canscale;
211}
212
213// set path to dvd block device or file structure/iso
214void ddvd_set_dvd_path(struct ddvd *pconfig, const char *path)
215{
216        if (pconfig->dvd_path != NULL)
217                free(pconfig->dvd_path);
218
219        pconfig->dvd_path = strdup(path);
220}
221
222// set language
223void ddvd_set_language(struct ddvd *pconfig, const char lang[2])
224{
225        memcpy(pconfig->language, lang, 2);
226}
227
228// set internal ac3 decoding (needs liba52 which will be dynamically loaded)
229void ddvd_set_ac3thru(struct ddvd *pconfig, int ac3thru)
230{
231        pconfig->ac3thru = ac3thru;
232}
233
234// set video options
235void ddvd_set_video_ex(struct ddvd *pconfig, int aspect, int tv_mode, int tv_mode2, int tv_system)
236{
237        pconfig->aspect = aspect;
238        pconfig->tv_mode = tv_mode;
239        pconfig->tv_mode2 = tv_mode2;
240        pconfig->tv_system = tv_system;
241}
242
243// set subtitle stream id
244void ddvd_set_spu(struct ddvd *pconfig, int spu_id)
245{
246        ddvd_send_key(pconfig, DDVD_SET_SUBTITLE);
247        ddvd_send_key(pconfig, spu_id);
248}
249
250// set audio stream id
251void ddvd_set_audio(struct ddvd *pconfig, int audio_id)
252{
253        ddvd_send_key(pconfig, DDVD_SET_AUDIO);
254        ddvd_send_key(pconfig, audio_id);
255}
256
257// set video options
258void ddvd_set_video(struct ddvd *pconfig, int aspect, int tv_mode, int tv_system)
259{
260        ddvd_set_video_ex(pconfig, aspect, tv_mode, tv_mode, tv_system);
261}
262
263// send commands/keys to the main player
264void ddvd_send_key(struct ddvd *pconfig, int key)
265{
266        safe_write(pconfig->key_pipe[1], &key, sizeof(int));
267}
268
269// skip n seconds in playing n>0 forward - n<0 backward
270void ddvd_skip_seconds(struct ddvd *pconfig, int seconds)
271{
272        if (seconds < 0)
273                ddvd_send_key(pconfig, DDVD_SKIP_BWD);
274        else
275                ddvd_send_key(pconfig, DDVD_SKIP_FWD);
276
277        ddvd_send_key(pconfig, seconds);
278}
279
280// jump to beginning of given title
281void ddvd_set_title(struct ddvd *pconfig, int title)
282{
283        ddvd_send_key(pconfig, DDVD_SET_TITLE);
284        ddvd_send_key(pconfig, title);
285}
286
287// jump to beginning of given chapter
288void ddvd_set_chapter(struct ddvd *pconfig, int chapter)
289{
290        ddvd_send_key(pconfig, DDVD_SET_CHAPTER);
291        ddvd_send_key(pconfig, chapter);
292}
293
294// get and process the next message from the main player
295int ddvd_get_next_message(struct ddvd *pconfig, int blocked)
296{
297        int res;
298        int i;
299
300        if (ddvd_readpipe(pconfig->message_pipe[0], &res, sizeof(int), blocked) != sizeof(int))
301                res = DDVD_NULL;
302
303        switch (res)            // more data to process ?
304        {
305        case DDVD_COLORTABLE_UPDATE:
306                for (i = 0; i < 4; i++)
307                        ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_col[i], sizeof(struct ddvd_color), 1);
308                break;
309        case DDVD_SHOWOSD_TIME:
310                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_time, sizeof(pconfig->last_time), 1);
311                break;
312        case DDVD_SHOWOSD_STATE_FFWD:
313                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_trickspeed, sizeof(pconfig->last_trickspeed), 1);
314                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_time, sizeof(pconfig->last_time), 1);
315                break;
316        case DDVD_SHOWOSD_STATE_FBWD:
317                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_trickspeed, sizeof(pconfig->last_trickspeed), 1);
318                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_time, sizeof(pconfig->last_time), 1);
319                break;
320        case DDVD_SHOWOSD_STRING:
321                ddvd_readpipe(pconfig->message_pipe[0], pconfig->last_string, sizeof(pconfig->last_string), 1);
322                break;
323        case DDVD_SHOWOSD_AUDIO:
324                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_audio_id, sizeof(int), 1);
325                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_audio_lang, sizeof(uint16_t), 1);
326                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_audio_type, sizeof(int), 1);
327                break;
328        case DDVD_SHOWOSD_SUBTITLE:
329                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_spu_id, sizeof(int), 1);
330                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_spu_lang, sizeof(uint16_t), 1);
331                break;
332        case DDVD_SCREEN_UPDATE:
333                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->blit_area, sizeof(pconfig->blit_area), 1);
334                break;
335        case DDVD_SHOWOSD_ANGLE:
336                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->angle_current, sizeof(int), 1);
337                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->angle_num, sizeof(int), 1);
338                break;
339        case DDVD_SIZE_CHANGED:
340                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_size, sizeof(struct ddvd_size_evt), 1);
341                break;
342        case DDVD_PROGRESSIVE_CHANGED:
343                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_progressive, sizeof(struct ddvd_progressive_evt), 1);
344                break;
345        case DDVD_FRAMERATE_CHANGED:
346                ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_framerate, sizeof(struct ddvd_framerate_evt), 1);
347                break;
348        default:
349                break;
350        }
351        return res;
352}
353
354// get last blit area
355void ddvd_get_last_blit_area(struct ddvd *pconfig, int *x_start, int *x_end, int *y_start, int *y_end)
356{
357        struct ddvd_resize_return *ptr = &pconfig->blit_area;
358        memcpy(x_start, &ptr->x_start, sizeof(int));
359        memcpy(x_end, &ptr->x_end, sizeof(int));
360        memcpy(y_start, &ptr->y_start, sizeof(int));
361        memcpy(y_end, &ptr->y_end, sizeof(int));
362}
363
364/*void ddvd_get_blit_destination(struct ddvd *pconfig, int *x_offset, int *y_offset, int *width, int *height)
365{
366        struct ddvd_resize_return *ptr = &pconfig->blit_area;
367
368        *x_offset = ptr->x_offset;
369        *y_offset = ptr->y_offset;
370        *width = ptr->width;
371        *height = ptr->height;
372}*/
373
374// get angle info
375void ddvd_get_angle_info(struct ddvd*pconfig, int *current, int *num)
376{
377        memcpy(current, &pconfig->angle_current, sizeof(pconfig->angle_current));
378        memcpy(num, &pconfig->angle_num, sizeof(pconfig->angle_num));
379}
380
381// get last colortable for 8bit mode (4 colors)
382void ddvd_get_last_colortable(struct ddvd *pconfig, void *colortable)
383{
384        memcpy(colortable, pconfig->last_col, sizeof(pconfig->last_col));
385}
386
387// get last received playing time as struct ddvd_time
388void ddvd_get_last_time(struct ddvd *pconfig, void *timestamp)
389{
390        memcpy(timestamp, &pconfig->last_time, sizeof(pconfig->last_time));
391}
392
393// get the actual trickspeed (2-64x) when in trickmode
394void ddvd_get_last_trickspeed(struct ddvd *pconfig, void *trickspeed)
395{
396        memcpy(trickspeed, &pconfig->last_trickspeed, sizeof(pconfig->last_trickspeed));
397}
398
399// get last text message from player
400void ddvd_get_last_string(struct ddvd *pconfig, void *text)
401{
402        memcpy(text, pconfig->last_string, sizeof(pconfig->last_string));
403}
404
405// get the number of available audio tracks
406void ddvd_get_audio_count(struct ddvd *pconfig, void *count)
407{
408        int c = 0;
409        int i;
410        for ( i = 0; i < MAX_AUDIO; i++)
411        {
412                if ( pconfig->audio_format[i] != -1 )
413                        c++;
414        }
415        memcpy(count, &c, sizeof(int));
416}
417
418// get the active audio track
419void ddvd_get_last_audio(struct ddvd *pconfig, void *id, void *lang, void *type)
420{
421        memcpy(id, &pconfig->last_audio_id, sizeof(pconfig->last_audio_id));
422        memcpy(lang, &pconfig->last_audio_lang, sizeof(pconfig->last_audio_lang));
423        memcpy(type, &pconfig->last_audio_type, sizeof(pconfig->last_audio_type));
424}
425
426// get audio track details for given audio track id
427void ddvd_get_audio_byid(struct ddvd *pconfig, int audio_id, void *lang, void *type)
428{
429        int audio_id_logical;
430        uint16_t audio_lang = 0xFFFF;
431        audio_id_logical = dvdnav_get_audio_logical_stream(dvdnav, audio_id);
432        audio_lang = dvdnav_audio_stream_to_lang(dvdnav, audio_id_logical);
433        if (audio_lang == 0xFFFF)
434                audio_lang = 0x2D2D;
435        memcpy(lang, &audio_lang, sizeof(uint16_t));
436        memcpy(type, &pconfig->audio_format[audio_id], sizeof(int));
437}
438
439// get the active SPU track
440void ddvd_get_last_spu(struct ddvd *pconfig, void *id, void *lang)
441{
442        memcpy(id, &pconfig->last_spu_id, sizeof(pconfig->last_spu_id));
443        memcpy(lang, &pconfig->last_spu_lang, sizeof(pconfig->last_spu_lang));
444}
445
446// get the number of available subtitle tracks
447void ddvd_get_spu_count(struct ddvd *pconfig, void *count)
448{
449        int c = 0;
450        int i;
451        for ( i = 0; i < MAX_SPU; i++)
452        {
453                if ( pconfig->spu_map[i] != -1 )
454                        c++;
455        }
456        memcpy(count, &c, sizeof(int));
457}
458
459// get audio track details for given subtitle track id
460void ddvd_get_spu_byid(struct ddvd *pconfig, int spu_id, void *lang)
461{
462        uint16_t spu_lang = 0xFFFF;
463        if (spu_id < MAX_SPU & pconfig->spu_map[spu_id] > -1)
464                spu_lang = dvdnav_spu_stream_to_lang(dvdnav, pconfig->spu_map[spu_id]);
465        memcpy(lang, &spu_lang, sizeof(uint16_t));
466}
467
468// get dvd title string
469void ddvd_get_title_string(struct ddvd *pconfig, char *title_string)
470{
471        memcpy(title_string, pconfig->title_string, sizeof(pconfig->title_string));
472}
473
474// get actual position for resuming
475void ddvd_get_resume_pos(struct ddvd *pconfig, struct ddvd_resume *resume_info)
476{
477        memcpy(&resume_info->title, &pconfig->resume_title, sizeof(pconfig->resume_title));
478        memcpy(&resume_info->chapter, &pconfig->resume_chapter, sizeof(pconfig->resume_chapter));
479        memcpy(&resume_info->block, &pconfig->resume_block, sizeof(pconfig->resume_block));
480        memcpy(&resume_info->audio_id, &pconfig->resume_audio_id, sizeof(pconfig->resume_audio_id));
481        memcpy(&resume_info->audio_lock, &pconfig->resume_audio_lock, sizeof(pconfig->resume_audio_lock));
482        memcpy(&resume_info->spu_id, &pconfig->resume_spu_id, sizeof(pconfig->resume_spu_id));
483        memcpy(&resume_info->spu_lock, &pconfig->resume_spu_lock, sizeof(pconfig->resume_spu_lock));
484}
485
486void ddvd_get_last_size(struct ddvd *pconfig, int *width, int *height, int *aspect)
487{
488        *width = pconfig->last_size.width;
489        *height = pconfig->last_size.height;
490        *aspect = pconfig->last_size.aspect;
491}
492
493void ddvd_get_last_progressive(struct ddvd *pconfig, int *progressive)
494{
495        *progressive = pconfig->last_progressive.progressive;
496}
497
498void ddvd_get_last_framerate(struct ddvd *pconfig, int *framerate)
499{
500        *framerate = pconfig->last_framerate.framerate;
501}
502
503struct ddvd_spu_return merge(struct ddvd_spu_return a, struct ddvd_spu_return b)
504{
505        struct ddvd_spu_return r;
506        r = b;
507       
508        if (a.x_start !=  a.x_end || a.y_start != a.y_end)
509        {
510                        /* union old and new area */
511                if (a.x_start < r.x_start)
512                        r.x_start = a.x_start;
513                if (a.y_start < r.y_start)
514                        r.y_start = a.y_start;
515                if (a.x_end > r.x_end)
516                        r.x_end = a.x_end;
517                if (a.y_end > r.y_end)
518                        r.y_end = a.y_end;
519        }
520        return r;
521}
522
523//needed for titan
524#if defined(__sh__)
525int ddvd_get_dvd_aspect(struct ddvd *playerconfig)
526{
527        if(playerconfig != NULL)
528                return playerconfig->dvd_aspect;
529        else
530                return -1;
531}
532#endif
533
534static int calc_x_scale_offset(int dvd_aspect, int tv_mode, int tv_mode2, int tv_aspect)
535{
536        int x_offset=0;
537
538        if (dvd_aspect == 0 && tv_mode == DDVD_PAN_SCAN) {
539                switch (tv_aspect) {
540                case DDVD_16_10:
541                        x_offset = (ddvd_screeninfo_xres - ddvd_screeninfo_xres * 12 / 15) / 2;  // correct 16:10 (broadcom 15:9) panscan (pillarbox) overlay
542                        break;
543                case DDVD_16_9:
544                        x_offset = (ddvd_screeninfo_xres - ddvd_screeninfo_xres * 3 / 4) / 2; // correct 16:9 panscan (pillarbox) overlay
545                default:
546                        break;
547                }
548        }
549
550        if (dvd_aspect >= 2 && tv_aspect == DDVD_4_3 && tv_mode == DDVD_PAN_SCAN)
551                x_offset = -(ddvd_screeninfo_xres * 4 / 3 - ddvd_screeninfo_xres) / 2;
552
553        if (dvd_aspect >= 2 && tv_aspect == DDVD_16_10 && tv_mode2 == DDVD_PAN_SCAN)
554                x_offset = -(ddvd_screeninfo_xres * 16 / 15 - ddvd_screeninfo_xres) / 2;
555
556        return x_offset;
557}
558
559static int calc_y_scale_offset(int dvd_aspect, int tv_mode, int tv_mode2, int tv_aspect)
560{
561        int y_offset = 0;
562
563        if (dvd_aspect == 0 && tv_mode == DDVD_LETTERBOX) {
564                switch (tv_aspect) {
565                case DDVD_16_10:
566                        y_offset = (ddvd_screeninfo_yres * 15 / 12 - ddvd_screeninfo_yres) / 2; // correct 16:10 (broacom 15:9) letterbox overlay
567                        break;
568                case DDVD_16_9:
569                        y_offset = (ddvd_screeninfo_yres * 4 / 3 - ddvd_screeninfo_yres) / 2; // correct 16:9 letterbox overlay
570                default:
571                        break;
572                }
573        }
574
575        if (dvd_aspect >= 2 && tv_aspect == DDVD_4_3 && tv_mode == DDVD_LETTERBOX)
576                y_offset = -(ddvd_screeninfo_yres - ddvd_screeninfo_yres * 3 / 4) / 2;
577
578        if (dvd_aspect >= 2 && tv_aspect == DDVD_16_10 && tv_mode2 == DDVD_LETTERBOX)
579                y_offset = -(ddvd_screeninfo_yres - ddvd_screeninfo_yres * 15 / 16) / 2;
580
581        return y_offset;
582}
583
584#if CONFIG_API_VERSION >= 3
585static int readMpegProc(char *str, int decoder)
586{
587        int val = -1;
588        char tmp[64];
589        sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
590        FILE *f = fopen(tmp, "r");
591        if (f)
592        {
593                fscanf(f, "%x", &val);
594                fclose(f);
595        }
596        return val;
597}
598
599static int readApiSize(int fd, int *xres, int *yres, int *aspect)
600{
601        video_size_t size;
602        if (!ioctl(fd, VIDEO_GET_SIZE, &size))
603        {
604                *xres = size.w;
605                *yres = size.h;
606                *aspect = size.aspect_ratio == 0 ? 2 : 3;  // convert dvb api to etsi
607                return 0;
608        }
609        return -1;
610}
611
612static int readApiFrameRate(int fd, int *framerate)
613{
614        unsigned int frate;
615        if (!ioctl(fd, VIDEO_GET_FRAME_RATE, &frate))
616        {
617                *framerate = frate;
618                return 0;
619        }
620        return -1;
621}
622#endif
623
624// the main player loop
625enum ddvd_result ddvd_run(struct ddvd *playerconfig)
626{
627        if (playerconfig->lfb == NULL) {
628                printf("Frame/backbuffer not given to libdreamdvd. Will not start the player !\n");
629                return DDVD_INVAL;
630        }
631
632        // we need to know the first vts_change and the next cell change for resuming a dvd
633        int first_vts_change = 1;
634        int next_cell_change = 0;
635        int ddvd_have_ntsc = -1;
636       
637        ddvd_screeninfo_xres = playerconfig->xres;
638        ddvd_screeninfo_yres = playerconfig->yres;
639        ddvd_screeninfo_stride = playerconfig->stride;
640        int ddvd_screeninfo_bypp = playerconfig->bypp;
641        int message_pipe = playerconfig->message_pipe[1];
642        int key_pipe = playerconfig->key_pipe[0];
643        unsigned char *p_lfb = playerconfig->lfb;
644        enum ddvd_result res = DDVD_OK;
645        int msg;
646        // try to load liba52.so.0 for softdecoding
647#if defined(__sh__)
648#else
649        int have_liba52 = ddvd_load_liba52();
650#endif
651       
652        // decide which resize routine we should use
653        // on 4bpp mode we use bicubic resize for sd skins because we get much better results with subtitles and the speed is ok
654        // for hd skins we use nearest neighbor resize because upscaling to hd is too slow with bicubic resize
655        if (ddvd_screeninfo_bypp == 1)
656                ddvd_resize_pixmap = ddvd_resize_pixmap_spu = &ddvd_resize_pixmap_1bpp;
657        else if (ddvd_screeninfo_xres > 720)
658                ddvd_resize_pixmap = ddvd_resize_pixmap_spu = &ddvd_resize_pixmap_xbpp;
659        else
660        {
661                ddvd_resize_pixmap = &ddvd_resize_pixmap_xbpp;
662                ddvd_resize_pixmap_spu = &ddvd_resize_pixmap_xbpp_smooth;
663        }
664
665        uint8_t *last_iframe = NULL;
666        uint8_t *spu_buffer = NULL;
667        uint8_t *spu_backbuffer = NULL;
668
669        // init backbuffer (SPU)
670        ddvd_lbb = malloc(720 * 576);   // the spu backbuffer is always max DVD PAL 720x576 pixel (NTSC 720x480)
671        if (ddvd_lbb == NULL) {
672                perror("SPU-Backbuffer <mem allocation failed>");
673                res = DDVD_NOMEM;
674                goto err_malloc;
675        }
676        ddvd_lbb2 = malloc(ddvd_screeninfo_xres * ddvd_screeninfo_yres * ddvd_screeninfo_bypp);
677        if (ddvd_lbb2 == NULL) {
678                perror("SPU-Backbuffer <mem allocation failed>");
679                res = DDVD_NOMEM;
680                goto err_malloc;
681        }
682       
683        last_iframe = malloc(320 * 1024);
684        if (last_iframe == NULL) {
685                perror("malloc");
686                res = DDVD_NOMEM;
687                goto err_malloc;
688        }
689
690        spu_buffer = malloc(2 * (128 * 1024));
691        if (spu_buffer == NULL) {
692                perror("malloc");
693                res = DDVD_NOMEM;
694                goto err_malloc;
695        }
696
697        spu_backbuffer = malloc(NUM_SPU_BACKBUFFER * 2 * (128 * 1024));
698        if (spu_backbuffer == NULL) {
699                perror("malloc");
700                res = DDVD_NOMEM;
701                goto err_malloc;
702        }
703
704        struct ddvd_resize_return blit_area;
705       
706        memset(ddvd_lbb, 0, 720 * 576);
707        memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear screen                 
708        blit_area.x_start = blit_area.y_start = 0;
709        blit_area.x_end = ddvd_screeninfo_xres - 1;
710        blit_area.y_end = ddvd_screeninfo_yres - 1;
711        blit_area.x_offset = 0;
712        blit_area.y_offset = 0;
713        blit_area.width = ddvd_screeninfo_xres;
714        blit_area.height = ddvd_screeninfo_yres;
715       
716        msg = DDVD_SCREEN_UPDATE;
717        safe_write(message_pipe, &msg, sizeof(int));
718        safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
719       
720        printf("Opening output...\n");
721
722#if CONFIG_API_VERSION == 1
723        ddvd_output_fd = open("/dev/video", O_WRONLY);
724        if (ddvd_output_fd == -1) {
725                perror("/dev/video");
726                res = DDVD_BUSY;
727                goto err_open_output_fd;
728        }
729
730        ddvd_fdvideo = open("/dev/dvb/card0/video0", O_RDWR);
731        if (ddvd_fdvideo == -1) {
732                perror("/dev/dvb/card0/video0");
733                res = DDVD_BUSY;
734                goto err_open_fdvideo;
735        }
736
737        ddvd_fdaudio = open("/dev/dvb/card0/audio0", O_RDWR);
738        if (ddvd_fdaudio == -1) {
739                perror("/dev/dvb/card0/audio0");
740                res = DDVD_BUSY;
741                goto err_open_fdaudio;
742        }
743
744        ddvd_ac3_fd = open("/dev/sound/dsp1", O_RDWR);
745        if (ddvd_ac3_fd == -1) {
746                perror("/dev/sound/dsp1");
747                res = DDVD_BUSY;
748                goto err_open_ac3_fd;
749        }
750
751        if (ioctl(ddvd_fdvideo, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY) < 0)
752                perror("VIDEO_SELECT_SOURCE");
753        if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
754                perror("VIDEO_CLEAR_BUFFER");
755        if (ioctl(ddvd_fdvideo, VIDEO_PLAY) < 0)
756                perror("VIDEO_PLAY");
757
758        if (ioctl(ddvd_fdaudio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0)
759                perror("AUDIO_SELECT_SOURCE");
760        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
761                perror("AUDIO_CLEAR_BUFFER");
762        if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
763                perror("AUDIO_PLAY");
764
765#elif CONFIG_API_VERSION == 3
766        ddvd_output_fd = ddvd_fdvideo = open("/dev/dvb/adapter0/video0", O_RDWR);
767        if (ddvd_fdvideo == -1) {
768                perror("/dev/dvb/adapter0/video0");
769                res = DDVD_BUSY;
770                goto err_open_fdvideo;
771        }
772
773        ddvd_ac3_fd = ddvd_fdaudio = open("/dev/dvb/adapter0/audio0", O_RDWR);
774        if (ddvd_fdaudio == -1) {
775                perror("/dev/dvb/adapter0/audio0");
776                res = DDVD_BUSY;
777                goto err_open_ac3_fd;
778        }
779
780        if (ioctl(ddvd_fdvideo, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY) < 0)
781                perror("VIDEO_SELECT_SOURCE");
782        if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
783                perror("VIDEO_CLEAR_BUFFER");
784        if (ioctl(ddvd_fdvideo, VIDEO_SET_STREAMTYPE, 0) < 0)   // set mpeg2
785                perror("VIDEO_SET_STREAMTYPE");
786        if (ioctl(ddvd_fdvideo, VIDEO_PLAY) < 0)
787                perror("VIDEO_PLAY");
788
789        if (ioctl(ddvd_fdaudio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0)
790                perror("AUDIO_SELECT_SOURCE");
791        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
792                perror("AUDIO_CLEAR_BUFFER");
793        if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
794                perror("AUDIO_PLAY");
795#else
796#error please define CONFIG_API_VERSION to be 1 or 3
797#endif
798
799        int i;
800// show startup screen
801#if SHOW_START_SCREEN == 1
802#if CONFIG_API_VERSION == 1
803        //that really sucks but there is no other way
804        for (i = 0; i < 10; i++)
805                safe_write(ddvd_output_fd, ddvd_startup_logo, sizeof(ddvd_startup_logo));
806#else
807        unsigned char pes_header[] = { 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x80, 0x00, 0x00 };
808        safe_write(ddvd_output_fd, pes_header, sizeof(pes_header));
809        safe_write(ddvd_output_fd, ddvd_startup_logo, sizeof(ddvd_startup_logo));
810#endif
811#endif
812
813        int audio_type = DDVD_UNKNOWN;
814
815#if CONFIG_API_VERSION == 3
816        ddvd_set_pcr_offset();
817#endif
818
819        uint8_t mem[DVD_VIDEO_LB_LEN];
820        uint8_t *buf = mem;
821        int result, event, len;
822
823        unsigned char lpcm_data[2048 * 6 * 6 /*4608 */ ];
824        int mpa_header_length;
825        int mpa_count, mpa_count2;
826        uint8_t mpa_data[2048 * 4];
827        int ac3_len;
828        int16_t ac3_tmp[2048 * 6 * 6];
829
830        ddvd_mpa_init(48000, 192000);   //init MPA Encoder with 48kHz and 192k Bitrate
831
832        int ac3thru = 1;
833#if defined(__sh__)
834#else
835        if (have_liba52) {
836                state = a52_init(0);    //init AC3 Decoder
837                ac3thru = playerconfig->ac3thru;
838        }
839#endif
840
841        char osdtext[512];
842        strcpy(osdtext, "");
843
844        int tv_aspect = playerconfig->aspect;   //0-> 4:3 lb 1-> 4:3 ps 2-> 16:9 3-> always 16:9
845        int tv_mode = playerconfig->tv_mode;
846        int tv_mode2 = playerconfig->tv_mode2; // just used when tv_aspect is 16:10 and dvd_aspect is 16:9
847        int dvd_aspect = 0;     //0-> 4:3 2-> 16:9
848        int dvd_scale_perm = 0;
849        int tv_scale = 0;       //0-> off 1-> letterbox 2-> panscan
850        int spu_active_id = -1;
851        int finished = 0;
852        int audio_id;
853        int report_audio_info = 0;
854
855        struct ddvd_spu_return last_spu_return;
856        struct ddvd_resize_return last_blit_area;
857        memcpy(&last_blit_area,&blit_area,sizeof(struct ddvd_resize_return));
858        last_spu_return.x_start = last_spu_return.y_start = 0;
859        last_spu_return.x_end = last_spu_return.y_end = 0;
860       
861        ddvd_trickmode = TOFF;
862        ddvd_trickspeed = 0;
863
864        int rccode;
865        int ismute = 0;
866
867        if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
868                perror("AUDIO_SET_AV_SYNC");
869#if CONFIG_API_VERSION == 1     
870        // set video system
871        int pal_ntsc = playerconfig->tv_system;
872        int saa;
873        if (pal_ntsc == 1)
874                saa = SAA_NTSC;
875        else
876                saa = SAA_PAL;
877        int saafd = open("/dev/dbox/saa0", O_RDWR);
878        if (saafd >= 0) {
879                if (ioctl(saafd, SAAIOSENC, &saa) < 0)
880                        perror("SAAIOSENC");
881                close(saafd);
882        }
883#else
884        {
885                struct ddvd_size_evt evt;
886                int msg = DDVD_SIZE_CHANGED;
887                readApiSize(ddvd_fdvideo, &evt.width, &evt.height, &evt.aspect);
888                safe_write(message_pipe, &msg, sizeof(int));
889                safe_write(message_pipe, &evt, sizeof(evt));
890        }
891        {
892                struct ddvd_framerate_evt evt;
893                int msg = DDVD_FRAMERATE_CHANGED;
894                readApiFrameRate(ddvd_fdvideo, &evt.framerate);
895                safe_write(message_pipe, &msg, sizeof(int));
896                safe_write(message_pipe, &evt, sizeof(evt));
897        }
898        {
899                struct ddvd_progressive_evt evt;
900                int msg = DDVD_PROGRESSIVE_CHANGED;
901                evt.progressive = readMpegProc("progressive", 0);
902                safe_write(message_pipe, &msg, sizeof(int));
903                safe_write(message_pipe, &evt, sizeof(evt));
904        }
905#endif
906       
907        /* open dvdnav handle */
908        printf("Opening DVD...%s\n", playerconfig->dvd_path);
909        if (dvdnav_open(&dvdnav, playerconfig->dvd_path) != DVDNAV_STATUS_OK) {
910                printf("Error on dvdnav_open\n");
911                sprintf(osdtext, "Error: Cant open DVD Source: %s", playerconfig->dvd_path);
912                msg = DDVD_SHOWOSD_STRING;
913                safe_write(message_pipe, &msg, sizeof(int));
914                safe_write(message_pipe, &osdtext, sizeof(osdtext));
915                res = DDVD_FAIL_OPEN;
916                goto err_dvdnav_open;
917        }
918
919// nit: dekativate cache, does not work with all dvd
920// on some dvd menu is not allays displayed
921//#if defined(__sh__)
922        /* set read ahead cache usage to yes for ufs910 */
923//      if (dvdnav_set_readahead_flag(dvdnav, 1) != DVDNAV_STATUS_OK) {
924//#else
925        /* set read ahead cache usage to no */
926        if (dvdnav_set_readahead_flag(dvdnav, 0) != DVDNAV_STATUS_OK) {
927//#endif
928                printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav));
929                res = DDVD_FAIL_PREFS;
930                goto err_dvdnav;
931        }
932
933        /* set the language */
934        if (dvdnav_menu_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK ||
935            dvdnav_audio_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK ||
936            dvdnav_spu_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK) {
937                printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav));
938                res = DDVD_FAIL_PREFS;
939                goto err_dvdnav;
940        }
941
942        /* set the PGC positioning flag to have position information relatively to the
943         * whole feature instead of just relatively to the current chapter */
944        if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) {
945                printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav));
946                res = DDVD_FAIL_PREFS;
947                goto err_dvdnav;
948        }
949
950        int audio_lock = 0;
951        int spu_lock = 0;
952        for (i=0; i < MAX_AUDIO; i++)
953                playerconfig->audio_format[i] = -1;
954
955        for (i=0; i < MAX_SPU; i++)
956                playerconfig->spu_map[i] = -1;
957
958        unsigned long long vpts, apts, spts, pts;
959
960        audio_id = dvdnav_get_active_audio_stream(dvdnav);
961        ddvd_playmode = PLAY;
962
963        ddvd_lbb_changed = 0;
964
965        unsigned long long spu_backpts[NUM_SPU_BACKBUFFER];
966
967        ddvd_play_empty(FALSE);
968        ddvd_get_time();        //set timestamp
969
970        playerconfig->in_menu = 0;
971
972        const char *dvd_titlestring;
973        if (dvdnav_get_title_string(dvdnav, &dvd_titlestring) == DVDNAV_STATUS_OK)
974                strcpy(playerconfig->title_string, dvd_titlestring);
975
976        msg = DDVD_SHOWOSD_TITLESTRING;
977        safe_write(message_pipe, &msg, sizeof(int));
978
979        /* the read loop which regularly calls dvdnav_get_next_block
980         * and handles the returned events */
981        int reached_eof = 0;
982        int reached_sof = 0;
983
984        while (!finished) {
985                pci_t *pci = 0;
986                dsi_t *dsi = 0;
987                int buttonN = -1;
988                int in_menu = 0;
989
990                /* the main reading function */
991                if (ddvd_playmode == PLAY) {    //skip when not in play mode
992                        // trickmode
993                        if (ddvd_trickmode) {
994                                if (ddvd_trick_timer_end <= ddvd_get_time()) {
995                                        if (ddvd_trickmode == FASTBW) { //jump back ?
996                                                uint32_t pos, len;
997                                                dvdnav_get_position(dvdnav, &pos, &len);
998                                                //90000 = 1 Sek. -> 45000 = 0.5 Sek. -> Speed Faktor=2
999                                                int64_t posneu = ((pos * ddvd_lastCellEventInfo.pgc_length) / len) - (45000 * 2 * ddvd_trickspeed);
1000                                                int64_t posneu2 = posneu <= 0 ? 0 : (posneu * len) / ddvd_lastCellEventInfo.pgc_length;
1001                                                dvdnav_sector_search(dvdnav, posneu2, SEEK_SET);
1002                                                if (posneu < 0) {       // reached begin of movie
1003                                                        reached_sof = 1;
1004                                                        msg = DDVD_SHOWOSD_TIME;
1005                                                } else {
1006                                                        msg = DDVD_SHOWOSD_STATE_FBWD;
1007                                                }
1008                                        } else if (ddvd_trickmode == FASTFW) {  //jump forward ?
1009                                                uint32_t pos, len;
1010                                                dvdnav_get_position(dvdnav, &pos, &len);
1011                                                //90000 = 1 Sek. -> 22500 = 0.25 Sek. -> Speed Faktor=2
1012                                                int64_t posneu = ((pos * ddvd_lastCellEventInfo.pgc_length) / len) + (22500 * 2 * ddvd_trickspeed);
1013                                                int64_t posneu2 = (posneu * len) / ddvd_lastCellEventInfo.pgc_length;
1014                                                if (posneu2 && len && posneu2 >= len) { // reached end of movie
1015                                                        posneu2 = len - 250;
1016                                                        reached_eof = 1;
1017                                                        msg = DDVD_SHOWOSD_TIME;
1018                                                } else {
1019                                                        msg = DDVD_SHOWOSD_STATE_FFWD;
1020                                                }
1021                                                dvdnav_sector_search(dvdnav, posneu2, SEEK_SET);
1022                                        }
1023                                        ddvd_trick_timer_end = ddvd_get_time() + 300;
1024                                        ddvd_lpcm_count = 0;
1025                                }
1026                        }
1027
1028// nit: dekativate cache, does not work with all dvd
1029// on some dvd menu is not allays displayed
1030//#if defined(__sh__)
1031//                      result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len);
1032//#else
1033                        result = dvdnav_get_next_block(dvdnav, buf, &event, &len);
1034//#endif
1035                        if (result == DVDNAV_STATUS_ERR) {
1036                                printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav));
1037                                sprintf(osdtext, "Error: Getting next block: %s", dvdnav_err_to_string(dvdnav));
1038                                msg = DDVD_SHOWOSD_STRING;
1039                                safe_write(message_pipe, &msg, sizeof(int));
1040                                safe_write(message_pipe, &osdtext, sizeof(osdtext));
1041                                res = DDVD_FAIL_READ;
1042                                goto err_dvdnav;
1043                        }
1044
1045send_message:
1046                        // send OSD Data
1047                        if (msg > 0) {
1048                                struct ddvd_time info;
1049                                switch (msg) {
1050                                case DDVD_SHOWOSD_TIME:
1051                                        info = ddvd_get_osd_time(playerconfig);
1052                                        safe_write(message_pipe, &msg, sizeof(int));
1053                                        safe_write(message_pipe, &info, sizeof(struct ddvd_time));
1054                                        break;
1055                                case DDVD_SHOWOSD_STATE_FFWD:
1056                                        info = ddvd_get_osd_time(playerconfig);
1057                                        safe_write(message_pipe, &msg, sizeof(int));
1058                                        safe_write(message_pipe, &ddvd_trickspeed, sizeof(int));
1059                                        safe_write(message_pipe, &info, sizeof(struct ddvd_time));
1060                                        break;
1061                                case DDVD_SHOWOSD_STATE_FBWD:
1062                                        info = ddvd_get_osd_time(playerconfig);
1063                                        safe_write(message_pipe, &msg, sizeof(int));
1064                                        safe_write(message_pipe, &ddvd_trickspeed, sizeof(int));
1065                                        safe_write(message_pipe, &info, sizeof(struct ddvd_time));
1066                                        break;
1067                                default:
1068                                        break;
1069                                }
1070                                msg = 0;
1071                        }
1072
1073                        if (reached_eof) {
1074                                msg = DDVD_EOF_REACHED;
1075                                safe_write(message_pipe, &msg, sizeof(int));
1076                                reached_eof = 0;
1077                        }
1078
1079                        if (reached_sof) {
1080                                msg = DDVD_SOF_REACHED;
1081                                safe_write(message_pipe, &msg, sizeof(int));
1082                                reached_sof = 0;
1083                        }
1084
1085                        if (ddvd_get_time() > playerconfig->next_time_update) {
1086                                msg = DDVD_SHOWOSD_TIME;
1087                                goto send_message;
1088                        }
1089                        // send iFrame
1090                        if (ddvd_iframesend < 0) {
1091#if CONFIG_API_VERSION == 1
1092                                ddvd_device_clear();
1093#endif
1094                                ddvd_iframesend = 0;
1095                        }
1096
1097                        if (ddvd_iframesend > 0) {
1098#if CONFIG_API_VERSION == 1
1099                                ddvd_device_clear();
1100#endif
1101                                if (ddvd_still_frame && ddvd_last_iframe_len) {
1102#if 0
1103                                        static int ifnum = 0;
1104                                        static char ifname[255];
1105                                        snprintf(ifname, 255, "/tmp/dvd.iframe.%3.3d.asm.pes", ifnum++);
1106                                        FILE *f = fopen(ifname, "wb");
1107                                        fwrite(last_iframe, 1, ddvd_last_iframe_len, f);
1108                                        fclose(f);
1109#endif
1110
1111#if CONFIG_API_VERSION == 1
1112                                        //that really sucks but there is no other way
1113                                        int i;
1114                                        for (i = 0; i < 10; i++)
1115                                                safe_write(ddvd_output_fd, last_iframe, ddvd_last_iframe_len);
1116#else
1117                                        safe_write(ddvd_output_fd, last_iframe, ddvd_last_iframe_len);
1118#endif
1119                                        //printf("Show iframe with size: %d\n",ddvd_last_iframe_len);
1120                                        ddvd_last_iframe_len = 0;
1121                                }
1122
1123                                ddvd_iframesend = -1;
1124                        }
1125                        // wait timer
1126                        if (ddvd_wait_timer_active) {
1127                                if (ddvd_wait_timer_end <= ddvd_get_time()) {
1128                                        ddvd_wait_timer_active = 0;
1129                                        dvdnav_still_skip(dvdnav);
1130                                        //printf("wait timer done\n");
1131                                }
1132                        }
1133                        // SPU timer
1134                        if (ddvd_spu_timer_active) {
1135                                if (ddvd_spu_timer_end <= ddvd_get_time()) {
1136                                        ddvd_spu_timer_active = 0;
1137                                                /* the last_spu bbox is still filled with the correct value, no need to blit full screen */
1138                                                /* TODO: only clear part of backbuffer */
1139                                        memset(ddvd_lbb, 0, 720 * 576); //clear SPU backbuffer
1140                                        ddvd_lbb_changed = 1;
1141                                }
1142                        }
1143
1144                        switch (event) {
1145                        case DVDNAV_BLOCK_OK:
1146                                /* We have received a regular block of the currently playing MPEG stream.
1147                                 * So we do some demuxing and decoding. */
1148                                {
1149
1150                                        // collect audio data
1151                                        int stream_type = buf[14 + buf[14 + 8] + 9];
1152                                        if (((buf[14 + 3]) & 0xF0) == 0xC0)
1153                                                playerconfig->audio_format[(buf[14 + 3]) - 0xC0] = DDVD_MPEG;
1154                                        if ((buf[14 + 3]) == 0xBD && (stream_type & 0xF8) == 0x80)
1155                                                playerconfig->audio_format[stream_type - 0x80] = DDVD_AC3;
1156                                        if ((buf[14 + 3]) == 0xBD && (stream_type & 0xF8) == 0x88)
1157                                                playerconfig->audio_format[stream_type - 0x88] = DDVD_DTS;
1158                                        if ((buf[14 + 3]) == 0xBD && (stream_type & 0xF8) == 0xA0)
1159                                                playerconfig->audio_format[stream_type - 0xA0] = DDVD_LPCM;
1160
1161                                        if ((buf[14 + 3] & 0xF0) == 0xE0) {     // video
1162                                                int pes_len = ((buf[14+4]<<8)|buf[14+5]) + 6;
1163                                                int padding = len - (14 + pes_len);
1164                                                if (buf[14 + 7] & 128) {
1165                                                        /* damn gcc bug */
1166                                                        vpts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1167                                                        vpts |= buf[14 + 10] << 22;
1168                                                        vpts |= (buf[14 + 11] >> 1) << 15;
1169                                                        vpts |= buf[14 + 12] << 7;
1170                                                        vpts |= (buf[14 + 14] >> 1);
1171                                                        //printf("VPTS? %X\n",(int)vpts);
1172                                                }
1173#if CONFIG_API_VERSION == 1
1174                                                // Eliminate 00 00 01 B4 sequence error packet because it breaks the pallas mpeg decoder
1175                                                // This is very strange because the 00 00 01 B4 is partly inside the header extension ...
1176                                                if (buf[21] == 0x00 && buf[22] == 0x00 && buf[23] == 0x01 && buf[24] == 0xB4) {
1177                                                        buf[21] = 0x01;
1178                                                }
1179                                                if (buf[22] == 0x00 && buf[23] == 0x00 && buf[24] == 0x01 && buf[25] == 0xB4) {
1180                                                        buf[22] = 0x01;
1181                                                }
1182#endif
1183                                                // if we have 16:9 Zoom Mode on the DVD and we use a "always 16:9" mode on tv we have
1184                                                // to patch the mpeg header and the Sequence Display Extension inside the Stream in some cases
1185                                                if (dvd_aspect == 3 && ((tv_aspect == DDVD_16_9 && (tv_mode == DDVD_PAN_SCAN || tv_mode == DDVD_LETTERBOX)) ||
1186                                                    (tv_aspect == DDVD_16_10 && (tv_mode2 == DDVD_PAN_SCAN || tv_mode2 == DDVD_LETTERBOX)))) {
1187                                                        int z=0;
1188                                                        for (z=0; z<2040; z++)
1189                                                        {
1190                                                                if (buf[z] == 0x0 && buf[z+1] == 0x0 && buf[z+2] ==0x01 && buf[z+3] == 0xB5 && (buf[z+4] == 0x22 || buf[z+4] == 0x23))
1191                                                                {
1192                                                                        buf[z+5]=0x22;
1193                                                                        buf[z+5]=0x0B;
1194                                                                        buf[z+6]=0x42;
1195                                                                        buf[z+7]=0x12;
1196                                                                        buf[z+8]=0x00;
1197                                                                }
1198                                                        }
1199                                                        if (buf[33] == 0 && buf[33 + 1] == 0 && buf[33 + 2] == 1 && buf[33 + 3] == 0xB3) {
1200                                                                buf[33 + 7] = (buf[33 + 7] & 0xF) + 0x30;
1201                                                        }
1202                                                        if (buf[36] == 0 && buf[36 + 1] == 0 && buf[36 + 2] == 1 && buf[36 + 3] == 0xB3) {
1203                                                                buf[36 + 7] = (buf[36 + 7] & 0xF) + 0x30;
1204                                                        }
1205                                                }
1206
1207                                                // check yres for detecting ntsc/pal
1208                                                if (ddvd_have_ntsc == -1) {
1209                                                        if ((buf[33] == 0 && buf[33 + 1] == 0 && buf[33 + 2] == 1 && buf[33 + 3] == 0xB3 && ((buf[33+5] & 0xF) << 8) + buf[33+6] == 0x1E0)
1210                                                                || (buf[36] == 0 && buf[36 + 1] == 0 && buf[36 + 2] == 1 && buf[36 + 3] == 0xB3 && ((buf[36+5] & 0xF) << 8) + buf[36+6] == 0x1E0))
1211                                                                ddvd_have_ntsc = 1;
1212                                                        else
1213                                                                ddvd_have_ntsc = 0;
1214                                                }
1215
1216                                                if (padding > 8) {
1217                                                        memcpy(buf+14+pes_len, "\x00\x00\x01\xE0\x00\x00\x80\x00\x00", 9);
1218                                                        pes_len += 9;
1219                                                }
1220
1221                                                safe_write(ddvd_output_fd, buf + 14, pes_len);
1222
1223                                                if (padding && padding < 9)
1224                                                        safe_write(ddvd_output_fd, "\x00\x00\x01\xE0\x00\x00\x80\x00\x00", 9);
1225
1226                                                // 14+8 header_length
1227                                                // 14+(header_length)+3  -> start mpeg header
1228                                                // buf[14+buf[14+8]+3] start mpeg header
1229
1230                                                int datalen = (buf[19] + (buf[18] << 8) + 6) - buf[14 + 8];     // length mpeg packet
1231                                                int data = buf[14 + buf[14 + 8] + 3];   // start mpeg packet(header)
1232
1233                                                int do_copy = (ddvd_iframerun == 0x01) && !(buf[data] == 0 && buf[data + 1] == 0 && buf[data + 2] == 1) ? 1 : 0;
1234                                                int have_pictureheader = 0;
1235                                                int haveslice = 0;
1236                                                int setrun = 0;
1237
1238                                                while (datalen > 3) {
1239                                                        if (buf[data] == 0 && buf[data + 1] == 0 && buf[data + 2] == 1) {
1240                                                                if (buf[data + 3] == 0x00 && datalen > 6) { //picture
1241                                                                        if (!setrun) {
1242                                                                                ddvd_iframerun = ((buf[data + 5] >> 3) & 0x07);
1243                                                                                setrun = 1;
1244                                                                        }
1245                                                                        if (ddvd_iframerun < 0x01 || 0x03 < ddvd_iframerun) {
1246                                                                                data++;
1247                                                                                datalen--;
1248                                                                                continue;
1249                                                                        }
1250                                                                        have_pictureheader = 1;
1251                                                                        data += 5;
1252                                                                        datalen -= 5;
1253                                                                        datalen = 6;
1254                                                                } else if (buf[data + 3] == 0xB3 && datalen >= 8) { //sequence header
1255                                                                        ddvd_last_iframe_len = 0;       // clear iframe buffer
1256                                                                        data += 7;
1257                                                                        datalen -= 7;
1258                                                                } else if (buf[data + 3] == 0xBE) { //padding stream
1259                                                                        break;
1260                                                                } else if (0x01 <= buf[data + 3] && buf[data + 3] <= 0xaf) { //slice ?
1261                                                                        if (!have_pictureheader && ddvd_last_iframe_len == 0)
1262                                                                                haveslice = 1;
1263                                                                }
1264                                                        }
1265                                                        data++;
1266                                                        datalen--;
1267                                                }
1268                                                if ((ddvd_iframerun <= 0x01 || do_copy) && ddvd_still_frame) {
1269                                                        if (haveslice)
1270                                                                ddvd_iframerun = 0xFF;
1271                                                        else if (ddvd_last_iframe_len < (320 * 1024) - ((buf[19] + (buf[18] << 8) + 6) - buf[14 + 8])) {
1272                                                                int len = buf[19] + (buf[18] << 8) + 6;
1273                                                                int skip = buf[14+8] + 9; // skip complete pes header
1274                                                                len -= skip;
1275                                                                if (ddvd_last_iframe_len == 0) { // add simple pes header without pts
1276                                                                        memcpy(last_iframe, "\x00\x00\x01\xE0\x00\x00\x80\x00\x00", 9);
1277                                                                        ddvd_last_iframe_len += 9;
1278                                                                }
1279                                                                memcpy(last_iframe + ddvd_last_iframe_len, buf + 14 + skip, len);
1280                                                                ddvd_last_iframe_len += len;
1281                                                        }
1282                                                }
1283                                        } else if ((buf[14 + 3]) == 0xC0 + audio_id)    // mpeg audio
1284                                        {
1285                                                if (audio_type != DDVD_MPEG) {
1286                                                        //printf("Switch to MPEG Audio\n");
1287#ifdef __sh__
1288                                                        //stop audio bevor change encoding
1289                                                        if (ioctl(ddvd_fdaudio, AUDIO_STOP) < 0)
1290                                                                perror("AUDIO_STOP");
1291                                                        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
1292                                                                perror("AUDIO_CLEAR_BUFFER");
1293#endif
1294                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1295                                                                perror("AUDIO_SET_AV_SYNC");
1296                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
1297                                                                perror("AUDIO_SET_BYPASS_MODE");
1298#ifdef __sh__
1299                                                        //start audio after encoding set
1300                                                        if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
1301                                                                perror("AUDIO_PLAY");
1302#endif
1303                                                        audio_type = DDVD_MPEG;
1304                                                }
1305
1306                                                if (buf[14 + 7] & 128) {
1307                                                        /* damn gcc bug */
1308                                                        apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1309                                                        apts |= buf[14 + 10] << 22;
1310                                                        apts |= (buf[14 + 11] >> 1) << 15;
1311                                                        apts |= buf[14 + 12] << 7;
1312                                                        apts |= (buf[14 + 14] >> 1);
1313                                                        //printf("APTS? %X\n",(int)apts);
1314                                                }
1315
1316                                                safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1317                                        } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0xA0 + audio_id)     // lpcm audio
1318                                        {
1319                                                if (audio_type != DDVD_LPCM) {
1320                                                        //printf("Switch to LPCM Audio\n");
1321#ifdef __sh__
1322                                                        //stop audio bevor change encoding
1323                                                        if (ioctl(ddvd_fdaudio, AUDIO_STOP) < 0)
1324                                                                perror("AUDIO_STOP");
1325                                                        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
1326                                                                perror("AUDIO_CLEAR_BUFFER");
1327#endif
1328                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1329                                                                perror("AUDIO_SET_AV_SYNC");
1330#ifdef HARDWARE_SUPPORT_LPCM
1331                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 6) < 0)
1332#else
1333                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 0) < 0)
1334#endif
1335                                                                perror("AUDIO_SET_BYPASS_MODE");
1336#ifdef __sh__
1337                                                        //start audio after encoding set
1338                                                        if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
1339                                                                perror("AUDIO_PLAY");
1340#endif
1341                                                        audio_type = DDVD_LPCM;
1342                                                        ddvd_lpcm_count = 0;
1343                                                }
1344                                                if (buf[14 + 7] & 128) {
1345                                                        /* damn gcc bug */
1346                                                        apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1347                                                        apts |= buf[14 + 10] << 22;
1348                                                        apts |= (buf[14 + 11] >> 1) << 15;
1349                                                        apts |= buf[14 + 12] << 7;
1350                                                        apts |= (buf[14 + 14] >> 1);
1351                                                        //printf("APTS? %X\n",(int)apts);
1352                                                }
1353#ifndef HARDWARE_SUPPORT_LPCM
1354                                                int i = 0;
1355                                                char abuf[(((buf[18] << 8) | buf[19]) - buf[22] - 14)];
1356    #if BYTE_ORDER == BIG_ENDIAN
1357                                                // just copy, byte order is correct on ppc machines
1358                                                memcpy(abuf, buf + 14 + buf[14 + 8] + 9 + 7, (((buf[18] << 8) | buf[19]) - buf[22] - 14));
1359                                                i = (((buf[18] << 8) | buf[19]) - buf[22] - 14);
1360    #else
1361                                                // byte swapping .. we become the wrong byteorder on lpcm on the 7025
1362                                                while (i < (((buf[18] << 8) | buf[19]) - buf[22] - 14)) {
1363                                                        abuf[i + 0] = (buf[14 + buf[14 + 8] + 9 + 7 + i + 1]);
1364                                                        abuf[i + 1] = (buf[14 + buf[14 + 8] + 9 + 7 + i + 0]);
1365                                                        i += 2;
1366                                                }
1367    #endif
1368                                                // we will encode the raw lpcm data to mpeg audio and send them with pts
1369                                                // information to the decoder to get a sync. playing the pcm data via
1370                                                // oss will break the pic/sound sync. So believe it or not, this is the
1371                                                // smartest way to get a synced lpcm track ;-)
1372                                                if (ddvd_lpcm_count == 0) {     // save mpeg header with pts
1373                                                        memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1374                                                        mpa_header_length = buf[14 + 8] + 9;
1375                                                }
1376                                                if (ddvd_lpcm_count + i >= 4608) {      //we have to send 4608 bytes to the encoder
1377                                                        memcpy(lpcm_data + ddvd_lpcm_count, abuf, 4608 - ddvd_lpcm_count);
1378                                                        //encode
1379                                                        mpa_count = ddvd_mpa_encode_frame(mpa_data + mpa_header_length, 4608, lpcm_data);
1380                                                        //patch pes__packet_length
1381                                                        mpa_count = mpa_count + mpa_header_length - 6;
1382                                                        mpa_data[4] = mpa_count >> 8;
1383                                                        mpa_data[5] = mpa_count & 0xFF;
1384                                                        //patch header type to mpeg
1385                                                        mpa_data[3] = 0xC0;
1386                                                        //write
1387                                                        safe_write(ddvd_ac3_fd, mpa_data, mpa_count + mpa_header_length);
1388                                                        memcpy(lpcm_data, abuf + (4608 - ddvd_lpcm_count), i - (4608 - ddvd_lpcm_count));
1389                                                        ddvd_lpcm_count = i - (4608 - ddvd_lpcm_count);
1390                                                        memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1391                                                        mpa_header_length = buf[14 + 8] + 9;
1392                                                } else {
1393                                                        memcpy(lpcm_data + ddvd_lpcm_count, abuf, i);
1394                                                        ddvd_lpcm_count += i;
1395                                                }
1396#else
1397                                                safe_write(ddvd_ac3_fd, buf+14 , buf[19]+(buf[18]<<8)+6);
1398#endif
1399                                        } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0x88 + audio_id) {   // dts audio
1400                                                if (audio_type != DDVD_DTS) {
1401                                                        //printf("Switch to DTS Audio (thru)\n");
1402#ifdef __sh__
1403                                                        //stop audio bevor change encoding
1404                                                        if (ioctl(ddvd_fdaudio, AUDIO_STOP) < 0)
1405                                                                perror("AUDIO_STOP");
1406                                                        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
1407                                                                perror("AUDIO_CLEAR_BUFFER");
1408#endif
1409                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1410                                                                perror("AUDIO_SET_AV_SYNC");
1411#ifdef CONVERT_TO_DVB_COMPLIANT_DTS
1412                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 2) < 0)  // DTS (dvb compliant)
1413#else
1414                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 5) < 0)  // DTS VOB
1415                                                                perror("AUDIO_SET_BYPASS_MODE");
1416#endif
1417#ifdef __sh__
1418                                                        //start audio after encoding set
1419                                                        if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
1420                                                                perror("AUDIO_PLAY");
1421#endif
1422                                                        audio_type = DDVD_DTS;
1423                                                }
1424
1425                                                if (buf[14 + 7] & 128) {
1426                                                        /* damn gcc bug */
1427                                                        apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1428                                                        apts |= buf[14 + 10] << 22;
1429                                                        apts |= (buf[14 + 11] >> 1) << 15;
1430                                                        apts |= buf[14 + 12] << 7;
1431                                                        apts |= (buf[14 + 14] >> 1);
1432                                                        //printf("APTS? %X\n",(int)apts);
1433                                                }
1434
1435#ifdef CONVERT_TO_DVB_COMPLIANT_DTS
1436                                                        unsigned short pes_len = (buf[14 + 4] << 8 | buf[14 + 5]);
1437                                                        pes_len -= 4;   // strip first 4 bytes of pes payload
1438                                                        buf[14 + 4] = pes_len >> 8;     // patch pes len
1439                                                        buf[15 + 4] = pes_len & 0xFF;
1440
1441                                                        safe_write(ddvd_ac3_fd, buf + 14, 9 + buf[14 + 8]);     // write pes_header
1442                                                        safe_write(ddvd_ac3_fd, buf + 14 + 9 + buf[14 + 8] + 4, pes_len - (3 + buf[14 + 8]));   // write pes_payload
1443#else
1444                                                        safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1445#endif
1446                                        } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0x80 + audio_id) {   // ac3 audio
1447                                                if (audio_type != DDVD_AC3) {
1448                                                        //printf("Switch to AC3 Audio\n");
1449#if defined(__sh__)
1450                                                        if (ac3thru) {
1451#else
1452                                                        if (ac3thru || !have_liba52) {  // !have_liba52 and !ac3thru should never happen, but who knows ;)
1453#endif
1454                                                       
1455#ifdef __sh__
1456                                                        //stop audio bevor change encoding
1457                                                        if (ioctl(ddvd_fdaudio, AUDIO_STOP) < 0)
1458                                                                perror("AUDIO_STOP");
1459                                                        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
1460                                                                perror("AUDIO_CLEAR_BUFFER");
1461#endif
1462                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1463                                                                perror("AUDIO_SET_AV_SYNC");
1464#ifdef CONVERT_TO_DVB_COMPLIANT_AC3
1465                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 0) < 0)  // AC3 (dvb compliant)
1466#else
1467                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 3) < 0)  // AC3 VOB
1468#endif
1469                                                                perror("AUDIO_SET_BYPASS_MODE");
1470#ifdef __sh__
1471                                                        //start audio after encoding set
1472                                                        if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
1473                                                                perror("AUDIO_PLAY");
1474#endif
1475                                                        } else {
1476#ifdef __sh__
1477                                                                //stop audio bevor change encoding
1478                                                                if (ioctl(ddvd_fdaudio, AUDIO_STOP) < 0)
1479                                                                        perror("AUDIO_STOP");
1480                                                                if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
1481                                                                        perror("AUDIO_CLEAR_BUFFER");
1482#endif
1483                                                                if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1484                                                                        perror("AUDIO_SET_AV_SYNC");
1485                                                                if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
1486                                                                        perror("AUDIO_SET_BYPASS_MODE");
1487#ifdef __sh__
1488                                                                //start audio after encoding set
1489                                                                if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
1490                                                                        perror("AUDIO_PLAY");
1491#endif
1492                                                        }
1493                                                        audio_type = DDVD_AC3;
1494                                                }
1495
1496                                                if (buf[14 + 7] & 128) {
1497                                                        /* damn gcc bug */
1498                                                        apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1499                                                        apts |= buf[14 + 10] << 22;
1500                                                        apts |= (buf[14 + 11] >> 1) << 15;
1501                                                        apts |= buf[14 + 12] << 7;
1502                                                        apts |= (buf[14 + 14] >> 1);
1503                                                        //printf("APTS? %X\n",(int)apts);
1504                                                }
1505
1506#if defined(__sh__)
1507                                                if (ac3thru) {
1508#else
1509                                                if (ac3thru || !have_liba52) {  // !have_liba52 and !ac3thru should never happen, but who knows ;)
1510#endif
1511#if defined(__sh__)
1512                                                safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1513#else
1514#ifdef CONVERT_TO_DVB_COMPLIANT_AC3
1515                                                        unsigned short pes_len = (buf[14 + 4] << 8 | buf[14 + 5]);
1516                                                        pes_len -= 4;   // strip first 4 bytes of pes payload
1517                                                        buf[14 + 4] = pes_len >> 8;     // patch pes len
1518                                                        buf[15 + 4] = pes_len & 0xFF;
1519
1520                                                        safe_write(ddvd_ac3_fd, buf + 14, 9 + buf[14 + 8]);     // write pes_header
1521                                                        safe_write(ddvd_ac3_fd, buf + 14 + 9 + buf[14 + 8] + 4, pes_len - (3 + buf[14 + 8]));   // write pes_payload
1522#else
1523                                                        safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1524#endif
1525#endif /* __sh__ */
1526                                                        //fwrite(buf+buf[22]+27, 1, ((buf[18]<<8)|buf[19])-buf[22]-7, fac3); //debugwrite
1527                                                } else {
1528                                                        // a bit more funny than lpcm sound, because we do a complete recoding here
1529                                                        // we will decode the ac3 data to plain lpcm and will then encode to mpeg
1530                                                        // audio and send them with pts information to the decoder to get a sync.
1531
1532                                                        // decode and convert ac3 to raw lpcm
1533                                                        ac3_len = ddvd_ac3_decode(buf + buf[22] + 27, ((buf[18] << 8) | buf[19]) - buf[22] - 7, ac3_tmp);
1534
1535                                                        // save the pes header incl. PTS
1536                                                        memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1537                                                        mpa_header_length = buf[14 + 8] + 9;
1538
1539                                                        //apts-=(((unsigned long long)(ddvd_lpcm_count)*90)/192);
1540
1541                                                        //mpa_data[14]=(int)((apts<<1)&0xFF);
1542                                                        //mpa_data[12]=(int)((apts>>7)&0xFF);
1543                                                        //mpa_data[11]=(int)(((apts<<1)>>15)&0xFF);
1544                                                        //mpa_data[10]=(int)((apts>>22)&0xFF);
1545
1546                                                        // copy lpcm data into buffer for encoding
1547                                                        memcpy(lpcm_data + ddvd_lpcm_count, ac3_tmp, ac3_len);
1548                                                        ddvd_lpcm_count += ac3_len;
1549
1550                                                        // encode the whole packet to mpa
1551                                                        mpa_count2 = mpa_count = 0;
1552                                                        while (ddvd_lpcm_count >= 4608) {
1553                                                                mpa_count = ddvd_mpa_encode_frame(mpa_data + mpa_header_length + mpa_count2, 4608, lpcm_data);
1554                                                                mpa_count2 += mpa_count;
1555                                                                ddvd_lpcm_count -= 4608;
1556                                                                memcpy(lpcm_data, lpcm_data + 4608, ddvd_lpcm_count);
1557                                                        }
1558
1559                                                        // patch pes__packet_length
1560                                                        mpa_count = mpa_count2 + mpa_header_length - 6;
1561                                                        mpa_data[4] = mpa_count >> 8;
1562                                                        mpa_data[5] = mpa_count & 0xFF;
1563
1564                                                        // patch header type to mpeg
1565                                                        mpa_data[3] = 0xC0;
1566
1567                                                        // write to decoder
1568                                                        safe_write(ddvd_ac3_fd, mpa_data, mpa_count2 + mpa_header_length);
1569
1570                                                }
1571                                        } else if ((buf[14 + 3]) == 0xBD && ((buf[14 + buf[14 + 8] + 9]) & 0xE0) == 0x20 && ((buf[14 + buf[14 + 8] + 9]) & 0x1F) == spu_active_id) {    // SPU packet
1572                                                memcpy(spu_buffer + ddvd_spu_ptr, buf + buf[22] + 14 + 10, 2048 - (buf[22] + 14 + 10));
1573                                                ddvd_spu_ptr += 2048 - (buf[22] + 14 + 10);
1574
1575                                                if (buf[14 + 7] & 128) {
1576                                                        /* damn gcc bug */
1577#if CONFIG_API_VERSION == 3
1578                                                        spts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1579                                                        spts |= buf[14 + 10] << 22;
1580                                                        spts |= (buf[14 + 11] >> 1) << 15;
1581                                                        spts |= buf[14 + 12] << 7;
1582                                                        spts |= (buf[14 + 14] >> 1);
1583#else
1584                                                        spts = (buf[14 + 9] >> 1) << 29;        // need a corrected "spts" because vulcan/pallas will give us a 32bit pts instead of 33bit
1585                                                        spts |= buf[14 + 10] << 21;
1586                                                        spts |= (buf[14 + 11] >> 1) << 14;
1587                                                        spts |= buf[14 + 12] << 6;
1588                                                        spts |= buf[14 + 12] >> 2;
1589#endif
1590                                                        //printf("SPTS? %X\n",(int)spts);
1591                                                }
1592
1593                                                if (ddvd_spu_ptr >= (spu_buffer[0] << 8 | spu_buffer[1]))       // SPU packet complete ?
1594                                                {
1595                                                        if (ddvd_spu_backnr == NUM_SPU_BACKBUFFER)      // backbuffer already full ?
1596                                                        {
1597                                                                printf("dropped SPU frame\n");
1598                                                                int tmplen = (spu_backbuffer[0] << 8 | spu_backbuffer[1]);
1599                                                                memcpy(spu_backbuffer, spu_backbuffer + tmplen, ddvd_spu_backptr - tmplen);     // delete oldest SPU packet
1600                                                                int i;
1601                                                                for (i = 0; i < NUM_SPU_BACKBUFFER - 1; ++i)
1602                                                                        spu_backpts[i] = spu_backpts[i + 1];
1603                                                                ddvd_spu_backnr = NUM_SPU_BACKBUFFER - 1;
1604                                                                ddvd_spu_backptr -= tmplen;
1605                                                        }
1606
1607                                                        memcpy(spu_backbuffer + ddvd_spu_backptr, spu_buffer, (spu_buffer[0] << 8 | spu_buffer[1]));    // copy into backbuffer
1608                                                        spu_backpts[ddvd_spu_backnr++] = spts;  // store pts
1609                                                        ddvd_spu_backptr += (spu_buffer[0] << 8 | spu_buffer[1]);       // increase ptr
1610
1611                                                        ddvd_spu_ptr = 0;
1612                                                }
1613                                        }
1614                                }
1615                                break;
1616
1617                        case DVDNAV_NOP:
1618                                /* Nothing to do here. */
1619                                break;
1620
1621                        case DVDNAV_STILL_FRAME:
1622                                /* We have reached a still frame. So we start a timer to wait
1623                                 * the amount of time specified by the still's length while still handling
1624                                 * user input to make menus and other interactive stills work.
1625                                 * A length of 0xff means an indefinite still which has to be skipped
1626                                 * indirectly by some user interaction. */
1627                                {
1628                                        if (ddvd_iframesend == 0 && ddvd_last_iframe_len)
1629                                                ddvd_iframesend = 1;
1630
1631                                        dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf;
1632                                        if (still_event->length < 0xff) {
1633                                                if (!ddvd_wait_timer_active) {
1634                                                        ddvd_wait_timer_active = 1;
1635                                                        ddvd_wait_timer_end = ddvd_get_time() + (still_event->length * 1000);   //ms
1636                                                }
1637                                        } else
1638                                                ddvd_wait_for_user = 1;
1639                                }
1640                                break;
1641
1642                        case DVDNAV_WAIT:
1643                                /* We have reached a point in DVD playback, where timing is critical.
1644                                 * We dont use readahead, so we can simply skip the wait state. */
1645                                dvdnav_wait_skip(dvdnav);
1646                                break;
1647
1648                        case DVDNAV_SPU_CLUT_CHANGE:
1649                                /* We received a new color lookup table so we read and store
1650                                 * it */
1651                                {
1652                                        int i = 0, i2 = 0;
1653                                        uint8_t pal[16 * 4];
1654#if BYTE_ORDER == BIG_ENDIAN
1655                                        memcpy(pal, buf, 16 * sizeof(uint32_t));
1656#else
1657                                        for (; i < 16; ++i)
1658                                                *(int *)(pal + i * 4) = htonl(*(int *)(buf + i * 4));
1659                                        i = 0;
1660#endif
1661                                        while (i < 16 * 4) {
1662                                                int y = buf[i + 1];
1663                                                signed char cr = buf[i + 2];    //v
1664                                                signed char cb = buf[i + 3];    //u
1665                                                //printf("%d %d %d ->", y, cr, cb);
1666                                                y = pal[i + 1];
1667                                                cr = pal[i + 2];        //v
1668                                                cb = pal[i + 3];        //u
1669                                                //printf(" %d %d %d\n", y, cr, cb);
1670                                                i += 4;
1671                                        }
1672                                        i = 0;
1673
1674                                        while (i < 16 * 4) {
1675                                                int y = pal[i + 1];
1676                                                signed char cr = pal[i + 2];    //v
1677                                                signed char cb = pal[i + 3];    //u
1678
1679                                                y = 76310 * (y - 16);   //yuv2rgb
1680                                                cr -= 128;
1681                                                cb -= 128;
1682                                                int r = CLAMP((y + 104635 * cr) >> 16);
1683                                                int g = CLAMP((y - 53294 * cr - 25690 * cb) >> 16);
1684                                                int b = CLAMP((y + 132278 * cb) >> 16);
1685
1686                                                ddvd_bl[i2] = b << 8;
1687                                                ddvd_gn[i2] = g << 8;
1688                                                ddvd_rd[i2] = r << 8;
1689                                                i += 4;
1690                                                i2++;
1691                                        }
1692                                        //CHANGE COLORMAP
1693                                }
1694                                break;
1695
1696                        case DVDNAV_SPU_STREAM_CHANGE:
1697                                /* We received a new SPU stream ID */
1698                                if (spu_lock)
1699                                        break;
1700
1701                                dvdnav_spu_stream_change_event_t *ev = (dvdnav_spu_stream_change_event_t *) buf;
1702                                switch (tv_scale) {
1703                                case 0: //off
1704                                        spu_active_id = ev->physical_wide;
1705                                        break;
1706                                case 1: //letterbox
1707                                        spu_active_id = ev->physical_letterbox;
1708                                        break;
1709                                case 2: //panscan
1710                                        spu_active_id = ev->physical_pan_scan;
1711                                        break;
1712                                default:        // should not happen
1713                                        spu_active_id = ev->physical_wide;
1714                                        break;
1715                                }       
1716                                uint16_t spu_lang = 0xFFFF;
1717                                int spu_id_logical, count_tmp;
1718                                spu_id_logical = -1;
1719                                count_tmp = spu_active_id;
1720                                while (count_tmp >= 0 && count_tmp < MAX_SPU)
1721                                {
1722                                        spu_id_logical = playerconfig->spu_map[count_tmp];
1723                                        if (spu_id_logical >= 0)
1724                                                count_tmp = 0;
1725                                        count_tmp--;
1726                                }
1727                               
1728                                spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
1729                                if (spu_lang == 0xFFFF) {
1730                                        spu_lang = 0x2D2D;      // SPU "off, unknown or maybe menuoverlays"
1731                                        spu_id_logical = -1;
1732                                }                                                       
1733                                msg = DDVD_SHOWOSD_SUBTITLE;
1734                                int report_spu = spu_id_logical > 31 ? -1 : spu_id_logical;
1735                                safe_write(message_pipe, &msg, sizeof(int));
1736                                safe_write(message_pipe, &report_spu, sizeof(int));
1737                                safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
1738                                //printf("SPU Stream change: w %X l: %X p: %X active: %X\n",ev->physical_wide,ev->physical_letterbox,ev->physical_pan_scan,spu_active_id);
1739                                break;
1740
1741                        case DVDNAV_AUDIO_STREAM_CHANGE:
1742                                /* We received a new Audio stream ID  */
1743                                if (!audio_lock)
1744                                {
1745                                        audio_id = dvdnav_get_active_audio_stream(dvdnav);
1746                                        report_audio_info = 1;
1747                                }
1748                                break;
1749
1750                        case DVDNAV_HIGHLIGHT:
1751                                /* Lets display some Buttons */
1752                                if (ddvd_clear_buttons == 0) {
1753                                        dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *) buf;
1754
1755                                        pci = dvdnav_get_current_nav_pci(dvdnav);
1756                                        dsi = dvdnav_get_current_nav_dsi(dvdnav);
1757                                        dvdnav_highlight_area_t hl;
1758                                       
1759                                        memcpy(&blit_area,&last_blit_area,sizeof(struct ddvd_resize_return));
1760                                        memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear backbuffer ..
1761                                        msg = DDVD_SCREEN_UPDATE;       // wipe old highlight
1762                                        safe_write(message_pipe, &msg, sizeof(int));
1763                                        safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
1764                                        //printf("destination area to wipe: %d %d %d %d\n",blit_area.x_start,blit_area.x_end,blit_area.y_start,blit_area.y_end);
1765                                       
1766                                        //struct ddvd_resize_return blit_area;
1767                                        blit_area.x_start = blit_area.x_end = blit_area.y_start = blit_area.y_end = 0;
1768                                               
1769                                        int libdvdnav_workaround = 0;
1770
1771                                        if (pci->hli.hl_gi.btngr_ns) {
1772                                                int btns_per_group = 36 / pci->hli.hl_gi.btngr_ns;
1773                                                btni_t *btni = NULL;
1774                                                int modeMask = 1 << tv_scale;
1775
1776                                                if (!btni && pci->hli.hl_gi.btngr_ns >= 1 && (pci->hli.hl_gi.btngr1_dsp_ty & modeMask)) {
1777                                                        btni = &pci->hli.btnit[0 * btns_per_group + highlight_event->buttonN - 1];
1778                                                }
1779                                                if (!btni && pci->hli.hl_gi.btngr_ns >= 2 && (pci->hli.hl_gi.btngr2_dsp_ty & modeMask)) {
1780                                                        btni = &pci->hli.btnit[1 * btns_per_group + highlight_event->buttonN - 1];
1781                                                }
1782                                                if (!btni && pci->hli.hl_gi.btngr_ns >= 3 && (pci->hli.hl_gi.btngr3_dsp_ty & modeMask)) {
1783                                                        btni = &pci->hli.btnit[2 * btns_per_group + highlight_event->buttonN - 1];
1784                                                }
1785
1786                                                if (btni && btni->btn_coln != 0) {
1787                                                        // get and set clut for actual button
1788                                                        unsigned char tmp, tmp2;
1789                                                        struct ddvd_color colneu;
1790                                                        int i;
1791                                                        msg = DDVD_COLORTABLE_UPDATE;
1792                                                        if (ddvd_screeninfo_bypp == 1)
1793                                                                safe_write(message_pipe, &msg, sizeof(int));
1794                                                        for (i = 0; i < 4; i++) {
1795                                                                tmp = ((pci->hli.btn_colit.btn_coli[btni->btn_coln - 1][0]) >> (16 + 4 * i)) & 0xf;
1796                                                                tmp2 = ((pci->hli.btn_colit.btn_coli[btni->btn_coln - 1][0]) >> (4 * i)) & 0xf;
1797                                                                colneu.blue = ddvd_bl[i + 252] = ddvd_bl[tmp];
1798                                                                colneu.green = ddvd_gn[i + 252] = ddvd_gn[tmp];
1799                                                                colneu.red = ddvd_rd[i + 252] = ddvd_rd[tmp];
1800                                                                colneu.trans = ddvd_tr[i + 252] = (0xF - tmp2) * 0x1111;
1801                                                                if (ddvd_screeninfo_bypp == 1)
1802                                                                        safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
1803                                                        }
1804                                                        msg = DDVD_NULL;
1805                                                        //CHANGE COLORMAP
1806
1807                                                        memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer ..
1808                                                        //copy button into screen
1809                                                        for (i = btni->y_start; i < btni->y_end; i++) {
1810                                                                if (ddvd_screeninfo_bypp == 1)
1811                                                                        memcpy(ddvd_lbb2 + btni->x_start + 720 * (i),
1812                                                                               ddvd_lbb + btni->x_start + 720 * (i),
1813                                                                               btni->x_end - btni->x_start);
1814                                                                else
1815                                                                        ddvd_blit_to_argb(ddvd_lbb2 + btni->x_start * ddvd_screeninfo_bypp +
1816                                                                                          720 * ddvd_screeninfo_bypp * i,
1817                                                                                          ddvd_lbb + btni->x_start + 720 * (i),
1818                                                                                          btni->x_end - btni->x_start);
1819                                                        }
1820                                                        blit_area.x_start = btni->x_start;
1821                                                        blit_area.x_end = btni->x_end;
1822                                                        blit_area.y_start = btni->y_start;
1823                                                        blit_area.y_end = btni->y_end;
1824                                                        libdvdnav_workaround = 1;
1825                                                }
1826                                        }
1827                                        if (!libdvdnav_workaround && dvdnav_get_highlight_area(pci, highlight_event->buttonN, 0, &hl) == DVDNAV_STATUS_OK) {
1828                                                // get and set clut for actual button
1829                                                unsigned char tmp, tmp2;
1830                                                struct ddvd_color colneu;
1831                                                int i;
1832                                                msg = DDVD_COLORTABLE_UPDATE;
1833                                                if (ddvd_screeninfo_bypp == 1)
1834                                                        safe_write(message_pipe, &msg, sizeof(int));
1835                                                for (i = 0; i < 4; i++) {
1836                                                        tmp = ((hl.palette) >> (16 + 4 * i)) & 0xf;
1837                                                        tmp2 = ((hl.palette) >> (4 * i)) & 0xf;
1838                                                        colneu.blue = ddvd_bl[i + 252] = ddvd_bl[tmp];
1839                                                        colneu.green = ddvd_gn[i + 252] = ddvd_gn[tmp];
1840                                                        colneu.red = ddvd_rd[i + 252] = ddvd_rd[tmp];
1841                                                        colneu.trans = ddvd_tr[i + 252] = (0xF - tmp2) * 0x1111;
1842                                                        if (ddvd_screeninfo_bypp == 1)
1843                                                                safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
1844                                                }
1845                                                msg = DDVD_NULL;
1846                                                //CHANGE COLORMAP
1847
1848                                                memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer ..
1849                                                //copy button into screen
1850                                                for (i = hl.sy; i < hl.ey; i++) {
1851                                                        if (ddvd_screeninfo_bypp == 1)
1852                                                                memcpy(ddvd_lbb2 + hl.sx + 720 * (i),
1853                                                                       ddvd_lbb + hl.sx + 720 * (i), hl.ex - hl.sx);
1854                                                        else
1855                                                                ddvd_blit_to_argb(ddvd_lbb2 + hl.sx * ddvd_screeninfo_bypp + 720 * ddvd_screeninfo_bypp * i,
1856                                                                                  ddvd_lbb + hl.sx + 720 * (i), hl.ex - hl.sx);
1857                                                }
1858                                                blit_area.x_start = hl.sx;
1859                                                blit_area.x_end = hl.ex;
1860                                                blit_area.y_start = hl.sy;
1861                                                blit_area.y_end = hl.ey;
1862                                                libdvdnav_workaround = 1;
1863                                        }
1864                                        if (!libdvdnav_workaround)
1865                                                memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer ..
1866                                        else
1867                                        {
1868                                                int y_source = ddvd_have_ntsc ? 480 : 576; // correct ntsc overlay
1869                                                int x_offset = calc_x_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
1870                                                int y_offset = calc_y_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
1871
1872                                                uint64_t start=ddvd_get_time();
1873                                                int resized = 0;
1874
1875                                                if ((x_offset != 0 || y_offset != 0 || y_source != ddvd_screeninfo_yres || ddvd_screeninfo_xres != 720) && !playerconfig->canscale)
1876                                                {
1877//                                                      printf("resizing\n");
1878                                                        resized = 1;
1879                                                        blit_area = ddvd_resize_pixmap(ddvd_lbb2, 720, y_source, ddvd_screeninfo_xres, ddvd_screeninfo_yres, x_offset, y_offset, blit_area.x_start, blit_area.x_end, blit_area.y_start, blit_area.y_end, ddvd_screeninfo_bypp); // resize
1880                                                }
1881
1882                                                blit_area.width = ddvd_screeninfo_xres;
1883                                                blit_area.height = ddvd_screeninfo_yres;
1884
1885                                                if (resized)
1886                                                {
1887                                                        blit_area.x_offset = 0;
1888                                                        blit_area.y_offset = 0;
1889                                                } else
1890                                                {
1891                                                        blit_area.x_offset = x_offset;
1892                                                        blit_area.y_offset = y_offset;
1893                                                }
1894                                                memcpy(p_lfb, ddvd_lbb2, ddvd_screeninfo_xres * ddvd_screeninfo_yres * ddvd_screeninfo_bypp); //copy backbuffer into screen
1895                                                //printf("needed time for resizing: %d ms\n",(int)(ddvd_get_time()-start));
1896                                                //printf("destination area to blit: %d %d %d %d\n",blit_area.x_start,blit_area.x_end,blit_area.y_start,blit_area.y_end);
1897                                                msg = DDVD_SCREEN_UPDATE;
1898                                                safe_write(message_pipe, &msg, sizeof(int));
1899                                                safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
1900                                                memcpy(&last_blit_area,&blit_area,sizeof(struct ddvd_resize_return)); // safe blit area for next wipe
1901                                        }
1902                                } else {
1903                                        ddvd_clear_buttons = 0;
1904                                        //printf("clear buttons\n");
1905                                }
1906                                break;
1907
1908                        case DVDNAV_VTS_CHANGE:
1909                                {
1910                                        /* Some status information like video aspect and video scale permissions do
1911                                         * not change inside a VTS. Therefore we will set it new at this place */
1912                                        ddvd_play_empty(FALSE);
1913                                        audio_lock = 0; // reset audio & spu lock
1914                                        spu_lock = 0;
1915                                        for ( i = 0; i < MAX_AUDIO; i++)
1916                                                playerconfig->audio_format[i] = -1;
1917                                        // fill spu_map with data
1918                                        int count_tmp,spu_tmp;
1919                                        for (count_tmp = 0; count_tmp < MAX_SPU; count_tmp++)
1920                                                playerconfig->spu_map[count_tmp] = -1;
1921                                        for (count_tmp = 0; count_tmp < MAX_SPU; count_tmp++)
1922                                        {
1923                                                spu_tmp = dvdnav_get_spu_logical_stream(dvdnav, count_tmp);
1924                                                if (spu_tmp >= 0 && spu_tmp < MAX_SPU)
1925                                                        playerconfig->spu_map[spu_tmp] = count_tmp;
1926                                        }
1927                                       
1928                                        dvd_aspect = dvdnav_get_video_aspect(dvdnav);
1929                                       
1930//needed for titan
1931#if defined(__sh__)
1932                                        playerconfig->dvd_aspect = dvd_aspect;
1933#endif
1934
1935                                        dvd_scale_perm = dvdnav_get_video_scale_permission(dvdnav);
1936                                        tv_scale = ddvd_check_aspect(dvd_aspect, dvd_scale_perm, tv_aspect, tv_mode);
1937                                        //printf("DVD Aspect: %d TV Aspect: %d Scale: %d Allowed: %d\n",dvd_aspect,tv_aspect,tv_scale,dvd_scale_perm);
1938                                       
1939                                        // resuming a dvd ?
1940                                        if (playerconfig->should_resume && first_vts_change) {
1941                                                first_vts_change = 0;
1942                                                int title_numbers,part_numbers;
1943                                                dvdnav_get_number_of_titles(dvdnav, &title_numbers);
1944                                                dvdnav_get_number_of_parts(dvdnav, playerconfig->resume_title, &part_numbers);
1945                                                if (playerconfig->resume_title <= title_numbers && playerconfig->resume_title > 0 && playerconfig->resume_chapter <= part_numbers && playerconfig->resume_chapter > 0) {
1946                                                        dvdnav_part_play(dvdnav, playerconfig->resume_title, playerconfig->resume_chapter);
1947                                                        next_cell_change = 1;
1948                                                } else {
1949                                                        playerconfig->should_resume = 0;
1950                                                        playerconfig->resume_title = 0;
1951                                                        playerconfig->resume_chapter = 0;
1952                                                        playerconfig->resume_block = 0;
1953                                                        playerconfig->resume_audio_id = 0;
1954                                                        playerconfig->resume_audio_lock = 0;
1955                                                        playerconfig->resume_spu_id = 0;
1956                                                        playerconfig->resume_spu_lock = 0;                                                     
1957                                                        perror("DVD resuming failed");
1958                                                }
1959                                               
1960                                               
1961                                        }
1962                                }
1963                                break;
1964
1965                        case DVDNAV_CELL_CHANGE:
1966                                {
1967                                        /* Store new cell information */
1968                                        memcpy(&ddvd_lastCellEventInfo, buf, sizeof(dvdnav_cell_change_event_t));
1969
1970                                        if ((ddvd_still_frame & CELL_STILL) && ddvd_iframesend == 0 && ddvd_last_iframe_len)
1971                                                ddvd_iframesend = 1;
1972
1973                                        ddvd_still_frame = (dvdnav_get_next_still_flag(dvdnav) != 0) ? CELL_STILL : 0;
1974                                       
1975                                        // resuming a dvd ?
1976                                        if (playerconfig->should_resume && next_cell_change) {
1977                                                next_cell_change = 0;
1978                                                playerconfig->should_resume = 0;
1979                                                if (dvdnav_sector_search(dvdnav, playerconfig->resume_block, SEEK_SET) != DVDNAV_STATUS_OK)
1980                                                {
1981                                                        perror("DVD resuming failed");
1982                                                } else {
1983                                                        audio_id = playerconfig->resume_audio_id;
1984                                                        audio_lock = 1;//playerconfig->resume_audio_lock;
1985                                                        spu_active_id = playerconfig->resume_spu_id;
1986                                                        spu_lock = 1;//playerconfig->resume_spu_lock;
1987                                                        report_audio_info = 1;
1988                                                        uint16_t spu_lang = 0xFFFF;
1989                                                        int spu_id_logical, count_tmp;
1990                                                        count_tmp = spu_active_id;
1991                                                        while (count_tmp >= 0)
1992                                                        {
1993                                                                spu_id_logical = playerconfig->spu_map[count_tmp];
1994                                                                if (spu_id_logical >= 0)
1995                                                                        count_tmp = 0;
1996                                                                count_tmp--;
1997                                                        }
1998                                                        spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
1999                                                        if (spu_lang == 0xFFFF) {
2000                                                                spu_lang = 0x2D2D;      // SPU "off"
2001                                                                spu_active_id = -1;
2002                                                                spu_id_logical = -1;
2003                                                        }
2004                                                        msg = DDVD_SHOWOSD_SUBTITLE;
2005                                                        int report_spu = spu_id_logical > 31 ? -1 : spu_id_logical;
2006                                                        safe_write(message_pipe, &msg, sizeof(int));
2007                                                        safe_write(message_pipe, &report_spu, sizeof(int));
2008                                                        safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
2009                                                        msg = DDVD_SHOWOSD_TIME; // send new position to the frontend
2010                                                }
2011                                                playerconfig->resume_title = 0;
2012                                                playerconfig->resume_chapter = 0;
2013                                                playerconfig->resume_block = 0;
2014                                                playerconfig->resume_audio_id = 0;
2015                                                playerconfig->resume_audio_lock = 0;
2016                                                playerconfig->resume_spu_id = 0;
2017                                                playerconfig->resume_spu_lock = 0;
2018                                        }
2019                                        // multiple angels ?
2020                                        int num = 0, current = 0;
2021                                        dvdnav_get_angle_info(dvdnav, &current, &num);
2022                                        msg = DDVD_SHOWOSD_ANGLE;
2023                                        safe_write(message_pipe, &msg, sizeof(int));
2024                                        safe_write(message_pipe, &current, sizeof(int));
2025                                        safe_write(message_pipe, &num, sizeof(int));
2026                                }
2027                                break;
2028
2029                        case DVDNAV_NAV_PACKET:
2030                                /* A NAV packet provides PTS discontinuity information, angle linking information and
2031                                 * button definitions for DVD menus. We have to handle some stilframes here */
2032                                pci = dvdnav_get_current_nav_pci(dvdnav);
2033                                dsi = dvdnav_get_current_nav_dsi(dvdnav);
2034
2035                                if ((ddvd_still_frame & NAV_STILL) && ddvd_iframesend == 0 && ddvd_last_iframe_len)
2036                                        ddvd_iframesend = 1;
2037
2038                                if (dsi->vobu_sri.next_video == 0xbfffffff)
2039                                        ddvd_still_frame |= NAV_STILL;  //|= 1;
2040                                else
2041                                        ddvd_still_frame &= ~NAV_STILL; //&= 1;
2042                                break;
2043
2044                        case DVDNAV_HOP_CHANNEL:
2045                                /* This event is issued whenever a non-seamless operation has been executed.
2046                                 * So we drop our buffers */
2047                                ddvd_play_empty(TRUE);
2048                                break;
2049
2050                        case DVDNAV_STOP:
2051                                /* Playback should end here. */
2052                                printf("DVDNAV_STOP\n");
2053                                playerconfig->resume_title = 0;
2054                                playerconfig->resume_chapter = 0;
2055                                playerconfig->resume_block = 0;
2056                                playerconfig->resume_audio_id = 0;
2057                                playerconfig->resume_audio_lock = 0;
2058                                playerconfig->resume_spu_id = 0;
2059                                playerconfig->resume_spu_lock = 0;
2060                                finished = 1;
2061                                break;
2062
2063                        default:
2064                                printf("Unknown event (%i)\n", event);
2065                                finished = 1;
2066                                break;
2067                        }
2068                }
2069                // spu handling
2070#if CONFIG_API_VERSION == 1
2071                unsigned int tpts;
2072                if (ioctl(ddvd_output_fd, VIDEO_GET_PTS, &tpts) < 0)
2073                        perror("VIDEO_GET_PTS");
2074                pts = (unsigned long long)tpts;
2075                signed long long diff = spu_backpts[0] - pts;
2076                if (ddvd_spu_backnr > 0 && diff <= 0xFF)        // we only have a 32bit pts on vulcan/pallas (instead of 33bit) so we need some tolerance on syncing SPU for menus
2077                                                                                                        // so on non animated menus the buttons will be displayed to soon, but we we have to accept it
2078#else
2079
2080// nit: VIDEO_GET_EVENT blocks here
2081// if dvd can't start VIDEO_GET_PTS overflows console with output
2082#if defined(__sh__)
2083                ioctl(ddvd_fdvideo, VIDEO_GET_PTS, &pts);
2084#else
2085                if (ioctl(ddvd_fdvideo, VIDEO_GET_PTS, &pts) < 0)
2086                        perror("VIDEO_GET_PTS");
2087//              printf("pts %d, dvd_spu_backnr = %d, spu_backpts = %d\n",
2088//                      (int)pts, (int)ddvd_spu_backnr, (int) spu_backpts[0]);
2089                struct video_event event;
2090                if (!ioctl(ddvd_fdvideo, VIDEO_GET_EVENT, &event))
2091                {
2092                        switch(event.type)
2093                        {
2094                        case VIDEO_EVENT_SIZE_CHANGED:
2095                        {
2096                                struct ddvd_size_evt evt;
2097                                int msg = DDVD_SIZE_CHANGED;
2098                                evt.width = event.u.size.w;
2099                                evt.height = event.u.size.h;
2100                                evt.aspect = event.u.size.aspect_ratio;
2101                                safe_write(message_pipe, &msg, sizeof(int));
2102                                safe_write(message_pipe, &evt, sizeof(evt));
2103                                break;
2104                        }
2105                        case VIDEO_EVENT_FRAME_RATE_CHANGED:
2106                        {
2107                                struct ddvd_framerate_evt evt;
2108                                int msg = DDVD_FRAMERATE_CHANGED;
2109                                evt.framerate = event.u.frame_rate;
2110                                safe_write(message_pipe, &msg, sizeof(int));
2111                                safe_write(message_pipe, &evt, sizeof(evt));
2112                                break;
2113                        }
2114                        case 16: // VIDEO_EVENT_PROGRESSIVE_CHANEGD
2115                        {
2116                                struct ddvd_progressive_evt evt;
2117                                int msg = DDVD_PROGRESSIVE_CHANGED;
2118                                evt.progressive = event.u.frame_rate;
2119                                safe_write(message_pipe, &msg, sizeof(int));
2120                                safe_write(message_pipe, &evt, sizeof(evt));
2121                                break;
2122                        }
2123                        }
2124                }
2125#endif
2126                if (ddvd_spu_backnr > 0 && pts >= spu_backpts[0])
2127#endif
2128                {
2129                        int tmplen = (spu_backbuffer[0] << 8 | spu_backbuffer[1]);
2130                       
2131                        // we dont support overlapping spu timers yet, so we have to clear the screen if there is such a case
2132                        int whole_screen = 0;
2133                        if (ddvd_spu_timer_active || last_spu_return.display_time < 0)
2134                                memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear screen ..
2135                                        /* the last subtitle's bbox is still in last_spu_return, so this subtitle will enlarge this bbox. */
2136                       
2137                        memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer ..
2138//                      printf("[SPU] previous bbox: %d %d %d %d\n",
2139//                              last_spu_return.x_start, last_spu_return.x_end,
2140//                              last_spu_return.y_start, last_spu_return.y_end);
2141                        last_spu_return = merge(last_spu_return, ddvd_spu_decode_data(spu_backbuffer, tmplen)); // decode
2142//                      printf("[SPU] merged   bbox: %d %d %d %d\n",
2143//                              last_spu_return.x_start, last_spu_return.x_end,
2144//                              last_spu_return.y_start, last_spu_return.y_end);
2145                        ddvd_display_time = last_spu_return.display_time;
2146                        ddvd_lbb_changed = 1;
2147                       
2148                        struct ddvd_color colneu;
2149                        int ctmp;
2150                        msg = DDVD_COLORTABLE_UPDATE;
2151                        if (ddvd_screeninfo_bypp == 1)
2152                                safe_write(message_pipe, &msg, sizeof(int));
2153                        for (ctmp = 0; ctmp < 4; ctmp++) {
2154                                colneu.blue = ddvd_bl[ctmp + 252];
2155                                colneu.green = ddvd_gn[ctmp + 252];
2156                                colneu.red = ddvd_rd[ctmp + 252];
2157                                colneu.trans = ddvd_tr[ctmp + 252];
2158                                if (ddvd_screeninfo_bypp == 1)
2159                                        safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
2160                        }
2161                        msg = DDVD_NULL;
2162
2163                        memcpy(spu_backbuffer, spu_backbuffer + tmplen, ddvd_spu_backptr - tmplen);     // delete SPU packet
2164                        int i;
2165                        for (i = 0; i < NUM_SPU_BACKBUFFER - 1; ++i)
2166                                spu_backpts[i] = spu_backpts[i + 1];
2167                               
2168                        ddvd_spu_backnr--;
2169                        ddvd_spu_backptr -= tmplen;
2170                       
2171//                      printf("[SPU] backnr = %d, backptr = %d\n", ddvd_spu_backnr, ddvd_spu_backptr);
2172
2173                        // set timer
2174                        if (ddvd_display_time > 0) {
2175                                ddvd_spu_timer_active = 1;
2176                                ddvd_spu_timer_end = ddvd_get_time() + (ddvd_display_time * 10);        //ms
2177                        } else
2178                                ddvd_spu_timer_active = 0;
2179
2180                        // dont display SPU if spu sets the HIDE command or the actual SPU track is marked as hide (bit 7) and the packet had no FORCE command
2181                        if (last_spu_return.force_hide == SPU_HIDE || ((dvdnav_get_active_spu_stream(dvdnav) & 0x80) && last_spu_return.force_hide != SPU_FORCE && !spu_lock)) {
2182                                ddvd_lbb_changed = 0;
2183                                ddvd_spu_timer_active = 0;
2184                        }
2185
2186                        pci = dvdnav_get_current_nav_pci(dvdnav);       //update highlight buttons
2187                        dsi = dvdnav_get_current_nav_dsi(dvdnav);
2188                        if (pci->hli.hl_gi.btn_ns > 0) {
2189                                dvdnav_get_current_highlight(dvdnav, &buttonN);
2190                                if (buttonN == 0)
2191                                        buttonN = 1;
2192                                if (buttonN > pci->hli.hl_gi.btn_ns)
2193                                        buttonN = pci->hli.hl_gi.btn_ns;
2194                                dvdnav_button_select(dvdnav, pci, buttonN);
2195                                ddvd_lbb_changed = 0;
2196                                in_menu = 1;
2197                        }
2198                }
2199
2200                if (!in_menu) {
2201                        if (!pci)
2202                                pci = dvdnav_get_current_nav_pci(dvdnav);
2203
2204                        in_menu = pci && pci->hli.hl_gi.btn_ns > 0;
2205                }
2206
2207                if ((dvdnav_is_domain_vmgm(dvdnav) || dvdnav_is_domain_vtsm(dvdnav) || in_menu) && !playerconfig->in_menu) {
2208                        int bla = DDVD_MENU_OPENED;
2209                        safe_write(message_pipe, &bla, sizeof(int));
2210                        playerconfig->in_menu = 1;
2211                } else if (!(dvdnav_is_domain_vmgm(dvdnav) || dvdnav_is_domain_vtsm(dvdnav) || in_menu) && playerconfig->in_menu) {
2212                        int bla = DDVD_MENU_CLOSED;
2213                        safe_write(message_pipe, &bla, sizeof(int));
2214                        playerconfig->in_menu = 0;
2215                }
2216
2217                if (ddvd_wait_for_user) {
2218                        struct pollfd pfd[1];   // make new pollfd array
2219                        pfd[0].fd = key_pipe;
2220                        pfd[0].events = POLLIN | POLLPRI | POLLERR;
2221                        poll(pfd, 1, -1);
2222                }
2223                //Userinput
2224                if (ddvd_readpipe(key_pipe, &rccode, sizeof(int), 0) == sizeof(int)) {
2225                        int keydone = 1;
2226
2227                        if (!dsi)
2228                                dsi = dvdnav_get_current_nav_dsi(dvdnav);
2229
2230                        if (buttonN == -1)
2231                                dvdnav_get_current_highlight(dvdnav, &buttonN);
2232
2233                        switch (rccode) // actions inside and outside of menu
2234                        {
2235                                case DDVD_SET_MUTE:
2236                                        ismute = 1;
2237                                        break;
2238                                case DDVD_UNSET_MUTE:
2239                                        ismute = 0;
2240                                        break;
2241                                default:
2242                                        keydone = 0;
2243                                        break;
2244                        }
2245
2246                        if (!keydone && in_menu) {
2247                                switch (rccode) //Actions inside a Menu
2248                                {
2249                                case DDVD_KEY_UP:       //Up
2250                                        dvdnav_upper_button_select(dvdnav, pci);
2251                                        break;
2252                                case DDVD_KEY_DOWN:     //Down
2253                                        dvdnav_lower_button_select(dvdnav, pci);
2254                                        break;
2255                                case DDVD_KEY_LEFT:     //left
2256                                        dvdnav_left_button_select(dvdnav, pci);
2257                                        break;
2258                                case DDVD_KEY_RIGHT:    //right
2259                                        dvdnav_right_button_select(dvdnav, pci);
2260                                        break;
2261                                case DDVD_KEY_OK:       //OK
2262                                        ddvd_wait_for_user = 0;
2263                                        memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear screen ..
2264                                        memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer
2265                                        memset(ddvd_lbb2, 0, 720 * 576 * ddvd_screeninfo_bypp); //clear 2nd backbuffer
2266                                        blit_area.x_start = blit_area.y_start = 0;
2267                                        blit_area.x_end = ddvd_screeninfo_xres - 1;
2268                                        blit_area.y_end = ddvd_screeninfo_yres - 1;
2269                                        blit_area.x_offset = 0;
2270                                        blit_area.y_offset = 0;
2271                                        blit_area.width = ddvd_screeninfo_xres;
2272                                        blit_area.height = ddvd_screeninfo_yres;
2273                                        msg = DDVD_SCREEN_UPDATE;
2274                                        safe_write(message_pipe, &msg, sizeof(int));
2275                                        safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
2276                                       
2277                                        ddvd_clear_buttons = 1;
2278                                        dvdnav_button_activate(dvdnav, pci);
2279                                        ddvd_play_empty(TRUE);
2280                                        if (ddvd_wait_timer_active)
2281                                                ddvd_wait_timer_active = 0;
2282                                        break;
2283                                case DDVD_KEY_MENU:     //Dream
2284                                        if (dvdnav_menu_call(dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
2285                                                ddvd_play_empty(TRUE);
2286                                        break;
2287                                case DDVD_KEY_AUDIOMENU:        //Audio
2288                                        if (dvdnav_menu_call(dvdnav, DVD_MENU_Audio) == DVDNAV_STATUS_OK)
2289                                                ddvd_play_empty(TRUE);
2290                                        break;
2291                                case DDVD_KEY_EXIT:     //Exit
2292                                        {
2293                                                printf("DDVD_KEY_EXIT (menu)\n");
2294                                                playerconfig->resume_title = 0;
2295                                                playerconfig->resume_chapter = 0;
2296                                                playerconfig->resume_block = 0;
2297                                                playerconfig->resume_audio_id = 0;
2298                                                playerconfig->resume_audio_lock = 0;
2299                                                playerconfig->resume_spu_id = 0;
2300                                                playerconfig->resume_spu_lock = 0;
2301                                                finished = 1;
2302                                        }
2303                                        break;                                         
2304                                case DDVD_SKIP_FWD:
2305                                case DDVD_SKIP_BWD:
2306                                case DDVD_SET_TITLE:
2307                                case DDVD_SET_CHAPTER:
2308                                        // we must empty the pipe here...
2309                                        ddvd_readpipe(key_pipe, &keydone, sizeof(int), 1);
2310                                default:
2311                                        break;
2312                                }
2313                        } else if (!keydone)    //Actions inside a Movie
2314                        {
2315                                switch (rccode) //Main Actions
2316                                {
2317                                case DDVD_KEY_PREV_CHAPTER:     //left
2318                                        {
2319                                                int titleNo, chapterNumber, chapterNo;
2320                                                dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2321                                                dvdnav_get_number_of_parts(dvdnav, titleNo, &chapterNumber);
2322                                                chapterNo--;
2323                                                if (chapterNo > chapterNumber)
2324                                                        chapterNo = 1;
2325                                                if (chapterNo <= 0)
2326                                                        chapterNo = chapterNumber;
2327                                                dvdnav_part_play(dvdnav, titleNo, chapterNo);
2328                                                ddvd_play_empty(TRUE);
2329                                                msg = DDVD_SHOWOSD_TIME;
2330                                                break;
2331                                        }
2332                                case DDVD_KEY_NEXT_CHAPTER:     //right
2333                                        {
2334                                                int titleNo, chapterNumber, chapterNo;
2335                                                dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2336                                                dvdnav_get_number_of_parts(dvdnav, titleNo, &chapterNumber);
2337                                                chapterNo++;
2338                                                if (chapterNo > chapterNumber)
2339                                                        chapterNo = 1;
2340                                                if (chapterNo <= 0)
2341                                                        chapterNo = chapterNumber;
2342                                                dvdnav_part_play(dvdnav, titleNo, chapterNo);
2343                                                ddvd_play_empty(TRUE);
2344                                                msg = DDVD_SHOWOSD_TIME;
2345                                                break;
2346                                        }
2347                                case DDVD_KEY_PREV_TITLE:
2348                                        {
2349                                                int titleNo, titleNumber, chapterNo;
2350                                                dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2351                                                dvdnav_get_number_of_titles(dvdnav, &titleNumber);
2352                                                titleNo--;
2353                                                if (titleNo > titleNumber)
2354                                                        titleNo = 1;
2355                                                if (titleNo <= 0)
2356                                                        titleNo = titleNumber;
2357                                                dvdnav_part_play(dvdnav, titleNo, 1);
2358                                                ddvd_play_empty(TRUE);
2359                                                msg = DDVD_SHOWOSD_TIME;
2360                                                break;
2361                                        }
2362                                case DDVD_KEY_NEXT_TITLE:
2363                                        {
2364                                                int titleNo, titleNumber, chapterNo;
2365                                                dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2366                                                dvdnav_get_number_of_titles(dvdnav, &titleNumber);
2367                                                titleNo++;
2368                                                if (titleNo > titleNumber)
2369                                                        titleNo = 1;
2370                                                if (titleNo <= 0)
2371                                                        titleNo = titleNumber;
2372                                                dvdnav_part_play(dvdnav, titleNo, 1);
2373                                                ddvd_play_empty(TRUE);
2374                                                msg = DDVD_SHOWOSD_TIME;
2375                                                break;
2376                                        }
2377                                case DDVD_KEY_PAUSE:    // Pause
2378                                        {
2379                                                if (ddvd_playmode == PLAY) {
2380                                                        ddvd_playmode = PAUSE;
2381                                                        if (ioctl(ddvd_fdaudio, AUDIO_PAUSE) < 0)
2382                                                                perror("AUDIO_PAUSE");
2383                                                        if (ioctl(ddvd_fdvideo, VIDEO_FREEZE) < 0)
2384                                                                perror("VIDEO_FREEZE");
2385                                                        msg = DDVD_SHOWOSD_STATE_PAUSE;
2386                                                        safe_write(message_pipe, &msg, sizeof(int));
2387                                                        break;
2388                                                } else if (ddvd_playmode != PAUSE)
2389                                                        break;
2390                                                // fall through to PLAY
2391                                        }
2392                                case DDVD_KEY_PLAY:     // Play
2393                                        {
2394                                                if (ddvd_playmode == PAUSE || ddvd_trickmode) {
2395                                                        ddvd_playmode = PLAY;
2396key_play:
2397#if CONFIG_API_VERSION == 1
2398                                                        ddvd_device_clear();
2399#endif
2400                                                        if (ddvd_trickmode && !ismute)
2401                                                                if (ioctl(ddvd_fdaudio, AUDIO_SET_MUTE, 0) < 0)
2402                                                                        perror("AUDIO_SET_MUTE");
2403                                                        ddvd_trickmode = TOFF;
2404                                                        if (ddvd_playmode == PLAY) {
2405                                                                if (ioctl(ddvd_fdaudio, AUDIO_CONTINUE) < 0)
2406                                                                        perror("AUDIO_CONTINUE");
2407                                                                if (ioctl(ddvd_fdvideo, VIDEO_CONTINUE) < 0)
2408                                                                        perror("VIDEO_CONTINUE");
2409                                                                msg = DDVD_SHOWOSD_STATE_PLAY;
2410                                                                safe_write(message_pipe, &msg, sizeof(int));
2411                                                        }
2412                                                        msg = DDVD_SHOWOSD_TIME;
2413                                                }
2414                                                break;
2415                                        }
2416                                case DDVD_KEY_MENU:     //Dream
2417                                        if (dvdnav_menu_call(dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
2418                                                ddvd_play_empty(TRUE);
2419                                        break;
2420                                case DDVD_KEY_AUDIOMENU:        //Audio
2421                                        if (dvdnav_menu_call(dvdnav, DVD_MENU_Audio) == DVDNAV_STATUS_OK)
2422                                                ddvd_play_empty(TRUE);
2423                                        break;
2424                                case DDVD_KEY_EXIT:     //Exit
2425                                        {
2426                                                printf("DDVD_KEY_EXIT (menu)\n");
2427                                                int resume_title, resume_chapter; //safe resume info
2428                                                uint32_t resume_block, total_block;
2429                                                if (dvdnav_current_title_info(dvdnav, &resume_title, &resume_chapter) && (0 != resume_title)) {
2430                                                        if(dvdnav_get_position (dvdnav, &resume_block, &total_block) == DVDNAV_STATUS_OK) {
2431                                                                playerconfig->resume_title = resume_title;
2432                                                                playerconfig->resume_chapter = resume_chapter;
2433                                                                playerconfig->resume_block = resume_block;
2434                                                                playerconfig->resume_audio_id = audio_id;
2435                                                                playerconfig->resume_audio_lock = audio_lock;
2436                                                                playerconfig->resume_spu_id = spu_active_id;
2437                                                                playerconfig->resume_spu_lock = spu_lock;
2438                                                        } else perror("error getting resume position");
2439                                                } perror("error getting resume position");                                     
2440                                                finished = 1;
2441                                        }
2442                                        break;                                         
2443                                case DDVD_KEY_FFWD:     //FastForward
2444                                case DDVD_KEY_FBWD:     //FastBackward
2445                                        {
2446                                                if (ddvd_trickmode == TOFF) {
2447                                                        if (ioctl(ddvd_fdaudio, AUDIO_SET_MUTE, 1) < 0)
2448                                                                perror("AUDIO_SET_MUTE");
2449                                                        ddvd_trickspeed = 2;
2450                                                        ddvd_trickmode = (rccode == DDVD_KEY_FBWD ? FASTBW : FASTFW);
2451                                                } else if (ddvd_trickmode == (rccode == DDVD_KEY_FBWD ? FASTFW : FASTBW)) {
2452                                                        ddvd_trickspeed /= 2;
2453                                                        if (ddvd_trickspeed == 1) {
2454                                                                ddvd_trickspeed = 0;
2455                                                                goto key_play;
2456                                                        }
2457                                                } else if (ddvd_trickspeed < 64)
2458                                                        ddvd_trickspeed *= 2;
2459                                                break;
2460                                        }
2461                                case DDVD_KEY_AUDIO:    //jump to next audio track
2462                                        {
2463                                                int count = 0;
2464                                                audio_id = (audio_id == MAX_AUDIO-1 ? 0 : audio_id+1);
2465                                                while (playerconfig->audio_format[audio_id] == -1 && count++ < MAX_AUDIO-1)
2466                                                {
2467                                                        audio_id = (audio_id == 7 ? 0 : audio_id+1);
2468                                                }
2469                                                report_audio_info = 1;
2470                                                ddvd_play_empty(TRUE);
2471                                                audio_lock = 1;
2472                                                ddvd_lpcm_count = 0;
2473                                                break;
2474                                        }
2475                                case DDVD_SET_AUDIO:    //change to given audio track
2476                                        {
2477                                                int set_audio_id;
2478                                                ddvd_readpipe(key_pipe, &set_audio_id, sizeof(int), 1);
2479                                                printf("DDVD_SET_AUDIO %i (prev %i)\n", set_audio_id, audio_id);
2480                                                if (set_audio_id < MAX_AUDIO && playerconfig->audio_format[audio_id] != -1)
2481                                                        audio_id = set_audio_id;
2482                                                report_audio_info = 1;
2483                                                ddvd_play_empty(TRUE);
2484                                                audio_lock = 1;
2485                                                ddvd_lpcm_count = 0;
2486                                                break;
2487                                        }
2488                                case DDVD_KEY_SUBTITLE: //jump to next spu track
2489                                case DDVD_SET_SUBTITLE: //change to given spu track
2490                                        {
2491                                                uint16_t spu_lang = 0xFFFF;
2492                                                int spu_id_logical;
2493                                                if (rccode == DDVD_KEY_SUBTITLE)
2494                                                {
2495                                                        int count_tmp;
2496                                                        spu_id_logical = -1;
2497                                                        count_tmp = spu_active_id;
2498                                                        while (count_tmp >= 0)
2499                                                        {
2500                                                                spu_id_logical = playerconfig->spu_map[count_tmp];
2501                                                                if (spu_id_logical >= 0)
2502                                                                        count_tmp = 0;
2503                                                                count_tmp--;
2504                                                        }
2505                                                        spu_id_logical++;
2506                                                        spu_active_id = dvdnav_get_spu_logical_stream(dvdnav, spu_id_logical);
2507                                                }
2508                                                else if (rccode == DDVD_SET_SUBTITLE)
2509                                                {
2510                                                        ddvd_readpipe(key_pipe, &spu_id_logical, sizeof(int), 1);
2511                                                        printf("DDVD_SET_SUBTITLE %i (prev %i)\n", spu_id_logical, spu_active_id);
2512                                                        if (spu_id_logical < MAX_SPU && playerconfig->spu_map[spu_id_logical] > -1)
2513                                                                spu_active_id = dvdnav_get_spu_logical_stream(dvdnav, spu_id_logical);
2514                                                }
2515                                                spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
2516                                                if (spu_lang == 0xFFFF) {
2517                                                        spu_lang = 0x2D2D;      // SPU "off"
2518                                                        spu_active_id = -1;
2519                                                        spu_id_logical = -1;
2520                                                }
2521                                                spu_lock = 1;
2522                                                msg = DDVD_SHOWOSD_SUBTITLE;
2523                                                int report_spu = spu_id_logical > 31 ? -1 : spu_id_logical;
2524                                                safe_write(message_pipe, &msg, sizeof(int));
2525                                                safe_write(message_pipe, &report_spu, sizeof(int));
2526                                                safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
2527                                                break;
2528                                        }
2529                                case DDVD_KEY_ANGLE: //change angle
2530                                        {
2531                                                int num = 0, current = 0;
2532                                                dvdnav_get_angle_info(dvdnav, &current, &num);
2533                                                if(num != 0) {
2534                                                        current++;
2535                                                if(current > num)
2536                                                        current = 1;
2537                                                }
2538                                                dvdnav_angle_change(dvdnav, current);
2539                                                msg = DDVD_SHOWOSD_ANGLE;
2540                                                safe_write(message_pipe, &msg, sizeof(int));
2541                                                safe_write(message_pipe, &current, sizeof(int));
2542                                                safe_write(message_pipe, &num, sizeof(int));
2543                                                break;
2544                                        }
2545                                case DDVD_GET_ANGLE: //frontend wants angle info
2546                                        {
2547                                                int num = 0, current = 0;
2548                                                dvdnav_get_angle_info(dvdnav, &current, &num);
2549                                                msg = DDVD_SHOWOSD_ANGLE;
2550                                                safe_write(message_pipe, &msg, sizeof(int));
2551                                                safe_write(message_pipe, &current, sizeof(int));
2552                                                safe_write(message_pipe, &num, sizeof(int));
2553                                                break;
2554                                        }
2555                                case DDVD_GET_TIME:     // frontend wants actual time
2556                                        msg = DDVD_SHOWOSD_TIME;
2557                                        break;
2558                                case DDVD_SKIP_FWD:
2559                                case DDVD_SKIP_BWD:
2560                                        {
2561                                                int skip;
2562                                                ddvd_readpipe(key_pipe, &skip, sizeof(int), 1);
2563                                                if (ddvd_trickmode == TOFF) {
2564                                                        uint32_t pos, len;
2565                                                        dvdnav_get_position(dvdnav, &pos, &len);
2566                                                        printf("DDVD_SKIP pos=%u len=%u \n", pos, len);
2567                                                        //90000 = 1 Sek.
2568                                                        if (!len)
2569                                                                len = 1;
2570                                                        long long int posneu = ((pos * ddvd_lastCellEventInfo.pgc_length) / len) + (90000 * skip);
2571                                                        printf("DDVD_SKIP posneu1=%lld\n", posneu);
2572                                                        long long int posneu2 = posneu <= 0 ? 0 : (posneu * len) / ddvd_lastCellEventInfo.pgc_length;
2573                                                        printf("DDVD_SKIP posneu2=%lld\n", posneu2);
2574                                                        if (len && posneu2 && posneu2 >= len)   // reached end of movie
2575                                                        {
2576                                                                posneu2 = len - 250;
2577                                                                reached_eof = 1;
2578                                                        }
2579                                                        dvdnav_sector_search(dvdnav, posneu2, SEEK_SET);
2580                                                        ddvd_lpcm_count = 0;
2581                                                        msg = DDVD_SHOWOSD_TIME;
2582                                                }
2583                                                break;
2584                                        }
2585                                case DDVD_SET_TITLE:
2586                                        {
2587                                                int title, totalTitles;
2588                                                ddvd_readpipe(key_pipe, &title, sizeof(int), 1);
2589                                                dvdnav_get_number_of_titles(dvdnav, &totalTitles);
2590                                                printf("DDVD_SET_TITLE %d/%d\n", title, totalTitles);
2591                                                if (title <= totalTitles) {
2592                                                        dvdnav_part_play(dvdnav, title, 0);
2593                                                        ddvd_play_empty(TRUE);
2594                                                        msg = DDVD_SHOWOSD_TIME;
2595                                                }
2596                                                break;
2597                                        }
2598                                case DDVD_SET_CHAPTER:
2599                                        {
2600                                                int chapter, totalChapters, chapterNo, titleNo;
2601                                                ddvd_readpipe(key_pipe, &chapter, sizeof(int), 1);
2602                                                dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2603                                                dvdnav_get_number_of_parts(dvdnav, titleNo, &totalChapters);
2604                                                printf("DDVD_SET_CHAPTER %d/%d in title %d\n", chapter, totalChapters, titleNo);
2605                                                if (chapter <= totalChapters) {
2606                                                        dvdnav_part_play(dvdnav, titleNo, chapter);
2607                                                        ddvd_play_empty(TRUE);
2608                                                        msg = DDVD_SHOWOSD_TIME;
2609                                                }
2610                                                break;
2611                                        }
2612                                default:
2613                                        break;
2614                                }
2615                        }
2616                }
2617                // spu handling
2618                if (ddvd_lbb_changed == 1) {
2619                       
2620                        if (ddvd_screeninfo_bypp == 1)
2621                                memcpy(ddvd_lbb2, ddvd_lbb, 720 * 576);
2622                        else {
2623                                int i = 0;
2624                                for (i = last_spu_return.y_start; i < last_spu_return.y_end; ++i)
2625                                        ddvd_blit_to_argb(ddvd_lbb2 + (i * 720 + last_spu_return.x_start) * ddvd_screeninfo_bypp, ddvd_lbb + i * 720 + last_spu_return.x_start, last_spu_return.x_end - last_spu_return.x_start);
2626                        }
2627                        //struct ddvd_resize_return blit_area;
2628                        blit_area.x_start = last_spu_return.x_start;
2629                        blit_area.x_end = last_spu_return.x_end;
2630                        blit_area.y_start = last_spu_return.y_start;
2631                        blit_area.y_end = last_spu_return.y_end;
2632                        if (!ddvd_spu_timer_active)
2633                        {
2634                                        /* in case this is the last action for this subtitle's bbox (i.e. no timer has been set), then we will clear the bbox.
2635                                           otherwise, we will leave it there, so it will be contained in the next update as well. */
2636                                last_spu_return.x_start = last_spu_return.x_end = 0;
2637                                last_spu_return.y_start = last_spu_return.y_end = 0;
2638                        }
2639
2640                        int y_source = ddvd_have_ntsc ? 480 : 576; // correct ntsc overlay
2641                        int x_offset = calc_x_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
2642                        int y_offset = calc_y_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
2643
2644                        uint64_t start=ddvd_get_time();
2645                        int resized = 0;
2646                        if ((x_offset != 0 || y_offset != 0 || y_source != ddvd_screeninfo_yres || ddvd_screeninfo_xres != 720) && !playerconfig->canscale)
2647                        {
2648//                              printf("resizing.. (x=%d y=%d %d %d, %d)\n", x_offset, y_offset, y_source, ddvd_screeninfo_yres, ddvd_screeninfo_xres );
2649                                blit_area = ddvd_resize_pixmap_spu(ddvd_lbb2, 720, y_source, ddvd_screeninfo_xres, ddvd_screeninfo_yres, x_offset, y_offset, blit_area.x_start, blit_area.x_end, blit_area.y_start, blit_area.y_end, ddvd_screeninfo_bypp); // resize
2650                                resized = 1;
2651                        }
2652                        memcpy(p_lfb, ddvd_lbb2, ddvd_screeninfo_xres * ddvd_screeninfo_yres * ddvd_screeninfo_bypp); //copy backbuffer into screen
2653
2654                        if (resized)
2655                        {
2656                                blit_area.x_offset = 0;
2657                                blit_area.y_offset = 0;
2658                                blit_area.width = 720;
2659                                blit_area.height = 576;
2660                        } else
2661                        {
2662                                blit_area.x_offset = x_offset;
2663                                blit_area.y_offset = y_offset;
2664                                blit_area.width = ddvd_screeninfo_xres;
2665                                blit_area.height = ddvd_screeninfo_yres;
2666                        }
2667
2668                        //printf("needed time for resizing: %d ms\n",(int)(ddvd_get_time()-start));
2669                        //printf("destination area to blit: %d %d %d %d Time: %d\n",blit_area.x_start,blit_area.x_end,blit_area.y_start,blit_area.y_end,last_spu_return.display_time);
2670                        int msg_old = msg;      // save and restore msg it may not be empty
2671                        msg = DDVD_SCREEN_UPDATE;
2672                        safe_write(message_pipe, &msg, sizeof(int));
2673                        safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
2674                       
2675                        msg = msg_old;
2676                        ddvd_lbb_changed = 0;           
2677                }
2678                // report audio info
2679                if (report_audio_info) {
2680                        if (playerconfig->audio_format[audio_id] > -1) {
2681                                uint16_t audio_lang = 0xFFFF;
2682                                int audio_id_logical;
2683                                audio_id_logical = dvdnav_get_audio_logical_stream(dvdnav, audio_id);
2684                                audio_lang = dvdnav_audio_stream_to_lang(dvdnav, audio_id_logical);
2685                                if (audio_lang == 0xFFFF)
2686                                        audio_lang = 0x2D2D;   
2687                                int msg_old = msg;      // save and restore msg it may not bee empty
2688                                msg = DDVD_SHOWOSD_AUDIO;
2689                                safe_write(message_pipe, &msg, sizeof(int));
2690                                safe_write(message_pipe, &audio_id, sizeof(int));
2691                                safe_write(message_pipe, &audio_lang, sizeof(uint16_t));
2692                                safe_write(message_pipe, &playerconfig->audio_format[audio_id], sizeof(int));
2693                                msg = msg_old;
2694                                report_audio_info = 0;
2695                        }
2696                }
2697        }
2698
2699err_dvdnav:
2700        /* destroy dvdnav handle */
2701        if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK)
2702                printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav));
2703
2704err_dvdnav_open:
2705        if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
2706                perror("VIDEO_CLEAR_BUFFER");
2707        if (ioctl(ddvd_fdvideo, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX) < 0)
2708                perror("VIDEO_SELECT_SOURCE");
2709        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
2710                perror("AUDIO_CLEAR_BUFFER");
2711        if (ioctl(ddvd_fdaudio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX) < 0)
2712                perror("AUDIO_SELECT_SOURCE");
2713        if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)      // restore AudioDecoder State
2714                perror("AUDIO_SET_AV_SYNC");
2715        close(ddvd_ac3_fd);
2716err_open_ac3_fd:
2717        close(ddvd_fdaudio);
2718err_open_fdaudio:
2719        close(ddvd_fdvideo);
2720err_open_fdvideo:
2721        close(ddvd_output_fd);
2722err_open_output_fd:
2723
2724#if defined(__sh__)
2725#else
2726        if (have_liba52) {
2727                a52_free(state);
2728                ddvd_close_liba52();
2729        }
2730#endif
2731
2732        //Clear Screen
2733        //struct ddvd_resize_return blit_area;                 
2734        blit_area.x_start = blit_area.y_start = 0;
2735        blit_area.x_end = ddvd_screeninfo_xres - 1;
2736        blit_area.y_end = ddvd_screeninfo_yres - 1;
2737        blit_area.x_offset = 0;
2738        blit_area.y_offset = 0;
2739        blit_area.width = ddvd_screeninfo_xres;
2740        blit_area.height = ddvd_screeninfo_yres;
2741        memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);
2742        msg = DDVD_SCREEN_UPDATE;
2743        safe_write(message_pipe, &msg, sizeof(int));
2744        safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
2745
2746err_malloc:
2747        // clean up
2748        if (ddvd_lbb != NULL)
2749                free(ddvd_lbb);
2750        if (ddvd_lbb2 != NULL)
2751                free(ddvd_lbb2);
2752        if (last_iframe != NULL)
2753                free(last_iframe);
2754        if (spu_buffer != NULL)
2755                free(spu_buffer);
2756        if (spu_backbuffer != NULL)
2757                free(spu_backbuffer);
2758
2759#if CONFIG_API_VERSION == 3
2760        ddvd_unset_pcr_offset();
2761#endif
2762        return res;
2763}
2764
2765/*
2766 * internal functions
2767 */
2768
2769// reading from pipe
2770static int ddvd_readpipe(int pipefd, void *dest, size_t bytes, int blocked_read)
2771{
2772        size_t bytes_completed = 0;
2773
2774        while (bytes_completed < bytes) {
2775                ssize_t rd = read(pipefd, dest + bytes_completed, bytes - bytes_completed);
2776                if (rd < 0) {
2777                        if (errno == EAGAIN) {
2778                                if (blocked_read || bytes_completed) {
2779                                        usleep(1);
2780                                        continue;
2781                                }
2782                                break;  // leave while loop
2783                        }
2784                        /* else if (errno == ????) // hier sollte evtl noch geschaut werden welcher error code kommt wenn die pipe geschlossen wurde...
2785                           break; */
2786                        printf("unhandled read error %d(%m)\n", errno);
2787                }
2788
2789                bytes_completed += rd;
2790                if (!blocked_read && !bytes_completed)
2791                        break;
2792        }
2793
2794        return bytes_completed;
2795}
2796
2797// get actual playing time
2798static struct ddvd_time ddvd_get_osd_time(struct ddvd *playerconfig)
2799{
2800        int titleNo;
2801        struct ddvd_time info;
2802        uint32_t pos, len;
2803
2804        info.pos_minutes = info.pos_hours = info.pos_seconds = info.pos_chapter = info.pos_title = 0;
2805        info.end_minutes = info.end_hours = info.end_seconds = info.end_chapter = 0;
2806
2807        dvdnav_get_number_of_titles(dvdnav, &info.end_title);
2808        dvdnav_current_title_info(dvdnav, &titleNo, &info.pos_chapter);
2809
2810        if (titleNo) {
2811                dvdnav_get_number_of_parts(dvdnav, titleNo, &info.end_chapter);
2812                dvdnav_get_position_in_title(dvdnav, &pos, &len);
2813
2814                uint64_t len_s = ddvd_lastCellEventInfo.pgc_length / 90000;
2815                uint64_t pos_s = ((ddvd_lastCellEventInfo.pgc_length / len) * pos) / 90000;
2816
2817                info.pos_minutes = pos_s / 60;
2818                info.pos_hours = info.pos_minutes / 60;
2819                info.pos_minutes = info.pos_minutes - (info.pos_hours * 60);
2820                info.pos_seconds = pos_s - ((info.pos_hours * 60) + info.pos_minutes) * 60;
2821                info.end_minutes = len_s / 60;
2822                info.end_hours = info.end_minutes / 60;
2823                info.end_minutes = info.end_minutes - (info.end_hours * 60);
2824                info.end_seconds = len_s - ((info.end_hours * 60) + info.end_minutes) * 60;
2825
2826                info.pos_title = titleNo;
2827        }
2828
2829        playerconfig->next_time_update = ddvd_get_time() + 1000;
2830
2831        return info;
2832}
2833
2834// video out aspect/scale
2835static int ddvd_check_aspect(int dvd_aspect, int dvd_scale_perm, int tv_aspect, int tv_mode)
2836{
2837        int tv_scale = 0; // widescreen spu
2838
2839        if (dvd_aspect == 0) // dvd 4:3
2840        {
2841                if((tv_aspect == DDVD_16_9 || tv_aspect == DDVD_16_10) && (tv_mode == DDVD_PAN_SCAN || tv_mode == DDVD_LETTERBOX))
2842                        tv_scale = 2; // pan_scan spu
2843                if (tv_aspect == DDVD_4_3 && tv_mode == DDVD_PAN_SCAN)
2844                        tv_scale = 2; // pan_scan spu
2845                if (tv_aspect == DDVD_4_3 && tv_mode == DDVD_LETTERBOX)
2846                        tv_scale = 1; // letterbox spu
2847        }
2848
2849        return tv_scale;
2850}
2851
2852// get timestamp
2853static uint64_t ddvd_get_time(void)
2854{
2855        static time_t t0 = 0;
2856        struct timeval t;
2857
2858        if (gettimeofday(&t, NULL) == 0) {
2859                if (t0 == 0)
2860                        t0 = t.tv_sec;  // this avoids an overflow (we only work with deltas)
2861                return (uint64_t) (t.tv_sec - t0) * 1000 + (uint64_t) (t.tv_usec / 1000);
2862        }
2863
2864        return 0;
2865}
2866
2867// Empty all Buffers
2868static void ddvd_play_empty(int device_clear)
2869{
2870        ddvd_wait_for_user = 0;
2871        ddvd_clear_buttons = 0;
2872        ddvd_lpcm_count = 0;
2873        ddvd_iframerun = 0;
2874        ddvd_still_frame = 0;
2875        ddvd_iframesend = 0;
2876        ddvd_last_iframe_len = 0;
2877        ddvd_spu_ptr = 0;
2878        ddvd_spu_backnr = 0;
2879        ddvd_spu_backptr = 0;
2880
2881        ddvd_wait_timer_active = 0;
2882        ddvd_wait_timer_end = 0;
2883
2884        ddvd_spu_timer_active = 0;
2885        ddvd_spu_timer_end = 0;
2886
2887        memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer
2888        ddvd_lbb_changed = 1;
2889       
2890        if (device_clear)
2891                ddvd_device_clear();
2892}
2893
2894// Empty Device Buffers
2895static void ddvd_device_clear(void)
2896{
2897        if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
2898                perror("AUDIO_CLEAR_BUFFER");
2899        if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
2900                perror("AUDIO_PLAY");
2901
2902        if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
2903                perror("VIDEO_CLEAR_BUFFER");
2904        if (ioctl(ddvd_fdvideo, VIDEO_PLAY) < 0)
2905                perror("VIDEO_PLAY");
2906
2907        if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
2908                perror("AUDIO_SET_AV_SYNC");
2909}
2910
2911// SPU Decoder
2912static struct ddvd_spu_return ddvd_spu_decode_data(const uint8_t * buffer, int len)
2913{
2914        int x1spu, x2spu, y1spu, y2spu, xspu, yspu;
2915        int offset[2], param_len;
2916        int size, datasize, controlsize, aligned, id;
2917        int menubutton = 0;
2918        int display_time = -1;
2919        int force_hide = SPU_NOP;
2920
2921        size = (buffer[0] << 8 | buffer[1]);
2922        datasize = (buffer[2] << 8 | buffer[3]);
2923        controlsize = (buffer[datasize + 2] << 8 | buffer[datasize + 3]);
2924
2925        //printf("SPU_dec: Size: %X Datasize: %X Controlsize: %X\n",size,datasize,controlsize);
2926        // parse header
2927        int i = datasize + 4;
2928
2929        while (i < size && buffer[i] != 0xFF) {
2930                switch (buffer[i]) {
2931                case 0x00:      /* force */
2932                        force_hide = SPU_FORCE;
2933                        i++;
2934                        break;
2935                case 0x01:      /* show */
2936                        force_hide = SPU_SHOW;
2937                        i++;
2938                        break;
2939                case 0x02:      /* hide */
2940                        force_hide = SPU_HIDE;
2941                        i++;
2942                        break;
2943                case 0x03:      /* palette */
2944                        {
2945                                ddvd_spudec_clut_t *clut = (ddvd_spudec_clut_t *) (buffer + i + 1);
2946                                //printf("update palette %d %d %d %d\n", clut->entry0, clut->entry1, clut->entry2, clut->entry3);
2947
2948                                ddvd_bl[3 + 252] = ddvd_bl[clut->entry0];
2949                                ddvd_gn[3 + 252] = ddvd_gn[clut->entry0];
2950                                ddvd_rd[3 + 252] = ddvd_rd[clut->entry0];
2951
2952                                ddvd_bl[2 + 252] = ddvd_bl[clut->entry1];
2953                                ddvd_gn[2 + 252] = ddvd_gn[clut->entry1];
2954                                ddvd_rd[2 + 252] = ddvd_rd[clut->entry1];
2955
2956                                ddvd_bl[1 + 252] = ddvd_bl[clut->entry2];
2957                                ddvd_gn[1 + 252] = ddvd_gn[clut->entry2];
2958                                ddvd_rd[1 + 252] = ddvd_rd[clut->entry2];
2959
2960                                ddvd_bl[0 + 252] = ddvd_bl[clut->entry3];
2961                                ddvd_gn[0 + 252] = ddvd_gn[clut->entry3];
2962                                ddvd_rd[0 + 252] = ddvd_rd[clut->entry3];
2963
2964                                //CHANGE COLORMAP
2965                                i += 3;
2966                        }
2967                        break;
2968                case 0x04:      /* transparency palette */
2969                        {
2970                                ddvd_spudec_clut_t *clut = (ddvd_spudec_clut_t *) (buffer + i + 1);
2971                                //printf("update transp palette %d %d %d %d\n", clut->entry0, clut->entry1, clut->entry2, clut->entry3);
2972
2973                                ddvd_tr[0 + 252] = (0xF - clut->entry3) * 0x1111;
2974                                ddvd_tr[1 + 252] = (0xF - clut->entry2) * 0x1111;
2975                                ddvd_tr[2 + 252] = (0xF - clut->entry1) * 0x1111;
2976                                ddvd_tr[3 + 252] = (0xF - clut->entry0) * 0x1111;
2977
2978                                //CHANGE COLORMAP
2979                                i += 3;
2980                        }
2981                        break;
2982                case 0x05:      /* image coordinates */
2983                        //printf("image coords\n");
2984                        xspu = x1spu = (((unsigned int)buffer[i + 1]) << 4) + (buffer[i + 2] >> 4);
2985                        yspu = y1spu = (((unsigned int)buffer[i + 4]) << 4) + (buffer[i + 5] >> 4);
2986                        x2spu = (((buffer[i + 2] & 0x0f) << 8) + buffer[i + 3]);
2987                        y2spu = (((buffer[i + 5] & 0x0f) << 8) + buffer[i + 6]);
2988                        //printf("%d %d %d %d\n", xspu, yspu, x2spu, y2spu);
2989                        i += 7;
2990                        break;
2991                case 0x06:      /* image 1 / image 2 offsets */
2992                        //printf("image offsets\n");
2993                        offset[0] = (((unsigned int)buffer[i + 1]) << 8) + buffer[i + 2];
2994                        offset[1] = (((unsigned int)buffer[i + 3]) << 8) + buffer[i + 4];
2995                        //printf("%d %d\n", offset[0], offset[1]);
2996                        i += 5;
2997                        break;
2998                case 0x07:      /* change color for a special area so overlays with more than 4 colors are possible - NOT IMPLEMENTET YET */
2999                        //printf("change color packet\n");
3000                        param_len = (buffer[i + 1] << 8 | buffer[i + 2]);
3001                        i += param_len + 1;
3002                        break;
3003                default:
3004                        i++;
3005                        break;
3006                }
3007        }
3008
3009        //get display time
3010        if (i + 6 <= size) {
3011                if (buffer[i + 5] == 0x02 && buffer[i + 6] == 0xFF) {
3012                        display_time = ((buffer[i + 1] << 8) + buffer[i + 2]);
3013                        //printf("Display Time: %d\n",ddvd_display_time);
3014                }
3015        }
3016        //printf("SPU_dec: Image coords x1: %d y1: %d x2: %d y2: %d\n",x1spu,y1spu,x2spu,y2spu);
3017        //printf("Offset[0]: %X Offset[1]: %X\n",offset[0],offset[1]);
3018
3019        // parse picture
3020
3021        aligned = 1;
3022        id = 0;
3023
3024        while (offset[1] < datasize + 2 && yspu <= 575) // there are some special cases the decoder tries to write more than 576 lines in our buffer and we dont want this ;)
3025        {
3026                u_int len;
3027                u_int code;
3028
3029                code = (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
3030                aligned = aligned ? 0 : 1;
3031
3032                if (code < 0x0004) {
3033                        code = (code << 4) | (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
3034                        aligned = aligned ? 0 : 1;
3035                        if (code < 0x0010) {
3036                                code = (code << 4) | (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
3037                                aligned = aligned ? 0 : 1;
3038                                if (code < 0x0040) {
3039                                        code = (code << 4) | (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
3040                                        aligned = aligned ? 0 : 1;
3041                                }
3042                        }
3043                }
3044
3045                len = code >> 2;
3046
3047                if (len == 0)
3048                        len = (x2spu - xspu) + 1;
3049
3050                memset(ddvd_lbb + xspu + 720 * (yspu), (code & 3) + 252, len);  //drawpixel into backbuffer
3051                xspu += len;
3052                if (xspu > x2spu) {
3053                        if (!aligned) {
3054                                code = (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
3055                                aligned = aligned ? 0 : 1;
3056                        }
3057                        xspu = x1spu;   //next line
3058                        yspu++;
3059                        id = id ? 0 : 1;
3060                }
3061        }
3062        struct ddvd_spu_return return_code;
3063        return_code.display_time = display_time;
3064        return_code.x_start = x1spu;
3065        return_code.x_end = x2spu;
3066        return_code.y_start = y1spu;
3067        return_code.y_end = y2spu;
3068        return_code.force_hide = force_hide;
3069       
3070        return return_code;
3071}
3072
3073// blit to argb in 32bit mode
3074#ifdef __sh__
3075#define alpha_composite(composite, fg, alpha, bg) {  \
3076    unsigned short temp = ((unsigned short)(fg)*(unsigned short)(alpha) +   \
3077    (unsigned short)(bg)*(unsigned short)(255 - (unsigned short)(alpha)) +  \
3078    (unsigned short)128);  \
3079    (composite) = (unsigned char)((temp + (temp >> 8)) >> 8);  \
3080}
3081#endif
3082static void ddvd_blit_to_argb(void *_dst, const void *_src, int pix)
3083{
3084        unsigned long *dst = _dst;
3085        const unsigned char *src = _src;
3086        while (pix--) {
3087                int p = (*src++);
3088                int a, r, g, b;
3089#ifdef __sh__
3090                int r1, g1, b1;
3091#endif         
3092                if (p == 0) {
3093                        r = g = b = a = 0;      //clear screen (transparency)
3094                } else {
3095#ifdef __sh__
3096                        a = 0xFF - (ddvd_tr[p] >> 8);
3097                        r1 = ddvd_rd[p] >> 8;
3098                        g1 = ddvd_gn[p] >> 8;
3099                        b1 = ddvd_bl[p] >> 8;
3100      alpha_composite(r, r1, a, 0);
3101      alpha_composite(g, g1, a, 0);
3102      alpha_composite(b, b1, a, 0);
3103#else
3104                        a = 0xFF - (ddvd_tr[p] >> 8);
3105                        r = ddvd_rd[p] >> 8;
3106                        g = ddvd_gn[p] >> 8;
3107                        b = ddvd_bl[p] >> 8;
3108#endif
3109                }
3110                *dst++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
3111        }
3112}
3113
3114#if CONFIG_API_VERSION == 3
3115
3116// set decoder buffer offsets to a minimum
3117static void ddvd_set_pcr_offset(void)
3118{
3119        write_string("/proc/stb/pcr/pcr_stc_offset", "200");
3120        write_string("/proc/stb/vmpeg/0/sync_offset", "200");
3121}
3122
3123// reset decoder buffer offsets
3124static void ddvd_unset_pcr_offset(void)
3125{
3126        write_string("/proc/stb/pcr/pcr_stc_offset", "2710");
3127        write_string("/proc/stb/vmpeg/0/sync_offset", "2710");
3128}
3129
3130#endif
3131
3132
3133// "nearest neighbor" pixmap resizing
3134struct ddvd_resize_return ddvd_resize_pixmap_xbpp(unsigned char *pixmap, int xsource, int ysource, int xdest, int ydest, int xoffset, int yoffset, int xstart, int xend, int ystart, int yend, int colors)
3135{
3136    int x_ratio = (int)((xsource<<16)/(xdest-2*xoffset)) ;
3137    int y_ratio = (int)(((ysource-2*yoffset)<<16)/ydest) ;
3138        int yoffset2 = (yoffset<<16)/y_ratio;
3139       
3140        unsigned char *pixmap_tmp;
3141        pixmap_tmp = (unsigned char *)malloc(xsource*ysource*colors);
3142        memcpy(pixmap_tmp, pixmap, xsource*ysource*colors);
3143        memset(pixmap, 0, xdest * ydest * colors);      //clear screen ..
3144        struct ddvd_resize_return return_code;
3145       
3146        return_code.x_start=(xstart<<16)/x_ratio; // transform input resize area to destination area
3147        return_code.x_end=(xend<<16)/x_ratio;
3148        return_code.y_start=((ystart<<16)/y_ratio)-yoffset2;
3149        return_code.y_end=((yend<<16)/y_ratio)-yoffset2;
3150        return_code.y_start = return_code.y_start < 0 ? 0 : return_code.y_start;
3151        return_code.y_end = return_code.y_end > ydest ? ydest : return_code.y_end;
3152       
3153        int x2, y2, c, i ,j;
3154    for (i=return_code.y_start;i<=return_code.y_end;i++) {
3155        for (j=return_code.x_start;j<=return_code.x_end;j++) {
3156            x2 = ((j*x_ratio)>>16) ;
3157            y2 = ((i*y_ratio)>>16)+yoffset ;
3158            for (c=0; c<colors; c++)
3159                                pixmap[((i*xdest)+j)*colors + c + xoffset*colors] = pixmap_tmp[((y2*xsource)+x2)*colors + c] ;
3160        }               
3161    }   
3162        free(pixmap_tmp);
3163       
3164        return_code.x_start+=xoffset; // correct xoffset
3165        return_code.x_end+=xoffset;
3166       
3167        return return_code;
3168}
3169
3170// bicubic picture resize
3171struct ddvd_resize_return ddvd_resize_pixmap_xbpp_smooth(unsigned char *pixmap, int xsource, int ysource, int xdest, int ydest, int xoffset, int yoffset, int xstart, int xend, int ystart, int yend, int colors)
3172{
3173        unsigned int xs,ys,xd,yd,dpixel,fx,fy;
3174        unsigned int c,tmp_i;
3175        int x,y,t,t1;
3176
3177        xs=xsource; // x-resolution source
3178        ys=ysource-2*yoffset; // y-resolution source
3179        xd=xdest-2*xoffset; // x-resolution destination
3180        yd=ydest; // y-resolution destination
3181        unsigned char *pixmap_tmp;
3182        pixmap_tmp = (unsigned char *)malloc(xsource*ysource*colors);
3183        memcpy(pixmap_tmp, pixmap, xsource*ysource*colors);
3184        memset(pixmap, 0, xdest * ydest * colors);      //clear screen ..
3185        struct ddvd_resize_return return_code;
3186       
3187        int yoffset2 = (yoffset<<16)/((ys<<16)/yd);
3188        return_code.x_start=(xstart<<16)/((xs<<16)/xd); // transform input resize area to destination area
3189        return_code.x_end=(xend<<16)/((xs<<16)/xd);
3190        return_code.y_start=((ystart<<16)/((ys<<16)/yd))-yoffset2;
3191        return_code.y_end=((yend<<16)/((ys<<16)/yd))-yoffset2;
3192        return_code.y_start = return_code.y_start < 0 ? 0 : return_code.y_start;
3193        return_code.y_end = return_code.y_end > ydest ? ydest : return_code.y_end;
3194       
3195        // get x scale factor, use bitshifting to get rid of floats
3196        fx=((xs-1)<<16)/xd;
3197
3198        // get y scale factor, use bitshifting to get rid of floats
3199        fy=((ys-1)<<16)/yd;
3200
3201        unsigned int sx1[xd],sx2[xd],sy1,sy2;
3202       
3203        // pre calculating sx1/sx2 for faster resizing
3204        for (x=return_code.x_start; x<=return_code.x_end; x++)
3205        {
3206                // first x source pixel for calculating destination pixel
3207                sx1[x]=(fx*x)>>16; //floor()
3208
3209                // last x source pixel for calculating destination pixel
3210                sx2[x]=sx1[x]+(fx>>16);
3211                if (fx & 0x7FFF) //ceil()
3212                        sx2[x]++;
3213        }
3214       
3215        // Scale
3216        for (y=return_code.y_start; y<=return_code.y_end; y++)
3217        {
3218
3219                // first y source pixel for calculating destination pixel
3220                sy1=(fy*y)>>16; //floor()
3221
3222                // last y source pixel for calculating destination pixel
3223                sy2=sy1+(fy>>16);
3224                if (fy & 0x7FFF) //ceil()
3225                        sy2++;
3226
3227                for (x=return_code.x_start; x<=return_code.x_end; x++)
3228                {
3229                        // we do this for every color
3230                        for (c=0; c<colors; c++)
3231                        {
3232                                // calculating destination pixel
3233                                tmp_i=0;
3234                                dpixel=0;
3235                                for (t1=sy1; t1<sy2; t1++)
3236                                {
3237                                        for (t=sx1[x]; t<=sx2[x]; t++)
3238                                        {
3239                                                tmp_i+=(int)pixmap_tmp[(t*colors)+c+((t1+yoffset)*xs*colors)];
3240                                                dpixel++;               
3241                                        }
3242                                }
3243                                // writing calculated pixel into destination pixmap
3244                                pixmap[((x+xoffset)*colors)+c+(y*(xd+2*xoffset)*colors)]=tmp_i/dpixel;
3245                        }
3246                }
3247        }
3248        free(pixmap_tmp);
3249       
3250        return_code.x_start+=xoffset; // correct xoffset
3251        return_code.x_end+=xoffset;
3252       
3253        return return_code;
3254}
3255
3256// very simple linear resize used for 1bypp mode
3257struct ddvd_resize_return ddvd_resize_pixmap_1bpp(unsigned char *pixmap, int xsource, int ysource, int xdest, int ydest, int xoffset, int yoffset, int xstart, int xend, int ystart, int yend, int colors)
3258{
3259        unsigned char *pixmap_tmp;
3260        pixmap_tmp = (unsigned char *)malloc(xsource * ysource * colors);
3261        memcpy(pixmap_tmp, pixmap, xsource * ysource * colors);
3262        memset(pixmap, 0, xdest * ydest * colors);      //clear screen ..
3263        struct ddvd_resize_return return_code;
3264       
3265        int i, fx, fy, tmp;
3266       
3267        // precalculate scale factor, use factor 10 to get rid of floats
3268        fx=xsource*10/(xdest-2*xoffset);
3269        fy=(ysource-2*yoffset)*10/ydest;
3270        int yoffset2 = (yoffset*10)/fy;
3271       
3272        return_code.x_start=(xstart*10)/fx; // transform input resize area to destination area
3273        return_code.x_end=(xend*10)/fx;
3274        return_code.y_start=(ystart*10)/fy;
3275        return_code.y_end=(yend*10)/fy;
3276        return_code.y_start = return_code.y_start < 0 ? 0 : return_code.y_start;
3277        return_code.y_end = return_code.y_end > ydest ? ydest : return_code.y_end;
3278       
3279        // scale x
3280        for (i = return_code.x_start; i <= return_code.x_end; i++)
3281                pixmap[i+xoffset]=pixmap_tmp[((fx*i)/10)];
3282
3283        // scale y
3284        for (i = return_code.y_start; i <= return_code.y_end; i++)
3285        {
3286                tmp=(fy*i)/10;
3287                if (tmp != i)
3288                        memcpy(pixmap + (i*xdest), pixmap + (tmp + yoffset) * xdest, xdest);
3289        }       
3290        free(pixmap_tmp);
3291       
3292        return_code.x_start+=xoffset; // correct xoffset
3293        return_code.x_end+=xoffset;
3294       
3295        return return_code;
3296}
3297
Note: See TracBrowser for help on using the repository browser.