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
samidec.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
* SAMI subtitle decoder
24
* @see http://msdn.microsoft.com/en-us/library/ms971327.aspx
25
*/
26
27
#include "
ass.h
"
28
#include "
libavutil/avstring.h
"
29
#include "
libavutil/bprint.h
"
30
31
typedef
struct
{
32
AVBPrint
source
;
33
AVBPrint
content
;
34
AVBPrint
full
;
35
}
SAMIContext
;
36
37
static
int
sami_paragraph_to_ass
(
AVCodecContext
*avctx,
const
char
*
src
)
38
{
39
SAMIContext
*sami = avctx->
priv_data
;
40
int
ret
= 0;
41
char
*
tag
=
NULL
;
42
char
*dupsrc =
av_strdup
(src);
43
char
*p = dupsrc;
44
45
av_bprint_clear
(&sami->
content
);
46
for
(;;) {
47
char
*saveptr =
NULL
;
48
int
prev_chr_is_space = 0;
49
AVBPrint *dst = &sami->
content
;
50
51
/* parse & extract paragraph tag */
52
p =
av_stristr
(p,
"<P"
);
53
if
(!p)
54
break
;
55
if
(p[2] !=
'>'
&& !
av_isspace
(p[2])) {
// avoid confusion with tags such as <PRE>
56
p++;
57
continue
;
58
}
59
if
(dst->len)
// add a separator with the previous paragraph if there was one
60
av_bprintf
(dst,
"\\N"
);
61
tag =
av_strtok
(p,
">"
, &saveptr);
62
if
(!tag || !saveptr)
63
break
;
64
p = saveptr;
65
66
/* check if the current paragraph is the "source" (speaker name) */
67
if
(
av_stristr
(tag,
"ID=Source"
) ||
av_stristr
(tag,
"ID=\"Source\""
)) {
68
dst = &sami->
source
;
69
av_bprint_clear
(dst);
70
}
71
72
/* if empty event -> skip subtitle */
73
while
(
av_isspace
(*p))
74
p++;
75
if
(!strncmp(p,
" "
, 6)) {
76
ret = -1;
77
goto
end
;
78
}
79
80
/* extract the text, stripping most of the tags */
81
while
(*p) {
82
if
(*p ==
'<'
) {
83
if
(!
av_strncasecmp
(p,
"<P"
, 2) && (p[2] ==
'>'
||
av_isspace
(p[2])))
84
break
;
85
if
(!
av_strncasecmp
(p,
"<BR"
, 3))
86
av_bprintf
(dst,
"\\N"
);
87
p++;
88
while
(*p && *p !=
'>'
)
89
p++;
90
if
(!*p)
91
break
;
92
if
(*p ==
'>'
)
93
p++;
94
continue
;
95
}
96
if
(!
av_isspace
(*p))
97
av_bprint_chars
(dst, *p, 1);
98
else
if
(!prev_chr_is_space)
99
av_bprint_chars
(dst,
' '
, 1);
100
prev_chr_is_space =
av_isspace
(*p);
101
p++;
102
}
103
}
104
105
av_bprint_clear
(&sami->
full
);
106
if
(sami->
source
.len)
107
av_bprintf
(&sami->
full
,
"{\\i1}%s{\\i0}\\N"
, sami->
source
.str);
108
av_bprintf
(&sami->
full
,
"%s"
, sami->
content
.str);
109
110
end
:
111
av_free
(dupsrc);
112
return
ret
;
113
}
114
115
static
int
sami_decode_frame
(
AVCodecContext
*avctx,
116
void
*
data
,
int
*got_sub_ptr,
AVPacket
*avpkt)
117
{
118
AVSubtitle
*sub =
data
;
119
const
char
*ptr = avpkt->
data
;
120
SAMIContext
*sami = avctx->
priv_data
;
121
122
if
(ptr && avpkt->
size
> 0 && !
sami_paragraph_to_ass
(avctx, ptr)) {
123
int
ts_start =
av_rescale_q
(avpkt->
pts
, avctx->
time_base
, (
AVRational
){1,100});
124
int
ts_duration = avpkt->
duration
!= -1 ?
125
av_rescale_q
(avpkt->
duration
, avctx->
time_base
, (
AVRational
){1,100}) : -1;
126
int
ret
=
ff_ass_add_rect_bprint
(sub, &sami->full, ts_start, ts_duration);
127
if
(
ret
< 0)
128
return
ret
;
129
}
130
*got_sub_ptr = sub->num_rects > 0;
131
return
avpkt->size;
132
}
133
134
static
av_cold
int
sami_init
(
AVCodecContext
*avctx)
135
{
136
SAMIContext
*sami = avctx->
priv_data
;
137
av_bprint_init
(&sami->
source
, 0, 2048);
138
av_bprint_init
(&sami->
content
, 0, 2048);
139
av_bprint_init
(&sami->
full
, 0, 2048);
140
return
ff_ass_subtitle_header_default
(avctx);
141
}
142
143
static
av_cold
int
sami_close
(
AVCodecContext
*avctx)
144
{
145
SAMIContext
*sami = avctx->
priv_data
;
146
av_bprint_finalize
(&sami->
source
,
NULL
);
147
av_bprint_finalize
(&sami->
content
,
NULL
);
148
av_bprint_finalize
(&sami->
full
,
NULL
);
149
return
0;
150
}
151
152
AVCodec
ff_sami_decoder
= {
153
.
name
=
"sami"
,
154
.long_name =
NULL_IF_CONFIG_SMALL
(
"SAMI subtitle"
),
155
.type =
AVMEDIA_TYPE_SUBTITLE
,
156
.id =
AV_CODEC_ID_SAMI
,
157
.priv_data_size =
sizeof
(
SAMIContext
),
158
.
init
=
sami_init
,
159
.close =
sami_close
,
160
.
decode
=
sami_decode_frame
,
161
};
Generated on Sun Mar 8 2015 02:34:59 for FFmpeg by
1.8.2