You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
10 KiB
332 lines
10 KiB
/*****************************************************************************
|
|
* media_track.c: Libvlc API media track
|
|
*****************************************************************************
|
|
* Copyright (C) 2020 VLC authors and VideoLAN
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <stdckdint.h>
|
|
|
|
#include <vlc/libvlc.h>
|
|
#include <vlc/libvlc_picture.h>
|
|
#include <vlc/libvlc_media.h>
|
|
#include <vlc/libvlc_events.h>
|
|
|
|
#include "libvlc_internal.h"
|
|
#include "media_internal.h"
|
|
|
|
struct libvlc_media_tracklist_t
|
|
{
|
|
size_t count;
|
|
libvlc_media_trackpriv_t *tracks[];
|
|
};
|
|
|
|
void
|
|
libvlc_media_trackpriv_from_es( libvlc_media_trackpriv_t *trackpriv,
|
|
const es_format_t *es )
|
|
{
|
|
libvlc_media_track_t *track = &trackpriv->t;
|
|
|
|
track->i_codec = es->i_codec;
|
|
track->i_original_fourcc = es->i_original_fourcc;
|
|
track->i_id = es->i_id;
|
|
|
|
track->i_profile = es->i_profile;
|
|
track->i_level = es->i_level;
|
|
|
|
track->i_bitrate = es->i_bitrate;
|
|
track->psz_language = es->psz_language != NULL ? strdup(es->psz_language) : NULL;
|
|
track->psz_description = es->psz_description != NULL ? strdup(es->psz_description) : NULL;
|
|
track->psz_id = NULL;
|
|
track->id_stable = false;
|
|
track->psz_name = NULL;
|
|
track->selected = false;
|
|
|
|
switch( es->i_cat )
|
|
{
|
|
case UNKNOWN_ES:
|
|
default:
|
|
track->i_type = libvlc_track_unknown;
|
|
break;
|
|
case VIDEO_ES:
|
|
track->video = &trackpriv->video;
|
|
track->i_type = libvlc_track_video;
|
|
track->video->i_height = es->video.i_visible_height;
|
|
track->video->i_width = es->video.i_visible_width;
|
|
track->video->i_sar_num = es->video.i_sar_num;
|
|
track->video->i_sar_den = es->video.i_sar_den;
|
|
track->video->i_frame_rate_num = es->video.i_frame_rate;
|
|
track->video->i_frame_rate_den = es->video.i_frame_rate_base;
|
|
|
|
assert( es->video.orientation >= ORIENT_TOP_LEFT &&
|
|
es->video.orientation <= ORIENT_RIGHT_BOTTOM );
|
|
track->video->i_orientation = (int) es->video.orientation;
|
|
|
|
assert( ( es->video.projection_mode >= PROJECTION_MODE_RECTANGULAR &&
|
|
es->video.projection_mode <= PROJECTION_MODE_EQUIRECTANGULAR ) ||
|
|
( es->video.projection_mode == PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD ) );
|
|
track->video->i_projection = (int) es->video.projection_mode;
|
|
|
|
vlc_viewpoint_to_euler(&es->video.pose,
|
|
&track->video->pose.f_yaw,
|
|
&track->video->pose.f_pitch,
|
|
&track->video->pose.f_roll);
|
|
track->video->pose.f_field_of_view = es->video.pose.fov;
|
|
|
|
assert( es->video.multiview_mode >= MULTIVIEW_2D &&
|
|
es->video.multiview_mode <= MULTIVIEW_STEREO_CHECKERBOARD );
|
|
track->video->i_multiview = (int) es->video.multiview_mode;
|
|
break;
|
|
case AUDIO_ES:
|
|
track->audio = &trackpriv->audio;
|
|
track->i_type = libvlc_track_audio;
|
|
track->audio->i_channels = es->audio.i_channels;
|
|
track->audio->i_rate = es->audio.i_rate;
|
|
break;
|
|
case SPU_ES:
|
|
track->subtitle = &trackpriv->subtitle;
|
|
track->i_type = libvlc_track_text;
|
|
track->subtitle->psz_encoding = es->subs.psz_encoding != NULL ?
|
|
strdup(es->subs.psz_encoding) : NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static libvlc_media_trackpriv_t *
|
|
libvlc_media_trackpriv_new( void )
|
|
{
|
|
libvlc_media_trackpriv_t *trackpriv =
|
|
malloc( sizeof (libvlc_media_trackpriv_t ) );
|
|
|
|
if( trackpriv == NULL )
|
|
return NULL;
|
|
|
|
trackpriv->es_id = NULL;
|
|
trackpriv->item_str_id = NULL;
|
|
vlc_atomic_rc_init( &trackpriv->rc );
|
|
return trackpriv;
|
|
}
|
|
|
|
static void libvlc_media_track_clean( libvlc_media_track_t *track )
|
|
{
|
|
free( track->psz_language );
|
|
free( track->psz_description );
|
|
free( track->psz_name );
|
|
switch( track->i_type )
|
|
{
|
|
case libvlc_track_audio:
|
|
break;
|
|
case libvlc_track_video:
|
|
break;
|
|
case libvlc_track_text:
|
|
free( track->subtitle->psz_encoding );
|
|
break;
|
|
case libvlc_track_unknown:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
libvlc_media_track_t *
|
|
libvlc_media_track_hold( libvlc_media_track_t *track )
|
|
{
|
|
libvlc_media_trackpriv_t *trackpriv =
|
|
container_of( track, libvlc_media_trackpriv_t, t );
|
|
vlc_atomic_rc_inc( &trackpriv->rc );
|
|
return track;
|
|
}
|
|
|
|
void
|
|
libvlc_media_track_release( libvlc_media_track_t *track )
|
|
{
|
|
libvlc_media_trackpriv_t *trackpriv =
|
|
container_of( track, libvlc_media_trackpriv_t, t );
|
|
|
|
if( vlc_atomic_rc_dec( &trackpriv->rc ) )
|
|
{
|
|
libvlc_media_track_clean( track );
|
|
if( trackpriv->es_id )
|
|
vlc_es_id_Release( trackpriv->es_id );
|
|
free( trackpriv->item_str_id );
|
|
free( trackpriv );
|
|
}
|
|
}
|
|
|
|
static libvlc_media_tracklist_t *
|
|
libvlc_media_tracklist_alloc( size_t count )
|
|
{
|
|
size_t size;
|
|
if (ckd_mul(&size, count, sizeof (libvlc_media_trackpriv_t *)) ||
|
|
ckd_add(&size, size, sizeof (libvlc_media_tracklist_t)))
|
|
return NULL;
|
|
|
|
libvlc_media_tracklist_t *list = malloc( size );
|
|
if( list == NULL )
|
|
return NULL;
|
|
|
|
list->count = 0;
|
|
return list;
|
|
}
|
|
|
|
libvlc_media_tracklist_t *
|
|
libvlc_media_tracklist_from_item( input_item_t *item, libvlc_track_type_t type )
|
|
{
|
|
size_t count = 0;
|
|
const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
|
|
|
|
for( size_t i = 0; i < item->es_vec.size; ++i )
|
|
{
|
|
const es_format_t *es_fmt = &item->es_vec.data[i].es;
|
|
if( es_fmt->i_cat == cat )
|
|
count++;
|
|
}
|
|
|
|
libvlc_media_tracklist_t *list = libvlc_media_tracklist_alloc( count );
|
|
|
|
if( count == 0 || list == NULL )
|
|
return list;
|
|
|
|
for( size_t i = 0; i < item->es_vec.size; ++i )
|
|
{
|
|
const struct input_item_es *item_es = &item->es_vec.data[i];
|
|
const es_format_t *es_fmt = &item_es->es;
|
|
if( es_fmt->i_cat == cat )
|
|
{
|
|
libvlc_media_trackpriv_t *trackpriv = libvlc_media_trackpriv_new();
|
|
if( trackpriv == NULL )
|
|
{
|
|
libvlc_media_tracklist_delete( list );
|
|
return NULL;
|
|
}
|
|
list->tracks[list->count++] = trackpriv;
|
|
libvlc_media_trackpriv_from_es( trackpriv, es_fmt );
|
|
|
|
trackpriv->item_str_id = strdup( item_es->id );
|
|
if( trackpriv->item_str_id == NULL )
|
|
{
|
|
libvlc_media_tracklist_delete( list );
|
|
return NULL;
|
|
}
|
|
trackpriv->t.psz_id = trackpriv->item_str_id;
|
|
trackpriv->t.id_stable = item_es->id_stable;
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
static void
|
|
libvlc_media_trackpriv_from_player_track( libvlc_media_trackpriv_t *trackpriv,
|
|
const struct vlc_player_track *track )
|
|
{
|
|
libvlc_media_trackpriv_from_es( trackpriv, &track->fmt );
|
|
|
|
trackpriv->es_id = vlc_es_id_Hold( track->es_id );
|
|
|
|
trackpriv->t.psz_id = vlc_es_id_GetStrId( track->es_id );
|
|
trackpriv->t.id_stable = vlc_es_id_IsStrIdStable( track->es_id );
|
|
trackpriv->t.psz_name = strdup( track->name );
|
|
trackpriv->t.selected = track->selected;
|
|
}
|
|
|
|
libvlc_media_track_t *
|
|
libvlc_media_track_create_from_player_track( const struct vlc_player_track *track )
|
|
{
|
|
libvlc_media_trackpriv_t *trackpriv = libvlc_media_trackpriv_new();
|
|
if( trackpriv == NULL )
|
|
return NULL;
|
|
libvlc_media_trackpriv_from_player_track( trackpriv, track );
|
|
return &trackpriv->t;
|
|
}
|
|
|
|
libvlc_media_tracklist_t *
|
|
libvlc_media_tracklist_from_player( vlc_player_t *player,
|
|
libvlc_track_type_t type, bool selected )
|
|
{
|
|
const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
|
|
|
|
size_t count = vlc_player_GetTrackCount( player, cat );
|
|
|
|
if( selected )
|
|
{
|
|
size_t selected_count = 0;
|
|
for( size_t i = 0; i < count; ++i )
|
|
{
|
|
const struct vlc_player_track *track =
|
|
vlc_player_GetTrackAt( player, cat, i );
|
|
assert( track );
|
|
if( track->selected )
|
|
selected_count++;
|
|
}
|
|
count = selected_count;
|
|
}
|
|
|
|
libvlc_media_tracklist_t *list = libvlc_media_tracklist_alloc( count );
|
|
|
|
if( count == 0 || list == NULL )
|
|
return list;
|
|
|
|
for( size_t i = 0; i < count; ++i )
|
|
{
|
|
const struct vlc_player_track *track =
|
|
vlc_player_GetTrackAt( player, cat, i );
|
|
assert( track );
|
|
|
|
if( selected && !track->selected )
|
|
continue;
|
|
|
|
libvlc_media_trackpriv_t *trackpriv = libvlc_media_trackpriv_new();
|
|
if( trackpriv == NULL )
|
|
{
|
|
libvlc_media_tracklist_delete( list );
|
|
return NULL;
|
|
}
|
|
list->tracks[list->count++] = trackpriv;
|
|
libvlc_media_trackpriv_from_player_track( trackpriv, track );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
size_t
|
|
libvlc_media_tracklist_count( const libvlc_media_tracklist_t *list )
|
|
{
|
|
return list->count;
|
|
}
|
|
|
|
libvlc_media_track_t *
|
|
libvlc_media_tracklist_at( libvlc_media_tracklist_t *list, size_t idx )
|
|
{
|
|
assert( idx < list->count );
|
|
return &list->tracks[idx]->t;
|
|
}
|
|
|
|
void
|
|
libvlc_media_tracklist_delete( libvlc_media_tracklist_t *list )
|
|
{
|
|
for( size_t i = 0; i < list->count; ++i )
|
|
{
|
|
libvlc_media_trackpriv_t *trackpriv = list->tracks[i];
|
|
libvlc_media_track_release( &trackpriv->t );
|
|
}
|
|
free( list );
|
|
}
|
|
|