Coverage Report

Created: 2023-06-07 06:30

/src/vlc/modules/codec/ttml/ttmlpes.h
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * ttmlpes.c : TTML subtitles in EN 303 560 payload
3
 *****************************************************************************
4
 * Copyright (C) 2018 VideoLabs, 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
21
#include <vlc_common.h>
22
#include <vlc_block.h>
23
#include <vlc_stream.h>
24
25
enum
26
{
27
    TTML_UNCOMPRESSED_DOCUMENT = 0x01,
28
    TTML_GZIP_COMPRESSED_DOCUMENT = 0x02,
29
};
30
31
struct ttml_in_pes_ctx
32
{
33
    vlc_tick_t i_offset; /* relative segment offset to apply */
34
    vlc_tick_t i_prev_block_time; /* because blocks are duplicated */
35
    vlc_tick_t i_prev_segment_start_time; /* because content can overlap */
36
};
37
38
static void ttml_in_pes_Init(struct ttml_in_pes_ctx *p)
39
0
{
40
0
    p->i_offset = 0;
41
0
    p->i_prev_block_time = -1;
42
0
    p->i_prev_segment_start_time = -1;
43
0
}
44
45
static inline bool TTML_in_PES(decoder_t *p_dec)
46
0
{
47
0
    return p_dec->fmt_in->i_codec == VLC_CODEC_TTML_TS;
48
0
}
49
50
static block_t * DecompressTTML( decoder_t *p_dec, const uint8_t *p_data, size_t i_data )
51
0
{
52
0
    block_t *p_decomp = NULL;
53
0
    block_t **pp_append = &p_decomp;
54
55
0
    stream_t *s = vlc_stream_MemoryNew( p_dec, (uint8_t *) p_data, i_data, true );
56
0
    if( !s )
57
0
        return NULL;
58
0
    stream_t *p_inflate = vlc_stream_FilterNew( s, "inflate" );
59
0
    if( p_inflate )
60
0
    {
61
0
        for( ;; )
62
0
        {
63
0
            *pp_append = vlc_stream_Block( p_inflate, 64 * 1024 );
64
0
            if( *pp_append == NULL ||
65
0
                (*pp_append)->i_buffer < 64*1024 )
66
0
                break;
67
0
            pp_append = &((*pp_append)->p_next);
68
0
        }
69
0
        s = p_inflate;
70
0
    }
71
0
    vlc_stream_Delete( s );
72
0
    return p_decomp ? block_ChainGather( p_decomp ) : NULL;
73
0
}
74
75
static int ParsePESEncap( decoder_t *p_dec,
76
                          struct ttml_in_pes_ctx *p_ctx,
77
                          int(*pf_decode)(decoder_t *, block_t *),
78
                          block_t *p_block )
79
0
{
80
0
    if( p_block == NULL ) /* No Drain */
81
0
        return VLCDEC_SUCCESS;
82
83
0
    if( p_block->i_buffer < 7 )
84
0
    {
85
0
        block_Release( p_block );
86
0
        return VLC_EGENERIC;
87
0
    }
88
89
0
    if( p_block->i_dts == p_ctx->i_prev_block_time )
90
0
    {
91
0
        block_Release( p_block );
92
0
        return VLC_SUCCESS;
93
0
    }
94
95
0
    int64_t i_segment_base = GetDWBE(p_block->p_buffer);
96
0
    i_segment_base = (i_segment_base << 16) | GetWBE(&p_block->p_buffer[4]);
97
0
    i_segment_base *= 100;
98
0
    uint8_t i_num_segments = p_block->p_buffer[6];
99
0
    size_t i_data = p_block->i_buffer - 7;
100
0
    const uint8_t *p_data = &p_block->p_buffer[7];
101
0
    p_ctx->i_offset = (p_block->i_dts - VLC_TICK_0) - i_segment_base;
102
0
    for( uint8_t i=0; i<i_num_segments; i++ )
103
0
    {
104
0
        if( i_data < 3 )
105
0
            break;
106
0
        uint8_t i_type = p_data[0];
107
0
        uint16_t i_size = GetWBE(&p_data[1]);
108
0
        if( i_size > i_data - 3 )
109
0
            break;
110
0
        block_t *p_segment = NULL;
111
0
        if( i_type == TTML_UNCOMPRESSED_DOCUMENT )
112
0
        {
113
0
            p_segment = block_Alloc( i_size );
114
0
            if( p_segment )
115
0
                memcpy( p_segment->p_buffer, &p_data[3], i_size );
116
0
        }
117
0
        else if( i_type == TTML_GZIP_COMPRESSED_DOCUMENT )
118
0
        {
119
0
            p_segment = DecompressTTML( p_dec, &p_data[3], i_size );
120
0
        }
121
122
0
        if( p_segment )
123
0
        {
124
0
            block_CopyProperties( p_segment, p_block );
125
0
            pf_decode( p_dec, p_segment );
126
0
        }
127
128
0
        p_data += 3 + i_size;
129
0
        i_data -= 3 + i_size;
130
0
    }
131
132
0
    p_ctx->i_prev_block_time = p_block->i_dts;
133
0
    block_Release( p_block );
134
0
    return VLC_SUCCESS;
135
0
}