[vlc-devel] [PATCH 2/7] demux: mock: split track configurations

Thomas Guillem thomas at gllm.fr
Tue Jun 9 13:31:55 CEST 2020



On Tue, Jun 9, 2020, at 10:38, Francois Cartegnie wrote:
> ---
>  modules/demux/mock.c       | 334 ++++++++++++++++++++-----------------
>  test/src/input/thumbnail.c |   4 +-
>  2 files changed, 187 insertions(+), 151 deletions(-)
> 
> diff --git a/modules/demux/mock.c b/modules/demux/mock.c
> index c75ea8bee1..0be5eb4859 100644
> --- a/modules/demux/mock.c
> +++ b/modules/demux/mock.c
> @@ -33,14 +33,6 @@
>  #include <vlc_input.h>
>  #include <vlc_vector.h>
>  
> -
> -struct mock_track
> -{
> -    es_format_t fmt;
> -    es_out_id_t *id;
> -};
> -typedef struct VLC_VECTOR(struct mock_track *) mock_track_vector;
> -
>  static ssize_t
>  var_InheritSsize(vlc_object_t *obj, const char *name)
>  {
> @@ -82,22 +74,25 @@ var_InheritFourcc(vlc_object_t *obj, const char *name)
>  }
>  
>  #define LIST_OPTIONS_AUDIO \
> +    Y(audio, packetized, bool, add_bool, var_InheritBool, true) \
> +    Y(audio, add_track_at, vlc_tick_t, add_integer, 
> var_InheritInteger, VLC_TICK_INVALID) \
>      Y(audio, channels, unsigned, add_integer, var_InheritUnsigned, 2) \
>      Y(audio, format, vlc_fourcc_t, add_string, var_InheritFourcc, 
> "u8") \
>      Y(audio, rate, unsigned, add_integer, var_InheritUnsigned, 44100) \
> -    Y(audio, packetized, bool, add_bool, var_InheritBool, true) \
>      Y(audio, sample_length, vlc_tick_t, add_integer, 
> var_InheritInteger, VLC_TICK_FROM_MS(40) )
>  
>  #define LIST_OPTIONS_VIDEO \
> +    Y(video, packetized, bool, add_bool, var_InheritBool, true)\
> +    Y(video, add_track_at, vlc_tick_t, add_integer, 
> var_InheritInteger, VLC_TICK_INVALID) \
>      Y(video, chroma, vlc_fourcc_t, add_string, var_InheritFourcc, 
> "I420") \
>      Y(video, width, unsigned, add_integer, var_InheritUnsigned, 640) \
>      Y(video, height, unsigned, add_integer, var_InheritUnsigned, 480) \
>      Y(video, frame_rate, unsigned, add_integer, var_InheritUnsigned, 
> 25) \
> -    Y(video, frame_rate_base, unsigned, add_integer, 
> var_InheritUnsigned, 1) \
> -    Y(video, packetized, bool, add_bool, var_InheritBool, true)
> +    Y(video, frame_rate_base, unsigned, add_integer, 
> var_InheritUnsigned, 1)
>  
>  #define LIST_OPTIONS_SUB \
> -    Y(sub, packetized, bool, add_bool, var_InheritBool, true)
> +    Y(sub, packetized, bool, add_bool, var_InheritBool, true)\
> +    Y(sub, add_track_at, vlc_tick_t, add_integer, var_InheritInteger, 
> VLC_TICK_INVALID)
>  
>  /* var_name, type, module_header_type, getter, default_value */
>  #define LIST_OPTIONS_GLOBAL \
> @@ -117,9 +112,6 @@ var_InheritFourcc(vlc_object_t *obj, const char 
> *name)
>      X(can_record, bool, add_bool, var_InheritBool, true) \
>      X(error, bool, add_bool, var_InheritBool, false) \
>      X(pts_delay, unsigned, add_integer, var_InheritUnsigned, 
> MS_FROM_VLC_TICK(DEFAULT_PTS_DELAY)) \
> -    X(add_video_track_at, vlc_tick_t, add_integer, var_InheritInteger, 
> VLC_TICK_INVALID ) \
> -    X(add_audio_track_at, vlc_tick_t, add_integer, var_InheritInteger, 
> VLC_TICK_INVALID ) \
> -    X(add_spu_track_at, vlc_tick_t, add_integer, var_InheritInteger, 
> VLC_TICK_INVALID ) \
>      X(config, char *, add_string, var_InheritString, NULL )
>  
>  #define LIST_OPTIONS \
> @@ -149,6 +141,23 @@ struct mock_sub_options
>  
>  #undef Y
>  
> +struct mock_track
> +{
> +    es_format_t fmt;
> +    es_out_id_t *id;
> +    union
> +    {
> +        struct mock_video_options video;
> +        struct mock_audio_options audio;
> +        struct mock_sub_options sub;
> +    } u;

You should use an anonymous union here.

> +};
> +typedef struct VLC_VECTOR(struct mock_track *) mock_track_vector;
> +static_assert(offsetof(struct mock_video_options, add_track_at) ==
> +              offsetof(struct mock_audio_options, add_track_at), 
> "inconsistent offset");
> +static_assert(offsetof(struct mock_video_options, add_track_at) ==
> +              offsetof(struct mock_sub_options, add_track_at), 
> "inconsistent offset");
> +

Why is this needed? You should add a comment.

>  struct demux_sys
>  {
>      mock_track_vector tracks;
> @@ -459,50 +468,85 @@ CreateSubBlock(demux_t *demux, struct mock_track 
> *track)
>  }
>  
>  static int
> -AppendMockTrack(demux_t *demux, const es_format_t *fmt, int id, int group,
> -                bool packetized)
> +CheckAndCreateTracksEs(demux_t *demux, vlc_tick_t pts, bool *created)
>  {
>      struct demux_sys *sys = demux->p_sys;
> -    struct mock_track *mock_track = malloc(sizeof(*mock_track));
> -    if (!mock_track)
> -        return VLC_EGENERIC;
> -    mock_track->fmt = *fmt;
> -    mock_track->fmt.i_id = id;
> -    mock_track->fmt.i_group = group;
> -    mock_track->fmt.b_packetized = packetized;
> -    mock_track->id = es_out_Add(demux->out, & mock_track->fmt);
> -    if (!mock_track->id)
> +    *created = false;
> +
> +    struct mock_track *track;
> +    vlc_vector_foreach(track, &sys->tracks)
>      {
> -        free(mock_track);
> -        return VLC_ENOMEM;
> +        if (track->id ||
> +           (track->u.video.add_track_at != VLC_TICK_INVALID &&
> +            pts < track->u.video.add_track_at))
> +            continue;
> +        track->id = es_out_Add(demux->out, & track->fmt);
> +        if (!track->id)
> +            return VLC_EGENERIC;
> +        *created = true;
>      }
> -    bool success = vlc_vector_push(&sys->tracks, mock_track);
> -    assert(success); (void) success; /* checked by reserve() */
> +
>      return VLC_SUCCESS;
>  }
>  
> -static int
> -InitVideoTracks(demux_t *demux, int group, size_t count)
> +static void
> +DeleteTrack(demux_t *demux, struct mock_track *track)
> +{
> +    if (track->id)
> +        es_out_Del(demux->out, track->id);
> +    es_format_Clean(&track->fmt);
> +    free(track);
> +}
> +
> +static struct mock_track *
> +CreateTrack(demux_t *demux, int i_cat, int id, int group)
>  {
>      struct demux_sys *sys = demux->p_sys;
> +    struct mock_track *track =  calloc(1, sizeof(*track));
> +    if (!track)
> +        return NULL;
>  
> -    if (count == 0)
> -        return VLC_SUCCESS;
> +    es_format_Init(&track->fmt, i_cat, 0);
> +    switch (i_cat)
> +    {
> +        case AUDIO_ES:
> +            track->u.audio = sys->audio;
> +            break;
> +        case VIDEO_ES:
> +            track->u.video = sys->video;
> +            break;
> +        case SPU_ES:
> +            track->u.sub = sys->sub;
> +            break;
> +        default:
> +            vlc_assert_unreachable();
> +            return NULL;
> +    }
> +
> +    track->fmt.i_group = group;
> +    track->fmt.i_id = id;
> +
> +    return track;
> +}
>  
> +static int
> +ConfigureVideoTrack(demux_t *demux,
> +                    const struct mock_video_options *options,
> +                    es_format_t *fmt)
> +{
> +    vlc_fourcc_t chroma = options->chroma;
>      const vlc_chroma_description_t *desc =
> -        vlc_fourcc_GetChromaDescription(sys->video.chroma);
> +        vlc_fourcc_GetChromaDescription(chroma);
>      if (!desc || desc->plane_count == 0)
> -        sys->video.chroma = 0;
> +        chroma = 0;
>  
>      const bool frame_rate_ok =
> -        sys->video.frame_rate != 0 && sys->video.frame_rate != 
> UINT_MAX &&
> -        sys->video.frame_rate_base != 0 && sys->video.frame_rate_base 
> != UINT_MAX;
> -    const bool chroma_ok = sys->video.chroma != 0;
> -    const bool size_ok = sys->video.width != UINT_MAX &&
> -                         sys->video.height != UINT_MAX;
> -
> -    if (sys->video.frame_rate == 0 || sys->video.frame_rate_base == 0
> -     || sys->video.chroma == 0)
> +        options->frame_rate != 0 && options->frame_rate != UINT_MAX &&
> +        options->frame_rate_base != 0 && options->frame_rate_base != 
> UINT_MAX;
> +    const bool chroma_ok = chroma != 0;
> +    const bool size_ok = options->width != UINT_MAX &&
> +                         options->height != UINT_MAX;
> +
>      if (!frame_rate_ok || !chroma_ok || !size_ok)
>      {
>          if (!frame_rate_ok)
> @@ -514,34 +558,27 @@ InitVideoTracks(demux_t *demux, int group, size_t 
> count)
>          return VLC_EGENERIC;
>      }
>  
> -    for (size_t i = 0; i < count; ++i)
> -    {
> -        es_format_t fmt;
> -        es_format_Init(&fmt, VIDEO_ES, sys->video.chroma);
> -        fmt.video.i_chroma = fmt.i_codec;
> -        fmt.video.i_width = fmt.video.i_visible_width = sys->video.width;
> -        fmt.video.i_height = fmt.video.i_visible_height = sys->video.height;
> -        fmt.video.i_frame_rate = sys->video.frame_rate;
> -        fmt.video.i_frame_rate_base = sys->video.frame_rate_base;
> -
> -        if (AppendMockTrack(demux, &fmt, i, group, sys->video.packetized))
> -            return VLC_ENOMEM;
> -    }
> +    fmt->i_codec = chroma;
> +    fmt->video.i_chroma = chroma;
> +    fmt->video.i_width = fmt->video.i_visible_width = options->width;
> +    fmt->video.i_height = fmt->video.i_visible_height = options->height;
> +    fmt->video.i_frame_rate = options->frame_rate;
> +    fmt->video.i_frame_rate_base = options->frame_rate_base;
> +
> +    fmt->b_packetized = options->packetized;
> +
>      return VLC_SUCCESS;
>  }
>  
>  static int
> -InitAudioTracks(demux_t *demux, int group, size_t count)
> +ConfigureAudioTrack(demux_t *demux,
> +                    const struct mock_audio_options *options,
> +                    es_format_t *fmt)
>  {
> -    struct demux_sys *sys = demux->p_sys;
> -
> -    if (count == 0)
> -        return VLC_SUCCESS;
> -
> -    const bool rate_ok = sys->audio.rate > 0 && sys->audio.rate != UINT_MAX;
> -    const bool format_ok = aout_BitsPerSample(sys->audio.format) != 0;
> -    const bool channels_ok = sys->audio.channels > 0 &&
> -                             sys->audio.channels <= AOUT_CHAN_MAX;
> +    const bool rate_ok = options->rate > 0 && options->rate != UINT_MAX;
> +    const bool format_ok = aout_BitsPerSample(options->format) != 0;
> +    const bool channels_ok = options->channels > 0 &&
> +                             options->channels <= AOUT_CHAN_MAX;
>  
>      if (!rate_ok || !format_ok || !channels_ok)
>      {
> @@ -555,7 +592,7 @@ InitAudioTracks(demux_t *demux, int group, size_t count)
>      }
>  
>      uint16_t physical_channels = 0;
> -    switch (sys->audio.channels)
> +    switch (options->channels)
>      {
>          case 1: physical_channels = AOUT_CHAN_CENTER; break;
>          case 2: physical_channels = AOUT_CHANS_2_0; break;
> @@ -569,38 +606,27 @@ InitAudioTracks(demux_t *demux, int group, size_t count)
>          default: vlc_assert_unreachable();
>      }
>  
> -    for (size_t i = 0; i < count; ++i)
> -    {
> -        es_format_t fmt;
> -        es_format_Init(&fmt, AUDIO_ES, sys->audio.format);
> -        fmt.audio.i_format = fmt.i_codec;
> -        fmt.audio.i_rate = sys->audio.rate;
> -        fmt.audio.i_physical_channels = physical_channels;
> -        aout_FormatPrepare(&fmt.audio);
> -
> -        if (AppendMockTrack(demux, &fmt, i, group, sys->audio.packetized))
> -            return VLC_ENOMEM;
> -    }
> +    fmt->i_codec = options->format;
> +    fmt->audio.i_format = options->format;
> +    fmt->audio.i_rate = options->rate;
> +    fmt->audio.i_physical_channels = physical_channels;
> +    aout_FormatPrepare(&fmt->audio);
> +
> +    fmt->b_packetized = options->packetized;
>  
>      return VLC_SUCCESS;
>  }
>  
>  static int
> -InitSubTracks(demux_t *demux, int group, size_t count)
> +ConfigureSubTrack(demux_t *demux,
> +                  const struct mock_sub_options *options,
> +                  es_format_t *fmt)
>  {
> -    struct demux_sys *sys = demux->p_sys;
> +    VLC_UNUSED(demux);
>  
> -    if (count == 0)
> -        return VLC_SUCCESS;
> +    fmt->i_codec = VLC_CODEC_SUBT;
>  
> -    for (size_t i = 0; i < count; ++i)
> -    {
> -        es_format_t fmt;
> -        es_format_Init(&fmt, SPU_ES, VLC_CODEC_SUBT);
> -
> -        if (AppendMockTrack(demux, &fmt, i, group, sys->sub.packetized))
> -            return VLC_ENOMEM;
> -    }
> +    fmt->b_packetized = options->packetized;
>  
>      return VLC_SUCCESS;
>  }
> @@ -615,6 +641,8 @@ DemuxAudio(demux_t *demux, vlc_tick_t step_length, 
> vlc_tick_t end_pts)
>          struct mock_track *track;
>          vlc_vector_foreach(track, &sys->tracks)
>          {
> +            if (!track->id)
> +                continue;
>              block_t *block;
>              switch (track->fmt.i_cat)
>              {
> @@ -649,6 +677,8 @@ DemuxVideo(demux_t *demux, vlc_tick_t step_length, 
> vlc_tick_t end_pts)
>          struct mock_track *track;
>          vlc_vector_foreach(track, &sys->tracks)
>          {
> +            if (!track->id)
> +                continue;
>              block_t *block;
>              switch (track->fmt.i_cat)
>              {
> @@ -680,10 +710,17 @@ static int
>  Demux(demux_t *demux)
>  {
>      struct demux_sys *sys = demux->p_sys;
> +    int ret = VLC_SUCCESS;
>  
>      if (sys->error)
>          return VLC_DEMUXER_EGENERIC;
>  
> +    /* Add late tracks if any */
> +    bool created;
> +    ret = CheckAndCreateTracksEs(demux, sys->pts, &created);
> +    if (ret != VLC_SUCCESS)
> +        return VLC_DEMUXER_EGENERIC;
> +
>      if (sys->audio_track_count > 0
>       && (sys->video_track_count > 0 || sys->sub_track_count > 0))
>          sys->pts = __MIN(sys->audio_pts, sys->video_pts);
> @@ -706,14 +743,13 @@ Demux(demux_t *demux)
>  
>      const vlc_tick_t step_length = __MAX(audio_step_length, video_step_length);
>  
> -    int ret = VLC_SUCCESS;
> -    bool audio_eof = true, video_eof = true, input_eof = true;
> +    bool eof = !created;
>      if (sys->audio_track_count > 0)
>      {
>          ret = DemuxAudio(demux, audio_step_length,
>                           __MIN(step_length + sys->audio_pts, sys->length));
>          if (sys->audio_pts + audio_step_length < sys->length)
> -            audio_eof = false;
> +            eof = false;
>      }
>  
>      if (ret == VLC_SUCCESS
> @@ -722,7 +758,7 @@ Demux(demux_t *demux)
>          ret = DemuxVideo(demux, video_step_length,
>                           __MIN(step_length + sys->video_pts, sys->length));
>          if (sys->video_pts + video_step_length < sys->length)
> -            video_eof = false;
> +            eof = false;
>      }
>  
>      /* No audio/video/sub: simulate that we read some inputs */
> @@ -730,54 +766,13 @@ Demux(demux_t *demux)
>      {
>          sys->pts += sys->input_sample_length;
>          if (sys->pts + sys->input_sample_length < sys->length)
> -            input_eof = false;
> +            eof = false;
>      }
>  
>      if (ret != VLC_SUCCESS)
>          return VLC_DEMUXER_EGENERIC;
>  
> -    /* Add late tracks if any */
> -    if (sys->add_video_track_at != VLC_TICK_INVALID &&
> -        sys->add_video_track_at <= sys->pts)
> -    {
> -        sys->add_video_track_at = VLC_TICK_INVALID;
> -
> -        ret = InitVideoTracks(demux, 0, 1);
> -        if (ret != VLC_SUCCESS)
> -            return VLC_DEMUXER_EGENERIC;
> -        sys->video_track_count++;
> -        sys->video_pts = sys->pts;
> -        video_eof = false;
> -    }
> -
> -    if (sys->add_audio_track_at != VLC_TICK_INVALID &&
> -        sys->add_audio_track_at <= sys->pts)
> -    {
> -        sys->add_audio_track_at = VLC_TICK_INVALID;
> -
> -        ret = InitAudioTracks(demux, 0, 1);
> -        if (ret != VLC_SUCCESS)
> -            return VLC_DEMUXER_EGENERIC;
> -        sys->audio_track_count++;
> -        sys->audio_pts = sys->pts;
> -        audio_eof = false;
> -    }
> -
> -    if (sys->add_spu_track_at != VLC_TICK_INVALID &&
> -        sys->add_spu_track_at <= sys->pts)
> -    {
> -        sys->add_spu_track_at = VLC_TICK_INVALID;
> -
> -        ret = InitSubTracks(demux, 0, 1);
> -        if (ret != VLC_SUCCESS)
> -            return VLC_DEMUXER_EGENERIC;
> -        sys->sub_track_count++;
> -        sys->video_pts = sys->pts;
> -        video_eof = false;
> -    }
> -
> -    return audio_eof && video_eof && input_eof ? VLC_DEMUXER_EOF
> -                                               : VLC_DEMUXER_SUCCESS;
> +    return eof ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS;
>  }
>  
>  static void
> @@ -789,8 +784,7 @@ Close(vlc_object_t *obj)
>      struct mock_track *track;
>      vlc_vector_foreach(track, &sys->tracks)
>      {
> -        es_out_Del(demux->out, track->id);
> -        free(track);
> +        DeleteTrack(demux, track);
>      }
>      vlc_vector_clear(&sys->tracks);
>  }
> @@ -799,6 +793,7 @@ static int
>  Open(vlc_object_t *obj)
>  {
>      demux_t *demux = (demux_t*)obj;
> +    int ret = VLC_EGENERIC;
>  
>      if (demux->out == NULL)
>          return VLC_EGENERIC;
> @@ -859,22 +854,63 @@ Open(vlc_object_t *obj)
>              return VLC_ENOMEM;
>      }
>  
> -    int ret;
> +    struct
> +    {
> +        int cat;
> +        ssize_t count;
> +    } trackscountmap[3] = {

Useless 3.

> +        { AUDIO_ES, sys->audio_track_count },
> +        { VIDEO_ES, sys->video_track_count },
> +        { SPU_ES,   sys->sub_track_count   },
> +    };
> +
>      for (ssize_t i = 0; i < sys->program_count; ++i)
>      {
> -        ret = InitVideoTracks(demux, i, sys->video_track_count);
> -        if (ret != VLC_SUCCESS)
> -            goto error;
> +        for (size_t j=0; j<3; ++j)

ARRAY_SIZE(trackscountmap)

> +        {
> +            for (ssize_t k=0; k<trackscountmap[j].count; ++k)
> +            {
> +                struct mock_track *track = CreateTrack(demux,
> +                                                       trackscountmap[j].cat,
> +                                                       (i << 10) + k, i);
> +                if (!track || !vlc_vector_push(&sys->tracks, track))
> +                {
> +                    if (track)
> +                        DeleteTrack(demux, track);
> +                    goto error;
> +                }
> +            }
> +        }
> +    }
> +    assert(track_count == sys->tracks.size);
>  
> -        ret = InitAudioTracks(demux, i, sys->audio_track_count);
> -        if (ret != VLC_SUCCESS)
> -            goto error;
>  
> -        ret = InitSubTracks(demux, i, sys->sub_track_count);
> +    struct mock_track *track;
> +    vlc_vector_foreach(track, &sys->tracks)
> +    {
> +        switch(track->fmt.i_cat)
> +        {
> +            case AUDIO_ES:
> +                ret = ConfigureAudioTrack(demux, &track->u.audio, &track->fmt);
> +                break;
> +            case VIDEO_ES:
> +                ret = ConfigureVideoTrack(demux, &track->u.video, &track->fmt);
> +                break;
> +            case SPU_ES:
> +                ret = ConfigureSubTrack(demux, &track->u.sub, &track->fmt);
> +                break;
> +            default:
> +                vlc_assert_unreachable();
> +                ret = VLC_EGENERIC;
> +                break;
> +        }
>          if (ret != VLC_SUCCESS)
>              goto error;
>      }
>  
> +    bool created;
> +    if (CheckAndCreateTracksEs(demux, VLC_TICK_0, &created) != VLC_SUCCESS)
> +        goto error;
>  
>      sys->pts = sys->audio_pts = sys->video_pts = VLC_TICK_0;
>      sys->current_title = 0;
> diff --git a/test/src/input/thumbnail.c b/test/src/input/thumbnail.c
> index 3a3e61a28e..766e8546ab 100644
> --- a/test/src/input/thumbnail.c
> +++ b/test/src/input/thumbnail.c
> @@ -55,7 +55,7 @@ const struct
>      /* Take a thumbnail of a file without video, which should timeout. 
> */
>      { 0, 1, VLC_TICK_INVALID, VLC_TICK_FROM_SEC( 60 ), .0f, false, 
> true, VLC_TICK_FROM_MS( 100 ), false },
>      /* Take a thumbnail of a file with a video track starting later */
> -    { 0, 1, VLC_TICK_FROM_SEC( 120 ), VLC_TICK_FROM_SEC( 60 ), .0f, 
> false, true,
> +    { 1, 1, VLC_TICK_FROM_SEC( 120 ), VLC_TICK_FROM_SEC( 60 ), .0f, 
> false, true,
>          VLC_TICK_FROM_SEC( 2 ), true },
>  };
>  
> @@ -123,7 +123,7 @@ static void test_thumbnails( libvlc_instance_t* p_vlc )
>          ctx.b_done = false;
>  
>          if ( asprintf( &psz_mrl, 
> "mock://video_track_count=%u;audio_track_count=%u"
> -                       ";length=%" PRId64 
> ";video_chroma=ARGB;add_video_track_at=%" PRId64,
> +                       ";length=%" PRId64 
> ";video_chroma=ARGB;video_add_track_at=%" PRId64,
>                         test_params[i].i_nb_video_tracks,
>                         test_params[i].i_nb_audio_tracks, MOCK_DURATION,
>                         test_params[i].i_add_video_track_at ) < 0 )
> -- 
> 2.25.4
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list