/src/vlc/modules/demux/mp4/fragments.c
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * fragments.c : MP4 fragments |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001-2015 VLC authors and VideoLAN |
5 | | * |
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. |
10 | | * |
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. |
15 | | * |
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 | | *****************************************************************************/ |
20 | | #ifdef HAVE_CONFIG_H |
21 | | # include "config.h" |
22 | | #endif |
23 | | |
24 | | #include "fragments.h" |
25 | | #include <limits.h> |
26 | | |
27 | | void MP4_Fragments_Index_Delete( mp4_fragments_index_t *p_index ) |
28 | 10.0k | { |
29 | 10.0k | if( p_index ) |
30 | 452 | { |
31 | 452 | free( p_index->pi_pos ); |
32 | 452 | free( p_index->p_times ); |
33 | 452 | free( p_index ); |
34 | 452 | } |
35 | 10.0k | } |
36 | | |
37 | | mp4_fragments_index_t * MP4_Fragments_Index_New( unsigned i_tracks, unsigned i_num ) |
38 | 452 | { |
39 | 452 | if( !i_tracks || !i_num || SIZE_MAX / i_num < i_tracks ) |
40 | 0 | return NULL; |
41 | 452 | mp4_fragments_index_t *p_index = malloc( sizeof(*p_index) ); |
42 | 452 | if( p_index ) |
43 | 452 | { |
44 | 452 | p_index->p_times = calloc( (size_t)i_num * i_tracks, sizeof(*p_index->p_times) ); |
45 | 452 | p_index->pi_pos = calloc( i_num, sizeof(*p_index->pi_pos) ); |
46 | 452 | if( !p_index->p_times || !p_index->pi_pos ) |
47 | 0 | { |
48 | 0 | MP4_Fragments_Index_Delete( p_index ); |
49 | 0 | return NULL; |
50 | 0 | } |
51 | 452 | p_index->i_entries = i_num; |
52 | 452 | p_index->i_last_time = 0; |
53 | 452 | p_index->i_tracks = i_tracks; |
54 | 452 | } |
55 | 452 | return p_index; |
56 | 452 | } |
57 | | |
58 | | stime_t MP4_Fragment_Index_GetTrackStartTime( mp4_fragments_index_t *p_index, |
59 | | unsigned i_track_index, uint64_t i_moof_pos ) |
60 | 106 | { |
61 | 157 | for( size_t i=0; i<p_index->i_entries; i++ ) |
62 | 156 | { |
63 | 156 | if( p_index->pi_pos[i] >= i_moof_pos ) |
64 | 105 | return p_index->p_times[i * p_index->i_tracks + i_track_index]; |
65 | 156 | } |
66 | 1 | return 0; |
67 | 106 | } |
68 | | |
69 | | stime_t MP4_Fragment_Index_GetTracksDuration( const mp4_fragments_index_t *p_index ) |
70 | 245 | { |
71 | 245 | return p_index->i_last_time; |
72 | 245 | } |
73 | | |
74 | | bool MP4_Fragments_Index_Lookup( mp4_fragments_index_t *p_index, stime_t *pi_time, |
75 | | uint64_t *pi_pos, unsigned i_track_index ) |
76 | 0 | { |
77 | 0 | if( *pi_time >= p_index->i_last_time || p_index->i_entries < 1 || |
78 | 0 | i_track_index >= p_index->i_tracks ) |
79 | 0 | return false; |
80 | | |
81 | 0 | for( size_t i=1; i<p_index->i_entries; i++ ) |
82 | 0 | { |
83 | 0 | if( p_index->p_times[i * p_index->i_tracks + i_track_index] > *pi_time ) |
84 | 0 | { |
85 | 0 | *pi_time = p_index->p_times[(i - 1) * p_index->i_tracks + i_track_index]; |
86 | 0 | *pi_pos = p_index->pi_pos[i - 1]; |
87 | 0 | return true; |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | 0 | *pi_time = p_index->p_times[(size_t)(p_index->i_entries - 1) * p_index->i_tracks]; |
92 | 0 | *pi_pos = p_index->pi_pos[p_index->i_entries - 1]; |
93 | 0 | return true; |
94 | 0 | } |
95 | | |
96 | | #ifdef MP4_VERBOSE |
97 | | static inline int64_t movietime_to_ms(stime_t time, uint32_t i_movie_timescale) |
98 | 3.32k | { |
99 | 3.32k | if( i_movie_timescale == INT64_C( 1000 ) ) |
100 | 0 | return time; |
101 | | |
102 | 3.32k | if( time <= INT64_MAX / INT64_C( 1000 ) ) |
103 | 3.31k | return time * INT64_C( 1000 ) / i_movie_timescale; |
104 | | |
105 | | /* overflow */ |
106 | 5 | int64_t q = time / i_movie_timescale; |
107 | 5 | int64_t r = time % i_movie_timescale; |
108 | 5 | return q * INT64_C( 1000 ) + r * INT64_C( 1000 ) / i_movie_timescale; |
109 | 0 | return INT64_C( 1000 ) * time / i_movie_timescale; |
110 | 3.32k | } |
111 | | |
112 | | void MP4_Fragments_Index_Dump( vlc_object_t *p_obj, const mp4_fragments_index_t *p_index, |
113 | | uint32_t i_movie_timescale ) |
114 | 452 | { |
115 | 1.73k | for( size_t i=0; i<p_index->i_entries; i++ ) |
116 | 1.28k | { |
117 | 1.28k | char *psz_starts = NULL; |
118 | | |
119 | 1.28k | stime_t i_end; |
120 | 1.28k | if( i + 1 == p_index->i_entries ) |
121 | 452 | i_end = p_index->i_last_time; |
122 | 830 | else |
123 | 830 | i_end = p_index->p_times[(i + 1) * p_index->i_tracks]; |
124 | | |
125 | 3.32k | for( unsigned j=0; j<p_index->i_tracks; j++ ) |
126 | 2.04k | { |
127 | 2.04k | char *psz_start = NULL; |
128 | 2.04k | if( 0 < asprintf( &psz_start, "%s [%u]%"PRId64"ms ", |
129 | 2.04k | (psz_starts) ? psz_starts : "", j, |
130 | 2.04k | movietime_to_ms(p_index->p_times[i * p_index->i_tracks + j], i_movie_timescale) ) ) |
131 | 2.04k | { |
132 | 2.04k | free( psz_starts ); |
133 | 2.04k | psz_starts = psz_start; |
134 | 2.04k | } |
135 | 2.04k | } |
136 | | |
137 | 1.28k | msg_Dbg( p_obj, "fragment offset @%"PRId64" %"PRId64"ms, start %s", |
138 | 1.28k | p_index->pi_pos[i], |
139 | 1.28k | movietime_to_ms( i_end, i_movie_timescale ), psz_starts ); |
140 | | |
141 | 1.28k | free( psz_starts ); |
142 | 1.28k | } |
143 | 452 | } |
144 | | #endif |