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
}
95
if
(!
av_isspace
(*p))
96
av_bprint_chars
(dst, *p, 1);
97
else
if
(!prev_chr_is_space)
98
av_bprint_chars
(dst,
' '
, 1);
99
prev_chr_is_space =
av_isspace
(*p);
100
p++;
101
}
102
}
103
104
av_bprint_clear
(&sami->
full
);
105
if
(sami->
source
.len)
106
av_bprintf
(&sami->
full
,
"{\\i1}%s{\\i0}\\N"
, sami->
source
.str);
107
av_bprintf
(&sami->
full
,
"%s\r\n"
, sami->
content
.str);
108
109
end
:
110
av_free
(dupsrc);
111
return
ret
;
112
}
113
114
static
int
sami_decode_frame
(
AVCodecContext
*avctx,
115
void
*
data
,
int
*got_sub_ptr,
AVPacket
*avpkt)
116
{
117
AVSubtitle
*sub =
data
;
118
const
char
*ptr = avpkt->
data
;
119
SAMIContext
*sami = avctx->
priv_data
;
120
121
if
(ptr && avpkt->
size
> 0 && !
sami_paragraph_to_ass
(avctx, ptr)) {
122
int
ts_start =
av_rescale_q
(avpkt->
pts
, avctx->
time_base
, (
AVRational
){1,100});
123
int
ts_duration = avpkt->
duration
!= -1 ?
124
av_rescale_q
(avpkt->
duration
, avctx->
time_base
, (
AVRational
){1,100}) : -1;
125
ff_ass_add_rect
(sub, sami->full.str, ts_start, ts_duration, 0);
126
}
127
*got_sub_ptr = sub->num_rects > 0;
128
return
avpkt->size;
129
}
130
131
static
av_cold
int
sami_init
(
AVCodecContext
*avctx)
132
{
133
SAMIContext
*sami = avctx->
priv_data
;
134
av_bprint_init
(&sami->
source
, 0, 2048);
135
av_bprint_init
(&sami->
content
, 0, 2048);
136
av_bprint_init
(&sami->
full
, 0, 2048);
137
return
ff_ass_subtitle_header_default
(avctx);
138
}
139
140
static
av_cold
int
sami_close
(
AVCodecContext
*avctx)
141
{
142
SAMIContext
*sami = avctx->
priv_data
;
143
av_bprint_finalize
(&sami->
source
, NULL);
144
av_bprint_finalize
(&sami->
content
, NULL);
145
av_bprint_finalize
(&sami->
full
, NULL);
146
return
0;
147
}
148
149
AVCodec
ff_sami_decoder
= {
150
.
name
=
"sami"
,
151
.long_name =
NULL_IF_CONFIG_SMALL
(
"SAMI subtitle"
),
152
.type =
AVMEDIA_TYPE_SUBTITLE
,
153
.id =
AV_CODEC_ID_SAMI
,
154
.priv_data_size =
sizeof
(
SAMIContext
),
155
.
init
=
sami_init
,
156
.
close
=
sami_close
,
157
.
decode
=
sami_decode_frame
,
158
};
Generated on Sat Jan 25 2014 19:51:54 for FFmpeg by
1.8.2