[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