[vlc-devel] [PATCH] bluray: add support for stream input

Rémi Denis-Courmont remi at remlab.net
Tue Dec 15 09:34:55 CET 2015


Le 2015-12-15 10:27, Petri Hintukainen a écrit :
> Enable playback of BluRay disc images over smb/ssh/...
> ---
>  modules/access/bluray.c | 149
> ++++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 125 insertions(+), 24 deletions(-)
>
> diff --git a/modules/access/bluray.c b/modules/access/bluray.c
> index 45ebdd6..95aaf25 100644
> --- a/modules/access/bluray.c
> +++ b/modules/access/bluray.c
> @@ -97,8 +97,18 @@ vlc_module_begin ()
>      add_shortcut("bluray", "file")
>
>      set_callbacks(blurayOpen, blurayClose)
> +
> +    /* demux module */
> +    add_submodule()
> +        set_description( N_("BluRay demuxer") )
> +        set_category( CAT_INPUT )
> +        set_subcategory( SUBCAT_INPUT_DEMUX )
> +        set_capability( "demux", 5 )
> +        set_callbacks( blurayOpen, blurayClose )
> +
>  vlc_module_end ()
>
> +
>  /* libbluray's overlay.h defines 2 types of overlay 
> (bd_overlay_plane_e). */
>  #define MAX_OVERLAY 2
>
> @@ -172,6 +182,9 @@ struct  demux_sys_t
>      bool                b_flushed;
>      bool                b_pl_playing;       /* true when playing 
> playlist */
>
> +    /* stream input */
> +    vlc_mutex_t         read_block_lock;
> +
>      /* Used to store bluray disc path */
>      char                *psz_bd_path;
>  };
> @@ -469,19 +482,94 @@ static void attachThumbnail(demux_t *p_demux)
>  }
>
>
> 
> /*****************************************************************************
> + * stream input
> +
> 
> *****************************************************************************/
> +
> +static int probeStream(demux_t *p_demux)
> +{
> +    /* input must be seekable */
> +    bool b_canseek = false, b_canfastseek = false;
> +    stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
> +    stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_canfastseek 
> );

Unused??

> +    if (!b_canseek) {
> +        return VLC_EGENERIC;
> +    }
> +
> +    /* first sector(s) should be filled with zeros */
> +    size_t i_peek;
> +    const uint8_t *p_peek;
> +    i_peek = stream_Peek( p_demux->s, &p_peek, 2048 );
> +    if( i_peek < 512 ) {
> +        return VLC_EGENERIC;
> +    }
> +    while (i_peek > 0) {
> +        if (p_peek[ --i_peek ]) {
> +            return VLC_EGENERIC;
> +        }
> +    }

I fear this will yield a lot of false positives :(

> +
> +    return VLC_SUCCESS;
> +}
> +
> +static int blurayReadBlock(void *object, void *buf, int lba, int 
> num_blocks)
> +{
> +    int result = -1;
> +
> +    if (object) {
> +        demux_t *p_demux = (demux_t*)object;
> +        demux_sys_t *p_sys = p_demux->p_sys;
> +
> +        vlc_mutex_lock(&p_sys->read_block_lock);
> +        if (p_demux->s) {
> +            if (stream_Seek( p_demux->s, (int64_t)lba * 2048 ) ==
> VLC_SUCCESS) {
> +                size_t  req = (size_t)2048 * num_blocks;
> +                ssize_t got;
> +
> +                got = stream_Read( p_demux->s, buf, req);
> +                if (got < 0 || (size_t)got != req) {
> +                    msg_Err(p_demux, "read from lba %d failed: got
> %zd/%zu", lba, got, req);
> +                }
> +                if (got > 0) {
> +                    result = got / 2048;
> +                }
> +            } else {
> +                msg_Err(p_demux, "seek to lba %d failed", lba);
> +            }
> +        }
> +        vlc_mutex_unlock(&p_sys->read_block_lock);
> +    }
> +
> +    return result;
> +}
> +
> 
> +/*****************************************************************************
>   * blurayOpen: module init function
>
> 
> *****************************************************************************/
> +
>  static int blurayOpen(vlc_object_t *object)
>  {
>      demux_t *p_demux = (demux_t*)object;
>      demux_sys_t *p_sys;
> +    bool forced;
>
>      const char *error_msg = NULL;
>  #define BLURAY_ERROR(s) do { error_msg = s; goto error; } while(0)
>
> -    if (strcmp(p_demux->psz_access, "bluray")) {
> -        // TODO BDMV support, once we figure out what to do in 
> libbluray
> -        return VLC_EGENERIC;
> +    forced = !strcmp(p_demux->psz_access, "bluray");
> +
> +    if (p_demux->s) {
> +        if (p_demux->psz_access == NULL ||
> !strcmp(p_demux->psz_access, "file")) {
> +            /* use access_demux for local files */
> +            return VLC_EGENERIC;
> +        }
> +
> +        if (probeStream(p_demux) != VLC_SUCCESS) {
> +            return VLC_EGENERIC;
> +        }
> +    } else {
> +        if (!forced || !p_demux->psz_file) {
> +            return VLC_EGENERIC;
> +        }
>      }
>
>      /* */
> @@ -502,32 +590,45 @@ static int blurayOpen(vlc_object_t *object)
>      TAB_INIT(p_sys->i_title, p_sys->pp_title);
>      TAB_INIT(p_sys->i_attachments, p_sys->attachments);
>
> -    /* store current bd path */
> -    if (p_demux->psz_file)
> -        p_sys->psz_bd_path = strdup(p_demux->psz_file);
> -
> -    /* If we're passed a block device, try to convert it to the
> mount point. */
> -    FindMountPoint(&p_sys->psz_bd_path);
> -
>      last_log_handle = p_demux;
>      bd_set_debug_handler(blurayLogHandler);
>
> -    p_sys->bluray = bd_open(p_sys->psz_bd_path, NULL);
> -    if (!p_sys->bluray) {
> -        free(p_sys->psz_bd_path);
> -        free(p_sys);
> -        return VLC_EGENERIC;
> -    }
> -
>      vlc_mutex_init(&p_sys->pl_info_lock);
>      vlc_mutex_init(&p_sys->bdj_overlay_lock);
> +    vlc_mutex_init(&p_sys->read_block_lock); /* used during
> bd_open_stream() */
> +
> +    var_AddCallback( p_demux->p_input, "intf-event", onIntfEvent, 
> p_demux );
> +
> +    /* Open BluRay */
> +    if (p_demux->s) {
> +        p_sys->bluray = bd_init();
> +        if (!bd_open_stream(p_sys->bluray, p_demux, 
> blurayReadBlock)) {
> +            bd_close(p_sys->bluray);
> +            p_sys->bluray = NULL;
> +        }
> +    } else {
> +        /* store current bd path */
> +        p_sys->psz_bd_path = strdup(p_demux->psz_file);
> +
> +        /* If we're passed a block device, try to convert it to the
> mount point. */
> +        FindMountPoint(&p_sys->psz_bd_path);
> +
> +        p_sys->bluray = bd_open(p_sys->psz_bd_path, NULL);
> +    }
> +    if (!p_sys->bluray) {
> +        goto error;
> +    }
>
>      /* Warning the user about AACS/BD+ */
>      const BLURAY_DISC_INFO *disc_info = 
> bd_get_disc_info(p_sys->bluray);
>
>      /* Is it a bluray? */
> -    if (!disc_info->bluray_detected)
> -        BLURAY_ERROR(_("Path doesn't appear to be a Blu-ray"));
> +    if (!disc_info->bluray_detected) {
> +        if (forced) {
> +            BLURAY_ERROR(_("Path doesn't appear to be a Blu-ray"));
> +        }
> +        goto error;
> +    }
>
>      msg_Info(p_demux, "First play: %i, Top menu: %i\n"
>                        "HDMV Titles: %i, BD-J Titles: %i, Other: %i",
> @@ -645,8 +746,6 @@ static int blurayOpen(vlc_object_t *object)
>      if (unlikely(p_sys->p_out == NULL))
>          goto error;
>
> -    var_AddCallback( p_demux->p_input, "intf-event", onIntfEvent, 
> p_demux );
> -
>      blurayResetParser(p_demux);
>      if (!p_sys->p_parser) {
>          msg_Err(p_demux, "Failed to create TS demuxer");
> @@ -684,8 +783,9 @@ static void blurayClose(vlc_object_t *object)
>       * 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->bluray) {
> +        bd_close(p_sys->bluray);
> +    }
>
>      blurayReleaseVout(p_demux);
>
> @@ -707,6 +807,7 @@ static void blurayClose(vlc_object_t *object)
>
>      vlc_mutex_destroy(&p_sys->pl_info_lock);
>      vlc_mutex_destroy(&p_sys->bdj_overlay_lock);
> +    vlc_mutex_destroy(&p_sys->read_block_lock);
>
>      free(p_sys->psz_bd_path);
>      free(p_sys);
> @@ -1717,7 +1818,7 @@ static int blurayControl(demux_t *p_demux, int
> query, va_list args)
>                        
> p_sys->attachments[p_sys->i_cover_idx]->psz_name );
>              vlc_meta_Set( p_meta, vlc_meta_ArtworkURL, psz_url );
>          }
> -        else if (meta->thumb_count > 0 && meta->thumbnails) {
> +        else if (meta->thumb_count > 0 && meta->thumbnails &&
> p_sys->psz_bd_path) {
>              char *psz_thumbpath;
>              if (asprintf(&psz_thumbpath, "%s" DIR_SEP "BDMV" DIR_SEP
> "META" DIR_SEP "DL" DIR_SEP "%s",
>                            p_sys->psz_bd_path,
> meta->thumbnails[0].path) > 0) {

-- 
Rémi Denis-Courmont
http://www.remlab.net/


More information about the vlc-devel mailing list