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

Petri Hintukainen phintuka at gmail.com
Tue Dec 15 10:13:29 CET 2015


On ti, 2015-12-15 at 10:34 +0200, Rémi Denis-Courmont wrote:
> 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??

Ok, leftover from testing.

I tried checking fastseek, but it is not enabled for sftp.

Maybe fastseek could be enabled for sftp ? Seeking with sftp is faster
than ex. with http. Fast enough so that disc images can be played over
relatively slow wifi link. Also, I don't think seeking works fast
enough with http or ftp.

> > +    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 :(

Are there any media file formats that start with 512 (or 2048) NUL
bytes ?

In DVD/BluRay image files first 32kb are empty (boot sector etc.).
Checking something else than NUL bytes would require seeking or
significantly larger preview, and that may cause other problems ?

Even if there's false positive, it will be noticed later when checking
the directory structure of disc image file. So, this check is there
just to make most common cases faster.

I think this check could be used also in dvdnav plugin (=> we could remove seeking from StreamProbeDVD()).

> > +    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) {
> 


More information about the vlc-devel mailing list