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
libavcodec
jacosubdec.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
* JACOsub subtitle decoder
24
* @see http://unicorn.us.com/jacosub/jscripts.html
25
*/
26
27
#include <
time.h
>
28
#include "
ass.h
"
29
#include "
jacosub.h
"
30
#include "
libavutil/avstring.h
"
31
#include "
libavutil/bprint.h
"
32
33
#undef time
34
35
static
int
insert_text
(
AVBPrint
*
dst
,
const
char
*in,
const
char
*
arg
)
36
{
37
av_bprintf
(dst,
"%s"
, arg);
38
return
0;
39
}
40
41
static
int
insert_datetime
(
AVBPrint
*
dst
,
const
char
*in,
const
char
*
arg
)
42
{
43
char
buf[16] = {0};
44
time_t now = time(0);
45
struct
tm ltime;
46
47
#if HAVE_LOCALTIME_R
48
localtime_r
(&now, <ime);
49
#else
50
ltime = *localtime(&now);
51
#endif
52
strftime(buf,
sizeof
(buf), arg, <ime);
53
av_bprintf
(dst,
"%s"
, buf);
54
return
0;
55
}
56
57
static
int
insert_color
(
AVBPrint
*
dst
,
const
char
*in,
const
char
*
arg
)
58
{
59
return
1;
// skip id
60
}
61
62
static
int
insert_font
(
AVBPrint
*
dst
,
const
char
*in,
const
char
*
arg
)
63
{
64
return
1;
// skip id
65
}
66
67
static
const
struct
{
68
const
char
*
from
;
69
const
char
*
arg
;
70
int (*
func
)(
AVBPrint
*
dst
,
const
char
*in,
const
char
*
arg
);
71
}
ass_codes_map
[] = {
72
{
"\\~"
,
"~"
,
insert_text
},
// tilde doesn't need escaping
73
{
"~"
,
"{\\h}"
,
insert_text
},
// hard space
74
{
"\\n"
,
"\\N"
,
insert_text
},
// newline
75
{
"\\D"
,
"%d %b %Y"
,
insert_datetime
},
// current date
76
{
"\\T"
,
"%H:%M"
,
insert_datetime
},
// current time
77
{
"\\N"
,
"{\\r}"
,
insert_text
},
// reset to default style
78
{
"\\I"
,
"{\\i1}"
,
insert_text
},
// italic on
79
{
"\\i"
,
"{\\i0}"
,
insert_text
},
// italic off
80
{
"\\B"
,
"{\\b1}"
,
insert_text
},
// bold on
81
{
"\\b"
,
"{\\b0}"
,
insert_text
},
// bold off
82
{
"\\U"
,
"{\\u1}"
,
insert_text
},
// underline on
83
{
"\\u"
,
"{\\u0}"
,
insert_text
},
// underline off
84
{
"\\C"
,
""
,
insert_color
},
// TODO: color
85
{
"\\F"
,
""
,
insert_font
},
// TODO: font
86
};
87
88
enum
{
89
ALIGN_VB
= 1<<0,
// vertical bottom, default
90
ALIGN_VM
= 1<<1,
// vertical middle
91
ALIGN_VT
= 1<<2,
// vertical top
92
ALIGN_JC
= 1<<3,
// justify center, default
93
ALIGN_JL
= 1<<4,
// justify left
94
ALIGN_JR
= 1<<5,
// justify right
95
};
96
97
static
void
jacosub_to_ass
(
AVCodecContext
*avctx,
AVBPrint
*
dst
,
const
char
*src)
98
{
99
int
i, valign = 0, halign = 0;
100
char
c
=
av_toupper
(*src);
101
char
directives[128] = {0};
102
103
/* extract the optional directives */
104
if
((c >=
'A'
&& c <=
'Z'
) || c ==
'['
) {
105
char
*p = directives;
106
char
*pend = directives +
sizeof
(directives) - 1;
107
108
do
*p++ =
av_toupper
(*src++);
109
while
(*src && !
jss_whitespace
(*src) && p < pend);
110
*p = 0;
111
src =
jss_skip_whitespace
(src);
112
}
113
114
/* handle directives (TODO: handle more of them, and more reliably) */
115
if
(strstr(directives,
"VB"
)) valign =
ALIGN_VB
;
116
else
if
(strstr(directives,
"VM"
)) valign =
ALIGN_VM
;
117
else
if
(strstr(directives,
"VT"
)) valign =
ALIGN_VT
;
118
if
(strstr(directives,
"JC"
)) halign =
ALIGN_JC
;
119
else
if
(strstr(directives,
"JL"
)) halign =
ALIGN_JL
;
120
else
if
(strstr(directives,
"JR"
)) halign =
ALIGN_JR
;
121
if
(valign || halign) {
122
if
(!valign) valign =
ALIGN_VB
;
123
if
(!halign) halign =
ALIGN_JC
;
124
switch
(valign | halign) {
125
case
ALIGN_VB
|
ALIGN_JL
:
av_bprintf
(dst,
"{\\an1}"
);
break
;
// bottom left
126
case
ALIGN_VB
|
ALIGN_JC
:
av_bprintf
(dst,
"{\\an2}"
);
break
;
// bottom center
127
case
ALIGN_VB
|
ALIGN_JR
:
av_bprintf
(dst,
"{\\an3}"
);
break
;
// bottom right
128
case
ALIGN_VM
|
ALIGN_JL
:
av_bprintf
(dst,
"{\\an4}"
);
break
;
// middle left
129
case
ALIGN_VM
|
ALIGN_JC
:
av_bprintf
(dst,
"{\\an5}"
);
break
;
// middle center
130
case
ALIGN_VM
|
ALIGN_JR
:
av_bprintf
(dst,
"{\\an6}"
);
break
;
// middle right
131
case
ALIGN_VT
|
ALIGN_JL
:
av_bprintf
(dst,
"{\\an7}"
);
break
;
// top left
132
case
ALIGN_VT
|
ALIGN_JC
:
av_bprintf
(dst,
"{\\an8}"
);
break
;
// top center
133
case
ALIGN_VT
|
ALIGN_JR
:
av_bprintf
(dst,
"{\\an9}"
);
break
;
// top right
134
}
135
}
136
137
/* process timed line */
138
while
(*src && *src !=
'\n'
) {
139
140
/* text continue on the next line */
141
if
(src[0] ==
'\\'
&& src[1] ==
'\n'
) {
142
src += 2;
143
while
(
jss_whitespace
(*src))
144
src++;
145
continue
;
146
}
147
148
/* special character codes */
149
for
(i = 0; i <
FF_ARRAY_ELEMS
(
ass_codes_map
); i++) {
150
const
char
*
from
=
ass_codes_map
[i].from;
151
const
char
*
arg
=
ass_codes_map
[i].arg;
152
size_t
codemap_len = strlen(from);
153
154
if
(!strncmp(src, from, codemap_len)) {
155
src += codemap_len;
156
src +=
ass_codes_map
[i].func(dst, src, arg);
157
break
;
158
}
159
}
160
161
/* simple char copy */
162
if
(i ==
FF_ARRAY_ELEMS
(
ass_codes_map
))
163
av_bprintf
(dst,
"%c"
, *src++);
164
}
165
av_bprintf
(dst,
"\r\n"
);
166
}
167
168
static
int
jacosub_decode_frame
(
AVCodecContext
*avctx,
169
void
*
data
,
int
*got_sub_ptr,
AVPacket
*avpkt)
170
{
171
AVSubtitle
*sub =
data
;
172
const
char
*ptr = avpkt->
data
;
173
174
if
(avpkt->
size
<= 0)
175
goto
end
;
176
177
if
(*ptr) {
178
AVBPrint
buffer
;
179
char
*dec_sub;
180
181
// skip timers
182
ptr =
jss_skip_whitespace
(ptr);
183
ptr = strchr(ptr,
' '
);
if
(!ptr)
goto
end
; ptr++;
184
ptr = strchr(ptr,
' '
);
if
(!ptr)
goto
end
; ptr++;
185
186
av_bprint_init
(&buffer,
JSS_MAX_LINESIZE
,
JSS_MAX_LINESIZE
);
187
jacosub_to_ass
(avctx, &buffer, ptr);
188
av_bprint_finalize
(&buffer, &dec_sub);
189
ff_ass_add_rect
(sub, dec_sub, avpkt->
pts
, avpkt->
duration
, 0);
190
av_free
(dec_sub);
191
}
192
193
end
:
194
*got_sub_ptr = sub->
num_rects
> 0;
195
return
avpkt->
size
;
196
}
197
198
AVCodec
ff_jacosub_decoder
= {
199
.
name
=
"jacosub"
,
200
.long_name =
NULL_IF_CONFIG_SMALL
(
"JACOsub subtitle"
),
201
.type =
AVMEDIA_TYPE_SUBTITLE
,
202
.id =
AV_CODEC_ID_JACOSUB
,
203
.init =
ff_ass_subtitle_header_default
,
204
.decode =
jacosub_decode_frame
,
205
};
Generated on Sat May 25 2013 03:58:35 for FFmpeg by
1.8.2