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 *****************************************************************************/
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
39 libvlc_media_trackpriv_t
*tracks
[];
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
;
59 track
->id_stable
= false;
60 track
->psz_name
= NULL
;
61 track
->selected
= false;
67 track
->i_type
= libvlc_track_unknown
;
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
;
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
;
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
;
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
)
121 trackpriv
->es_id
= NULL
;
122 vlc_atomic_rc_init( &trackpriv
->rc
);
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
:
136 case libvlc_track_video
:
138 case libvlc_track_text
:
139 free( track
->subtitle
->psz_encoding
);
141 case libvlc_track_unknown
:
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
);
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
);
171 static libvlc_media_tracklist_t
*
172 libvlc_media_tracklist_alloc( size_t count
)
175 if( mul_overflow( count
, sizeof(libvlc_media_trackpriv_t
*), &size
) )
177 if( add_overflow( size
, sizeof(libvlc_media_tracklist_t
), &size
) )
180 libvlc_media_tracklist_t
*list
= malloc( size
);
188 libvlc_media_tracklist_t
*
189 libvlc_media_tracklist_from_es_array( es_format_t
**es_array
,
191 libvlc_track_type_t type
)
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
)
202 libvlc_media_tracklist_t
*list
= libvlc_media_tracklist_alloc( count
);
204 if( count
== 0 || list
== NULL
)
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
);
217 list
->tracks
[list
->count
++] = trackpriv
;
218 libvlc_media_trackpriv_from_es( trackpriv
, es_array
[i
] );
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
)
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
)
261 for( size_t i
= 0; i
< count
; ++i
)
263 const struct vlc_player_track
*track
=
264 vlc_player_GetTrackAt( player
, cat
, i
);
267 libvlc_media_trackpriv_t
*trackpriv
= libvlc_media_trackpriv_new();
268 if( trackpriv
== NULL
)
270 libvlc_media_tracklist_delete( list
);
273 list
->tracks
[list
->count
++] = trackpriv
;
274 libvlc_media_trackpriv_from_player_track( trackpriv
, track
);
281 libvlc_media_tracklist_count( const libvlc_media_tracklist_t
*list
)
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
;
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
);