audiotrack: refactor
[vlc.git] / lib / media_track.c
bloba11c2973c65107fd687805054e4d8e60d2179d7c
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 track->i_codec = es->i_codec;
49 track->i_original_fourcc = es->i_original_fourcc;
50 track->i_id = es->i_id;
52 track->i_profile = es->i_profile;
53 track->i_level = es->i_level;
55 track->i_bitrate = es->i_bitrate;
56 track->psz_language = es->psz_language != NULL ? strdup(es->psz_language) : NULL;
57 track->psz_description = es->psz_description != NULL ? strdup(es->psz_description) : NULL;
58 track->psz_id = NULL;
59 track->id_stable = false;
60 track->psz_name = NULL;
61 track->selected = false;
63 switch( es->i_cat )
65 case UNKNOWN_ES:
66 default:
67 track->i_type = libvlc_track_unknown;
68 break;
69 case VIDEO_ES:
70 track->video = &trackpriv->video;
71 track->i_type = libvlc_track_video;
72 track->video->i_height = es->video.i_visible_height;
73 track->video->i_width = es->video.i_visible_width;
74 track->video->i_sar_num = es->video.i_sar_num;
75 track->video->i_sar_den = es->video.i_sar_den;
76 track->video->i_frame_rate_num = es->video.i_frame_rate;
77 track->video->i_frame_rate_den = es->video.i_frame_rate_base;
79 assert( es->video.orientation >= ORIENT_TOP_LEFT &&
80 es->video.orientation <= ORIENT_RIGHT_BOTTOM );
81 track->video->i_orientation = (int) es->video.orientation;
83 assert( ( es->video.projection_mode >= PROJECTION_MODE_RECTANGULAR &&
84 es->video.projection_mode <= PROJECTION_MODE_EQUIRECTANGULAR ) ||
85 ( es->video.projection_mode == PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD ) );
86 track->video->i_projection = (int) es->video.projection_mode;
88 track->video->pose.f_yaw = es->video.pose.yaw;
89 track->video->pose.f_pitch = es->video.pose.pitch;
90 track->video->pose.f_roll = es->video.pose.roll;
91 track->video->pose.f_field_of_view = es->video.pose.fov;
93 assert( es->video.multiview_mode >= MULTIVIEW_2D &&
94 es->video.multiview_mode <= MULTIVIEW_STEREO_CHECKERBOARD );
95 track->video->i_multiview = (int) es->video.multiview_mode;
96 break;
97 case AUDIO_ES:
98 track->audio = &trackpriv->audio;
99 track->i_type = libvlc_track_audio;
100 track->audio->i_channels = es->audio.i_channels;
101 track->audio->i_rate = es->audio.i_rate;
102 break;
103 case SPU_ES:
104 track->subtitle = &trackpriv->subtitle;
105 track->i_type = libvlc_track_text;
106 track->subtitle->psz_encoding = es->subs.psz_encoding != NULL ?
107 strdup(es->subs.psz_encoding) : NULL;
108 break;
112 static libvlc_media_trackpriv_t *
113 libvlc_media_trackpriv_new( void )
115 libvlc_media_trackpriv_t *trackpriv =
116 malloc( sizeof (libvlc_media_trackpriv_t ) );
118 if( trackpriv == NULL )
119 return NULL;
121 trackpriv->es_id = NULL;
122 vlc_atomic_rc_init( &trackpriv->rc );
123 return trackpriv;
126 void
127 libvlc_media_track_clean( libvlc_media_track_t *track )
129 free( track->psz_language );
130 free( track->psz_description );
131 free( track->psz_name );
132 switch( track->i_type )
134 case libvlc_track_audio:
135 break;
136 case libvlc_track_video:
137 break;
138 case libvlc_track_text:
139 free( track->subtitle->psz_encoding );
140 break;
141 case libvlc_track_unknown:
142 default:
143 break;
147 libvlc_media_track_t *
148 libvlc_media_track_hold( libvlc_media_track_t *track )
150 libvlc_media_trackpriv_t *trackpriv =
151 container_of( track, libvlc_media_trackpriv_t, t );
152 vlc_atomic_rc_inc( &trackpriv->rc );
153 return track;
156 void
157 libvlc_media_track_release( libvlc_media_track_t *track )
159 libvlc_media_trackpriv_t *trackpriv =
160 container_of( track, libvlc_media_trackpriv_t, t );
162 if( vlc_atomic_rc_dec( &trackpriv->rc ) )
164 libvlc_media_track_clean( track );
165 if( trackpriv->es_id )
166 vlc_es_id_Release( trackpriv->es_id );
167 free( trackpriv );
171 static libvlc_media_tracklist_t *
172 libvlc_media_tracklist_alloc( size_t count )
174 size_t size;
175 if( mul_overflow( count, sizeof(libvlc_media_trackpriv_t *), &size) )
176 return NULL;
177 if( add_overflow( size, sizeof(libvlc_media_tracklist_t), &size) )
178 return NULL;
180 libvlc_media_tracklist_t *list = malloc( size );
181 if( list == NULL )
182 return NULL;
184 list->count = 0;
185 return list;
188 libvlc_media_tracklist_t *
189 libvlc_media_tracklist_from_es_array( es_format_t **es_array,
190 size_t es_count,
191 libvlc_track_type_t type )
193 size_t count = 0;
194 const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
196 for( size_t i = 0; i < es_count; ++i )
198 if( es_array[i]->i_cat == cat )
199 count++;
202 libvlc_media_tracklist_t *list = libvlc_media_tracklist_alloc( count );
204 if( count == 0 || list == NULL )
205 return list;
207 for( size_t i = 0; i < es_count; ++i )
209 if( es_array[i]->i_cat == cat )
211 libvlc_media_trackpriv_t *trackpriv = libvlc_media_trackpriv_new();
212 if( trackpriv == NULL )
214 libvlc_media_tracklist_delete( list );
215 return NULL;
217 list->tracks[list->count++] = trackpriv;
218 libvlc_media_trackpriv_from_es( trackpriv, es_array[i] );
222 return list;
225 static void
226 libvlc_media_trackpriv_from_player_track( libvlc_media_trackpriv_t *trackpriv,
227 const struct vlc_player_track *track )
229 libvlc_media_trackpriv_from_es( trackpriv, &track->fmt );
231 trackpriv->es_id = vlc_es_id_Hold( track->es_id );
233 trackpriv->t.psz_id = vlc_es_id_GetStrId( track->es_id );
234 trackpriv->t.id_stable = vlc_es_id_IsStrIdStable( track->es_id );
235 trackpriv->t.psz_name = strdup( track->name );
236 trackpriv->t.selected = track->selected;
239 libvlc_media_track_t *
240 libvlc_media_track_create_from_player_track( const struct vlc_player_track *track )
242 libvlc_media_trackpriv_t *trackpriv = libvlc_media_trackpriv_new();
243 if( trackpriv == NULL )
244 return NULL;
245 libvlc_media_trackpriv_from_player_track( trackpriv, track );
246 return &trackpriv->t;
249 libvlc_media_tracklist_t *
250 libvlc_media_tracklist_from_player( vlc_player_t *player,
251 libvlc_track_type_t type )
253 const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
255 size_t count = vlc_player_GetTrackCount( player, cat );
256 libvlc_media_tracklist_t *list = libvlc_media_tracklist_alloc( count );
258 if( count == 0 || list == NULL )
259 return NULL;
261 for( size_t i = 0; i < count; ++i )
263 const struct vlc_player_track *track =
264 vlc_player_GetTrackAt( player, cat, i );
265 assert( track );
267 libvlc_media_trackpriv_t *trackpriv = libvlc_media_trackpriv_new();
268 if( trackpriv == NULL )
270 libvlc_media_tracklist_delete( list );
271 return NULL;
273 list->tracks[list->count++] = trackpriv;
274 libvlc_media_trackpriv_from_player_track( trackpriv, track );
277 return list;
280 size_t
281 libvlc_media_tracklist_count( const libvlc_media_tracklist_t *list )
283 return list->count;
286 libvlc_media_track_t *
287 libvlc_media_tracklist_at( libvlc_media_tracklist_t *list, size_t idx )
289 assert( idx < list->count );
290 return &list->tracks[idx]->t;
293 void
294 libvlc_media_tracklist_delete( libvlc_media_tracklist_t *list )
296 for( size_t i = 0; i < list->count; ++i )
298 libvlc_media_trackpriv_t *trackpriv = list->tracks[i];
299 libvlc_media_track_release( &trackpriv->t );
301 free( list );