Coverage Report

Created: 2026-10-28 08:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/subtitles.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2012 Clément Bœsch
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg 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 GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#ifndef AVFORMAT_SUBTITLES_H
22
#define AVFORMAT_SUBTITLES_H
23
24
#include <stdint.h>
25
#include <stddef.h>
26
#include "avformat.h"
27
#include "libavutil/bprint.h"
28
#include "avio_internal.h"
29
30
enum sub_sort {
31
    SUB_SORT_TS_POS = 0,    ///< sort by timestamps, then position
32
    SUB_SORT_POS_TS,        ///< sort by position, then timestamps
33
};
34
35
enum ff_utf_type {
36
    FF_UTF_8,       // or other 8 bit encodings
37
    FF_UTF16LE,
38
    FF_UTF16BE,
39
};
40
41
typedef struct {
42
    int type;
43
    AVIOContext *pb;
44
    unsigned char buf[8];
45
    int buf_pos, buf_len;
46
    FFIOContext buf_pb;
47
} FFTextReader;
48
49
/**
50
 * Initialize the FFTextReader from the given AVIOContext. This function will
51
 * read some bytes from pb, and test for UTF-8 or UTF-16 BOMs. Further accesses
52
 * to FFTextReader will read more data from pb.
53
 * If s is not NULL, the user will be warned if a UTF-16 conversion takes place.
54
 *
55
 * The purpose of FFTextReader is to transparently convert read data to UTF-8
56
 * if the stream had a UTF-16 BOM.
57
 *
58
 * @param s Pointer to provide av_log context
59
 * @param r object which will be initialized
60
 * @param pb stream to read from (referenced as long as FFTextReader is in use)
61
 */
62
void ff_text_init_avio(void *s, FFTextReader *r, AVIOContext *pb);
63
64
/**
65
 * Similar to ff_text_init_avio(), but sets it up to read from a bounded buffer.
66
 *
67
 * @param r object which will be initialized
68
 * @param buf buffer to read from (referenced as long as FFTextReader is in use)
69
 * @param size size of buf
70
 */
71
void ff_text_init_buf(FFTextReader *r, const void *buf, size_t size);
72
73
/**
74
 * Return the byte position of the next byte returned by ff_text_r8(). For
75
 * UTF-16 source streams, this will return the original position, but it will
76
 * be incorrect if a codepoint was only partially read with ff_text_r8().
77
 */
78
int64_t ff_text_pos(FFTextReader *r);
79
80
/**
81
 * Return the next byte. The return value is always 0 - 255. Returns 0 on EOF.
82
 * If the source stream is UTF-16, this reads from the stream converted to
83
 * UTF-8. On invalid UTF-16, 0 is returned.
84
 */
85
int ff_text_r8(FFTextReader *r);
86
87
/**
88
 * Return non-zero if EOF was reached.
89
 */
90
int ff_text_eof(FFTextReader *r);
91
92
/**
93
 * Like ff_text_r8(), but don't remove the byte from the buffer.
94
 */
95
int ff_text_peek_r8(FFTextReader *r);
96
97
/**
98
 * Read the given number of bytes (in UTF-8). On error or EOF, \0 bytes are
99
 * written.
100
 */
101
void ff_text_read(FFTextReader *r, char *buf, size_t size);
102
103
typedef struct {
104
    AVPacket **subs;         ///< array of subtitles packets
105
    int nb_subs;            ///< number of subtitles packets
106
    int allocated_size;     ///< allocated size for subs
107
    int current_sub_idx;    ///< current position for the read packet callback
108
    enum sub_sort sort;     ///< sort method to use when finalizing subtitles
109
    int keep_duplicates;    ///< set to 1 to keep duplicated subtitle events
110
} FFDemuxSubtitlesQueue;
111
112
/**
113
 * Insert a new subtitle event.
114
 *
115
 * @param event the subtitle line (not zero terminated) or NULL on not yet available event
116
 * @param len   the length of the event (in strlen() sense, so without '\0')
117
 * @param merge set to 1 if the current event should be concatenated with the
118
 *              previous one instead of adding a new entry, 0 otherwise
119
 */
120
AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q,
121
                                    const uint8_t *event, size_t len, int merge);
122
123
/**
124
 * Same as ff_subtitles_queue_insert but takes an AVBPrint input.
125
 * Avoids common errors like handling incomplete AVBPrint.
126
 */
127
AVPacket *ff_subtitles_queue_insert_bprint(FFDemuxSubtitlesQueue *q,
128
                                           const AVBPrint *event, int merge);
129
/**
130
 * Set missing durations, sort subtitles by PTS (and then byte position), and
131
 * drop duplicated events.
132
 */
133
void ff_subtitles_queue_finalize(void *log_ctx, FFDemuxSubtitlesQueue *q);
134
135
/**
136
 * Generic read_packet() callback for subtitles demuxers using this queue
137
 * system.
138
 */
139
int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt);
140
141
/**
142
 * Update current_sub_idx to emulate a seek. Except the first parameter, it
143
 * matches FFInputFormat->read_seek2 prototypes.
144
 */
145
int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int stream_index,
146
                            int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
147
148
/**
149
 * Remove and destroy all the subtitles packets.
150
 */
151
void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q);
152
153
int ff_subtitles_read_packet(AVFormatContext *s, AVPacket *pkt);
154
155
int ff_subtitles_read_seek(AVFormatContext *s, int stream_index,
156
                           int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
157
158
int ff_subtitles_read_close(AVFormatContext *s);
159
160
/**
161
 * SMIL helper to load next chunk ("<...>" or untagged content) in buf.
162
 *
163
 * @param c cached character, to avoid a backward seek
164
 * @return size of chunk or error, e.g. AVERROR(ENOMEM) on incomplete buf
165
 */
166
int ff_smil_extract_next_text_chunk(FFTextReader *tr, AVBPrint *buf, char *c);
167
168
/**
169
 * SMIL helper to point on the value of an attribute in the given tag.
170
 *
171
 * @param s    SMIL tag ("<...>")
172
 * @param attr the attribute to look for
173
 */
174
const char *ff_smil_get_attr_ptr(const char *s, const char *attr);
175
176
/**
177
 * @brief Same as ff_subtitles_read_text_chunk(), but read from an AVIOContext.
178
 */
179
av_warn_unused_result
180
int ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf);
181
182
/**
183
 * @brief Read a subtitles chunk from FFTextReader.
184
 *
185
 * A chunk is defined by a multiline "event", ending with a second line break.
186
 * The trailing line breaks are trimmed. CRLF are supported.
187
 * Example: "foo\r\nbar\r\n\r\nnext" will print "foo\r\nbar" into buf, and pb
188
 * will focus on the 'n' of the "next" string.
189
 *
190
 * @param tr  I/O context
191
 * @param buf an initialized buf where the chunk is written
192
 * @return 0 on success, error value otherwise, e.g. AVERROR(ENOMEM) if buf is incomplete
193
 *
194
 * @note buf is cleared before writing into it.
195
 */
196
av_warn_unused_result
197
int ff_subtitles_read_text_chunk(FFTextReader *tr, AVBPrint *buf);
198
199
/**
200
 * Get the number of characters to increment to jump to the next line, or to
201
 * the end of the string.
202
 * The function handles the following line breaks schemes:
203
 * LF, CRLF (MS), or standalone CR (old MacOS).
204
 */
205
static av_always_inline int ff_subtitles_next_line(const char *ptr)
206
10.2M
{
207
10.2M
    int n = strcspn(ptr, "\r\n");
208
10.2M
    ptr += n;
209
12.7M
    while (*ptr == '\r') {
210
2.51M
        ptr++;
211
2.51M
        n++;
212
2.51M
    }
213
10.2M
    if (*ptr == '\n')
214
8.36M
        n++;
215
10.2M
    return n;
216
10.2M
}
Unexecuted instantiation: aqtitledec.c:ff_subtitles_next_line
Unexecuted instantiation: assdec.c:ff_subtitles_next_line
img2dec.c:ff_subtitles_next_line
Line
Count
Source
206
59.9k
{
207
59.9k
    int n = strcspn(ptr, "\r\n");
208
59.9k
    ptr += n;
209
115k
    while (*ptr == '\r') {
210
55.7k
        ptr++;
211
55.7k
        n++;
212
55.7k
    }
213
59.9k
    if (*ptr == '\n')
214
48.3k
        n++;
215
59.9k
    return n;
216
59.9k
}
jacosubdec.c:ff_subtitles_next_line
Line
Count
Source
206
24.3k
{
207
24.3k
    int n = strcspn(ptr, "\r\n");
208
24.3k
    ptr += n;
209
42.7k
    while (*ptr == '\r') {
210
18.4k
        ptr++;
211
18.4k
        n++;
212
18.4k
    }
213
24.3k
    if (*ptr == '\n')
214
8.18k
        n++;
215
24.3k
    return n;
216
24.3k
}
Unexecuted instantiation: lrcdec.c:ff_subtitles_next_line
Unexecuted instantiation: mccdec.c:ff_subtitles_next_line
microdvddec.c:ff_subtitles_next_line
Line
Count
Source
206
838
{
207
838
    int n = strcspn(ptr, "\r\n");
208
838
    ptr += n;
209
2.63k
    while (*ptr == '\r') {
210
1.79k
        ptr++;
211
1.79k
        n++;
212
1.79k
    }
213
838
    if (*ptr == '\n')
214
417
        n++;
215
838
    return n;
216
838
}
Unexecuted instantiation: mpeg.c:ff_subtitles_next_line
mpl2dec.c:ff_subtitles_next_line
Line
Count
Source
206
749
{
207
749
    int n = strcspn(ptr, "\r\n");
208
749
    ptr += n;
209
2.60k
    while (*ptr == '\r') {
210
1.85k
        ptr++;
211
1.85k
        n++;
212
1.85k
    }
213
749
    if (*ptr == '\n')
214
107
        n++;
215
749
    return n;
216
749
}
mpsubdec.c:ff_subtitles_next_line
Line
Count
Source
206
6.46M
{
207
6.46M
    int n = strcspn(ptr, "\r\n");
208
6.46M
    ptr += n;
209
8.74M
    while (*ptr == '\r') {
210
2.27M
        ptr++;
211
2.27M
        n++;
212
2.27M
    }
213
6.46M
    if (*ptr == '\n')
214
4.65M
        n++;
215
6.46M
    return n;
216
6.46M
}
Unexecuted instantiation: pjsdec.c:ff_subtitles_next_line
Unexecuted instantiation: rcwtdec.c:ff_subtitles_next_line
Unexecuted instantiation: realtextdec.c:ff_subtitles_next_line
Unexecuted instantiation: samidec.c:ff_subtitles_next_line
Unexecuted instantiation: sccdec.c:ff_subtitles_next_line
Unexecuted instantiation: srtdec.c:ff_subtitles_next_line
stldec.c:ff_subtitles_next_line
Line
Count
Source
206
3.66M
{
207
3.66M
    int n = strcspn(ptr, "\r\n");
208
3.66M
    ptr += n;
209
3.82M
    while (*ptr == '\r') {
210
162k
        ptr++;
211
162k
        n++;
212
162k
    }
213
3.66M
    if (*ptr == '\n')
214
3.64M
        n++;
215
3.66M
    return n;
216
3.66M
}
Unexecuted instantiation: subtitles.c:ff_subtitles_next_line
Unexecuted instantiation: subviewer1dec.c:ff_subtitles_next_line
Unexecuted instantiation: subviewerdec.c:ff_subtitles_next_line
Unexecuted instantiation: tedcaptionsdec.c:ff_subtitles_next_line
Unexecuted instantiation: vplayerdec.c:ff_subtitles_next_line
Unexecuted instantiation: webvttdec.c:ff_subtitles_next_line
217
218
/**
219
 * Read a line of text. Discards line ending characters.
220
 * The function handles the following line breaks schemes:
221
 * LF, CRLF (MS), or standalone CR (old MacOS).
222
 *
223
 * Returns the number of bytes written to buf. Always writes a terminating 0,
224
 * similar as with snprintf.
225
 *
226
 * @note returns a negative error code if a \0 byte is found
227
 */
228
ptrdiff_t ff_subtitles_read_line(FFTextReader *tr, char *buf, size_t size);
229
230
#endif /* AVFORMAT_SUBTITLES_H */