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