FFmpeg  4.3
mpsubdec.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 /**
22  * @file
23  * MPlayer subtitles format demuxer
24  */
25 
26 #include "avformat.h"
27 #include "internal.h"
28 #include "subtitles.h"
29 
30 #define TSBASE 10000000
31 
32 typedef struct {
34 } MPSubContext;
35 
36 static int mpsub_probe(const AVProbeData *p)
37 {
38  const char *ptr = p->buf;
39  const char *ptr_end = p->buf + p->buf_size;
40 
41  while (ptr < ptr_end) {
42  int inc;
43 
44  if (!memcmp(ptr, "FORMAT=TIME", 11))
46  if (!memcmp(ptr, "FORMAT=", 7))
47  return AVPROBE_SCORE_EXTENSION / 3;
48  inc = ff_subtitles_next_line(ptr);
49  if (!inc)
50  break;
51  ptr += inc;
52  }
53  return 0;
54 }
55 
56 static int parse_line(const char *line, int64_t *value, int64_t *value2)
57 {
58  int vi, p1, p2;
59 
60  for (vi = 0; vi < 2; vi++) {
61  long long intval, fracval;
62  int n = av_sscanf(line, "%lld%n.%lld%n", &intval, &p1, &fracval, &p2);
63  if (n <= 0 || intval < INT64_MIN / TSBASE || intval > INT64_MAX / TSBASE)
64  return AVERROR_INVALIDDATA;
65 
66  intval *= TSBASE;
67 
68  if (n == 2) {
69  if (fracval < 0)
70  return AVERROR_INVALIDDATA;
71  for (;p2 - p1 < 7 + 1; p1--)
72  fracval *= 10;
73  for (;p2 - p1 > 7 + 1; p1++)
74  fracval /= 10;
75  if (intval > 0) intval += fracval;
76  else intval -= fracval;
77  line += p2;
78  } else
79  line += p1;
80 
81  *value = intval;
82 
83  value = value2;
84  }
85 
86  return 0;
87 }
88 
90 {
91  MPSubContext *mpsub = s->priv_data;
92  AVStream *st;
93  AVBPrint buf;
94  AVRational pts_info = (AVRational){ TSBASE, 1 }; // ts based by default
95  int res = 0;
96  int64_t current_pts = 0;
97  int i;
98  int common_factor = 0;
99 
101 
102  while (!avio_feof(s->pb)) {
103  char line[1024];
104  int64_t start, duration;
105  int fps, len = ff_get_line(s->pb, line, sizeof(line));
106 
107  if (!len)
108  break;
109 
110  line[strcspn(line, "\r\n")] = 0;
111 
112  if (sscanf(line, "FORMAT=%d", &fps) == 1 && fps > 3 && fps < 100) {
113  /* frame based timing */
114  pts_info = (AVRational){ TSBASE * fps, 1 };
115  } else if (parse_line(line, &start, &duration) >= 0) {
116  AVPacket *sub;
117  const int64_t pos = avio_tell(s->pb);
118 
119  ff_subtitles_read_chunk(s->pb, &buf);
120  if (buf.len) {
121  sub = ff_subtitles_queue_insert(&mpsub->q, buf.str, buf.len, 0);
122  if (!sub) {
123  res = AVERROR(ENOMEM);
124  goto end;
125  }
126  if ( current_pts < 0 && start < INT64_MIN - current_pts
127  || current_pts > 0 && start > INT64_MAX - current_pts) {
128  res = AVERROR_INVALIDDATA;
129  goto end;
130  }
131  sub->pts = current_pts + start;
132  if (duration < 0 || sub->pts > INT64_MAX - duration) {
133  res = AVERROR_INVALIDDATA;
134  goto end;
135  }
136  sub->duration = duration;
137 
138  common_factor = av_gcd(duration, common_factor);
139  common_factor = av_gcd(sub->pts, common_factor);
140 
141  current_pts = sub->pts + duration;
142  sub->pos = pos;
143  }
144  }
145  }
146 
147  if (common_factor > 1) {
148  common_factor = av_gcd(pts_info.num, common_factor);
149  for (i = 0; i < mpsub->q.nb_subs; i++) {
150  mpsub->q.subs[i].pts /= common_factor;
151  mpsub->q.subs[i].duration /= common_factor;
152  }
153  pts_info.num /= common_factor;
154  }
155 
156  st = avformat_new_stream(s, NULL);
157  if (!st) {
158  res = AVERROR(ENOMEM);
159  goto end;
160  }
161  avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num);
164 
165  ff_subtitles_queue_finalize(s, &mpsub->q);
166 
167 end:
168  if (res < 0)
169  ff_subtitles_queue_clean(&mpsub->q);
170 
171  av_bprint_finalize(&buf, NULL);
172  return res;
173 }
174 
176 {
177  MPSubContext *mpsub = s->priv_data;
178  return ff_subtitles_queue_read_packet(&mpsub->q, pkt);
179 }
180 
181 static int mpsub_read_seek(AVFormatContext *s, int stream_index,
182  int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
183 {
184  MPSubContext *mpsub = s->priv_data;
185  return ff_subtitles_queue_seek(&mpsub->q, s, stream_index,
186  min_ts, ts, max_ts, flags);
187 }
188 
190 {
191  MPSubContext *mpsub = s->priv_data;
192  ff_subtitles_queue_clean(&mpsub->q);
193  return 0;
194 }
195 
197  .name = "mpsub",
198  .long_name = NULL_IF_CONFIG_SMALL("MPlayer subtitles"),
199  .priv_data_size = sizeof(MPSubContext),
203  .read_seek2 = mpsub_read_seek,
205  .extensions = "sub",
206 };
AVInputFormat ff_mpsub_demuxer
Definition: mpsubdec.c:196
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static int mpsub_probe(const AVProbeData *p)
Definition: mpsubdec.c:36
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:375
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4938
void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
Same as ff_subtitles_read_text_chunk(), but read from an AVIOContext.
Definition: subtitles.c:402
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
#define TSBASE
Definition: mpsubdec.c:30
int num
Numerator.
Definition: rational.h:59
void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q)
Remove and destroy all the subtitles packets.
Definition: subtitles.c:302
static AVPacket pkt
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
Format I/O context.
Definition: avformat.h:1351
int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt)
Generic read_packet() callback for subtitles demuxers using this queue system.
Definition: subtitles.c:212
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:373
static int mpsub_read_seek(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Definition: mpsubdec.c:181
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4519
int64_t duration
Definition: movenc.c:63
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
#define AV_BPRINT_SIZE_UNLIMITED
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
unsigned int pos
Definition: spdifenc.c:410
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
Definition: graph2dot.c:48
int64_t av_gcd(int64_t a, int64_t b)
Compute the greatest common divisor of two integer operands.
Definition: mathematics.c:37
static int mpsub_read_header(AVFormatContext *s)
Definition: mpsubdec.c:89
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
Definition: avsscanf.c:962
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:444
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:443
static int parse_line(const char *line, int64_t *value, int64_t *value2)
Definition: mpsubdec.c:56
#define s(width, name)
Definition: cbs_vp9.c:257
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:786
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:527
Stream structure.
Definition: avformat.h:876
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
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:250
AVIOContext * pb
I/O context.
Definition: avformat.h:1393
static int mpsub_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mpsubdec.c:175
double value
Definition: eval.c:98
Rational number (pair of numerator and denominator).
Definition: rational.h:58
static int mpsub_read_close(AVFormatContext *s)
Definition: mpsubdec.c:189
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:451
This structure contains the data a format has to probe a file.
Definition: avformat.h:441
static int64_t pts
#define flags(name, subs,...)
Definition: cbs_av1.c:564
static av_always_inline int ff_subtitles_next_line(const char *ptr)
Get the number of characters to increment to jump to the next line, or to the end of the string...
Definition: subtitles.h:187
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
Main libavformat public API header.
raw UTF-8 text
Definition: codec_id.h:510
AVPacket * subs
array of subtitles packets
Definition: subtitles.h:103
FFDemuxSubtitlesQueue q
Definition: mpsubdec.c:33
int den
Denominator.
Definition: rational.h:60
int len
void * priv_data
Format private data.
Definition: avformat.h:1379
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:650
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:356
AVPacket * ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q, const uint8_t *event, size_t len, int merge)
Insert a new subtitle event.
Definition: subtitles.c:111
This structure stores compressed data.
Definition: packet.h:332
int nb_subs
number of subtitles packets
Definition: subtitles.h:104
void ff_subtitles_queue_finalize(void *log_ctx, FFDemuxSubtitlesQueue *q)
Set missing durations, sort subtitles by PTS (and then byte position), and drop duplicated events...
Definition: subtitles.c:194
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348