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 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
;
61 track
->id_stable
= false;
62 track
->psz_name
= NULL
;
63 track
->selected
= false;
69 track
->i_type
= libvlc_track_unknown
;
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
;
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
;
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
;
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
:
124 case libvlc_track_video
:
126 case libvlc_track_text
:
127 free( track
->subtitle
->psz_encoding
);
129 case libvlc_track_unknown
:
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
);
146 static libvlc_media_tracklist_t
*
147 libvlc_media_tracklist_alloc( size_t count
)
150 if( mul_overflow( count
, sizeof(libvlc_media_trackpriv_t
), &size
) )
152 if( add_overflow( size
, sizeof(libvlc_media_tracklist_t
), &size
) )
155 libvlc_media_tracklist_t
*list
= malloc( size
);
163 libvlc_media_tracklist_t
*
164 libvlc_media_tracklist_from_es_array( es_format_t
**es_array
,
166 libvlc_track_type_t type
)
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
)
177 libvlc_media_tracklist_t
*list
= libvlc_media_tracklist_alloc( count
);
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
++],
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
)
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
);
232 libvlc_media_trackpriv_t
*trackpriv
= &list
->tracks
[i
];
233 libvlc_media_trackpriv_from_player_track( trackpriv
, track
);
240 libvlc_media_tracklist_count( const libvlc_media_tracklist_t
*list
)
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
;
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
);