[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