Coverage Report

Created: 2026-03-07 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mpeg/ts_arib.c
Line
Count
Source
1
/*****************************************************************************
2
 * ts_arib.c : TS demux ARIB specific handling
3
 *****************************************************************************
4
 * Copyright (C) 2017 - VideoLAN Authors
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 General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 *****************************************************************************/
19
#ifdef HAVE_CONFIG_H
20
# include "config.h"
21
#endif
22
23
#include <vlc_common.h>
24
#include <vlc_demux.h>
25
26
#include "timestamps.h"
27
#include "ts_pid.h"
28
#include "ts.h"
29
30
#include "ts_arib.h"
31
32
/*
33
 * ARIB TR-B21
34
 * Logo PNG is 8 bit indexed dans the palette is missing,
35
 * provided as a CLUT. We need to reinject the CLUT as a
36
 * split palette + transparency (as PNG only allows split alpha table)
37
*/
38
39
/* ARIB TR-B14-1 Appendix 1 */
40
static const unsigned char CLUT_to_chunks[] = {
41
    /* size + PLTE */
42
    0x00, 0x00, 0x01, 0x80, 0x50, 0x4c, 0x54, 0x45,
43
    /* DATA ARIB TR-B14-1 Appendix 1 */
44
    0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, /* 0-7 */
45
    0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
46
47
    0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, /* 8-15 */
48
    0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
49
50
    0x00, 0x00, 0x55, 0x00, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x55, 0xaa, /* 16-23 */
51
    0x00, 0x55, 0xff, 0x00, 0xaa, 0x55, 0x00, 0xaa, 0xff, 0x00, 0xff, 0x55,
52
53
    0x00, 0xff, 0xaa, 0x55, 0x00, 0x00, 0x55, 0x00, 0x55, 0x55, 0x00, 0xaa, /* 24-31 */
54
    0x55, 0x00, 0xff, 0x55, 0x55, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0xaa,
55
56
    0x55, 0x55, 0xff, 0x55, 0xaa, 0x00, 0x55, 0xaa, 0x00, 0x55, 0xaa, 0x55, /* 32-39 */
57
    0x55, 0xaa, 0xaa, 0x55, 0xaa, 0xff, 0x55, 0xff, 0x00, 0x55, 0xff, 0x55,
58
59
    0x55, 0xff, 0xff, 0xaa, 0x00, 0x55, 0xaa, 0x00, 0xff, 0xaa, 0x55, 0x00, /* 40-47 */
60
    0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0x55,
61
62
    0xaa, 0xaa, 0xff, 0xaa, 0xff, 0x00, 0xaa, 0xff, 0x55, 0xaa, 0xff, 0xaa, /* 48-55 */
63
    0xaa, 0xff, 0xff, 0xff, 0x00, 0x55, 0xff, 0x00, 0xaa, 0xff, 0x55, 0x00,
64
65
    0xff, 0x55, 0x55, 0xff, 0x55, 0xaa, 0xff, 0x55, 0xff, 0xff, 0xaa, 0x00, /* 56-63 */
66
    0xff, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0xff, 0xaa, 0xff, 0xff, 0xff, 0x55,
67
68
    0xff, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, /* 64-71 */
69
    0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
70
71
    0xff, 0xff, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0xaa, 0x00, /* 72-79 */
72
    0x00, 0x00, 0xaa, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
73
74
    0x00, 0x00, 0x55, 0x00, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x55, 0xaa, /* 80-87 */
75
    0x00, 0x55, 0xff, 0x00, 0xaa, 0x55, 0x00, 0xaa, 0xff, 0x00, 0xff, 0x55,
76
77
    0x00, 0xff, 0xaa, 0x55, 0x00, 0x00, 0x55, 0x00, 0x55, 0x55, 0x00, 0xaa, /* 88-95 */
78
    0x55, 0x00, 0xff, 0x55, 0x55, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0xaa,
79
80
    0x55, 0x55, 0xff, 0x55, 0xaa, 0x00, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0xaa, /* 96-103 */
81
    0x55, 0xaa, 0xff, 0x55, 0xff, 0x00, 0x55, 0xff, 0x55, 0x55, 0xff, 0xaa,
82
83
    0x55, 0xff, 0xff, 0xaa, 0x00, 0x55, 0xaa, 0x00, 0xff, 0xaa, 0x55, 0x00, /* 104-111 */
84
    0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0x55,
85
86
    0xaa, 0xaa, 0xff, 0xaa, 0xff, 0x00, 0xaa, 0xff, 0x55, 0xaa, 0xff, 0xaa, /* 112-119 */
87
    0xaa, 0xff, 0xff, 0xff, 0x00, 0x55, 0xff, 0x00, 0xaa, 0xff, 0x55, 0x00,
88
89
    0xff, 0x55, 0x55, 0xff, 0x55, 0xaa, 0xff, 0x55, 0xff, 0xff, 0xaa, 0x00, /* 120-127 */
90
    0xff, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0xff, 0xaa, 0xff, 0xff, 0xff, 0x55,
91
92
    /* CRC32 (all data including type, without length and crc) . pngcheck output being the lazy way */
93
    0x4f, 0xed, 0xfc, 0x8d,
94
95
    /* Second Chunk */
96
97
    /* size + tRNS */
98
    0x00, 0x00, 0x00, 0x80, 0x74, 0x52, 0x4e, 0x53,
99
100
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-63 */
101
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
102
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
103
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
104
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
105
    0xff, 0xff, 0xff, 0xff,
106
107
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 64-127 */
108
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
109
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
110
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
111
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
112
    0x80, 0x80, 0x80, 0x80,
113
114
    /* CRC32 */
115
    0xfa, 0xe9, 0x51, 0x40,
116
};
117
static const unsigned int CLUT_to_chunks_len = sizeof(CLUT_to_chunks);
118
119
bool ts_arib_inject_png_palette( const uint8_t *p_in, size_t i_in, uint8_t **pp_out, size_t *pi_out )
120
0
{
121
0
    const uint8_t *p_data = p_in;
122
0
    const uint8_t *p_idat = NULL;
123
0
    size_t i_data = i_in - 8;
124
0
    p_data += 8;
125
0
    i_data -= 8;
126
127
0
    while( i_data > 11 )
128
0
    {
129
0
        uint32_t i_len = GetDWBE( p_data );
130
0
        if( i_len > 0x7FFFFFFFU || i_len > i_data - 12 )
131
0
            break;
132
133
0
        uint32_t i_chunk = VLC_FOURCC(p_data[4], p_data[5], p_data[6], p_data[7]);
134
0
        if( i_chunk == VLC_FOURCC('I', 'D', 'A', 'T') )
135
0
        {
136
0
            p_idat = p_data;
137
0
            break;
138
0
        }
139
140
0
        p_data += i_len + 12;
141
0
        i_data -= i_len + 12;
142
0
    }
143
144
0
    if( !p_idat )
145
0
        return false;
146
147
0
    {
148
0
        uint8_t *p_out = *pp_out = malloc( i_in + CLUT_to_chunks_len );
149
0
        if( !p_out )
150
0
            return false;
151
0
        *pi_out = i_in + CLUT_to_chunks_len;
152
153
0
        const size_t i_head = p_data - p_in;
154
0
        memcpy( p_out, p_in, i_head );
155
0
        memcpy( &p_out[i_head], CLUT_to_chunks, CLUT_to_chunks_len );
156
0
        memcpy( &p_out[i_head + CLUT_to_chunks_len], p_data, i_in - i_head );
157
0
    }
158
159
0
    return true;
160
0
}
161
162
163
void ts_arib_logo_dr_Delete( ts_arib_logo_dr_t *p_dr )
164
0
{
165
0
    free( p_dr->p_logo_char );
166
0
    free( p_dr );
167
0
}
168
169
ts_arib_logo_dr_t * ts_arib_logo_dr_Decode( const uint8_t *p_data, size_t i_data )
170
0
{
171
0
    if( i_data < 2 )
172
0
        return NULL;
173
174
0
    ts_arib_logo_dr_t *p_dr = calloc( 1, sizeof(*p_dr) );
175
0
    if( unlikely( p_dr == NULL ) )
176
0
        return NULL;
177
178
0
    p_dr->i_logo_version = p_data[0];
179
0
    switch( p_data[0] )
180
0
    {
181
0
        case 1:
182
0
            if( i_data != 7 )
183
0
                break;
184
0
            p_dr->i_logo_id = ((p_data[1] & 0x01) << 8) | p_data[2];
185
0
            p_dr->i_logo_version = ((p_data[3] & 0x0F) << 8) | p_data[4];
186
0
            p_dr->i_download_data_id = (p_data[5] << 8) | p_data[6];
187
0
            return p_dr;
188
0
        case 2:
189
0
            if( i_data != 3 )
190
0
                break;
191
0
            p_dr->i_logo_id = ((p_data[1] & 0x01) << 8) | p_data[2];
192
0
            return p_dr;
193
0
        case 3:
194
0
            if( i_data <= 2 )
195
0
                break;
196
197
0
            p_dr->p_logo_char = malloc( i_data - 1 );
198
0
            if( unlikely( p_dr->p_logo_char == NULL ) )
199
0
                break;
200
201
0
            p_dr->i_logo_char = i_data - 1;
202
0
            memcpy( p_dr->p_logo_char, &p_data[1], p_dr->i_logo_char );
203
0
            return p_dr;
204
0
        default:
205
0
            break;
206
0
    }
207
208
0
    ts_arib_logo_dr_Delete( p_dr );
209
    return NULL;
210
0
}