FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
microdvddec.c
Go to the documentation of this file.
1
/*
2
* MicroDVD subtitle demuxer
3
* Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org>
4
* Copyright (c) 2012 Clément Bœsch <ubitux@gmail.com>
5
*
6
* This file is part of FFmpeg.
7
*
8
* FFmpeg is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
12
*
13
* FFmpeg is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with FFmpeg; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
*/
22
23
#include "
avformat.h
"
24
#include "
internal.h
"
25
#include "
subtitles.h
"
26
#include "
libavutil/intreadwrite.h
"
27
28
#define MAX_LINESIZE 2048
29
30
31
typedef
struct
{
32
FFDemuxSubtitlesQueue
q
;
33
}
MicroDVDContext
;
34
35
36
static
int
microdvd_probe
(
AVProbeData
*p)
37
{
38
unsigned
char
c
;
39
const
uint8_t
*ptr = p->
buf
;
40
int
i;
41
42
if
(
AV_RB24
(ptr) == 0xEFBBBF)
43
ptr += 3;
/* skip UTF-8 BOM */
44
45
for
(i=0; i<3; i++) {
46
if
(sscanf(ptr,
"{%*d}{}%c"
, &c) != 1 &&
47
sscanf(ptr,
"{%*d}{%*d}%c"
, &c) != 1 &&
48
sscanf(ptr,
"{DEFAULT}{}%c"
, &c) != 1)
49
return
0;
50
ptr += strcspn(ptr,
"\n"
) + 1;
51
}
52
return
AVPROBE_SCORE_MAX
;
53
}
54
55
static
int64_t
get_pts
(
const
char
*
buf
)
56
{
57
int
frame
;
58
char
c
;
59
60
if
(sscanf(buf,
"{%d}{%c"
, &frame, &c) == 2)
61
return
frame
;
62
return
AV_NOPTS_VALUE
;
63
}
64
65
static
int
get_duration
(
const
char
*
buf
)
66
{
67
int
frame_start, frame_end;
68
69
if
(sscanf(buf,
"{%d}{%d}"
, &frame_start, &frame_end) == 2)
70
return
frame_end - frame_start;
71
return
-1;
72
}
73
74
static
int
microdvd_read_header
(
AVFormatContext
*
s
)
75
{
76
AVRational
pts_info = (
AVRational
){ 2997, 125 };
/* default: 23.976 fps */
77
MicroDVDContext
*microdvd = s->
priv_data
;
78
AVStream
*st =
avformat_new_stream
(s, NULL);
79
int
i = 0;
80
char
line
[
MAX_LINESIZE
];
81
82
if
(!st)
83
return
AVERROR
(ENOMEM);
84
85
while
(!
url_feof
(s->
pb
)) {
86
char
*p = line;
87
AVPacket
*sub;
88
int64_t pos =
avio_tell
(s->
pb
);
89
int
len
=
ff_get_line
(s->
pb
, line,
sizeof
(line));
90
91
if
(!len)
92
break
;
93
line[strcspn(line,
"\r\n"
)] = 0;
94
if
(i++ < 3) {
95
int
frame
;
96
double
fps;
97
char
c
;
98
99
if
((sscanf(line,
"{%d}{}%6lf"
, &frame, &fps) == 2 ||
100
sscanf(line,
"{%d}{%*d}%6lf"
, &frame, &fps) == 2)
101
&& frame <= 1 && fps > 3 && fps < 100)
102
pts_info =
av_d2q
(fps, 100000);
103
if
(!st->
codec
->
extradata
&& sscanf(line,
"{DEFAULT}{}%c"
, &c) == 1) {
104
st->
codec
->
extradata
=
av_strdup
(line + 11);
105
if
(!st->
codec
->
extradata
)
106
return
AVERROR
(ENOMEM);
107
st->
codec
->
extradata_size
= strlen(st->
codec
->
extradata
) + 1;
108
continue
;
109
}
110
}
111
#define SKIP_FRAME_ID \
112
p = strchr(p, '}'); \
113
if (!p) { \
114
av_log(s, AV_LOG_WARNING, "Invalid event \"%s\"" \
115
" at line %d\n", line, i); \
116
continue; \
117
} \
118
p++
119
SKIP_FRAME_ID
;
120
SKIP_FRAME_ID
;
121
if
(!*p)
122
continue
;
123
sub =
ff_subtitles_queue_insert
(µdvd->
q
, p, strlen(p), 0);
124
if
(!sub)
125
return
AVERROR
(ENOMEM);
126
sub->
pos
= pos;
127
sub->
pts
=
get_pts
(line);
128
sub->
duration
=
get_duration
(line);
129
}
130
ff_subtitles_queue_finalize
(µdvd->
q
);
131
avpriv_set_pts_info
(st, 64, pts_info.
den
, pts_info.
num
);
132
st->
codec
->
codec_type
=
AVMEDIA_TYPE_SUBTITLE
;
133
st->
codec
->
codec_id
=
AV_CODEC_ID_MICRODVD
;
134
return
0;
135
}
136
137
static
int
microdvd_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
138
{
139
MicroDVDContext
*microdvd = s->
priv_data
;
140
return
ff_subtitles_queue_read_packet
(µdvd->
q
, pkt);
141
}
142
143
static
int
microdvd_read_seek
(
AVFormatContext
*
s
,
int
stream_index,
144
int64_t min_ts, int64_t ts, int64_t max_ts,
int
flags
)
145
{
146
MicroDVDContext
*microdvd = s->
priv_data
;
147
return
ff_subtitles_queue_seek
(µdvd->
q
, s, stream_index,
148
min_ts, ts, max_ts, flags);
149
}
150
151
static
int
microdvd_read_close
(
AVFormatContext
*
s
)
152
{
153
MicroDVDContext
*microdvd = s->
priv_data
;
154
ff_subtitles_queue_clean
(µdvd->
q
);
155
return
0;
156
}
157
158
AVInputFormat
ff_microdvd_demuxer
= {
159
.
name
=
"microdvd"
,
160
.long_name =
NULL_IF_CONFIG_SMALL
(
"MicroDVD subtitle format"
),
161
.priv_data_size =
sizeof
(
MicroDVDContext
),
162
.
read_probe
=
microdvd_probe
,
163
.
read_header
=
microdvd_read_header
,
164
.
read_packet
=
microdvd_read_packet
,
165
.read_seek2 =
microdvd_read_seek
,
166
.
read_close
=
microdvd_read_close
,
167
};
Generated on Wed Jul 10 2013 23:48:01 for FFmpeg by
1.8.2