Coverage Report

Created: 2026-09-01 07:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mp4/fragments.c
Line
Count
Source
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
1
{
29
1
    if( p_index )
30
0
    {
31
0
        free( p_index->pi_pos );
32
0
        free( p_index->p_times );
33
0
        free( p_index );
34
0
    }
35
1
}
36
37
mp4_fragments_index_t * MP4_Fragments_Index_New( unsigned i_tracks, unsigned i_num )
38
0
{
39
0
    if( !i_tracks || !i_num || SIZE_MAX / i_num < i_tracks )
40
0
        return NULL;
41
0
    mp4_fragments_index_t *p_index = malloc( sizeof(*p_index) );
42
0
    if( p_index )
43
0
    {
44
0
        p_index->p_times = calloc( (size_t)i_num * i_tracks, sizeof(*p_index->p_times) );
45
0
        p_index->pi_pos = calloc( i_num, sizeof(*p_index->pi_pos) );
46
0
        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
0
        p_index->i_entries = i_num;
52
0
        p_index->i_last_time = 0;
53
0
        p_index->i_tracks = i_tracks;
54
0
    }
55
0
    return p_index;
56
0
}
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
0
{
61
0
    for( size_t i=0; i<p_index->i_entries; i++ )
62
0
    {
63
0
        if( p_index->pi_pos[i] >= i_moof_pos )
64
0
            return p_index->p_times[i * p_index->i_tracks + i_track_index];
65
0
    }
66
0
    return 0;
67
0
}
68
69
stime_t MP4_Fragment_Index_GetTracksDuration( const mp4_fragments_index_t *p_index )
70
0
{
71
0
    return p_index->i_last_time;
72
0
}
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
0
{
99
0
    if( i_movie_timescale == INT64_C( 1000 ) )
100
0
        return time;
101
102
0
    if( time <= INT64_MAX / INT64_C( 1000 ) )
103
0
        return time * INT64_C( 1000 ) / i_movie_timescale;
104
105
    /* overflow */
106
0
    int64_t q = time / i_movie_timescale;
107
0
    int64_t r = time % i_movie_timescale;
108
0
    return q * INT64_C( 1000 ) + r * INT64_C( 1000 ) / i_movie_timescale;
109
0
}
110
111
void MP4_Fragments_Index_Dump( vlc_object_t *p_obj, const mp4_fragments_index_t *p_index,
112
                               uint32_t i_movie_timescale )
113
0
{
114
0
    for( size_t i=0; i<p_index->i_entries; i++ )
115
0
    {
116
0
        char *psz_starts = NULL;
117
118
0
        stime_t i_end;
119
0
        if( i + 1 == p_index->i_entries )
120
0
            i_end = p_index->i_last_time;
121
0
        else
122
0
            i_end = p_index->p_times[(i + 1) * p_index->i_tracks];
123
124
0
        for( unsigned j=0; j<p_index->i_tracks; j++ )
125
0
        {
126
0
            char *psz_start = NULL;
127
0
            if( 0 < asprintf( &psz_start, "%s [%u]%"PRId64"ms ",
128
0
                      (psz_starts) ? psz_starts : "", j,
129
0
                  movietime_to_ms(p_index->p_times[i * p_index->i_tracks + j], i_movie_timescale) ) )
130
0
            {
131
0
                free( psz_starts );
132
0
                psz_starts = psz_start;
133
0
            }
134
0
        }
135
136
0
        msg_Dbg( p_obj, "fragment offset @%"PRId64" %"PRId64"ms, start %s",
137
0
                 p_index->pi_pos[i],
138
0
                 movietime_to_ms( i_end, i_movie_timescale ), psz_starts );
139
140
0
        free( psz_starts );
141
0
    }
142
0
}
143
#endif