[vlc-devel] [PATCH] libvlc: Add a new more extensible struct libvlc_media_track_t

Martin Storsjö martin at martin.st
Mon Feb 11 21:23:44 CET 2013


From: Jean-Baptiste Kempf <jb at videolan.org>

Due to the way this struct is allocated, it can be extended later
without breaking ABI.
---
Based on j-b's patch from last week, took most of Rémi's comments into
account:
- Added i_original_fourcc
- Made the union anonymous
- Renamed the struct to plain libvlc_media_track_t
- Allocating an array of pointers, where each struct is allocated individually,
  instead of just allocating a plain array, to make the struct extendable

It does duplicate parts of the libvlc_media_get_tracks_info function,
but gets rid of the assumption that all fields in the two structs
alias perfectly.

I'm still slightly weary about having the union - with them being
structured before the last elements (or even if the union was the
last element of the struct, it wouldn't be after the first new
field is added), you can't add more fields to the unions without
breaking ABI, which is what this is all about avoiding. So
would it perhaps be best to just flatten it altogether?
---
 include/vlc/libvlc_media.h |   53 +++++++++++++++++++++++++
 lib/libvlc.sym             |    2 +
 lib/media.c                |   94 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)

diff --git a/include/vlc/libvlc_media.h b/include/vlc/libvlc_media.h
index 7e61039..8a16c5a 100644
--- a/include/vlc/libvlc_media.h
+++ b/include/vlc/libvlc_media.h
@@ -170,6 +170,44 @@ typedef struct libvlc_media_track_info_t
 } libvlc_media_track_info_t;
 
 
+typedef struct libvlc_media_track_t
+{
+    /* Codec fourcc */
+    uint32_t    i_codec;
+    uint32_t    i_original_fourcc;
+    int         i_id;
+    libvlc_track_type_t i_type;
+
+    /* Codec specific */
+    int         i_profile;
+    int         i_level;
+
+    union {
+        struct {
+            /* Audio specific */
+            unsigned    i_channels;
+            unsigned    i_rate;
+        } audio;
+        struct {
+            /* Video specific */
+            unsigned    i_height;
+            unsigned    i_width;
+            unsigned    i_sar_num;
+            unsigned    i_sar_den;
+            float       f_frame_rate;
+        } video;
+        struct {
+            char *psz_encoding;
+        } subtitle;
+    };
+
+    unsigned int i_bitrate;
+    char *psz_language;
+    char *psz_description;
+
+} libvlc_media_track_t;
+
+
 /**
  * Create a media with a certain given media resource location,
  * for instance a valid URL.
@@ -512,6 +550,21 @@ LIBVLC_API void *libvlc_media_get_user_data( libvlc_media_t *p_md );
 LIBVLC_API
 int libvlc_media_get_tracks_info( libvlc_media_t *p_md,
                                   libvlc_media_track_info_t **tracks );
+LIBVLC_API
+int libvlc_media_get_tracks( libvlc_media_t *p_md,
+                             libvlc_media_track_t ***tracks );
+
+
+/**
+ * Release media descriptor's elementary streams description array
+ *
+ * \param p_tracks tracks info array to release
+ * \param i_count number of elements in the array
+ */
+LIBVLC_API
+void libvlc_media_tracks_release( libvlc_media_track_t **p_tracks,
+                                  int i_count );
+
 
 /** @}*/
 
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index 42dad5c..29f54f6 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -72,6 +72,7 @@ libvlc_media_get_state
 libvlc_media_get_stats
 libvlc_media_get_user_data
 libvlc_media_get_tracks_info
+libvlc_media_get_tracks
 libvlc_media_is_parsed
 libvlc_media_library_load
 libvlc_media_library_media_list
@@ -168,6 +169,7 @@ libvlc_media_set_meta
 libvlc_media_set_state
 libvlc_media_set_user_data
 libvlc_media_subitems
+libvlc_media_tracks_release
 libvlc_new
 libvlc_playlist_play
 libvlc_release
diff --git a/lib/media.c b/lib/media.c
index 600e10a..591e91b 100644
--- a/lib/media.c
+++ b/lib/media.c
@@ -734,3 +734,97 @@ libvlc_media_get_tracks_info( libvlc_media_t *p_md, libvlc_media_track_info_t **
     vlc_mutex_unlock( &p_input_item->lock );
     return i_es;
 }
+
+int
+libvlc_media_get_tracks( libvlc_media_t *p_md, libvlc_media_track_t *** pp_es )
+{
+    assert( p_md );
+
+    input_item_t *p_input_item = p_md->p_input_item;
+    vlc_mutex_lock( &p_input_item->lock );
+
+    const int i_es = p_input_item->i_es;
+    *pp_es = (i_es > 0) ? calloc( i_es, sizeof(**pp_es) ) : NULL;
+
+    if( !*pp_es ) /* no ES, or OOM */
+    {
+        vlc_mutex_unlock( &p_input_item->lock );
+        return 0;
+    }
+
+    /* Fill array */
+    for( int i = 0; i < i_es; i++ )
+    {
+        libvlc_media_track_t *p_mes = malloc( sizeof(*p_mes) );
+        if ( !p_mes )
+        {
+            libvlc_media_tracks_release( *pp_es, i_es );
+            *pp_es = NULL;
+            return 0;
+        }
+        (*pp_es)[i] = p_mes;
+
+        const es_format_t *p_es = p_input_item->es[i];
+
+        p_mes->i_codec = p_es->i_codec;
+        p_mes->i_original_fourcc = p_es->i_original_fourcc;
+        p_mes->i_id = p_es->i_id;
+
+        p_mes->i_profile = p_es->i_profile;
+        p_mes->i_level = p_es->i_level;
+
+        p_mes->i_bitrate = p_es->i_bitrate;
+        p_mes->psz_language = p_es->psz_language != NULL ? strdup(p_es->psz_language) : NULL;
+        p_mes->psz_description = p_es->psz_description != NULL ? strdup(p_es->psz_description) : NULL;
+
+        switch(p_es->i_cat)
+        {
+        case UNKNOWN_ES:
+        default:
+            p_mes->i_type = libvlc_track_unknown;
+            break;
+        case VIDEO_ES:
+            p_mes->i_type = libvlc_track_video;
+            p_mes->video.i_height = p_es->video.i_height;
+            p_mes->video.i_width = p_es->video.i_width;
+            p_mes->video.i_sar_num = p_es->video.i_sar_num;
+            p_mes->video.i_sar_den = p_es->video.i_sar_den;
+            p_mes->video.f_frame_rate = (float)p_es->video.i_frame_rate /
+                                               p_es->video.i_frame_rate_base;
+            break;
+        case AUDIO_ES:
+            p_mes->i_type = libvlc_track_audio;
+            p_mes->audio.i_channels = p_es->audio.i_channels;
+            p_mes->audio.i_rate = p_es->audio.i_rate;
+            break;
+        case SPU_ES:
+            p_mes->i_type = libvlc_track_text;
+            p_mes->subtitle.psz_encoding = p_es->subs.psz_encoding != NULL ?
+                                           strdup(p_es->subs.psz_encoding) : NULL;
+            break;
+        }
+    }
+
+    vlc_mutex_unlock( &p_input_item->lock );
+    return i_es;
+}
+
+
+/**************************************************************************
+ * Release media descriptor's elementary streams description array
+ **************************************************************************/
+void libvlc_media_tracks_release( libvlc_media_track_t **p_tracks, int i_count )
+{
+    if (!p_tracks)
+        return;
+    for (int i = 0; i < i_count; ++i) {
+        if ( !p_tracks[i] )
+            continue;
+        free( p_tracks[i]->psz_language );
+        free( p_tracks[i]->psz_description );
+        if (p_tracks[i]->i_type == libvlc_track_text)
+            free (p_tracks[i]->subtitle.psz_encoding);
+        free( p_tracks[i] );
+    }
+    free( p_tracks );
+}
-- 
1.7.10.4




More information about the vlc-devel mailing list