Coverage Report

Created: 2023-03-26 07:08

/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
0
{
29
0
    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
0
}
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
void MP4_Fragments_Index_Dump( vlc_object_t *p_obj, const mp4_fragments_index_t *p_index,
98
                               uint32_t i_movie_timescale )
99
0
{
100
0
    for( size_t i=0; i<p_index->i_entries; i++ )
101
0
    {
102
0
        char *psz_starts = NULL;
103
104
0
        stime_t i_end;
105
0
        if( i + 1 == p_index->i_entries )
106
0
            i_end = p_index->i_last_time;
107
0
        else
108
0
            i_end = p_index->p_times[(i + 1) * p_index->i_tracks];
109
110
0
        for( unsigned j=0; j<p_index->i_tracks; j++ )
111
0
        {
112
0
            char *psz_start = NULL;
113
0
            if( 0 < asprintf( &psz_start, "%s [%u]%"PRId64"ms ",
114
0
                      (psz_starts) ? psz_starts : "", j,
115
0
                  INT64_C( 1000 ) * p_index->p_times[i * p_index->i_tracks + j] / i_movie_timescale ) )
116
0
            {
117
0
                free( psz_starts );
118
0
                psz_starts = psz_start;
119
0
            }
120
0
        }
121
122
0
        msg_Dbg( p_obj, "fragment offset @%"PRId64" %"PRId64"ms, start %s",
123
0
                 p_index->pi_pos[i],
124
0
                 INT64_C( 1000 ) * i_end / i_movie_timescale, psz_starts );
125
126
0
        free( psz_starts );
127
0
    }
128
0
}
129
#endif