subtitles.c
Go to the documentation of this file.
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 #include "avformat.h"
22 #include "subtitles.h"
23 #include "libavutil/avassert.h"
24 #include "libavutil/avstring.h"
25 
27  const uint8_t *event, int len, int merge)
28 {
29  AVPacket *subs, *sub;
30 
31  if (merge && q->nb_subs > 0) {
32  /* merge with previous event */
33 
34  int old_len;
35  sub = &q->subs[q->nb_subs - 1];
36  old_len = sub->size;
37  if (av_grow_packet(sub, len) < 0)
38  return NULL;
39  memcpy(sub->data + old_len, event, len);
40  } else {
41  /* new event */
42 
43  if (q->nb_subs >= INT_MAX/sizeof(*q->subs) - 1)
44  return NULL;
45  subs = av_fast_realloc(q->subs, &q->allocated_size,
46  (q->nb_subs + 1) * sizeof(*q->subs));
47  if (!subs)
48  return NULL;
49  q->subs = subs;
50  sub = &subs[q->nb_subs++];
51  if (av_new_packet(sub, len) < 0)
52  return NULL;
53  sub->flags |= AV_PKT_FLAG_KEY;
54  sub->pts = sub->dts = 0;
55  memcpy(sub->data, event, len);
56  }
57  return sub;
58 }
59 
60 static int cmp_pkt_sub(const void *a, const void *b)
61 {
62  const AVPacket *s1 = a;
63  const AVPacket *s2 = b;
64  if (s1->pts == s2->pts) {
65  if (s1->pos == s2->pos)
66  return 0;
67  return s1->pos > s2->pos ? 1 : -1;
68  }
69  return s1->pts > s2->pts ? 1 : -1;
70 }
71 
73 {
74  int i;
75 
76  qsort(q->subs, q->nb_subs, sizeof(*q->subs), cmp_pkt_sub);
77  for (i = 0; i < q->nb_subs; i++)
78  if (q->subs[i].duration == -1 && i < q->nb_subs - 1)
79  q->subs[i].duration = q->subs[i + 1].pts - q->subs[i].pts;
80 }
81 
83 {
84  AVPacket *sub = q->subs + q->current_sub_idx;
85 
86  if (q->current_sub_idx == q->nb_subs)
87  return AVERROR_EOF;
88  av_copy_packet(pkt, sub);
89 
90  pkt->dts = pkt->pts;
91  q->current_sub_idx++;
92  return 0;
93 }
94 
96  int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
97 {
98  if (flags & AVSEEK_FLAG_BYTE) {
99  return AVERROR(ENOSYS);
100  } else if (flags & AVSEEK_FLAG_FRAME) {
101  if (ts < 0 || ts >= q->nb_subs)
102  return AVERROR(ERANGE);
103  q->current_sub_idx = ts;
104  } else {
105  int i, idx = -1;
106  int64_t min_ts_diff = INT64_MAX;
107  int64_t ts_selected;
108  /* TODO: q->subs[] is sorted by pts so we could do a binary search */
109  for (i = 0; i < q->nb_subs; i++) {
110  int64_t pts = q->subs[i].pts;
111  uint64_t ts_diff = FFABS(pts - ts);
112  if (pts >= min_ts && pts <= max_ts && ts_diff < min_ts_diff) {
113  min_ts_diff = ts_diff;
114  idx = i;
115  }
116  }
117  if (idx < 0)
118  return AVERROR(ERANGE);
119  /* look back in the latest subtitles for overlapping subtitles */
120  ts_selected = q->subs[idx].pts;
121  for (i = idx - 1; i >= 0; i--) {
122  if (q->subs[i].duration <= 0)
123  continue;
124  if (q->subs[i].pts > ts_selected - q->subs[i].duration)
125  idx = i;
126  else
127  break;
128  }
129  q->current_sub_idx = idx;
130  }
131  return 0;
132 }
133 
135 {
136  int i;
137 
138  for (i = 0; i < q->nb_subs; i++)
139  av_free_packet(&q->subs[i]);
140  av_freep(&q->subs);
141  q->nb_subs = q->allocated_size = q->current_sub_idx = 0;
142 }
143 
145 {
146  int i = 0;
147  char end_chr;
148 
149  if (!*c) // cached char?
150  *c = avio_r8(pb);
151  if (!*c)
152  return 0;
153 
154  end_chr = *c == '<' ? '>' : '<';
155  do {
156  av_bprint_chars(buf, *c, 1);
157  *c = avio_r8(pb);
158  i++;
159  } while (*c != end_chr && *c);
160  if (end_chr == '>') {
161  av_bprint_chars(buf, '>', 1);
162  *c = 0;
163  }
164  return i;
165 }
166 
167 const char *ff_smil_get_attr_ptr(const char *s, const char *attr)
168 {
169  int in_quotes = 0;
170  const int len = strlen(attr);
171 
172  while (*s) {
173  while (*s) {
174  if (!in_quotes && av_isspace(*s))
175  break;
176  in_quotes ^= *s == '"'; // XXX: support escaping?
177  s++;
178  }
179  while (av_isspace(*s))
180  s++;
181  if (!av_strncasecmp(s, attr, len) && s[len] == '=')
182  return s + len + 1 + (s[len + 1] == '"');
183  }
184  return NULL;
185 }
186 
187 static inline int is_eol(char c)
188 {
189  return c == '\r' || c == '\n';
190 }
191 
193 {
194  char eol_buf[5];
195  int n = 0, i = 0, nb_eol = 0;
196 
197  av_bprint_clear(buf);
198 
199  for (;;) {
200  char c = avio_r8(pb);
201 
202  if (!c)
203  break;
204 
205  /* ignore all initial line breaks */
206  if (n == 0 && is_eol(c))
207  continue;
208 
209  /* line break buffering: we don't want to add the trailing \r\n */
210  if (is_eol(c)) {
211  nb_eol += c == '\n';
212  if (nb_eol == 2)
213  break;
214  eol_buf[i++] = c;
215  if (i == sizeof(eol_buf) - 1)
216  break;
217  continue;
218  }
219 
220  /* only one line break followed by data: we flush the line breaks
221  * buffer */
222  if (i) {
223  eol_buf[i] = 0;
224  av_bprintf(buf, "%s", eol_buf);
225  i = nb_eol = 0;
226  }
227 
228  av_bprint_chars(buf, c, 1);
229  n++;
230  }
231 }
static int cmp_pkt_sub(const void *a, const void *b)
Definition: subtitles.c:60
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:93
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
int64_t pos
byte position in stream, -1 if unknown
void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
Read a subtitles chunk.
Definition: subtitles.c:192
int av_copy_packet(AVPacket *dst, AVPacket *src)
Copy packet, including contents.
Definition: avpacket.c:236
void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q)
Remove and destroy all the subtitles packets.
Definition: subtitles.c:134
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:222
int allocated_size
allocated size for subs
Definition: subtitles.h:31
AVPacket * ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q, const uint8_t *event, int len, int merge)
Insert a new subtitle event.
Definition: subtitles.c:26
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
Format I/O context.
Definition: avformat.h:944
const char * ff_smil_get_attr_ptr(const char *s, const char *attr)
SMIL helper to point on the value of an attribute in the given tag.
Definition: subtitles.c:167
uint8_t
int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt)
Generic read_packet() callback for subtitles demuxers using this queue system.
Definition: subtitles.c:82
static AVPacket pkt
Definition: demuxing.c:56
#define b
Definition: input.c:42
uint8_t * data
#define AVERROR_EOF
End of file.
Definition: error.h:55
int duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
#define s2
Definition: regdef.h:39
static int is_eol(char c)
Definition: subtitles.c:187
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given block if it is not large enough, otherwise do nothing.
simple assert() macros that are a bit more flexible than ISO C assert().
int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.c:298
int flags
A combination of AV_PKT_FLAG values.
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
Buffer to print data progressively.
Definition: bprint.h:75
int ff_smil_extract_next_chunk(AVIOContext *pb, AVBPrint *buf, char *c)
SMIL helper to load next chunk ("<...>" or untagged content) in buf.
Definition: subtitles.c:144
void ff_subtitles_queue_finalize(FFDemuxSubtitlesQueue *q)
Set missing durations and sort subtitles by PTS, and then byte position.
Definition: subtitles.c:72
#define FFABS(a)
Definition: common.h:53
NULL
Definition: eval.c:55
int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Update current_sub_idx to emulate a seek.
Definition: subtitles.c:95
void * buf
Definition: avisynth_c.h:594
synthesis window for stochastic i
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition: avformat.h:1744
#define s1
Definition: regdef.h:38
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static void merge(GetBitContext *gb, uint8_t *dst, uint8_t *src, int size)
Merge two consequent lists of equal size depending on bits read.
static int flags
Definition: cpu.c:23
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:185
Main libavformat public API header.
static double c[64]
AVPacket * subs
array of subtitles packets
Definition: subtitles.h:29
int av_grow_packet(AVPacket *pkt, int grow_by)
Increase packet size, correctly zeroing padding.
Definition: avpacket.c:105
int current_sub_idx
current position for the read packet callback
Definition: subtitles.h:32
int len
#define AVSEEK_FLAG_FRAME
seeking based on frame number
Definition: avformat.h:1746
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
This structure stores compressed data.
int nb_subs
number of subtitles packets
Definition: subtitles.h:30
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition: bprint.c:116