2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "libmpdemux/stheader.h"
33 #include "subassconvert.h"
36 struct ass_track
*ass_track
;
38 bool incomplete_event
;
41 static void free_last_event(ASS_Track
*track
)
43 assert(track
->n_events
> 0);
44 ass_free_event(track
, track
->n_events
- 1);
48 static int init(struct sh_sub
*sh
, struct osd_state
*osd
)
50 struct sd_ass_priv
*ctx
;
52 if (sh
->initialized
) {
55 ctx
= talloc_zero(NULL
, struct sd_ass_priv
);
57 if (sh
->type
== 'a') {
58 ctx
->ass_track
= ass_new_track(osd
->ass_library
);
60 ass_process_codec_private(ctx
->ass_track
, sh
->extradata
,
63 ctx
->ass_track
= mp_ass_default_track(osd
->ass_library
, sh
->opts
);
66 ctx
->vsfilter_aspect
= sh
->type
== 'a';
70 static void decode(struct sh_sub
*sh
, struct osd_state
*osd
, void *data
,
71 int data_len
, double pts
, double duration
)
73 unsigned char *text
= data
;
74 struct sd_ass_priv
*ctx
= sh
->context
;
75 ASS_Track
*track
= ctx
->ass_track
;
77 if (sh
->type
== 'a') { // ssa/ass subs
78 ass_process_chunk(track
, data
, data_len
,
79 (long long)(pts
*1000 + 0.5),
80 (long long)(duration
*1000 + 0.5));
84 if (pts
== MP_NOPTS_VALUE
) {
85 mp_msg(MSGT_SUBREADER
, MSGL_WARN
, "Subtitle without pts, ignored\n");
88 long long ipts
= pts
* 1000 + 0.5;
89 long long iduration
= duration
* 1000 + 0.5;
90 if (ctx
->incomplete_event
) {
91 ctx
->incomplete_event
= false;
92 ASS_Event
*event
= track
->events
+ track
->n_events
- 1;
93 if (ipts
<= event
->Start
)
94 free_last_event(track
);
96 event
->Duration
= ipts
- event
->Start
;
98 // Note: we rely on there being guaranteed 0 bytes after data packets
99 int len
= strlen(text
);
101 // Some tracks use a whitespace (but not empty) packet to mark end
102 // of previous subtitle.
103 for (int i
= 0; i
< len
; i
++)
104 if (!strchr(" \f\n\r\t\v", text
[i
]))
105 goto not_all_whitespace
;
110 subassconvert_subrip(text
, buf
, sizeof(buf
));
111 for (int i
= 0; i
< track
->n_events
; i
++)
112 if (track
->events
[i
].Start
== ipts
113 && (duration
<= 0 || track
->events
[i
].Duration
== iduration
)
114 && strcmp(track
->events
[i
].Text
, buf
) == 0)
115 return; // We've already added this subtitle
118 ctx
->incomplete_event
= true;
120 int eid
= ass_alloc_event(track
);
121 ASS_Event
*event
= track
->events
+ eid
;
123 event
->Duration
= iduration
;
124 event
->Style
= track
->default_style
;
125 event
->Text
= strdup(buf
);
128 static void get_bitmaps(struct sh_sub
*sh
, struct osd_state
*osd
,
129 struct sub_bitmaps
*res
)
131 struct sd_ass_priv
*ctx
= sh
->context
;
132 struct MPOpts
*opts
= osd
->opts
;
134 if (osd
->sub_pts
== MP_NOPTS_VALUE
)
137 double scale
= osd
->normal_scale
;
138 if (ctx
->vsfilter_aspect
&& opts
->ass_vsfilter_aspect_compat
)
139 scale
= osd
->vsfilter_scale
;
140 ASS_Renderer
*renderer
= osd
->ass_renderer
;
141 mp_ass_configure(renderer
, opts
, &osd
->dim
, osd
->unscaled
);
142 ass_set_aspect_ratio(renderer
, scale
, 1);
144 res
->imgs
= ass_render_frame(renderer
, ctx
->ass_track
,
145 osd
->sub_pts
* 1000 + .5, &changed
);
147 res
->bitmap_id
= ++res
->bitmap_pos_id
;
149 res
->bitmap_pos_id
++;
150 res
->type
= SUBBITMAP_LIBASS
;
153 static void reset(struct sh_sub
*sh
, struct osd_state
*osd
)
155 struct sd_ass_priv
*ctx
= sh
->context
;
156 if (ctx
->incomplete_event
)
157 free_last_event(ctx
->ass_track
);
158 ctx
->incomplete_event
= false;
161 static void uninit(struct sh_sub
*sh
)
163 struct sd_ass_priv
*ctx
= sh
->context
;
165 ass_free_track(ctx
->ass_track
);
169 const struct sd_functions sd_ass
= {
172 .get_bitmaps
= get_bitmaps
,
179 struct sh_sub
*sd_ass_create_from_track(struct ass_track
*track
,
180 bool vsfilter_aspect
,
183 struct sh_sub
*sh
= talloc(NULL
, struct sh_sub
);
186 sh
->title
= track
->name
;
187 sh
->sd_driver
= &sd_ass
;
188 struct sd_ass_priv
*ctx
= talloc_zero(sh
, struct sd_ass_priv
);
190 ctx
->ass_track
= track
;
191 ctx
->vsfilter_aspect
= vsfilter_aspect
;
192 sh
->initialized
= true;