lib: add new player track API
[vlc.git] / lib / media_track.c
blobb7b575698a8a31385935282b9710169f035206ae
1 /*****************************************************************************
2 * media_track.c: Libvlc API media track
3 *****************************************************************************
4 * Copyright (C) 2020 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <assert.h>
26 #include <errno.h>
28 #include <vlc/libvlc.h>
29 #include <vlc/libvlc_picture.h>
30 #include <vlc/libvlc_media.h>
31 #include <vlc/libvlc_events.h>
33 #include "libvlc_internal.h"
34 #include "media_internal.h"
36 struct libvlc_media_tracklist_t
38 size_t count;
39 libvlc_media_trackpriv_t tracks[];
42 void
43 libvlc_media_trackpriv_from_es( libvlc_media_trackpriv_t *trackpriv,
44 const es_format_t *es )
46 libvlc_media_track_t *track = &trackpriv->t;
48 trackpriv->es_id = NULL;
50 track->i_codec = es->i_codec;
51 track->i_original_fourcc = es->i_original_fourcc;
52 track->i_id = es->i_id;
54 track->i_profile = es->i_profile;
55 track->i_level = es->i_level;
57 track->i_bitrate = es->i_bitrate;
58 track->psz_language = es->psz_language != NULL ? strdup(es->psz_language) : NULL;
59 track->psz_description = es->psz_description != NULL ? strdup(es->psz_description) : NULL;
60 track->psz_id = NULL;
61 track->id_stable = false;
62 track->psz_name = NULL;
63 track->selected = false;
65 switch( es->i_cat )
67 case UNKNOWN_ES:
68 default:
69 track->i_type = libvlc_track_unknown;
70 break;
71 case VIDEO_ES:
72 track->video = &trackpriv->video;
73 track->i_type = libvlc_track_video;
74 track->video->i_height = es->video.i_visible_height;
75 track->video->i_width = es->video.i_visible_width;
76 track->video->i_sar_num = es->video.i_sar_num;
77 track->video->i_sar_den = es->video.i_sar_den;
78 track->video->i_frame_rate_num = es->video.i_frame_rate;
79 track->video->i_frame_rate_den = es->video.i_frame_rate_base;
81 assert( es->video.orientation >= ORIENT_TOP_LEFT &&
82 es->video.orientation <= ORIENT_RIGHT_BOTTOM );
83 track->video->i_orientation = (int) es->video.orientation;
85 assert( ( es->video.projection_mode >= PROJECTION_MODE_RECTANGULAR &&
86 es->video.projection_mode <= PROJECTION_MODE_EQUIRECTANGULAR ) ||
87 ( es->video.projection_mode == PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD ) );
88 track->video->i_projection = (int) es->video.projection_mode;
90 track->video->pose.f_yaw = es->video.pose.yaw;
91 track->video->pose.f_pitch = es->video.pose.pitch;
92 track->video->pose.f_roll = es->video.pose.roll;
93 track->video->pose.f_field_of_view = es->video.pose.fov;
95 assert( es->video.multiview_mode >= MULTIVIEW_2D &&
96 es->video.multiview_mode <= MULTIVIEW_STEREO_CHECKERBOARD );
97 track->video->i_multiview = (int) es->video.multiview_mode;
98 break;
99 case AUDIO_ES:
100 track->audio = &trackpriv->audio;
101 track->i_type = libvlc_track_audio;
102 track->audio->i_channels = es->audio.i_channels;
103 track->audio->i_rate = es->audio.i_rate;
104 break;
105 case SPU_ES:
106 track->subtitle = &trackpriv->subtitle;
107 track->i_type = libvlc_track_text;
108 track->subtitle->psz_encoding = es->subs.psz_encoding != NULL ?
109 strdup(es->subs.psz_encoding) : NULL;
110 break;
114 void
115 libvlc_media_track_clean( libvlc_media_track_t *track )
117 free( track->psz_language );
118 free( track->psz_description );
119 free( track->psz_name );
120 switch( track->i_type )
122 case libvlc_track_audio:
123 break;
124 case libvlc_track_video:
125 break;
126 case libvlc_track_text:
127 free( track->subtitle->psz_encoding );
128 break;
129 case libvlc_track_unknown:
130 default:
131 break;
135 void
136 libvlc_media_track_delete( libvlc_media_track_t *track )
138 libvlc_media_trackpriv_t *trackpriv =
139 container_of( track, libvlc_media_trackpriv_t, t );
140 libvlc_media_track_clean( track );
141 if( trackpriv->es_id )
142 vlc_es_id_Release( trackpriv->es_id );
143 free( trackpriv );
146 static libvlc_media_tracklist_t *
147 libvlc_media_tracklist_alloc( size_t count )
149 size_t size;
150 if( mul_overflow( count, sizeof(libvlc_media_trackpriv_t), &size) )
151 return NULL;
152 if( add_overflow( size, sizeof(libvlc_media_tracklist_t), &size) )
153 return NULL;
155 libvlc_media_tracklist_t *list = malloc( size );
156 if( list == NULL )
157 return NULL;
159 list->count = count;
160 return list;
163 libvlc_media_tracklist_t *
164 libvlc_media_tracklist_from_es_array( es_format_t **es_array,
165 size_t es_count,
166 libvlc_track_type_t type )
168 size_t count = 0;
169 const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
171 for( size_t i = 0; i < es_count; ++i )
173 if( es_array[i]->i_cat == cat )
174 count++;
177 libvlc_media_tracklist_t *list = libvlc_media_tracklist_alloc( count );
179 if( count == 0 )
180 return list;
182 count = 0;
183 for( size_t i = 0; i < es_count; ++i )
185 if( es_array[i]->i_cat == cat )
186 libvlc_media_trackpriv_from_es( &list->tracks[count++],
187 es_array[i] );
190 return list;
193 void
194 libvlc_media_trackpriv_from_player_track( libvlc_media_trackpriv_t *trackpriv,
195 const struct vlc_player_track *track )
197 libvlc_media_trackpriv_from_es( trackpriv, &track->fmt );
199 trackpriv->es_id = vlc_es_id_Hold( track->es_id );
201 trackpriv->t.psz_id = vlc_es_id_GetStrId( track->es_id );
202 trackpriv->t.id_stable = vlc_es_id_IsStrIdStable( track->es_id );
203 trackpriv->t.psz_name = strdup( track->name );
204 trackpriv->t.selected = track->selected;
207 libvlc_media_track_t *
208 libvlc_media_track_create_from_player_track( const struct vlc_player_track *track )
210 libvlc_media_trackpriv_t *trackpriv = malloc( sizeof(*trackpriv) );
211 if( trackpriv == NULL )
212 return NULL;
213 libvlc_media_trackpriv_from_player_track( trackpriv, track );
214 return &trackpriv->t;
217 libvlc_media_tracklist_t *
218 libvlc_media_tracklist_from_player( vlc_player_t *player,
219 libvlc_track_type_t type )
221 const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
223 size_t count = vlc_player_GetTrackCount( player, cat );
224 libvlc_media_tracklist_t *list = libvlc_media_tracklist_alloc( count );
226 for( size_t i = 0; i < count; ++i )
228 const struct vlc_player_track *track =
229 vlc_player_GetTrackAt( player, cat, i );
230 assert( track );
232 libvlc_media_trackpriv_t *trackpriv = &list->tracks[i];
233 libvlc_media_trackpriv_from_player_track( trackpriv, track );
236 return list;
239 size_t
240 libvlc_media_tracklist_count( const libvlc_media_tracklist_t *list )
242 return list->count;
245 libvlc_media_track_t *
246 libvlc_media_tracklist_at( libvlc_media_tracklist_t *list, size_t idx )
248 assert( idx < list->count );
249 return &list->tracks[idx].t;
252 void
253 libvlc_media_tracklist_delete( libvlc_media_tracklist_t *list )
255 for( size_t i = 0; i < list->count; ++i )
257 libvlc_media_trackpriv_t *trackpriv = &list->tracks[i];
258 libvlc_media_track_clean( &trackpriv->t );
260 if( trackpriv->es_id != NULL )
261 vlc_es_id_Release( trackpriv->es_id );
263 free( list );