FFmpeg
1.2.4
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
realtextdec.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
27
#include "
avformat.h
"
28
#include "
internal.h
"
29
#include "
subtitles.h
"
30
#include "libavutil/avstring.h"
31
#include "libavutil/bprint.h"
32
#include "libavutil/intreadwrite.h"
33
34
typedef
struct
{
35
FFDemuxSubtitlesQueue
q
;
36
}
RealTextContext
;
37
38
static
int
realtext_probe
(
AVProbeData
*p)
39
{
40
const
unsigned
char
*ptr = p->
buf
;
41
42
if
(
AV_RB24
(ptr) == 0xEFBBBF)
43
ptr += 3;
/* skip UTF-8 BOM */
44
return
!
av_strncasecmp
(ptr,
"<window"
, 7) ?
AVPROBE_SCORE_MAX
/2 : 0;
45
}
46
47
static
int
read_ts
(
const
char
*s)
48
{
49
int
hh, mm, ss, ms;
50
51
if
(sscanf(s,
"%u:%u:%u.%u"
, &hh, &mm, &ss, &ms) == 4)
return
(hh*3600 + mm*60 + ss) * 100 + ms;
52
if
(sscanf(s,
"%u:%u:%u"
, &hh, &mm, &ss ) == 3)
return
(hh*3600 + mm*60 + ss) * 100;
53
if
(sscanf(s,
"%u:%u.%u"
, &mm, &ss, &ms) == 3)
return
( mm*60 + ss) * 100 + ms;
54
if
(sscanf(s,
"%u:%u"
, &mm, &ss ) == 2)
return
( mm*60 + ss) * 100;
55
if
(sscanf(s,
"%u.%u"
, &ss, &ms) == 2)
return
( ss) * 100 + ms;
56
return
strtol(s,
NULL
, 10) * 100;
57
}
58
59
static
int
realtext_read_header
(
AVFormatContext
*s)
60
{
61
RealTextContext
*rt = s->
priv_data
;
62
AVStream
*st =
avformat_new_stream
(s,
NULL
);
63
AVBPrint
buf;
64
char
c
= 0;
65
int
res = 0,
duration
=
read_ts
(
"60"
);
// default duration is 60 seconds
66
67
if
(!st)
68
return
AVERROR
(ENOMEM);
69
avpriv_set_pts_info
(st, 64, 1, 100);
70
st->
codec
->
codec_type
=
AVMEDIA_TYPE_SUBTITLE
;
71
st->
codec
->
codec_id
=
AV_CODEC_ID_REALTEXT
;
72
73
av_bprint_init
(&buf, 0,
AV_BPRINT_SIZE_UNLIMITED
);
74
75
while
(!
url_feof
(s->
pb
)) {
76
AVPacket
*sub;
77
const
int64_t pos =
avio_tell
(s->
pb
) - (c != 0);
78
int
n =
ff_smil_extract_next_chunk
(s->
pb
, &buf, &c);
79
80
if
(n == 0)
81
break
;
82
83
if
(!
av_strncasecmp
(buf.str,
"<window"
, 7)) {
84
/* save header to extradata */
85
const
char
*p =
ff_smil_get_attr_ptr
(buf.str,
"duration"
);
86
87
if
(p)
88
duration
=
read_ts
(p);
89
st->
codec
->
extradata
=
av_strdup
(buf.str);
90
if
(!st->
codec
->
extradata
) {
91
res =
AVERROR
(ENOMEM);
92
goto
end
;
93
}
94
st->
codec
->
extradata_size
= buf.len + 1;
95
}
else
{
96
/* if we just read a <time> tag, introduce a new event, otherwise merge
97
* with the previous one */
98
int
merge
= !
av_strncasecmp
(buf.str,
"<time"
, 5) ? 0 : 1;
99
sub =
ff_subtitles_queue_insert
(&rt->
q
, buf.str, buf.len, merge);
100
if
(!sub) {
101
res =
AVERROR
(ENOMEM);
102
goto
end
;
103
}
104
if
(!merge) {
105
const
char
*begin =
ff_smil_get_attr_ptr
(buf.str,
"begin"
);
106
const
char
*
end
=
ff_smil_get_attr_ptr
(buf.str,
"end"
);
107
108
sub->
pos
= pos;
109
sub->
pts
= begin ?
read_ts
(begin) : 0;
110
sub->
duration
= end ? (
read_ts
(end) - sub->
pts
) :
duration
;
111
}
112
}
113
av_bprint_clear
(&buf);
114
}
115
ff_subtitles_queue_finalize
(&rt->
q
);
116
117
end
:
118
av_bprint_finalize
(&buf,
NULL
);
119
return
res;
120
}
121
122
static
int
realtext_read_packet
(
AVFormatContext
*s,
AVPacket
*
pkt
)
123
{
124
RealTextContext
*rt = s->
priv_data
;
125
return
ff_subtitles_queue_read_packet
(&rt->
q
, pkt);
126
}
127
128
static
int
realtext_read_seek
(
AVFormatContext
*s,
int
stream_index,
129
int64_t min_ts, int64_t ts, int64_t max_ts,
int
flags
)
130
{
131
RealTextContext
*rt = s->
priv_data
;
132
return
ff_subtitles_queue_seek
(&rt->
q
, s, stream_index,
133
min_ts, ts, max_ts, flags);
134
}
135
136
static
int
realtext_read_close
(
AVFormatContext
*s)
137
{
138
RealTextContext
*rt = s->
priv_data
;
139
ff_subtitles_queue_clean
(&rt->
q
);
140
return
0;
141
}
142
143
AVInputFormat
ff_realtext_demuxer
= {
144
.
name
=
"realtext"
,
145
.long_name =
NULL_IF_CONFIG_SMALL
(
"RealText subtitle format"
),
146
.priv_data_size =
sizeof
(
RealTextContext
),
147
.
read_probe
=
realtext_probe
,
148
.
read_header
=
realtext_read_header
,
149
.
read_packet
=
realtext_read_packet
,
150
.read_seek2 =
realtext_read_seek
,
151
.
read_close
=
realtext_read_close
,
152
.extensions =
"rt"
,
153
};
Generated on Fri Nov 29 2013 19:15:07 for FFmpeg by
1.8.1.2