[vlc-devel] [PATCH 08/12] bluray: Adding support for overlay.

Hugo Beauzée-Luyssen beauze.h at gmail.com
Sun Jan 22 00:31:03 CET 2012


---
 modules/access/bluray.c |  189 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 179 insertions(+), 10 deletions(-)

diff --git a/modules/access/bluray.c b/modules/access/bluray.c
index 9c4484a..fe43556 100644
--- a/modules/access/bluray.c
+++ b/modules/access/bluray.c
@@ -4,6 +4,7 @@
  * Copyright © 2010-2011 VideoLAN, VLC authors and libbluray AUTHORS
  *
  * Authors: Jean-Baptiste Kempf <jb at videolan.org>
+ *          Hugo Beauzée-Luyssen <hugo at videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
@@ -32,6 +33,8 @@
 #include <vlc_demux.h>                      /* demux_t */
 #include <vlc_input.h>                      /* Seekpoints, chapters */
 #include <vlc_dialog.h>                     /* BD+/AACS warnings */
+#include <vlc_picture.h>
+#include <vlc_vout.h>
 
 #include <libbluray/bluray.h>
 #include <libbluray/meta_data.h>
@@ -63,6 +66,8 @@ vlc_module_begin ()
     set_callbacks( blurayOpen, blurayClose )
 vlc_module_end ()
 
+//libbluray's overlay.h defines 2 types of overlay.
+#define MAX_OVERLAY 2
 
 struct demux_sys_t
 {
@@ -73,6 +78,13 @@ struct demux_sys_t
     unsigned int    i_longest_title;
     input_title_t **pp_title;
 
+    /* Overlay stuff */
+    subpicture_t    *p_pic[MAX_OVERLAY];
+    int             current_overlay; // -1 if no current overlay;
+
+    input_thread_t  *p_input;
+    vout_thread_t   *p_vout;
+
     /* TS stream */
     stream_t       *p_parser;
 };
@@ -119,7 +131,8 @@ static int blurayOpen( vlc_object_t *object )
     if (unlikely(!p_sys)) {
         return VLC_ENOMEM;
     }
-    p_sys->p_parser = NULL;
+    memset( p_sys, 0, sizeof( *p_sys ) );
+    p_sys->current_overlay = -1;
 
     /* init demux info fields */
     p_demux->info.i_update    = 0;
@@ -187,6 +200,9 @@ static int blurayOpen( vlc_object_t *object )
     bool    b_menu = var_CreateGetBool( p_demux, "bluray-menu" );
     if ( b_menu )
     {
+        p_sys->p_input = demux_GetParentInput( p_demux );
+        if ( unlikely( p_sys->p_input == NULL ) )
+            goto error;
         //Starting playback from main menu
         bd_play( p_sys->bluray );
         //Registering overlay event handler
@@ -235,6 +251,18 @@ static void blurayClose( vlc_object_t *object )
     demux_t *p_demux = (demux_t*)object;
     demux_sys_t *p_sys = p_demux->p_sys;
 
+    /*
+     * Close libbluray first. This will close all the overlays before we release p_vout
+     *
+     * bd_close( NULL ) can crash
+     */
+    assert(p_sys->bluray);
+    bd_close(p_sys->bluray);
+
+    if ( p_sys->p_vout != NULL )
+        vlc_object_release( p_sys->p_vout );
+    if ( p_sys->p_input != NULL )
+        vlc_object_release( p_sys->p_input );
     if (p_sys->p_parser)
         stream_Delete(p_sys->p_parser);
 
@@ -243,18 +271,147 @@ static void blurayClose( vlc_object_t *object )
         vlc_input_title_Delete(p_sys->pp_title[i]);
     TAB_CLEAN( p_sys->i_title, p_sys->pp_title );
 
-    /* bd_close( NULL ) can crash */
-    assert(p_sys->bluray);
-    bd_close(p_sys->bluray);
     free(p_sys);
 }
 
+static void blurayDeleteOverlaySubPic( demux_t *p_demux, int i_plane )
+{
+    demux_sys_t     *p_sys = p_demux->p_sys;
+
+    if ( p_sys->p_pic[i_plane] == NULL )
+        return ;
+    if ( p_sys->p_vout )
+        vout_FlushSubpictureChannel( p_sys->p_vout, p_sys->p_pic[i_plane]->i_channel );
+    else
+        subpicture_Delete( p_sys->p_pic[i_plane] );
+    p_sys->p_pic[i_plane] = NULL;
+}
+
+static void blurayCloseOverlay( demux_t *p_demux )
+{
+    demux_sys_t     *p_sys = p_demux->p_sys;
+
+    for ( int i = 0; i < MAX_OVERLAY; ++i )
+        blurayDeleteOverlaySubPic( p_demux, i );
+    p_demux->p_sys->current_overlay = -1;
+    if ( p_sys->p_vout != NULL )
+    {
+        vlc_object_release( p_sys->p_vout );
+        p_sys->p_vout = NULL;
+    }
+}
+
+static void blurayDisplayOverlay( demux_t *p_demux, const BD_OVERLAY* const ov )
+{
+    demux_sys_t     *p_sys = p_demux->p_sys;
+    /*
+     * Mark the overlay as available, but don't display it right now.
+     * the blurayDemuxMenu will send it to vout, as it may be unavailable when
+     * the overlay is computed
+     */
+    p_sys->current_overlay = ov->plane;
+}
+
+static void blurayInitOverlay( demux_t *p_demux, const BD_OVERLAY* const ov )
+{
+    demux_sys_t     *p_sys = p_demux->p_sys;
+
+    if ( p_sys->p_pic[ov->plane] != NULL )
+        blurayDeleteOverlaySubPic( p_demux, ov->plane );
+
+    p_sys->p_pic[ov->plane] = subpicture_New( NULL );
+    p_sys->p_pic[ov->plane]->i_original_picture_width = ov->w;
+    p_sys->p_pic[ov->plane]->i_original_picture_height = ov->h;
+    p_sys->p_pic[ov->plane]->b_ephemer = true;
+    p_sys->p_pic[ov->plane]->b_absolute = true;
+}
+
+static void blurayClearOverlay( demux_t *p_demux, const BD_OVERLAY* const ov )
+{
+    demux_sys_t     *p_sys = p_demux->p_sys;
+
+    //FIXME
+}
+
+static void blurayDrawOverlay( demux_t *p_demux, const BD_OVERLAY* const ov )
+{
+    demux_sys_t     *p_sys = p_demux->p_sys;
+
+    if ( ov->img )
+    {
+        video_format_t          fmt;
+        video_format_Init( &fmt, 0 );
+        video_format_Setup( &fmt, VLC_CODEC_YUVP, ov->w, ov->h, 1, 1 );
+
+        subpicture_region_t     *region = subpicture_region_New( &fmt );
+        region->i_x = ov->x;
+        region->i_y = ov->y;
+
+        const BD_PG_RLE_ELEM    *img = ov->img;
+        for ( int y = 0; y < ov->h; y++ )
+        {
+            for ( int x = 0; x < ov->w; )
+            {
+                memset( region->p_picture->p[0].p_pixels +
+                        y * region->p_picture->p[0].i_pitch + x,
+                        img->color, img->len );
+                x += img->len;
+                img++;
+            }
+        }
+        if ( ov->palette )
+        {
+            region->fmt.p_palette->i_entries = 256;
+            for ( int i = 0; i < 256; ++i )
+            {
+                region->fmt.p_palette->palette[i][0] = ov->palette[i].Y;
+                region->fmt.p_palette->palette[i][1] = ov->palette[i].Cb;
+                region->fmt.p_palette->palette[i][2] = ov->palette[i].Cr;
+                region->fmt.p_palette->palette[i][3] = ov->palette[i].T;
+            }
+        }
+        //Append the new region at the end of our current regions:
+        subpicture_region_t *p_reg = p_sys->p_pic[ov->plane]->p_region;
+        if ( p_reg == NULL )
+        {
+            p_sys->p_pic[ov->plane]->p_region = region;
+            return ;
+        }
+        while ( p_reg && p_reg->p_next )
+            p_reg = p_reg->p_next;
+        p_reg->p_next = region;
+    }
+}
+
 static void blurayOverlayProc( void *ptr, const BD_OVERLAY *const overlay )
 {
     demux_t     *p_demux = (demux_t*)ptr;
-    demux_sys_t *p_sys = p_demux->p_sys;
 
-    //FIXME
+    if ( overlay == NULL )
+    {
+        msg_Info( p_demux, "Closing overlay." );
+        blurayCloseOverlay( p_demux );
+        return ;
+    }
+    switch ( overlay->cmd )
+    {
+        case BD_OVERLAY_INIT:
+            blurayInitOverlay( p_demux, overlay );
+            break ;
+        case BD_OVERLAY_CLEAR:
+            blurayClearOverlay( p_demux, overlay );
+            break ;
+        case BD_OVERLAY_FLUSH:
+            msg_Info( p_demux, "Displaying overlay" );
+            blurayDisplayOverlay( p_demux, overlay );
+            break ;
+        case BD_OVERLAY_DRAW:
+            blurayDrawOverlay( p_demux, overlay );
+            break ;
+        default:
+            msg_Warn( p_demux, "Unknown BD overlay command: %u", overlay->cmd );
+            break ;
+    }
 }
 
 static int blurayInitTitles(demux_t *p_demux )
@@ -554,11 +711,9 @@ static int blurayDemuxMenu( demux_t *p_demux )
                                       NB_TS_PACKETS * BD_TS_PACKET_SIZE, &e );
     if ( nread == 0 ) //We need to handle events before doing anything
     {
-        if ( e.event == BD_EVENT_NONE )
-            msg_Info( p_demux, "We reached the end of a title" );
-        else
+        if ( e.event != BD_EVENT_NONE )
             blurayHandleEvent( p_demux, &e );
-        block_Release(p_block);
+        block_Release( p_block );
         return 1;
     }
     if (nread < 0)
@@ -568,6 +723,20 @@ static int blurayDemuxMenu( demux_t *p_demux )
     }
     p_block->i_buffer = nread;
 
+    if ( p_sys->current_overlay != -1 )
+    {
+        if ( p_sys->p_vout == NULL )
+            p_sys->p_vout = input_GetVout( p_sys->p_input );
+        if ( p_sys->p_vout != NULL )
+        {
+            p_sys->p_pic[p_sys->current_overlay]->i_start =
+                    p_sys->p_pic[p_sys->current_overlay]->i_stop = mdate();
+            p_sys->p_pic[p_sys->current_overlay]->i_channel =
+                    vout_RegisterSubpictureChannel( p_sys->p_vout );
+            vout_PutSubpicture( p_sys->p_vout, p_sys->p_pic[p_sys->current_overlay] );
+            p_sys->current_overlay = -1;
+        }
+    }
     stream_DemuxSend( p_sys->p_parser, p_block );
     return 1;
 }
-- 
1.7.8.4




More information about the vlc-devel mailing list