~ubuntu-branches/ubuntu/precise/vlc/precise-proposed

« back to all changes in this revision

Viewing changes to modules/access/bluray.c

  • Committer: Package Import Robot
  • Author(s): Benjamin Drung
  • Date: 2012-03-24 01:33:03 UTC
  • mfrom: (1.1.46) (3.5.39 sid)
  • Revision ID: package-import@ubuntu.com-20120324013303-km51kpl9kixydb8g
Really add the preinst from Didier Raboud to vlc to drop it's doc directory
before unpacking a symlink to vlc-nox's over it. (Closes: #613121, #662217)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 * bluray.c: Blu-ray disc support plugin
3
3
 *****************************************************************************
4
 
 * Copyright © 2010-2011 VideoLAN, VLC authors and libbluray AUTHORS
 
4
 * Copyright © 2010-2012 VideoLAN, VLC authors and libbluray AUTHORS
5
5
 *
6
6
 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
 
7
 *          Hugo Beauzée-Luyssen <hugo@videolan.org>
7
8
 *
8
9
 * This program is free software; you can redistribute it and/or modify it
9
10
 * under the terms of the GNU Lesser General Public License as published by
36
37
#include <vlc_demux.h>                      /* demux_t */
37
38
#include <vlc_input.h>                      /* Seekpoints, chapters */
38
39
#include <vlc_dialog.h>                     /* BD+/AACS warnings */
 
40
#include <vlc_vout.h>                       /* vout_PutSubpicture / subpicture_t */
39
41
 
40
42
#include <libbluray/bluray.h>
 
43
#include <libbluray/keys.h>
41
44
#include <libbluray/meta_data.h>
 
45
#include <libbluray/overlay.h>
42
46
 
43
47
/*****************************************************************************
44
48
 * Module descriptor
45
49
 *****************************************************************************/
46
50
 
 
51
#define BD_MENU_TEXT        N_( "Bluray menus" )
 
52
#define BD_MENU_LONGTEXT    N_( "Use bluray menus. If disabled, "\
 
53
                                "the movie will start directly" )
 
54
 
47
55
/* Callbacks */
48
56
static int  blurayOpen ( vlc_object_t * );
49
57
static void blurayClose( vlc_object_t * );
55
63
    set_category( CAT_INPUT )
56
64
    set_subcategory( SUBCAT_INPUT_ACCESS )
57
65
    set_capability( "access_demux", 200)
 
66
    add_bool( "bluray-menu", false, BD_MENU_TEXT, BD_MENU_LONGTEXT, false )
58
67
 
59
68
    add_shortcut( "bluray", "file" )
60
69
 
61
70
    set_callbacks( blurayOpen, blurayClose )
62
71
vlc_module_end ()
63
72
 
64
 
 
65
 
struct demux_sys_t
66
 
{
67
 
    BLURAY         *bluray;
 
73
/* libbluray's overlay.h defines 2 types of overlay (bd_overlay_plane_e). */
 
74
#define MAX_OVERLAY 2
 
75
 
 
76
typedef enum OverlayStatus {
 
77
    Closed = 0,
 
78
    ToDisplay,  //Used to mark the overlay to be displayed the first time.
 
79
    Displayed,
 
80
    Outdated    //used to update the overlay after it has been sent to the vout
 
81
} OverlayStatus;
 
82
 
 
83
typedef struct bluray_overlay_t
 
84
{
 
85
    VLC_GC_MEMBERS
 
86
 
 
87
    vlc_mutex_t         lock;
 
88
    subpicture_t        *p_pic;
 
89
    OverlayStatus       status;
 
90
    subpicture_region_t *p_regions;
 
91
} bluray_overlay_t;
 
92
 
 
93
struct  demux_sys_t
 
94
{
 
95
    BLURAY              *bluray;
68
96
 
69
97
    /* Titles */
70
 
    unsigned int    i_title;
71
 
    unsigned int    i_longest_title;
72
 
    input_title_t **pp_title;
 
98
    unsigned int        i_title;
 
99
    unsigned int        i_longest_title;
 
100
    input_title_t       **pp_title;
 
101
 
 
102
    /* Meta informations */
 
103
    const META_DL       *p_meta;
 
104
 
 
105
    /* Menus */
 
106
    bluray_overlay_t    *p_overlays[MAX_OVERLAY];
 
107
    int                 current_overlay; // -1 if no current overlay;
 
108
    bool                b_menu;
 
109
 
 
110
    /* */
 
111
    input_thread_t      *p_input;
 
112
    vout_thread_t       *p_vout;
73
113
 
74
114
    /* TS stream */
75
 
    stream_t       *p_parser;
 
115
    stream_t            *p_parser;
 
116
};
 
117
 
 
118
struct subpicture_updater_sys_t
 
119
{
 
120
    bluray_overlay_t    *p_overlay;
76
121
};
77
122
 
78
123
/*****************************************************************************
79
124
 * Local prototypes
80
125
 *****************************************************************************/
81
 
static int     blurayControl(demux_t *, int, va_list);
82
 
static int     blurayDemux  (demux_t *);
83
 
 
84
 
static int     blurayInitTitles(demux_t *p_demux );
85
 
static int     bluraySetTitle(demux_t *p_demux, int i_title);
 
126
static int   blurayControl(demux_t *, int, va_list);
 
127
static int   blurayDemux(demux_t *);
 
128
 
 
129
static int   blurayInitTitles(demux_t *p_demux );
 
130
static int   bluraySetTitle(demux_t *p_demux, int i_title);
 
131
 
 
132
static void  blurayOverlayProc(void *ptr, const BD_OVERLAY * const overlay);
 
133
 
 
134
static int   onMouseEvent(vlc_object_t *p_vout, const char *psz_var,
 
135
                          vlc_value_t old, vlc_value_t val, void *p_data);
86
136
 
87
137
#define FROM_TICKS(a) (a*CLOCK_FREQ / INT64_C(90000))
88
138
#define TO_TICKS(a)   (a*INT64_C(90000)/CLOCK_FREQ)
96
146
    demux_t *p_demux = (demux_t*)object;
97
147
    demux_sys_t *p_sys;
98
148
 
99
 
    char *pos_title;
100
 
    int i_title = -1;
101
149
    char bd_path[PATH_MAX] = { '\0' };
102
150
    const char *error_msg = NULL;
103
151
 
107
155
    }
108
156
 
109
157
    /* */
110
 
    p_demux->p_sys = p_sys = malloc(sizeof(*p_sys));
 
158
    p_demux->p_sys = p_sys = calloc(1, sizeof(*p_sys));
111
159
    if (unlikely(!p_sys)) {
112
160
        return VLC_ENOMEM;
113
161
    }
114
 
    p_sys->p_parser = NULL;
 
162
    p_sys->current_overlay = -1;
115
163
 
116
164
    /* init demux info fields */
117
165
    p_demux->info.i_update    = 0;
154
202
 
155
203
    /* Warning the user about AACS/BD+ */
156
204
    const BLURAY_DISC_INFO *disc_info = bd_get_disc_info(p_sys->bluray);
 
205
 
 
206
    /* Is it a bluray? */
 
207
    if (!disc_info->bluray_detected) {
 
208
        error_msg = "Path doesn't appear to be a bluray";
 
209
        goto error;
 
210
    }
 
211
 
157
212
    msg_Info(p_demux, "First play: %i, Top menu: %i\n"
158
213
                      "HDMV Titles: %i, BD-J Titles: %i, Other: %i",
159
214
             disc_info->first_play_supported, disc_info->top_menu_supported,
189
244
    }
190
245
 
191
246
    /* Get titles and chapters */
 
247
    p_sys->p_meta = bd_get_meta(p_sys->bluray);
 
248
    if (!p_sys->p_meta)
 
249
        msg_Warn(p_demux, "Failed to get meta info." );
 
250
 
192
251
    if (blurayInitTitles(p_demux) != VLC_SUCCESS) {
193
252
        goto error;
194
253
    }
195
254
 
196
 
    /* get title request */
197
 
    if ((pos_title = strrchr(bd_path, ':'))) {
198
 
        /* found character ':' for title information */
199
 
        *(pos_title++) = '\0';
200
 
        i_title = atoi(pos_title);
201
 
    }
202
 
 
203
 
    /* set start title number */
204
 
    if (bluraySetTitle(p_demux, i_title) != VLC_SUCCESS) {
205
 
        msg_Err( p_demux, "Could not set the title %d", i_title );
206
 
        goto error;
207
 
    }
208
 
 
209
 
    p_sys->p_parser   = stream_DemuxNew(p_demux, "ts", p_demux->out);
 
255
    /*
 
256
     * Initialize the event queue, so we can receive events in blurayDemux(Menu).
 
257
     */
 
258
    bd_get_event(p_sys->bluray, NULL);
 
259
 
 
260
    p_sys->b_menu = var_InheritBool(p_demux, "bluray-menu");
 
261
    if (p_sys->b_menu) {
 
262
        p_sys->p_input = demux_GetParentInput(p_demux);
 
263
        if (unlikely(!p_sys->p_input)) {
 
264
            error_msg = "Could not get parent input";
 
265
            goto error;
 
266
        }
 
267
 
 
268
        /* libbluray will start playback from "First-Title" title */
 
269
        if (bd_play(p_sys->bluray) == 0) {
 
270
            error_msg = "Failed to start bluray playback. Please try without menu support.";
 
271
            goto error;
 
272
        }
 
273
        /* Registering overlay event handler */
 
274
        bd_register_overlay_proc(p_sys->bluray, p_demux, blurayOverlayProc);
 
275
    } else {
 
276
        /* set start title number */
 
277
        if (bluraySetTitle(p_demux, p_sys->i_longest_title) != VLC_SUCCESS) {
 
278
            msg_Err( p_demux, "Could not set the title %d", p_sys->i_longest_title );
 
279
            goto error;
 
280
        }
 
281
    }
 
282
 
 
283
    p_sys->p_parser = stream_DemuxNew(p_demux, "ts", p_demux->out);
210
284
    if (!p_sys->p_parser) {
211
285
        msg_Err(p_demux, "Failed to create TS demuxer");
212
286
        goto error;
233
307
    demux_t *p_demux = (demux_t*)object;
234
308
    demux_sys_t *p_sys = p_demux->p_sys;
235
309
 
 
310
    /*
 
311
     * Close libbluray first.
 
312
     * This will close all the overlays before we release p_vout
 
313
     * bd_close( NULL ) can crash
 
314
     */
 
315
    assert(p_sys->bluray);
 
316
    bd_close(p_sys->bluray);
 
317
 
 
318
    if (p_sys->p_vout != NULL) {
 
319
        var_DelCallback(p_sys->p_vout, "mouse-moved", &onMouseEvent, p_demux);
 
320
        var_DelCallback(p_sys->p_vout, "mouse-clicked", &onMouseEvent, p_demux);
 
321
        vlc_object_release(p_sys->p_vout);
 
322
    }
 
323
    if (p_sys->p_input != NULL)
 
324
        vlc_object_release(p_sys->p_input);
236
325
    if (p_sys->p_parser)
237
326
        stream_Delete(p_sys->p_parser);
238
327
 
241
330
        vlc_input_title_Delete(p_sys->pp_title[i]);
242
331
    TAB_CLEAN( p_sys->i_title, p_sys->pp_title );
243
332
 
244
 
    /* bd_close( NULL ) can crash */
245
 
    assert(p_sys->bluray);
246
 
    bd_close(p_sys->bluray);
247
333
    free(p_sys);
248
334
}
249
335
 
 
336
/*****************************************************************************
 
337
 * subpicture_updater_t functions:
 
338
 *****************************************************************************/
 
339
static int subpictureUpdaterValidate( subpicture_t *p_subpic,
 
340
                                      bool b_fmt_src, const video_format_t *p_fmt_src,
 
341
                                      bool b_fmt_dst, const video_format_t *p_fmt_dst,
 
342
                                      mtime_t i_ts )
 
343
{
 
344
    VLC_UNUSED( b_fmt_src );
 
345
    VLC_UNUSED( b_fmt_dst );
 
346
    VLC_UNUSED( p_fmt_src );
 
347
    VLC_UNUSED( p_fmt_dst );
 
348
    VLC_UNUSED( i_ts );
 
349
 
 
350
    subpicture_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
 
351
    bluray_overlay_t         *p_overlay = p_upd_sys->p_overlay;
 
352
 
 
353
    vlc_mutex_lock(&p_overlay->lock);
 
354
    int res = p_overlay->status == Outdated;
 
355
    vlc_mutex_unlock(&p_overlay->lock);
 
356
    return res;
 
357
}
 
358
 
 
359
/* This should probably be moved to subpictures.c afterward */
 
360
static subpicture_region_t* subpicture_region_Clone(subpicture_region_t *p_region_src)
 
361
{
 
362
    if (!p_region_src)
 
363
        return NULL;
 
364
    subpicture_region_t *p_region_dst = subpicture_region_New(&p_region_src->fmt);
 
365
    if (unlikely(!p_region_dst))
 
366
        return NULL;
 
367
 
 
368
    p_region_dst->i_x      = p_region_src->i_x;
 
369
    p_region_dst->i_y      = p_region_src->i_y;
 
370
    p_region_dst->i_align  = p_region_src->i_align;
 
371
    p_region_dst->i_alpha  = p_region_src->i_alpha;
 
372
 
 
373
    p_region_dst->psz_text = p_region_src->psz_text ? strdup(p_region_src->psz_text) : NULL;
 
374
    p_region_dst->psz_html = p_region_src->psz_html ? strdup(p_region_src->psz_html) : NULL;
 
375
    if (p_region_src->p_style != NULL) {
 
376
        p_region_dst->p_style = malloc(sizeof(*p_region_dst->p_style));
 
377
        p_region_dst->p_style = text_style_Copy(p_region_dst->p_style,
 
378
                                                p_region_src->p_style);
 
379
    }
 
380
 
 
381
    //Palette is already copied by subpicture_region_New, we just have to duplicate p_pixels
 
382
    for (int i = 0; i < p_region_src->p_picture->i_planes; i++)
 
383
        memcpy(p_region_dst->p_picture->p[i].p_pixels,
 
384
               p_region_src->p_picture->p[i].p_pixels,
 
385
               p_region_src->p_picture->p[i].i_lines * p_region_src->p_picture->p[i].i_pitch);
 
386
    return p_region_dst;
 
387
}
 
388
 
 
389
static void subpictureUpdaterUpdate(subpicture_t *p_subpic,
 
390
                                    const video_format_t *p_fmt_src,
 
391
                                    const video_format_t *p_fmt_dst,
 
392
                                    mtime_t i_ts)
 
393
{
 
394
    VLC_UNUSED(p_fmt_src);
 
395
    VLC_UNUSED(p_fmt_dst);
 
396
    VLC_UNUSED(i_ts);
 
397
    subpicture_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
 
398
    bluray_overlay_t         *p_overlay = p_upd_sys->p_overlay;
 
399
 
 
400
    /*
 
401
     * When this function is called, all p_subpic regions are gone.
 
402
     * We need to duplicate our regions (stored internaly) to this subpic.
 
403
     */
 
404
    vlc_mutex_lock(&p_overlay->lock);
 
405
 
 
406
    subpicture_region_t *p_src = p_overlay->p_regions;
 
407
    if (!p_src)
 
408
        return;
 
409
 
 
410
    subpicture_region_t **p_dst = &(p_subpic->p_region);
 
411
    while (p_src != NULL) {
 
412
        *p_dst = subpicture_region_Clone(p_src);
 
413
        if (*p_dst == NULL)
 
414
            break;
 
415
        p_dst = &((*p_dst)->p_next);
 
416
        p_src = p_src->p_next;
 
417
    }
 
418
    if (*p_dst != NULL)
 
419
        (*p_dst)->p_next = NULL;
 
420
    p_overlay->status = Displayed;
 
421
    vlc_mutex_unlock(&p_overlay->lock);
 
422
}
 
423
 
 
424
static void subpictureUpdaterDestroy(subpicture_t *p_subpic)
 
425
{
 
426
    vlc_gc_decref(p_subpic->updater.p_sys->p_overlay);
 
427
}
 
428
 
 
429
/*****************************************************************************
 
430
 * User input events:
 
431
 *****************************************************************************/
 
432
static int onMouseEvent(vlc_object_t *p_vout, const char *psz_var, vlc_value_t old,
 
433
                        vlc_value_t val, void *p_data)
 
434
{
 
435
    demux_t     *p_demux = (demux_t*)p_data;
 
436
    demux_sys_t *p_sys   = p_demux->p_sys;
 
437
    mtime_t     now      = mdate();
 
438
    VLC_UNUSED(old);
 
439
    VLC_UNUSED(p_vout);
 
440
 
 
441
    if (psz_var[6] == 'm')   //Mouse moved
 
442
        bd_mouse_select(p_sys->bluray, now, val.coords.x, val.coords.y);
 
443
    else if (psz_var[6] == 'c') {
 
444
        bd_mouse_select(p_sys->bluray, now, val.coords.x, val.coords.y);
 
445
        bd_user_input(p_sys->bluray, now, BD_VK_MOUSE_ACTIVATE);
 
446
    } else {
 
447
        assert(0);
 
448
    }
 
449
    return VLC_SUCCESS;
 
450
}
 
451
 
 
452
/*****************************************************************************
 
453
 * libbluray overlay handling:
 
454
 *****************************************************************************/
 
455
static void blurayCleanOverayStruct(gc_object_t *p_gc)
 
456
{
 
457
    bluray_overlay_t *p_overlay = vlc_priv(p_gc, bluray_overlay_t);
 
458
 
 
459
    /*
 
460
     * This will be called when destroying the picture.
 
461
     * Don't delete it again from here!
 
462
     */
 
463
    vlc_mutex_destroy(&p_overlay->lock);
 
464
    subpicture_region_Delete(p_overlay->p_regions);
 
465
    free(p_overlay);
 
466
}
 
467
 
 
468
static void blurayCloseAllOverlays(demux_t *p_demux)
 
469
{
 
470
    demux_sys_t *p_sys = p_demux->p_sys;
 
471
 
 
472
    p_demux->p_sys->current_overlay = -1;
 
473
    if (p_sys->p_vout != NULL) {
 
474
        for (int i = 0; i < 0; i++) {
 
475
            if (p_sys->p_overlays[i] != NULL) {
 
476
                vout_FlushSubpictureChannel(p_sys->p_vout,
 
477
                                            p_sys->p_overlays[i]->p_pic->i_channel);
 
478
                vlc_gc_decref(p_sys->p_overlays[i]);
 
479
                p_sys->p_overlays[i] = NULL;
 
480
            }
 
481
        }
 
482
        var_DelCallback(p_sys->p_vout, "mouse-moved", &onMouseEvent, p_demux);
 
483
        var_DelCallback(p_sys->p_vout, "mouse-clicked", &onMouseEvent, p_demux);
 
484
        vlc_object_release(p_sys->p_vout);
 
485
        p_sys->p_vout = NULL;
 
486
    }
 
487
}
 
488
 
 
489
/*
 
490
 * Mark the overlay as "ToDisplay" status.
 
491
 * This will not send the overlay to the vout instantly, as the vout
 
492
 * may not be acquired (not acquirable) yet.
 
493
 * If is has already been acquired, the overlay has already been sent to it,
 
494
 * therefore, we only flag the overlay as "Outdated"
 
495
 */
 
496
static void blurayActivateOverlay(demux_t *p_demux, const BD_OVERLAY* const ov)
 
497
{
 
498
    demux_sys_t *p_sys = p_demux->p_sys;
 
499
 
 
500
    /*
 
501
     * If the overlay is already displayed, mark the picture as outdated.
 
502
     * We must NOT use vout_PutSubpicture if a picture is already displayed.
 
503
     */
 
504
    vlc_mutex_lock(&p_sys->p_overlays[ov->plane]->lock);
 
505
    if ((p_sys->p_overlays[ov->plane]->status == Displayed ||
 
506
            p_sys->p_overlays[ov->plane]->status == Outdated)
 
507
            && p_sys->p_vout) {
 
508
        p_sys->p_overlays[ov->plane]->status = Outdated;
 
509
        vlc_mutex_unlock(&p_sys->p_overlays[ov->plane]->lock);
 
510
        return;
 
511
    }
 
512
    /*
 
513
     * Mark the overlay as available, but don't display it right now.
 
514
     * the blurayDemuxMenu will send it to vout, as it may be unavailable when
 
515
     * the overlay is computed
 
516
     */
 
517
    p_sys->current_overlay = ov->plane;
 
518
    p_sys->p_overlays[ov->plane]->status = ToDisplay;
 
519
    vlc_mutex_unlock(&p_sys->p_overlays[ov->plane]->lock);
 
520
}
 
521
 
 
522
static void blurayInitOverlay(demux_t *p_demux, const BD_OVERLAY* const ov)
 
523
{
 
524
    demux_sys_t *p_sys = p_demux->p_sys;
 
525
 
 
526
    assert(p_sys->p_overlays[ov->plane] == NULL);
 
527
 
 
528
    p_sys->p_overlays[ov->plane] = calloc(1, sizeof(**p_sys->p_overlays));
 
529
    if (unlikely(!p_sys->p_overlays[ov->plane]))
 
530
        return;
 
531
 
 
532
    subpicture_updater_sys_t *p_upd_sys = malloc(sizeof(*p_upd_sys));
 
533
    if (unlikely(!p_upd_sys)) {
 
534
        free(p_sys->p_overlays[ov->plane]);
 
535
        p_sys->p_overlays[ov->plane] = NULL;
 
536
        return;
 
537
    }
 
538
    vlc_gc_init(p_sys->p_overlays[ov->plane], blurayCleanOverayStruct);
 
539
    /* Incrementing refcounter: vout + demux */
 
540
    vlc_gc_incref(p_sys->p_overlays[ov->plane]);
 
541
 
 
542
    p_upd_sys->p_overlay = p_sys->p_overlays[ov->plane];
 
543
    subpicture_updater_t updater = {
 
544
        .pf_validate = subpictureUpdaterValidate,
 
545
        .pf_update   = subpictureUpdaterUpdate,
 
546
        .pf_destroy  = subpictureUpdaterDestroy,
 
547
        .p_sys       = p_upd_sys,
 
548
    };
 
549
    p_sys->p_overlays[ov->plane]->p_pic = subpicture_New(&updater);
 
550
    p_sys->p_overlays[ov->plane]->p_pic->i_original_picture_width = ov->w;
 
551
    p_sys->p_overlays[ov->plane]->p_pic->i_original_picture_height = ov->h;
 
552
    p_sys->p_overlays[ov->plane]->p_pic->b_ephemer = true;
 
553
    p_sys->p_overlays[ov->plane]->p_pic->b_absolute = true;
 
554
}
 
555
 
 
556
/**
 
557
 * Destroy every regions in the subpicture.
 
558
 * This is done in two steps:
 
559
 * - Wiping our private regions list
 
560
 * - Flagging the overlay as outdated, so the changes are replicated from
 
561
 *   the subpicture_updater_t::pf_update
 
562
 * This doesn't destroy the subpicture, as the overlay may be used again by libbluray.
 
563
 */
 
564
static void blurayClearOverlay(demux_t *p_demux, const BD_OVERLAY* const ov)
 
565
{
 
566
    demux_sys_t *p_sys = p_demux->p_sys;
 
567
 
 
568
    vlc_mutex_lock(&p_sys->p_overlays[ov->plane]->lock);
 
569
 
 
570
    subpicture_region_ChainDelete(p_sys->p_overlays[ov->plane]->p_regions);
 
571
    p_sys->p_overlays[ov->plane]->p_regions = NULL;
 
572
    p_sys->p_overlays[ov->plane]->status = Outdated;
 
573
    vlc_mutex_unlock(&p_sys->p_overlays[ov->plane]->lock);
 
574
}
 
575
 
 
576
/*
 
577
 * This will draw to the overlay by adding a region to our region list
 
578
 * This will have to be copied to the subpicture used to render the overlay.
 
579
 */
 
580
static void blurayDrawOverlay(demux_t *p_demux, const BD_OVERLAY* const ov)
 
581
{
 
582
    demux_sys_t *p_sys = p_demux->p_sys;
 
583
 
 
584
    /*
 
585
     * Compute a subpicture_region_t.
 
586
     * It will be copied and sent to the vout later.
 
587
     */
 
588
    if (!ov->img)
 
589
        return;
 
590
 
 
591
    vlc_mutex_lock(&p_sys->p_overlays[ov->plane]->lock);
 
592
 
 
593
    /* Find a region to update */
 
594
    subpicture_region_t *p_reg = p_sys->p_overlays[ov->plane]->p_regions;
 
595
    subpicture_region_t *p_last = NULL;
 
596
    while (p_reg != NULL) {
 
597
        p_last = p_reg;
 
598
        if (p_reg->i_x == ov->x && p_reg->i_y == ov->y &&
 
599
                p_reg->fmt.i_width == ov->w && p_reg->fmt.i_height == ov->h)
 
600
            break;
 
601
        p_reg = p_reg->p_next;
 
602
    }
 
603
 
 
604
    /* If there is no region to update, create a new one. */
 
605
    if (!p_reg) {
 
606
        video_format_t fmt;
 
607
        video_format_Init(&fmt, 0);
 
608
        video_format_Setup(&fmt, VLC_CODEC_YUVP, ov->w, ov->h, 1, 1);
 
609
 
 
610
        p_reg = subpicture_region_New(&fmt);
 
611
        p_reg->i_x = ov->x;
 
612
        p_reg->i_y = ov->y;
 
613
        /* Append it to our list. */
 
614
        if (p_last != NULL)
 
615
            p_last->p_next = p_reg;
 
616
        else /* If we don't have a last region, then our list empty */
 
617
            p_sys->p_overlays[ov->plane]->p_regions = p_reg;
 
618
    }
 
619
 
 
620
    /* Now we can update the region, regardless it's an update or an insert */
 
621
    const BD_PG_RLE_ELEM *img = ov->img;
 
622
    for (int y = 0; y < ov->h; y++) {
 
623
        for (int x = 0; x < ov->w;) {
 
624
            memset(p_reg->p_picture->p[0].p_pixels +
 
625
                   y * p_reg->p_picture->p[0].i_pitch + x,
 
626
                   img->color, img->len);
 
627
            x += img->len;
 
628
            img++;
 
629
        }
 
630
    }
 
631
    if (ov->palette) {
 
632
        p_reg->fmt.p_palette->i_entries = 256;
 
633
        for (int i = 0; i < 256; ++i) {
 
634
            p_reg->fmt.p_palette->palette[i][0] = ov->palette[i].Y;
 
635
            p_reg->fmt.p_palette->palette[i][1] = ov->palette[i].Cb;
 
636
            p_reg->fmt.p_palette->palette[i][2] = ov->palette[i].Cr;
 
637
            p_reg->fmt.p_palette->palette[i][3] = ov->palette[i].T;
 
638
        }
 
639
    }
 
640
    vlc_mutex_unlock(&p_sys->p_overlays[ov->plane]->lock);
 
641
    /*
 
642
     * /!\ The region is now stored in our internal list, but not in the subpicture /!\
 
643
     */
 
644
}
 
645
 
 
646
static void blurayOverlayProc(void *ptr, const BD_OVERLAY *const overlay)
 
647
{
 
648
    demux_t *p_demux = (demux_t*)ptr;
 
649
 
 
650
    if (!overlay) {
 
651
        msg_Info(p_demux, "Closing overlay.");
 
652
        blurayCloseAllOverlays(p_demux);
 
653
        return;
 
654
    }
 
655
    switch (overlay->cmd) {
 
656
        case BD_OVERLAY_INIT:
 
657
            msg_Info(p_demux, "Initializing overlay");
 
658
            blurayInitOverlay(p_demux, overlay);
 
659
            break;
 
660
        case BD_OVERLAY_CLEAR:
 
661
            blurayClearOverlay(p_demux, overlay);
 
662
            break;
 
663
        case BD_OVERLAY_FLUSH:
 
664
            blurayActivateOverlay(p_demux, overlay);
 
665
            break;
 
666
        case BD_OVERLAY_DRAW:
 
667
            blurayDrawOverlay(p_demux, overlay);
 
668
            break;
 
669
        default:
 
670
            msg_Warn(p_demux, "Unknown BD overlay command: %u", overlay->cmd);
 
671
            break;
 
672
    }
 
673
}
 
674
 
 
675
static void bluraySendOverlayToVout(demux_t *p_demux)
 
676
{
 
677
    demux_sys_t *p_sys = p_demux->p_sys;
 
678
 
 
679
    assert(p_sys->current_overlay >= 0 &&
 
680
           p_sys->p_overlays[p_sys->current_overlay] != NULL &&
 
681
           p_sys->p_overlays[p_sys->current_overlay]->p_pic != NULL);
 
682
 
 
683
    p_sys->p_overlays[p_sys->current_overlay]->p_pic->i_start =
 
684
        p_sys->p_overlays[p_sys->current_overlay]->p_pic->i_stop = mdate();
 
685
    p_sys->p_overlays[p_sys->current_overlay]->p_pic->i_channel =
 
686
        vout_RegisterSubpictureChannel(p_sys->p_vout);
 
687
    /*
 
688
     * After this point, the picture should not be accessed from the demux thread,
 
689
     * as it is held by the vout thread.
 
690
     * This must be done only once per subpicture, ie. only once between each
 
691
     * blurayInitOverlay & blurayCloseOverlay call.
 
692
     */
 
693
    vout_PutSubpicture(p_sys->p_vout, p_sys->p_overlays[p_sys->current_overlay]->p_pic);
 
694
    /*
 
695
     * Mark the picture as Outdated, as it contains no region for now.
 
696
     * This will make the subpicture_updater_t call pf_update
 
697
     */
 
698
    p_sys->p_overlays[p_sys->current_overlay]->status = Outdated;
 
699
}
250
700
 
251
701
static int blurayInitTitles(demux_t *p_demux )
252
702
{
285
735
    return VLC_SUCCESS;
286
736
}
287
737
 
 
738
static void blurayResetParser( demux_t *p_demux )
 
739
{
 
740
    /*
 
741
     * This is a hack and will have to be removed.
 
742
     * The parser should be flushed, and not destroy/created each time
 
743
     * we are changing title.
 
744
     */
 
745
    demux_sys_t *p_sys = p_demux->p_sys;
 
746
    if (!p_sys->p_parser)
 
747
        return;
 
748
 
 
749
    stream_Delete(p_sys->p_parser);
 
750
    p_sys->p_parser = stream_DemuxNew(p_demux, "ts", p_demux->out);
 
751
    if (!p_sys->p_parser) {
 
752
        msg_Err(p_demux, "Failed to create TS demuxer");
 
753
    }
 
754
}
 
755
 
 
756
static void blurayUpdateTitle(demux_t *p_demux, unsigned i_title)
 
757
{
 
758
    blurayResetParser(p_demux);
 
759
    if (i_title >= p_demux->p_sys->i_title)
 
760
        return;
 
761
 
 
762
    /* read title info and init some values */
 
763
    p_demux->info.i_title = i_title;
 
764
    p_demux->info.i_seekpoint = 0;
 
765
    p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
 
766
}
288
767
 
289
768
/*****************************************************************************
290
769
 * bluraySetTitle: select new BD title
306
785
        msg_Err(p_demux, "cannot select bd title '%d'", p_demux->info.i_title);
307
786
        return VLC_EGENERIC;
308
787
    }
309
 
 
310
 
    /* read title info and init some values */
311
 
    p_demux->info.i_title = i_title;
312
 
    p_demux->info.i_seekpoint = 0;
313
 
    p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
 
788
    blurayUpdateTitle( p_demux, i_title );
314
789
 
315
790
    return VLC_SUCCESS;
316
791
}
381
856
        case DEMUX_GET_LENGTH:
382
857
        {
383
858
            int64_t *pi_length = (int64_t*)va_arg(args, int64_t *);
384
 
            *pi_length = CUR_LENGTH;
 
859
            *pi_length = p_demux->info.i_title < p_sys->i_title ? CUR_LENGTH : 0;
385
860
            return VLC_SUCCESS;
386
861
        }
387
862
        case DEMUX_SET_TIME:
400
875
        case DEMUX_GET_POSITION:
401
876
        {
402
877
            double *pf_position = (double*)va_arg( args, double * );
403
 
            *pf_position = (double)FROM_TICKS(bd_tell_time(p_sys->bluray))/CUR_LENGTH;
 
878
            *pf_position = p_demux->info.i_title < p_sys->i_title ?
 
879
                        (double)FROM_TICKS(bd_tell_time(p_sys->bluray))/CUR_LENGTH : 0.0;
404
880
            return VLC_SUCCESS;
405
881
        }
406
882
        case DEMUX_SET_POSITION:
412
888
 
413
889
        case DEMUX_GET_META:
414
890
        {
415
 
            struct meta_dl *meta = bd_get_meta(p_sys->bluray);
416
 
            if(!meta)
417
 
                return VLC_EGENERIC;
418
 
 
419
891
            vlc_meta_t *p_meta = (vlc_meta_t *) va_arg (args, vlc_meta_t*);
 
892
            const META_DL *meta = p_sys->p_meta;
 
893
            if (meta == NULL)
 
894
                return VLC_EGENERIC;
420
895
 
421
896
            if (!EMPTY_STR(meta->di_name)) vlc_meta_SetTitle(p_meta, meta->di_name);
422
897
 
447
922
    return VLC_SUCCESS;
448
923
}
449
924
 
 
925
static void blurayHandleEvent( demux_t *p_demux, const BD_EVENT *e )
 
926
{
 
927
    switch (e->event)
 
928
    {
 
929
        case BD_EVENT_TITLE:
 
930
            blurayUpdateTitle(p_demux, e->param);
 
931
            break;
 
932
        case BD_EVENT_PLAYITEM:
 
933
            break;
 
934
        case BD_EVENT_AUDIO_STREAM:
 
935
            break;
 
936
        case BD_EVENT_CHAPTER:
 
937
            p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
 
938
            p_demux->info.i_seekpoint = e->param;
 
939
            break;
 
940
        case BD_EVENT_ANGLE:
 
941
        case BD_EVENT_IG_STREAM:
 
942
        default:
 
943
            msg_Warn( p_demux, "event: %d param: %d", e->event, e->param );
 
944
            break;
 
945
    }
 
946
}
 
947
 
 
948
static void blurayHandleEvents( demux_t *p_demux )
 
949
{
 
950
    BD_EVENT e;
 
951
 
 
952
    while (bd_get_event(p_demux->p_sys->bluray, &e))
 
953
    {
 
954
        blurayHandleEvent(p_demux, &e);
 
955
    }
 
956
}
450
957
 
451
958
#define BD_TS_PACKET_SIZE (192)
452
959
#define NB_TS_PACKETS (200)
460
967
        return -1;
461
968
    }
462
969
 
463
 
    int nread = bd_read(p_sys->bluray, p_block->p_buffer,
 
970
    int nread = -1;
 
971
    if (p_sys->b_menu == false) {
 
972
        blurayHandleEvents(p_demux);
 
973
        nread = bd_read(p_sys->bluray, p_block->p_buffer,
464
974
                        NB_TS_PACKETS * BD_TS_PACKET_SIZE);
465
 
    if (nread < 0) {
466
 
        block_Release(p_block);
467
 
        return nread;
 
975
        if (nread < 0) {
 
976
            block_Release(p_block);
 
977
            return nread;
 
978
        }
 
979
    } else {
 
980
        BD_EVENT e;
 
981
        nread = bd_read_ext(p_sys->bluray, p_block->p_buffer,
 
982
                            NB_TS_PACKETS * BD_TS_PACKET_SIZE, &e);
 
983
        if (nread < 0)
 
984
        {
 
985
            block_Release(p_block);
 
986
            return -1;
 
987
        }
 
988
        if (nread == 0) {
 
989
            if (e.event == BD_EVENT_NONE)
 
990
                msg_Info(p_demux, "We reached the end of a title");
 
991
            else
 
992
                blurayHandleEvent(p_demux, &e);
 
993
            block_Release(p_block);
 
994
            return 1;
 
995
        }
 
996
        if (p_sys->current_overlay != -1) {
 
997
            vlc_mutex_lock(&p_sys->p_overlays[p_sys->current_overlay]->lock);
 
998
            if (p_sys->p_overlays[p_sys->current_overlay]->status == ToDisplay) {
 
999
                vlc_mutex_unlock(&p_sys->p_overlays[p_sys->current_overlay]->lock);
 
1000
                if (p_sys->p_vout == NULL)
 
1001
                    p_sys->p_vout = input_GetVout(p_sys->p_input);
 
1002
                if (p_sys->p_vout != NULL) {
 
1003
                    var_AddCallback(p_sys->p_vout, "mouse-moved", &onMouseEvent, p_demux);
 
1004
                    var_AddCallback(p_sys->p_vout, "mouse-clicked", &onMouseEvent, p_demux);
 
1005
                    bluraySendOverlayToVout(p_demux);
 
1006
                }
 
1007
            } else
 
1008
                vlc_mutex_unlock(&p_sys->p_overlays[p_sys->current_overlay]->lock);
 
1009
        }
468
1010
    }
469
1011
 
470
1012
    p_block->i_buffer = nread;
471
1013
 
472
 
    stream_DemuxSend( p_sys->p_parser, p_block );
 
1014
    stream_DemuxSend(p_sys->p_parser, p_block);
473
1015
 
474
1016
    return 1;
475
1017
}