[vlc-commits] [Git][videolan/vlc][master] stream: introduce typed operations for stream

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sat Mar 11 18:14:58 UTC 2023



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
f77921f4 by Loïc at 2023-03-11T18:01:48+00:00
stream: introduce typed operations for stream

This commit introduce a typed virtual table for operations on stream,
aiming at replacing the legacy pf_control() callback which is using
va_list. As a counterpart to the typed virtual table, typed methods
are also introduce.

The operations can be implemented by the modules directly right now
and will be used when possible. This is done to provide type safety
at every level.

When no operation is provided (ie, stream_t.ops is NULL) by a module
implementation, the legacy pf_control will be used instead as a
fallback.

The commit doesn't migrate any of access/stream_filter/… modules yet.
The commit also doesn't introduce the demux specific callbacks yet.

- - - - -


2 changed files:

- include/vlc_stream.h
- src/input/stream.c


Changes:

=====================================
include/vlc_stream.h
=====================================
@@ -23,7 +23,9 @@
 #ifndef VLC_STREAM_H
 #define VLC_STREAM_H 1
 
+#include <vlc_tick.h>
 #include <vlc_block.h>
+#include <vlc_input.h>
 
 # ifdef __cplusplus
 extern "C" {
@@ -38,6 +40,45 @@ extern "C" {
  * Byte streams and byte stream filter modules interface
  */
 
+struct vlc_stream_operations {
+    /* Cannot fail */
+    bool (*can_seek)(stream_t *);
+    bool (*can_pause)(stream_t *);
+    bool (*can_control_pace)(stream_t *);
+
+    int (*get_pts_delay)(stream_t *, vlc_tick_t *);
+    int (*get_seekpoint)(stream_t *, unsigned *);
+    int (*get_signal)(stream_t *, double *, double *);
+    int (*get_title)(stream_t *, unsigned *);
+    int (*get_meta)(stream_t *, vlc_meta_t *);
+    int (*get_type)(stream_t *, int *);
+
+    int (*set_pause_state)(stream_t *, bool);
+    int (*set_seek_point)(stream_t *, int);
+    int (*set_title)(stream_t *, int);
+
+    void (*close)(stream_t *);
+
+    union {
+        struct {
+            bool (*can_fastseek)(stream_t *);
+
+            int (*get_size)(stream_t *, uint64_t *);
+            int (*get_title_info)(stream_t *, input_title_t ***, int *);
+            int (*get_content_type)(stream_t *, char **);
+            int (*get_tags)(stream_t *, const block_t **);
+            int (*get_private_id_state)(stream_t *, int, bool *);
+
+            int (*set_record_state)(stream_t *, bool, const char *, const char *);
+            int (*set_private_id_state)(stream_t *, int, bool);
+            int (*set_private_id_ca)(stream_t *, void *);
+        } stream;
+        struct {
+            /* TODO: Add the demux callbacks */
+        } demux;
+    };
+};
+
 /**
  * stream_t definition
  */
@@ -125,12 +166,20 @@ struct stream_t
     /**
      * Stream control.
      *
-     * Cannot be NULL.
+     * Legacy way of implementing callbacks.
+     * \ref vlc_stream_operations should be prefered.
      *
      * \see stream_query_e
      */
     int         (*pf_control)(stream_t *, int i_query, va_list);
 
+    /**
+     * Implementation of the Stream/Demux API.
+     *
+     * If NULL all operations will be redirected to \ref stream_t.pf_control.
+     */
+    const struct vlc_stream_operations *ops;
+
     /**
      * Private data pointer
      */
@@ -325,12 +374,125 @@ VLC_API void vlc_stream_Delete(stream_t *s);
 
 VLC_API stream_t *vlc_stream_CommonNew(vlc_object_t *, void (*)(stream_t *));
 
+VLC_USED static inline bool vlc_stream_CanSeek(stream_t *s)
+{
+    bool can_seek = false;
+    vlc_stream_Control(s, STREAM_CAN_SEEK, &can_seek);
+    return can_seek;
+}
+
+VLC_USED static inline bool vlc_stream_CanFastSeek(stream_t *s)
+{
+    bool can_fast_seek = false;
+    vlc_stream_Control(s, STREAM_CAN_FASTSEEK, &can_fast_seek);
+    return can_fast_seek;
+}
+
+VLC_USED static inline bool vlc_stream_CanPause(stream_t *s)
+{
+    bool can_pause = false;
+    vlc_stream_Control(s, STREAM_CAN_PAUSE, &can_pause);
+    return can_pause;
+}
+
+VLC_USED static inline bool vlc_stream_CanPace(stream_t *s)
+{
+    bool can_control_pace = false;
+    vlc_stream_Control(s, STREAM_CAN_CONTROL_PACE, &can_control_pace);
+    return can_control_pace;
+}
+
+VLC_USED static inline int vlc_stream_GetPtsDelay(stream_t *s, vlc_tick_t *pts_delay)
+{
+    return vlc_stream_Control(s, STREAM_GET_PTS_DELAY, pts_delay);
+}
+
+VLC_USED static inline int vlc_stream_GetSeekpoint(stream_t *s, unsigned *seekpoint)
+{
+    return vlc_stream_Control(s, STREAM_GET_SEEKPOINT, seekpoint);
+}
+
+VLC_USED static inline int vlc_stream_GetSignal(stream_t *s, double *quality, double *strength)
+{
+    return vlc_stream_Control(s, STREAM_GET_SIGNAL, quality, strength);
+}
+
+VLC_USED static inline int vlc_stream_GetTitle(stream_t *s, unsigned *title)
+{
+    return vlc_stream_Control(s, STREAM_GET_TITLE, title);
+}
+
+VLC_USED static inline int vlc_stream_GetMeta(stream_t *s, vlc_meta_t *meta)
+{
+    return vlc_stream_Control(s, STREAM_GET_META, meta);
+}
+
+VLC_USED static inline int vlc_stream_GetType(stream_t *s, int *type)
+{
+    return vlc_stream_Control(s, STREAM_GET_TYPE, type);
+}
+
 /**
  * Get the size of the stream.
  */
-VLC_USED static inline int vlc_stream_GetSize( stream_t *s, uint64_t *size )
+VLC_USED static inline int vlc_stream_GetSize(stream_t *s, uint64_t *size)
+{
+    return vlc_stream_Control(s, STREAM_GET_SIZE, size);
+}
+
+VLC_USED static inline int vlc_stream_GetTitleInfo(stream_t *s, input_title_t ***title_info, int *size)
+{
+    return vlc_stream_Control(s, STREAM_GET_TITLE_INFO, title_info, size);
+}
+
+VLC_USED static inline int vlc_stream_GetContentType(stream_t *s, char **content_type)
+{
+    return vlc_stream_Control(s, STREAM_GET_CONTENT_TYPE, content_type);
+}
+
+VLC_USED static inline int vlc_stream_GetTags(stream_t *s, const block_t **tags)
+{
+    return vlc_stream_Control(s, STREAM_GET_TAGS, tags);
+}
+
+VLC_USED static inline int vlc_stream_GetPrivateIdState(stream_t *s, int priv_id, bool *state)
+{
+    return vlc_stream_Control(s, STREAM_GET_PRIVATE_ID_STATE, priv_id, state);
+}
+
+VLC_USED static inline int vlc_stream_SetPauseState(stream_t *s, bool pause_state)
+{
+    return vlc_stream_Control(s, STREAM_SET_PAUSE_STATE, pause_state);
+}
+
+VLC_USED static inline int vlc_stream_SetSeekPoint(stream_t *s, int seekpoint)
+{
+    return vlc_stream_Control(s, STREAM_SET_SEEKPOINT, seekpoint);
+}
+
+VLC_USED static inline int vlc_stream_SetTitle(stream_t *s, int title)
+{
+    return vlc_stream_Control(s, STREAM_SET_TITLE, title);
+}
+
+VLC_USED static inline int vlc_stream_SetRecordState(stream_t *s, bool record_state, const char *dir_path, const char *ext)
+{
+    return vlc_stream_Control(s, STREAM_SET_RECORD_STATE, record_state, dir_path, ext);
+}
+
+VLC_USED static inline int vlc_stream_SetPrivateIdState(stream_t *s, int priv_id, bool state)
+{
+    return vlc_stream_Control(s, STREAM_SET_PRIVATE_ID_STATE, priv_id, state);
+}
+
+/**
+ * Set the private ID ca.
+ *
+ * The ca arg is of type `en50221_capmt_info_t`.
+ */
+VLC_USED static inline int vlc_stream_SetPrivateIdCa(stream_t *s, void *ca)
 {
-    return vlc_stream_Control( s, STREAM_GET_SIZE, size );
+    return vlc_stream_Control(s, STREAM_SET_PRIVATE_ID_CA, ca);
 }
 
 static inline int64_t stream_Size( stream_t *s )
@@ -360,7 +522,7 @@ static inline bool stream_HasExtension( stream_t *s, const char *extension )
 static inline char *stream_ContentType( stream_t *s )
 {
     char *res;
-    if( vlc_stream_Control( s, STREAM_GET_CONTENT_TYPE, &res ) )
+    if (vlc_stream_GetContentType(s, &res))
         return NULL;
     return res;
 }


=====================================
src/input/stream.c
=====================================
@@ -26,6 +26,7 @@
 #endif
 
 #include <assert.h>
+#include <stdbool.h>
 #include <stdalign.h>
 #include <stdlib.h>
 #include <string.h>
@@ -91,6 +92,7 @@ stream_t *vlc_stream_CustomNew(vlc_object_t *parent,
     s->pf_seek = NULL;
     s->pf_control = NULL;
     s->p_sys = NULL;
+    s->ops = NULL;
     assert(destroy != NULL);
     priv->destroy = destroy;
     priv->block = NULL;
@@ -142,6 +144,9 @@ void vlc_stream_Delete(stream_t *s)
 {
     stream_priv_t *priv = stream_priv(s);
 
+    if (s->ops != NULL && s->ops->close != NULL) {
+        s->ops->close(s);
+    }
     priv->destroy(s);
     stream_CommonDelete(s);
 }
@@ -701,7 +706,18 @@ int vlc_stream_vaControl(stream_t *s, int cmd, va_list args)
         case STREAM_SET_TITLE:
         case STREAM_SET_SEEKPOINT:
         {
-            int ret = s->pf_control(s, cmd, args);
+            int ret;
+
+            if (s->ops != NULL && cmd == STREAM_SET_TITLE) {
+                int title = va_arg(args, int);
+                ret = s->ops->set_title(s, title);
+            } else if (s->ops != NULL && cmd == STREAM_SET_SEEKPOINT) {
+                int seekpoint = va_arg(args, int);
+                ret = s->ops->set_seek_point(s, seekpoint);
+            } else {
+                ret = s->pf_control(s, cmd, args);
+            }
+
             if (ret != VLC_SUCCESS)
                 return ret;
 
@@ -722,7 +738,154 @@ int vlc_stream_vaControl(stream_t *s, int cmd, va_list args)
             return VLC_SUCCESS;
         }
     }
-    return s->pf_control(s, cmd, args);
+
+    if (s->ops == NULL)
+        return s->pf_control(s, cmd, args);
+
+    switch (cmd) {
+        case STREAM_CAN_SEEK:
+        {
+            bool *can_seek = va_arg(args, bool *);
+            if (s->ops->can_seek != NULL) {
+                *can_seek = s->ops->can_seek(s);
+            } else {
+                *can_seek = false;
+            }
+            return VLC_SUCCESS;
+        }
+        case STREAM_CAN_FASTSEEK:
+        {
+            bool *can_fastseek = va_arg(args, bool *);
+            if (s->ops->stream.can_fastseek != NULL) {
+                *can_fastseek = s->ops->stream.can_fastseek(s);
+            } else {
+                *can_fastseek = false;
+            }
+            return VLC_SUCCESS;
+        }
+        case STREAM_CAN_PAUSE:
+        {
+            bool *can_pause = va_arg(args, bool *);
+            if (s->ops->can_pause != NULL) {
+                *can_pause = s->ops->can_pause(s);
+            } else {
+                *can_pause = false;
+            }
+            return VLC_SUCCESS;
+        }
+        case STREAM_CAN_CONTROL_PACE:
+        {
+            bool *can_control_pace = va_arg(args, bool *);
+            if (s->ops->can_control_pace != NULL) {
+                *can_control_pace = s->ops->can_control_pace(s);
+            } else {
+                *can_control_pace = false;
+            }
+            return VLC_SUCCESS;
+        }
+        case STREAM_GET_SIZE:
+            if (s->ops->stream.get_size != NULL) {
+                uint64_t *size = va_arg(args, uint64_t *);
+                return s->ops->stream.get_size(s, size);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_PTS_DELAY:
+            if (s->ops->get_pts_delay != NULL) {
+                vlc_tick_t *pts_delay = va_arg(args, vlc_tick_t *);
+                return s->ops->get_pts_delay(s, pts_delay);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_TITLE_INFO:
+            if (s->ops->stream.get_title_info != NULL) {
+                input_title_t ***title_info = va_arg(args, input_title_t ***);
+                int *unk = va_arg(args, int *);
+                return s->ops->stream.get_title_info(s, title_info, unk);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_TITLE:
+            if (s->ops->get_title != NULL) {
+                unsigned *title = va_arg(args, unsigned *);
+                return s->ops->get_title(s, title);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_SEEKPOINT:
+            if (s->ops->get_seekpoint != NULL) {
+                unsigned *seekpoint = va_arg(args, unsigned *);
+                return s->ops->get_seekpoint(s, seekpoint);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_META:
+            if (s->ops->get_meta != NULL) {
+                vlc_meta_t *meta = va_arg(args, vlc_meta_t *);
+                return s->ops->get_meta(s, meta);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_CONTENT_TYPE:
+            if (s->ops->stream.get_content_type != NULL) {
+                char **content_type = va_arg(args, char **);
+                return s->ops->stream.get_content_type(s, content_type);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_SIGNAL:
+            if (s->ops->get_signal != NULL) {
+                double *quality = va_arg(args, double *);
+                double *strength = va_arg(args, double *);
+                return s->ops->get_signal(s, quality, strength);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_TAGS:
+            if (s->ops->stream.get_tags != NULL) {
+                const block_t **block = va_arg(args, const block_t **);
+                return s->ops->stream.get_tags(s, block);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_TYPE:
+            if (s->ops->get_type != NULL) {
+                int *type = va_arg(args, int *);
+                return s->ops->get_type(s, type);
+            }
+            return VLC_EGENERIC;
+        case STREAM_GET_PRIVATE_ID_STATE:
+            if (s->ops->stream.get_private_id_state != NULL) {
+                int priv_data = va_arg(args, int);
+                bool *selected = va_arg(args, bool *);
+                return s->ops->stream.get_private_id_state(s, priv_data, selected);
+            }
+            return VLC_EGENERIC;
+        case STREAM_SET_PAUSE_STATE:
+            if (s->ops->set_pause_state != NULL) {
+                bool pause_state = (bool)va_arg(args, int);
+                return s->ops->set_pause_state(s, pause_state);
+            }
+            return VLC_EGENERIC;
+        case STREAM_SET_RECORD_STATE:
+            if (s->ops->stream.set_record_state != NULL) {
+                bool record_state = (bool)va_arg(args, int);
+                const char *dir_path = NULL;
+                const char *ext = NULL;
+                if (record_state) {
+                    dir_path = va_arg(args, const char *);
+                    ext = va_arg(args, const char *);
+                }
+                return s->ops->stream.set_record_state(s, record_state, dir_path, ext);
+            }
+            return VLC_EGENERIC;
+        case STREAM_SET_PRIVATE_ID_STATE:
+            if (s->ops->stream.set_private_id_state != NULL) {
+                int priv_data = va_arg(args, int);
+                bool selected = (bool)va_arg(args, int);
+                return s->ops->stream.set_private_id_state(s, priv_data, selected);
+            }
+            return VLC_EGENERIC;
+        case STREAM_SET_PRIVATE_ID_CA:
+            if (s->ops->stream.set_private_id_ca != NULL) {
+                void *payload = va_arg(args, void *);
+                return s->ops->stream.set_private_id_ca(s, payload);
+            }
+            return VLC_EGENERIC;
+        default:
+            vlc_assert_unreachable();
+    }
 }
 
 /**



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/f77921f42741e7ea41eb34ba803a0f3292295e1b

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/f77921f42741e7ea41eb34ba803a0f3292295e1b
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list