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
assenc.c
Go to the documentation of this file.
1
/*
2
* SSA/ASS muxer
3
* Copyright (c) 2008 Michael Niedermayer
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "
avformat.h
"
23
#include "
internal.h
"
24
25
typedef
struct
ASSContext
{
26
unsigned
int
extra_index
;
27
int
write_ts
;
// 0: ssa (timing in payload), 1: ass (matroska like)
28
}
ASSContext
;
29
30
static
int
write_header
(
AVFormatContext
*
s
)
31
{
32
ASSContext
*ass = s->
priv_data
;
33
AVCodecContext
*avctx= s->
streams
[0]->
codec
;
34
uint8_t
*last= NULL;
35
36
if
(s->
nb_streams
!= 1 || (avctx->
codec_id
!=
AV_CODEC_ID_SSA
&&
37
avctx->
codec_id
!=
AV_CODEC_ID_ASS
)) {
38
av_log
(s,
AV_LOG_ERROR
,
"Exactly one ASS/SSA stream is needed.\n"
);
39
return
-1;
40
}
41
ass->
write_ts
= avctx->
codec_id
==
AV_CODEC_ID_ASS
;
42
avpriv_set_pts_info
(s->
streams
[0], 64, 1, 100);
43
44
while
(ass->
extra_index
< avctx->
extradata_size
){
45
uint8_t
*p = avctx->
extradata
+ ass->
extra_index
;
46
uint8_t
*
end
= strchr(p,
'\n'
);
47
if
(!end) end= avctx->
extradata
+ avctx->
extradata_size
;
48
else
end++;
49
50
avio_write
(s->
pb
, p, end-p);
51
ass->
extra_index
+= end-p;
52
53
if
(last && !memcmp(last,
"[Events]"
, 8))
54
break
;
55
last=p;
56
}
57
58
avio_flush
(s->
pb
);
59
60
return
0;
61
}
62
63
static
int
write_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
64
{
65
ASSContext
*ass = s->
priv_data
;
66
67
if
(ass->
write_ts
) {
68
long
int
layer;
69
char
*p;
70
int64_t
start
= pkt->
pts
;
71
int64_t
end
= start + pkt->
duration
;
72
int
hh1, mm1, ss1, ms1;
73
int
hh2, mm2, ss2, ms2;
74
75
p = pkt->
data
+ strcspn(pkt->
data
,
","
) + 1;
// skip ReadOrder
76
layer = strtol(p, &p, 10);
77
if
(*p ==
','
)
78
p++;
79
hh1 = (int)(start / 360000); mm1 = (int)(start / 6000) % 60;
80
hh2 = (int)(end / 360000); mm2 = (int)(end / 6000) % 60;
81
ss1 = (int)(start / 100) % 60; ms1 = (int)(start % 100);
82
ss2 = (int)(end / 100) % 60; ms2 = (int)(end % 100);
83
if
(hh1 > 9) hh1 = 9, mm1 = 59, ss1 = 59, ms1 = 99;
84
if
(hh2 > 9) hh2 = 9, mm2 = 59, ss2 = 59, ms2 = 99;
85
avio_printf
(s->
pb
,
"Dialogue: %ld,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n"
,
86
layer, hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, p);
87
}
else
{
88
avio_write
(s->
pb
, pkt->
data
, pkt->
size
);
89
}
90
return
0;
91
}
92
93
static
int
write_trailer
(
AVFormatContext
*
s
)
94
{
95
ASSContext
*ass = s->
priv_data
;
96
AVCodecContext
*avctx= s->
streams
[0]->
codec
;
97
98
avio_write
(s->
pb
, avctx->
extradata
+ ass->
extra_index
,
99
avctx->
extradata_size
- ass->
extra_index
);
100
101
return
0;
102
}
103
104
AVOutputFormat
ff_ass_muxer
= {
105
.
name
=
"ass"
,
106
.long_name =
NULL_IF_CONFIG_SMALL
(
"SSA (SubStation Alpha) subtitle"
),
107
.mime_type =
"text/x-ssa"
,
108
.extensions =
"ass,ssa"
,
109
.priv_data_size =
sizeof
(
ASSContext
),
110
.subtitle_codec =
AV_CODEC_ID_SSA
,
111
.
write_header
=
write_header
,
112
.
write_packet
=
write_packet
,
113
.
write_trailer
=
write_trailer
,
114
.
flags
=
AVFMT_GLOBALHEADER
|
AVFMT_NOTIMESTAMPS
|
AVFMT_TS_NONSTRICT
,
115
};
Generated on Wed Jul 10 2013 23:47:55 for FFmpeg by
1.8.2