FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
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
21
/**
22
* @file
23
* RealText subtitle demuxer
24
* @see http://service.real.com/help/library/guides/ProductionGuide/prodguide/htmfiles/realtext.htm
25
*/
26
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 Sat May 25 2013 04:01:09 for FFmpeg by
1.8.2