Commit e9bc965e authored by Laurent Aimar's avatar Laurent Aimar

Added initial uncrypted blu-ray support.

It is very limited:
 - Uncrypted only
 - No ISO or direct disc device
 - No menu
 - No still frame
 - No angle
 - No out of mux stream (some subtitles use it)

It does:
 - title (MPLS)
 - chapter (mark)
 - correct seek
 - hide invalid ES for a given MPLS
parent af438710
......@@ -5821,6 +5821,7 @@ AC_CONFIG_FILES([
AC_CONFIG_FILES([
modules/access/Makefile
modules/access/bd/Makefile
modules/access/bda/Makefile
modules/access/dshow/Makefile
modules/access/dvb/Makefile
......
......@@ -3,7 +3,7 @@
# obviously does not. Here is a fix for that.
LIBTOOL=@LIBTOOL@ --tag=CC
BASE_SUBDIRS = dvb mms cdda rtp rtsp rtmp vcd vcdx screen
BASE_SUBDIRS = dvb mms cdda rtp rtsp rtmp vcd vcdx screen bd
EXTRA_SUBDIRS = bda dshow
SUBDIRS = $(BASE_SUBDIRS)
DIST_SUBDIRS = $(BASE_SUBDIRS) $(EXTRA_SUBDIRS)
......
SOURCES_access_bd = \
bd.c \
mpls.c \
mpls.h \
clpi.c \
clpi.h \
$(NULL)
libvlc_LTLIBRARIES += libaccess_bd_plugin.la
This diff is collapsed.
/*****************************************************************************
* clpi.c: BluRay Disc CLPI
*****************************************************************************
* Copyright (C) 2009 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <limits.h>
#include <vlc_common.h>
#include <vlc_bits.h>
#include "clpi.h"
/* */
void bd_clpi_stc_Parse( bd_clpi_stc_t *p_stc, bs_t *s )
{
p_stc->i_pcr_pid = bs_read( s, 16 );
p_stc->i_packet = bs_read( s, 32 );
p_stc->i_start = bs_read( s, 32 );
p_stc->i_end = bs_read( s, 32 );
}
void bd_clpi_stream_Parse( bd_clpi_stream_t *p_stream, bs_t *s )
{
p_stream->i_pid = bs_read( s, 16 );
const int i_length = bs_read( s, 8 );
p_stream->i_type = bs_read( s, 8 );
/* Ignore the rest */
if( i_length > 1 )
bs_skip( s, 8*i_length - 8 );
}
void bd_clpi_ep_map_Clean( bd_clpi_ep_map_t *p_ep_map )
{
free( p_ep_map->p_ep );
}
int bd_clpi_ep_map_Parse( bd_clpi_ep_map_t *p_ep_map,
bs_t *s, const int i_ep_map_start )
{
p_ep_map->i_pid = bs_read( s, 16 );
bs_skip( s, 10 );
p_ep_map->i_type = bs_read( s, 4 );
const int i_coarse = bs_read( s, 16 );
const int i_fine = bs_read( s, 18 );
const uint32_t i_coarse_start = bs_read( s, 32 );
p_ep_map->i_ep = i_fine;
p_ep_map->p_ep = calloc( i_fine, sizeof(*p_ep_map->p_ep) );
if( !p_ep_map->p_ep )
return VLC_EGENERIC;
bs_t cs = *s;
bs_skip( &cs, 8*(i_ep_map_start + i_coarse_start) - bs_pos( s ) );
const uint32_t i_fine_start = bs_read( &cs, 32 );
for( int i = 0; i < i_coarse; i++ )
{
const int i_fine_id = bs_read( &cs, 18 );
const int i_pts = bs_read( &cs, 14 );
const uint32_t i_packet = bs_read( &cs, 32 );
for( int j = i_fine_id; j < p_ep_map->i_ep; j++ )
{
p_ep_map->p_ep[j].i_pts = (int64_t)(i_pts & ~1) << 19;
p_ep_map->p_ep[j].i_packet = i_packet & ~( (1 << 17) - 1 );
}
}
bs_t fs = *s;
bs_skip( &fs, 8*(i_ep_map_start + i_coarse_start + i_fine_start) - bs_pos( s ) );
for( int i = 0; i < i_fine; i++ )
{
const bool b_angle_point = bs_read( &fs, 1 );
bs_skip( &fs, 3 ); /* I end position offset */
const int i_pts = bs_read( &fs, 11 );
const int i_packet = bs_read( &fs, 17 );
p_ep_map->p_ep[i].b_angle_point = b_angle_point;
p_ep_map->p_ep[i].i_pts |= i_pts << 9;
p_ep_map->p_ep[i].i_packet |= i_packet;
}
return VLC_SUCCESS;
}
void bd_clpi_Clean( bd_clpi_t *p_clpi )
{
free( p_clpi->p_stc );
free( p_clpi->p_stream );
for( int i = 0; i < p_clpi->i_ep_map; i++ )
bd_clpi_ep_map_Clean( &p_clpi->p_ep_map[i] );
free( p_clpi->p_ep_map );
}
int bd_clpi_Parse( bd_clpi_t *p_clpi, bs_t *s, int i_id )
{
const int i_start = bs_pos( s ) / 8;
/* */
if( bs_read( s, 32 ) != 0x48444D56 )
return VLC_EGENERIC;
if( bs_read( s, 32 ) != 0x30323030 )
return VLC_EGENERIC;
/* */
const uint32_t i_sequence_start = bs_read( s, 32 );
const uint32_t i_program_start = bs_read( s, 32 );
const uint32_t i_cpi_start = bs_read( s, 32 );
bs_skip( s, 32 ); /* mark start */
bs_skip( s, 32 ); /* extension start */
/* */
p_clpi->i_id = i_id;
/* Read sequence */
bs_t ss = *s;
bs_skip( &ss, 8 * ( i_start + i_sequence_start ) - bs_pos( s ) );
bs_skip( &ss, 32 ); /* Length */
bs_skip( &ss, 8 );
bs_skip( &ss, 8 ); /* ATC sequence count (MUST be 1 ?) */
bs_skip( &ss, 32 ); /* ATC start (MUST be 0) */
const int i_stc = bs_read( &ss, 8 );
bs_skip( &ss, 8 ); /* STC ID offset (MUST be 0 ? */
p_clpi->p_stc = calloc( i_stc, sizeof(*p_clpi->p_stc) );
for( p_clpi->i_stc = 0; p_clpi->i_stc < i_stc; p_clpi->i_stc++ )
{
if( !p_clpi->p_stc )
break;
bd_clpi_stc_Parse( &p_clpi->p_stc[p_clpi->i_stc], &ss );
}
/* Program */
bs_t ps = *s;
bs_skip( &ps, 8 * ( i_start + i_program_start ) - bs_pos( s ) );
bs_skip( &ps, 32 ); /* Length */
bs_skip( &ps, 8 );
bs_skip( &ps, 8 ); /* Program count (MUST be 1 ?) */
bs_skip( &ps, 32 ); /* Program sequence start (MUST be 0) */
p_clpi->i_pmt_pid = bs_read( &ps, 16 );
const int i_stream = bs_read( &ps, 8 );
bs_skip( &ps, 8 ); /* Group count (MUST be 1 ?) */
p_clpi->p_stream = calloc( i_stream, sizeof(*p_clpi->p_stream) );
for( p_clpi->i_stream = 0; p_clpi->i_stream < i_stream; p_clpi->i_stream++ )
{
if( !p_clpi->p_stream )
break;
bd_clpi_stream_Parse( &p_clpi->p_stream[p_clpi->i_stream], &ps );
}
/* Read CPI */
bs_t cs = *s;
bs_skip( &cs, 8 * ( i_start + i_cpi_start ) - bs_pos( s ) );
const uint32_t i_cpi_length = bs_read( &cs, 32 );
if( i_cpi_length > 0 )
{
bs_skip( &cs, 12 );
bs_skip( &cs, 4 ); /* Type (MUST be 1) */
/* EPMap */
const int i_epmap_start = bs_pos( &cs ) / 8;
bs_skip( &cs, 8 );
const int i_ep_map = bs_read( &cs, 8 );
p_clpi->p_ep_map = calloc( i_ep_map, sizeof(*p_clpi->p_ep_map) );
for( p_clpi->i_ep_map = 0; p_clpi->i_ep_map < i_ep_map; p_clpi->i_ep_map++ )
{
if( !p_clpi->p_ep_map )
break;
if( bd_clpi_ep_map_Parse( &p_clpi->p_ep_map[p_clpi->i_ep_map],
&cs, i_epmap_start ) )
break;
}
}
else
{
p_clpi->i_ep_map = 0;
p_clpi->p_ep_map = NULL;
}
return VLC_SUCCESS;
}
/*****************************************************************************
* clpi.h: BluRay Disc CLPI
*****************************************************************************
* Copyright (C) 2009 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
typedef struct
{
int i_pcr_pid;
int64_t i_packet; /* TS Packet number */
int64_t i_start; /* Presentation start time in 45kHz */
int64_t i_end; /* Presentation end time in 45kHz */
} bd_clpi_stc_t;
void bd_clpi_stc_Parse( bd_clpi_stc_t *p_stc, bs_t *s );
typedef struct
{
int i_pid; /* PID of the associated stream */
int i_type; /* Stream type of the associated stream */
} bd_clpi_stream_t;
void bd_clpi_stream_Parse( bd_clpi_stream_t *p_stream, bs_t *s );
typedef struct
{
bool b_angle_point; /* EP angle point change */
int64_t i_packet; /* TS packet number */
int64_t i_pts; /* PTS of the associated stream (90kHz, 33bits) */
} bd_clpi_ep_t;
typedef struct
{
int i_pid; /* PID of the associated stream */
int i_type; /* Stream type of the associated stream */
int i_ep;
bd_clpi_ep_t *p_ep;
} bd_clpi_ep_map_t;
void bd_clpi_ep_map_Clean( bd_clpi_ep_map_t *p_ep_map );
int bd_clpi_ep_map_Parse( bd_clpi_ep_map_t *p_ep_map,
bs_t *s, const int i_ep_map_start );
typedef struct
{
int i_id;
int i_stc;
bd_clpi_stc_t *p_stc;
int i_pmt_pid;
int i_stream;
bd_clpi_stream_t *p_stream;
int i_ep_map;
bd_clpi_ep_map_t *p_ep_map;
} bd_clpi_t;
void bd_clpi_Clean( bd_clpi_t *p_clpi );
int bd_clpi_Parse( bd_clpi_t *p_clpi, bs_t *s, int i_id );
This diff is collapsed.
/*****************************************************************************
* mpls.h: BluRay Disc MPLS
*****************************************************************************
* Copyright (C) 2009 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
typedef enum
{
BD_MPLS_STREAM_TYPE_PLAY_ITEM = 0x01,
BD_MPLS_STREAM_TYPE_SUB_PATH = 0x02,
BD_MPLS_STREAM_TYPE_IN_MUX_SUB_PATH = 0x03,
} bd_mpls_stream_type_t;
typedef enum
{
BD_MPLS_STREAM_CLASS_PRIMARY_VIDEO = 0,
BD_MPLS_STREAM_CLASS_PRIMARY_AUDIO,
BD_MPLS_STREAM_CLASS_PG,
BD_MPLS_STREAM_CLASS_IG,
BD_MPLS_STREAM_CLASS_SECONDARY_AUDIO,
BD_MPLS_STREAM_CLASS_SECONDARY_PIP_PG,
} bd_mpls_stream_class_t;
typedef enum
{
BD_MPLS_STREAM_CHARSET_UNKNOWN = -1,
BD_MPLS_STREAM_CHARSET_UTF8 = 0x01,
BD_MPLS_STREAM_CHARSET_UTF16 = 0x02,
BD_MPLS_STREAM_CHARSET_SHIFT_JIS = 0x03,
BD_MPLS_STREAM_CHARSET_KSC = 0x04,
BD_MPLS_STREAM_CHARSET_GB18030 = 0x05,
BD_MPLS_STREAM_CHARSET_GB2312 = 0x06,
BD_MPLS_STREAM_CHARSET_BIG5 = 0x7,
} bd_mpls_stream_charset_t;
typedef struct
{
/* Stream entry */
int i_type; /* Type of the stream entry (bd_mpls_stream_type_t) */
int i_class; /* Class of the stream entry (bd_mpls_stream_class_t) */
union
{
struct
{
int i_pid; /* PID of the associated stream */
} play_item;
struct
{
int i_sub_path_id; /* Index of the sub path entry */
int i_sub_clip_id; /* Index of the sub clip entry (?) */
int i_pid; /* PID of the associated stream */
} sub_path;
struct
{
int i_sub_path_id; /* Index of the sub path entry */
int i_pid; /* PID of the associated stream */
} in_mux_sub_path;
};
/* Stream attributes */
int i_stream_type; /* MPEG-2 TS stream_type */
char psz_language[3+1]; /* ISO-639 code, empty if NA */
int i_charset; /* For text stream only (bd_mpls_stream_attributes_charset_t) */
} bd_mpls_stream_t;
void bd_mpls_stream_Parse( bd_mpls_stream_t *p_stream, bs_t *s, int i_class );
typedef enum
{
BD_MPLS_PLAY_ITEM_CONNECTION_NOT_SEAMLESS = 0x01,
BD_MPLS_PLAY_ITEM_CONNECTION_SEAMLESS_5 = 0x05,
BD_MPLS_PLAY_ITEM_CONNECTION_SEAMLESS_6 = 0x06,
} bd_mpls_play_item_connection_t;
typedef enum
{
BD_MPLS_PLAY_ITEM_STILL_NONE = 0x00,
BD_MPLS_PLAY_ITEM_STILL_FINITE = 0x01,
BD_MPLS_PLAY_ITEM_STILL_INFINITE = 0x02,
} bd_mpls_play_item_still_t;
typedef struct
{
int i_id;
int i_stc_id;
} bd_mpls_clpi_t;
typedef struct
{
int i_connection; /* Connection with previous play item (bd_mpls_play_item_connection_t) */
int64_t i_in_time; /* Start time in 45kHz */
int64_t i_out_time; /* Stop time in 45kHz */
int i_still; /* Still mode (bd_mpls_play_item_still_t) */
int i_still_time; /* Still time for BD_MPLS_PLAY_ITEM_STILL_FINITE (second?) */
/* Default clpi/angle */
bd_mpls_clpi_t clpi;
/* Extra clpi (multiple angles) */
int i_clpi;
bd_mpls_clpi_t *p_clpi;
bool b_angle_different_audio;
bool b_angle_seamless;
/* */
int i_stream;
bd_mpls_stream_t *p_stream;
} bd_mpls_play_item_t;
void bd_mpls_play_item_Clean( bd_mpls_play_item_t *p_item );
void bd_mpls_play_item_Parse( bd_mpls_play_item_t *p_item, bs_t *s );
typedef enum
{
BD_MPLS_SUB_PATH_TYPE_PRIMARY_AUDIO = 0x02,
BD_MPLS_SUB_PATH_TYPE_IG = 0x03,
BD_MPLS_SUB_PATH_TYPE_TEXT_SUB = 0x04,
BD_MPLS_SUB_PATH_TYPE_OUT_OF_MUX_AND_SYNC = 0x05,
BD_MPLS_SUB_PATH_TYPE_OUT_OF_MUX_AND_ASYNC = 0x06,
BD_MPLS_SUB_PATH_TYPE_IN_OF_MUX_AND_SYNC = 0x07,
} bd_mpls_sub_path_type_t;
typedef struct
{
int i_type; /* Sub path type (bd_mpls_sub_path_type_t) */
bool b_repeat; /* Repeated sub-path */
int i_item;
/* TODO
bd_mpls_sub_play_item_t *p_item;
*/
} bd_mpls_sub_path_t;
void bd_mpls_sub_path_Parse( bd_mpls_sub_path_t *p_path, bs_t *s );
typedef enum
{
BD_MPLS_MARK_TYPE_RESUME = 0x00,
BD_MPLS_MARK_TYPE_BOOKMARK = 0x01,
BD_MPLS_MARK_TYPE_SKIP = 0x02,
} bd_mpls_mark_type_t;
typedef struct
{
int i_type; /* Type of the mark (bd_mpls_mark_type_t) */
int i_play_item_id; /* Play item ID */
int64_t i_time; /* Time of the mark in 45kHz */
int i_entry_es_pid; /* Entry ES PID */
} bd_mpls_mark_t;
void bd_mpls_mark_Parse( bd_mpls_mark_t *p_mark, bs_t *s );
typedef struct
{
int i_id;
int i_play_item;
bd_mpls_play_item_t *p_play_item;
int i_sub_path;
bd_mpls_sub_path_t *p_sub_path;
int i_mark;
bd_mpls_mark_t *p_mark;
} bd_mpls_t;
void bd_mpls_Clean( bd_mpls_t *p_mpls );
int bd_mpls_Parse( bd_mpls_t *p_mpls, bs_t *s, int i_id );
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment