[vlc-devel] [PATCH] lua: input: Expose tracks through lua bindings

Hugo Beauzée-Luyssen hugo at beauzee.fr
Thu Jan 5 16:22:30 CET 2017


---
 modules/lua/libs/input.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++
 share/lua/README.txt     |  30 +++++++
 2 files changed, 254 insertions(+)

diff --git a/modules/lua/libs/input.c b/modules/lua/libs/input.c
index 6d14ebce78..9882f88cb8 100644
--- a/modules/lua/libs/input.c
+++ b/modules/lua/libs/input.c
@@ -46,6 +46,11 @@
 
 static input_item_t* vlclua_input_item_get_internal( lua_State *L );
 
+typedef struct input_track
+{
+    int i_id;
+} input_track;
+
 input_thread_t * vlclua_get_input_internal( lua_State *L )
 {
     extension_t *p_extension = vlclua_extension_get( L );
@@ -382,6 +387,222 @@ static int vlclua_input_item_set_meta( lua_State *L )
     return 1;
 }
 
+static int vlclua_input_compare_track_id( lua_State* L )
+{
+    input_track* left  = luaL_checkudata( L, 1, "track" );
+    input_track* right = luaL_checkudata( L, 2, "track" );
+    lua_pushboolean( L, left != NULL && right != NULL &&
+            left->i_id == right->i_id );
+    return 1;
+}
+
+static input_track* vlclua_input_item_create_track( lua_State* L, int i_track_id )
+{
+    input_track* p_track = lua_newuserdata( L, sizeof( *p_track ) );
+    if ( p_track == NULL )
+        return NULL;
+    if ( luaL_newmetatable( L, "track" ) )
+    {
+        lua_pushcfunction( L, vlclua_input_compare_track_id );
+        lua_setfield( L, -2, "__eq" );
+    }
+    lua_setmetatable( L, -2 );
+    p_track->i_id = i_track_id;
+    return p_track;
+}
+
+static const char* orientation_to_str(video_orientation_t orient)
+{
+    switch (orient)
+    {
+    case ORIENT_TOP_LEFT:
+        return "topleft";
+    case ORIENT_TOP_RIGHT:
+        return "topright";
+    case ORIENT_BOTTOM_LEFT:
+        return "bottomleft";
+    case ORIENT_BOTTOM_RIGHT:
+        return "bottomright";
+    case ORIENT_LEFT_TOP:
+        return "lefttop";
+    case ORIENT_LEFT_BOTTOM:
+        return "leftbottom";
+    case ORIENT_RIGHT_TOP:
+        return "righttop";
+    case ORIENT_RIGHT_BOTTOM:
+        return "rightbottom";
+    default:
+        vlc_assert_unreachable();
+    }
+}
+
+static const char* projection_to_str(video_projection_mode_t proj)
+{
+    switch (proj)
+    {
+    case PROJECTION_MODE_RECTANGULAR:
+        return "rectangular";
+    case PROJECTION_MODE_EQUIRECTANGULAR:
+        return "equirectangular";
+    case PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD:
+        return "cubemap";
+    default:
+        vlc_assert_unreachable();
+    }
+}
+
+static const char* vlclua_input_item_es_track_name( const char* psz_track_type )
+{
+    if ( strcmp( psz_track_type, "video" ) == 0 )
+        return "video-es";
+    else if ( strcmp( psz_track_type, "audio" ) == 0 )
+        return "audio-es";
+    else if ( strcmp( psz_track_type, "spu" ) == 0 )
+        return "spu-es";
+    return NULL;
+}
+
+#define PUSH_INT( val, name ) \
+    lua_pushinteger( L, val ); \
+    lua_setfield( L, -2, name );
+
+#define PUSH_STR( val, name ) \
+    lua_pushstring( L, val ); \
+    lua_setfield( L, -2, name );
+
+#define PUSH_NUM( val, name ) \
+    lua_pushnumber( L, val ); \
+    lua_setfield( L, -2, name );
+
+static int vlclua_input_item_tracks( lua_State *L )
+{
+    input_item_t *p_item = vlclua_input_item_get_internal( L );
+    lua_newtable( L );
+
+    vlc_mutex_lock( &p_item->lock );
+    for ( int i = 0; i < p_item->i_es; ++i )
+    {
+        const es_format_t* p_es = p_item->es[i];
+
+        lua_newtable( L );
+        lua_pushlstring( L, (const char*)&p_es->i_codec, 4 );
+        lua_setfield( L, -2, "codec" );
+        lua_pushlstring( L, (const char*)&p_es->i_original_fourcc, 4 );
+        lua_setfield( L, -2, "original_fourcc" );
+        input_track* p_track = vlclua_input_item_create_track( L, p_es->i_id );
+        if ( unlikely( p_track == NULL ) )
+        {
+            vlc_mutex_unlock( &p_item->lock );
+            return luaL_error( L, "Failed to allocate memory" );
+        }
+        lua_setfield( L, -2, "id" );
+        PUSH_INT( p_es->i_profile, "profile" );
+        PUSH_INT( p_es->i_level, "level" );
+        PUSH_INT( p_es->i_bitrate, "bitrate" );
+        PUSH_STR( p_es->psz_language, "language" );
+        PUSH_STR( p_es->psz_description, "description" );
+
+        switch (p_es->i_cat)
+        {
+        //FIXME: Expose constants to avoid magic numbers
+        case VIDEO_ES:
+            PUSH_STR( "video", "type" );
+            lua_newtable( L );
+            PUSH_INT( p_es->video.i_visible_width, "width" );
+            PUSH_INT( p_es->video.i_visible_height, "height" );
+            PUSH_INT( p_es->video.i_sar_num, "sar_num" );
+            PUSH_INT( p_es->video.i_sar_den, "sar_den" );
+            PUSH_INT( p_es->video.i_frame_rate, "framerate" );
+            PUSH_INT( p_es->video.i_frame_rate_base, "framerate_den" );
+            PUSH_STR( orientation_to_str( p_es->video.orientation ), "orientation" );
+            PUSH_STR( projection_to_str( p_es->video.projection_mode ), "projection" );
+            PUSH_NUM( p_es->video.pose.f_yaw_degrees, "yaw" );
+            PUSH_NUM( p_es->video.pose.f_pitch_degrees, "pitch" );
+            PUSH_NUM( p_es->video.pose.f_roll_degrees, "roll" );
+            PUSH_NUM( p_es->video.pose.f_fov_degrees, "fov" );
+            lua_setfield( L, -2, "video" );
+            break;
+        case AUDIO_ES:
+            PUSH_STR( "audio", "type" );
+            lua_newtable( L );
+            PUSH_INT( p_es->audio.i_channels, "channels" );
+            PUSH_INT( p_es->audio.i_rate, "rate" );
+            lua_setfield( L, -2, "audio" );
+            break;
+        case SPU_ES:
+            PUSH_STR( "spu", "type" );
+            lua_newtable( L );
+            PUSH_STR( p_es->subs.psz_encoding, "encoding" );
+            lua_setfield( L, -2, "spu" );
+            break;
+        default:
+            PUSH_STR( "unknown", "type" );
+            break;
+        }
+        lua_rawseti( L, -2, i + 1 );
+    }
+    vlc_mutex_unlock( &p_item->lock );
+    return 1;
+}
+
+#undef PUSH_INT
+#undef PUSH_STR
+
+static int vlclua_input_item_current_track( lua_State* L )
+{
+    const char* psz_track_type = luaL_checkstring( L, 2 );
+    if ( psz_track_type == NULL )
+        return luaL_error( L, "vlc.input:set_track(): invalid track type provided" );
+    const char* psz_es_name = vlclua_input_item_es_track_name( psz_track_type );
+    if ( psz_es_name == NULL )
+        return luaL_error( L, "vlc.input:set_track(): invalid track type provided" );
+    input_thread_t* p_input_thread = vlclua_get_input_internal( L );
+    if ( p_input_thread == NULL )
+        return luaL_error( L, "vlc.input:current_track(): No playback in progress" );
+    int i_track = var_GetInteger( p_input_thread, psz_es_name );
+    vlclua_input_item_create_track( L, i_track );
+    vlc_object_release( p_input_thread );
+    return 1;
+}
+
+static int vlclua_input_item_select_track( lua_State* L )
+{
+    const char* psz_track_type = luaL_checkstring( L, 2 );
+    if ( psz_track_type == NULL )
+        return luaL_error( L, "vlc.input:set_track(): invalid track type provided" );
+    input_track* p_track = lua_touserdata( L, 3 );
+
+    const char* psz_es_name = vlclua_input_item_es_track_name( psz_track_type );
+    if ( psz_es_name == NULL )
+        return luaL_error( L, "vlc.input:set_track(): invalid track type provided" );
+
+    input_thread_t* p_input_thread = vlclua_get_input_internal( L );
+    if ( p_input_thread == NULL )
+        return luaL_error( L, "vlc.input:set_track: No playback in progress" );
+
+    if ( p_track == NULL )
+        var_SetInteger( p_input_thread, psz_es_name, -1 );
+    else
+    {
+        vlc_value_t val_list;
+        var_Change( p_input_thread, psz_es_name, VLC_VAR_GETCHOICES, &val_list, NULL );
+        for( int i = 0; i < val_list.p_list->i_count; i++ )
+        {
+            if( p_track->i_id == val_list.p_list->p_values[i].i_int )
+            {
+                if( strcmp( psz_track_type, "video-es" ) == 0 && var_SetBool( p_input_thread, psz_track_type, true ) < 0 )
+                    break;
+                if( var_SetInteger( p_input_thread, psz_es_name, p_track->i_id ) < 0 )
+                    break;
+                break;
+            }
+        }
+        var_FreeList( &val_list, NULL );
+    }
+    vlc_object_release( p_input_thread );
+    return 0;
+}
+
 /*****************************************************************************
  * Lua bindings
  *****************************************************************************/
@@ -408,6 +629,9 @@ static const luaL_Reg vlclua_input_item_reg[] = {
     { "duration", vlclua_input_item_duration },
     { "stats", vlclua_input_item_stats },
     { "info", vlclua_input_item_info },
+    { "tracks", vlclua_input_item_tracks },
+    { "current_track", vlclua_input_item_current_track },
+    { "select_track", vlclua_input_item_select_track },
     { NULL, NULL }
 };
 
diff --git a/share/lua/README.txt b/share/lua/README.txt
index d726fcf095..d1be6f8e14 100644
--- a/share/lua/README.txt
+++ b/share/lua/README.txt
@@ -132,6 +132,36 @@ input.item(): Get the current input item. Input item methods are:
     .send_bitrate
     .played_abuffers
     .lost_abuffers
+  :tracks(): Get information about the current tracks. This is a table with the following fields:
+    .codec
+    .original_fourcc
+    .id
+    .profile
+    .level
+    .bitrate
+    .language
+    .description
+    .type ("video", "audio", "spu" or "unknown")
+    .video (when type == "video")
+        .width
+        .height
+        .sar_num
+        .sar_den
+        .framerate
+        .framerate_den
+        .orientation
+        .projection
+        .yaw
+        .pitch
+        .roll
+        .fov
+    .audio (when type == "audio")
+        .channels
+        .rate
+    .spu (when type == "spu")
+        .encoding
+  :current_track(type): Get an object representing the current track ID
+  :select_track(type, id): Set the current track type to the provided track ID or nil to disable it
 
 Messages
 --------
-- 
2.11.0



More information about the vlc-devel mailing list