mirror of https://github.com/mpv-player/mpv
Add support for rendering matroska plaintext subtitles with libass.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19649 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
e12a9c7206
commit
cc29cb220f
101
libass/ass_mp.c
101
libass/ass_mp.c
|
@ -2,6 +2,8 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mp_msg.h"
|
||||
|
||||
#include "ass.h"
|
||||
#include "ass_mp.h"
|
||||
|
||||
|
@ -23,23 +25,13 @@ extern int subtitle_autoscale;
|
|||
extern double ass_internal_font_size_coeff;
|
||||
extern void process_force_style(ass_track_t* track);
|
||||
|
||||
/**
|
||||
* \brief Convert subdata to ass_track
|
||||
* \param subdata subtitles struct from subreader
|
||||
* \param fps video framerate
|
||||
* \return newly allocated ass_track, filled with subtitles from subdata
|
||||
*/
|
||||
ass_track_t* ass_read_subdata(sub_data* subdata, double fps) {
|
||||
ass_track_t* ass_default_track() {
|
||||
ass_track_t* track = ass_new_track();
|
||||
ass_style_t* style;
|
||||
ass_event_t* event;
|
||||
subtitle* sub;
|
||||
int sid, eid;
|
||||
int i;
|
||||
int sid;
|
||||
double fs;
|
||||
|
||||
track->track_type = TRACK_TYPE_ASS;
|
||||
track->name = subdata->filename ? strdup(subdata->filename) : 0;
|
||||
track->Timer = 100.;
|
||||
track->PlayResX = 384;
|
||||
track->PlayResY = 288;
|
||||
|
@ -71,22 +63,44 @@ ass_track_t* ass_read_subdata(sub_data* subdata, double fps) {
|
|||
style->ScaleX = 1.;
|
||||
style->ScaleY = 1.;
|
||||
|
||||
for (i = 0; i < subdata->sub_num; ++i) {
|
||||
int len = 0, j;
|
||||
char* p;
|
||||
char* end;
|
||||
sub = subdata->subtitles + i;
|
||||
eid = ass_alloc_event(track);
|
||||
event = track->events + eid;
|
||||
return track;
|
||||
}
|
||||
|
||||
event->Start = sub->start * 10;
|
||||
event->Duration = (sub->end - sub->start) * 10;
|
||||
if (!subdata->sub_uses_time) {
|
||||
event->Start *= 100. / fps;
|
||||
event->Duration *= 100. / fps;
|
||||
}
|
||||
static int check_duplicate_plaintext_event(ass_track_t* track)
|
||||
{
|
||||
int i;
|
||||
ass_event_t* evt = track->events + track->n_events - 1;
|
||||
|
||||
event->Style = sid;
|
||||
for (i = 0; i<track->n_events - 1; ++i) // ignoring last event, it is the one we are comparing with
|
||||
if (track->events[i].Start == evt->Start &&
|
||||
track->events[i].Duration == evt->Duration &&
|
||||
strcmp(track->events[i].Text, evt->Text) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert subtitle to ass_event_t for the given track
|
||||
* \param ass_track_t track
|
||||
* \param sub subtitle to convert
|
||||
* \return event id
|
||||
* note: assumes that subtitle is _not_ fps-based; caller must manually correct
|
||||
* Start and Duration in other case.
|
||||
**/
|
||||
int ass_process_subtitle(ass_track_t* track, subtitle* sub)
|
||||
{
|
||||
int eid;
|
||||
ass_event_t* event;
|
||||
int len = 0, j;
|
||||
char* p;
|
||||
char* end;
|
||||
|
||||
eid = ass_alloc_event(track);
|
||||
event = track->events + eid;
|
||||
|
||||
event->Start = sub->start * 10;
|
||||
event->Duration = (sub->end - sub->start) * 10;
|
||||
event->Style = 0;
|
||||
|
||||
for (j = 0; j < sub->lines; ++j)
|
||||
len += sub->text[j] ? strlen(sub->text[j]) : 0;
|
||||
|
@ -107,6 +121,41 @@ ass_track_t* ass_read_subdata(sub_data* subdata, double fps) {
|
|||
|
||||
p--; // remove last ' '
|
||||
*p = 0;
|
||||
|
||||
if (check_duplicate_plaintext_event(track)) {
|
||||
ass_free_event(track, eid);
|
||||
track->n_events--;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mp_msg(MSGT_GLOBAL, MSGL_V, "plaintext event at %" PRId64 ", +%" PRId64 ": %s \n",
|
||||
(int64_t)event->Start, (int64_t)event->Duration, event->Text);
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Convert subdata to ass_track
|
||||
* \param subdata subtitles struct from subreader
|
||||
* \param fps video framerate
|
||||
* \return newly allocated ass_track, filled with subtitles from subdata
|
||||
*/
|
||||
ass_track_t* ass_read_subdata(sub_data* subdata, double fps) {
|
||||
ass_track_t* track;
|
||||
int i;
|
||||
|
||||
track = ass_default_track();
|
||||
track->name = subdata->filename ? strdup(subdata->filename) : 0;
|
||||
|
||||
for (i = 0; i < subdata->sub_num; ++i) {
|
||||
int eid = ass_process_subtitle(track, subdata->subtitles + i);
|
||||
if (eid < 0)
|
||||
continue;
|
||||
if (!subdata->sub_uses_time) {
|
||||
track->events[eid].Start *= 100. / fps;
|
||||
track->events[eid].Duration *= 100. / fps;
|
||||
}
|
||||
}
|
||||
process_force_style(track);
|
||||
return track;
|
||||
|
|
|
@ -12,6 +12,8 @@ extern int extract_embedded_fonts;
|
|||
extern char **ass_force_style_list;
|
||||
extern int ass_use_margins;
|
||||
|
||||
ass_track_t* ass_default_track();
|
||||
int ass_process_subtitle(ass_track_t* track, subtitle* sub);
|
||||
ass_track_t* ass_read_subdata(sub_data* subdata, double fps);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2323,10 +2323,14 @@ demux_mkv_parse_ass_data (demuxer_t *demuxer)
|
|||
for (i = 0; i < mkv_d->num_tracks; i++)
|
||||
{
|
||||
track = mkv_d->tracks[i];
|
||||
if ((track->type != MATROSKA_TRACK_SUBTITLE) ||
|
||||
(track->subtitle_type != MATROSKA_SUBTYPE_SSA))
|
||||
if (track->type != MATROSKA_TRACK_SUBTITLE)
|
||||
continue;
|
||||
|
||||
track->sh_sub.type = 'a';
|
||||
|
||||
if (track->subtitle_type == MATROSKA_SUBTYPE_SSA)
|
||||
{
|
||||
track->sh_sub.ass_track = ass_new_track();
|
||||
size = track->private_size;
|
||||
m = demux_mkv_decode (track,track->private_data,&buffer,&size,2);
|
||||
if (buffer && m)
|
||||
|
@ -2335,9 +2339,12 @@ demux_mkv_parse_ass_data (demuxer_t *demuxer)
|
|||
track->private_data = buffer;
|
||||
track->private_size = size;
|
||||
}
|
||||
track->sh_sub.type = 'a';
|
||||
track->sh_sub.ass_track = ass_new_track();
|
||||
ass_process_codec_private(track->sh_sub.ass_track, track->private_data, track->private_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
track->sh_sub.ass_track = ass_default_track();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -2811,6 +2818,9 @@ demux_mkv_read_block_lacing (uint8_t *buffer, uint64_t *size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_subtitles(demuxer_t *demuxer, uint64_t timecode, int clear_all);
|
||||
|
||||
static void
|
||||
handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, char *block,
|
||||
int64_t size, uint64_t block_duration, uint64_t timecode)
|
||||
|
@ -2831,6 +2841,7 @@ handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, char *block,
|
|||
ass_process_chunk(track->sh_sub.ass_track, block, size, (long long)timecode, (long long)block_duration);
|
||||
return;
|
||||
}
|
||||
clear_subtitles(demuxer, timecode, 1);
|
||||
#endif
|
||||
|
||||
ptr1 = block;
|
||||
|
@ -2942,6 +2953,13 @@ handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, char *block,
|
|||
mkv_d->clear_subs_at[mkv_d->subs.lines++] = timecode + block_duration;
|
||||
|
||||
sub_utf8 = 1;
|
||||
#ifdef USE_ASS
|
||||
if (ass_enabled) {
|
||||
mkv_d->subs.start = timecode / 10;
|
||||
mkv_d->subs.end = (timecode + block_duration) / 10;
|
||||
ass_process_subtitle(track->sh_sub.ass_track, &mkv_d->subs);
|
||||
} else
|
||||
#endif
|
||||
vo_sub = &mkv_d->subs;
|
||||
vo_osd_changed (OSDTYPE_SUBTITLE);
|
||||
}
|
||||
|
@ -2958,6 +2976,9 @@ clear_subtitles(demuxer_t *demuxer, uint64_t timecode, int clear_all)
|
|||
{
|
||||
lines_cut = mkv_d->subs.lines;
|
||||
mkv_d->subs.lines = 0;
|
||||
#ifdef USE_ASS
|
||||
if (!ass_enabled)
|
||||
#endif
|
||||
if (lines_cut)
|
||||
{
|
||||
vo_sub = &mkv_d->subs;
|
||||
|
@ -2981,6 +3002,9 @@ clear_subtitles(demuxer_t *demuxer, uint64_t timecode, int clear_all)
|
|||
lines_cut = 1;
|
||||
}
|
||||
}
|
||||
#ifdef USE_ASS
|
||||
if (!ass_enabled)
|
||||
#endif
|
||||
if (lines_cut)
|
||||
{
|
||||
vo_sub = &mkv_d->subs;
|
||||
|
|
Loading…
Reference in New Issue