mirror of https://github.com/mpv-player/mpv
sub: turn subassconvert_ functions into sub converters
This means subassconvert.c is split in sd_srt.c and sd_microdvd.c. Now this code is involved in the sub conversion chain like sd_movtext is. The invocation of the converter in sd_ass.c is removed. This requires some other changes to make the new sub converter code work with loading external subtitles. Until now, subtitles loaded via subreader.c was assumed to be in plaintext, or for some formats, in ASS (except in -no-ass mode). Then these were added to an ASS_Track. Change this so that subtitles are always in their original format (as far as decoders/converters for them are available), and turn every sub event read by subreader.c as packet to the dec_sub.c subtitle chain. This removes differences between external/demuxed and -ass/-no-ass code paths further.
This commit is contained in:
parent
14dd951548
commit
e19ffa02aa
|
@ -1036,10 +1036,12 @@ static void add_dvd_tracks(struct MPContext *mpctx)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_ASS
|
||||
static int free_ass_track(void *ptr)
|
||||
static int free_sub_data(void *ptr)
|
||||
{
|
||||
struct ass_track *track = *(struct ass_track **)ptr;
|
||||
ass_free_track(track);
|
||||
struct sh_sub *sh_sub = *(struct sh_sub **)ptr;
|
||||
if (sh_sub->track)
|
||||
ass_free_track(sh_sub->track);
|
||||
talloc_free(sh_sub->sub_data);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
@ -1049,7 +1051,7 @@ struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename,
|
|||
{
|
||||
struct MPOpts *opts = &mpctx->opts;
|
||||
struct ass_track *asst = NULL;
|
||||
const char *codec = NULL;
|
||||
sub_data *subd = NULL;
|
||||
|
||||
if (filename == NULL)
|
||||
return NULL;
|
||||
|
@ -1059,30 +1061,23 @@ struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename,
|
|||
// through sd_ass makes the code much simpler, as sd_ass can handle all
|
||||
// the weird special-cases.
|
||||
#ifdef CONFIG_ASS
|
||||
if (opts->ass_enabled) {
|
||||
if (opts->ass_enabled)
|
||||
asst = mp_ass_read_stream(mpctx->ass_library, filename, opts->sub_cp);
|
||||
codec = "ass";
|
||||
}
|
||||
if (!asst) {
|
||||
sub_data *subd = sub_read_file(filename, fps, &mpctx->opts);
|
||||
if (subd) {
|
||||
codec = subd->codec;
|
||||
asst = mp_ass_read_subdata(mpctx->ass_library, opts, subd, fps);
|
||||
}
|
||||
talloc_free(subd);
|
||||
}
|
||||
if (asst) {
|
||||
if (!asst)
|
||||
subd = sub_read_file(filename, fps, &mpctx->opts);
|
||||
if (asst || subd) {
|
||||
struct demuxer *d = new_sub_pseudo_demuxer(opts);
|
||||
assert(d->num_streams == 1);
|
||||
struct sh_stream *s = d->streams[0];
|
||||
assert(s->type == STREAM_SUB);
|
||||
|
||||
s->codec = asst ? "ass" : subd->codec;
|
||||
s->sub->track = asst;
|
||||
s->codec = codec;
|
||||
s->sub->sub_data = subd;
|
||||
|
||||
struct ass_track **pptr = talloc(d, struct ass_track*);
|
||||
*pptr = asst;
|
||||
talloc_set_destructor(pptr, free_ass_track);
|
||||
struct sh_sub **pptr = talloc(d, struct sh_sub*);
|
||||
*pptr = s->sub;
|
||||
talloc_set_destructor(pptr, free_sub_data);
|
||||
|
||||
struct track *t = add_stream_track(mpctx, s, false);
|
||||
t->is_external = true;
|
||||
|
|
|
@ -163,8 +163,9 @@ typedef struct sh_sub {
|
|||
SH_COMMON
|
||||
unsigned char *extradata; // extra header data passed from demuxer
|
||||
int extradata_len;
|
||||
struct ass_track *track; // loaded by libass
|
||||
struct dec_sub *dec_sub; // decoder context
|
||||
struct ass_track *track; // loaded by libass
|
||||
struct sub_data *sub_data; // loaded by subreader.c
|
||||
struct dec_sub *dec_sub; // decoder context
|
||||
} sh_sub_t;
|
||||
|
||||
// demuxer.c:
|
||||
|
|
79
sub/ass_mp.c
79
sub/ass_mp.c
|
@ -102,85 +102,6 @@ ASS_Track *mp_ass_default_track(ASS_Library *library, struct MPOpts *opts)
|
|||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert subtitle to ASS_Events for the given track
|
||||
* \param track 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.
|
||||
**/
|
||||
static int ass_process_subtitle(ASS_Track *track, subtitle *sub)
|
||||
{
|
||||
int eid;
|
||||
ASS_Event *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 = track->default_style;
|
||||
|
||||
for (j = 0; j < sub->lines; ++j)
|
||||
len += sub->text[j] ? strlen(sub->text[j]) : 0;
|
||||
|
||||
len += 2 * sub->lines; // '\N', including the one after the last line
|
||||
len += 6; // {\anX}
|
||||
len += 1; // '\0'
|
||||
|
||||
event->Text = malloc(len);
|
||||
end = event->Text + len;
|
||||
p = event->Text;
|
||||
|
||||
if (sub->alignment)
|
||||
p += snprintf(p, end - p, "{\\an%d}", sub->alignment);
|
||||
|
||||
for (j = 0; j < sub->lines; ++j)
|
||||
p += snprintf(p, end - p, "%s\\N", sub->text[j]);
|
||||
|
||||
if (sub->lines > 0)
|
||||
p -= 2; // remove last "\N"
|
||||
*p = 0;
|
||||
|
||||
mp_msg(MSGT_ASS, 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 *mp_ass_read_subdata(ASS_Library *library, struct MPOpts *opts,
|
||||
sub_data *subdata, double fps)
|
||||
{
|
||||
ASS_Track *track;
|
||||
int i;
|
||||
|
||||
track = mp_ass_default_track(library, opts);
|
||||
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;
|
||||
}
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
ASS_Track *mp_ass_read_stream(ASS_Library *library, const char *fname,
|
||||
char *charset)
|
||||
{
|
||||
|
|
|
@ -47,8 +47,6 @@ struct osd_style_opts;
|
|||
void mp_ass_set_style(ASS_Style *style, struct osd_style_opts *opts);
|
||||
|
||||
ASS_Track *mp_ass_default_track(ASS_Library *library, struct MPOpts *opts);
|
||||
ASS_Track *mp_ass_read_subdata(ASS_Library *library, struct MPOpts *opts,
|
||||
sub_data *subdata, double fps);
|
||||
ASS_Track *mp_ass_read_stream(ASS_Library *library, const char *fname,
|
||||
char *charset);
|
||||
|
||||
|
|
|
@ -22,9 +22,10 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "demux/stheader.h"
|
||||
#include "sub/sd.h"
|
||||
#include "sub/sub.h"
|
||||
#include "sub/dec_sub.h"
|
||||
#include "sd.h"
|
||||
#include "sub.h"
|
||||
#include "dec_sub.h"
|
||||
#include "subreader.h"
|
||||
#include "core/options.h"
|
||||
#include "core/mp_msg.h"
|
||||
|
||||
|
@ -32,6 +33,8 @@ extern const struct sd_functions sd_ass;
|
|||
extern const struct sd_functions sd_lavc;
|
||||
extern const struct sd_functions sd_spu;
|
||||
extern const struct sd_functions sd_movtext;
|
||||
extern const struct sd_functions sd_srt;
|
||||
extern const struct sd_functions sd_microdvd;
|
||||
|
||||
static const struct sd_functions *sd_list[] = {
|
||||
#ifdef CONFIG_ASS
|
||||
|
@ -40,10 +43,12 @@ static const struct sd_functions *sd_list[] = {
|
|||
&sd_lavc,
|
||||
&sd_spu,
|
||||
&sd_movtext,
|
||||
&sd_srt,
|
||||
&sd_microdvd,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define MAX_NUM_SD 2
|
||||
#define MAX_NUM_SD 3
|
||||
|
||||
struct dec_sub {
|
||||
struct MPOpts *opts;
|
||||
|
@ -108,6 +113,55 @@ void sub_set_ass_renderer(struct dec_sub *sub, struct ass_library *ass_library,
|
|||
sub->init_sd.ass_renderer = ass_renderer;
|
||||
}
|
||||
|
||||
// Subtitles read with subreader.c
|
||||
static void read_sub_data(struct dec_sub *sub, struct sub_data *subdata)
|
||||
{
|
||||
assert(sub_accept_packets_in_advance(sub));
|
||||
char *temp = NULL;
|
||||
|
||||
for (int i = 0; i < subdata->sub_num; i++) {
|
||||
subtitle *st = &subdata->subtitles[i];
|
||||
// subdata is in 10 ms ticks, pts is in seconds
|
||||
double t = subdata->sub_uses_time ? 0.01 : (1 / subdata->fallback_fps);
|
||||
|
||||
int len = 0;
|
||||
for (int j = 0; j < st->lines; j++)
|
||||
len += st->text[j] ? strlen(st->text[j]) : 0;
|
||||
|
||||
len += 2 * st->lines; // '\N', including the one after the last line
|
||||
len += 6; // {\anX}
|
||||
len += 1; // '\0'
|
||||
|
||||
if (talloc_get_size(temp) < len) {
|
||||
talloc_free(temp);
|
||||
temp = talloc_array(NULL, char, len);
|
||||
}
|
||||
|
||||
char *p = temp;
|
||||
char *end = p + len;
|
||||
|
||||
if (st->alignment)
|
||||
p += snprintf(p, end - p, "{\\an%d}", st->alignment);
|
||||
|
||||
for (int j = 0; j < st->lines; j++)
|
||||
p += snprintf(p, end - p, "%s\\N", st->text[j]);
|
||||
|
||||
if (st->lines > 0)
|
||||
p -= 2; // remove last "\N"
|
||||
*p = 0;
|
||||
|
||||
struct demux_packet pkt = {0};
|
||||
pkt.pts = st->start * t;
|
||||
pkt.duration = (st->end - st->start) * t;
|
||||
pkt.buffer = temp;
|
||||
pkt.len = strlen(temp);
|
||||
|
||||
sub_decode(sub, &pkt);
|
||||
}
|
||||
|
||||
talloc_free(temp);
|
||||
}
|
||||
|
||||
static int sub_init_decoder(struct dec_sub *sub, struct sd *sd)
|
||||
{
|
||||
sd->driver = NULL;
|
||||
|
@ -148,8 +202,11 @@ void sub_init_from_sh(struct dec_sub *sub, struct sh_sub *sh)
|
|||
sub->sd[sub->num_sd] = sd;
|
||||
sub->num_sd++;
|
||||
// Try adding new converters until a decoder is reached
|
||||
if (sd->driver->get_bitmaps || sd->driver->get_text)
|
||||
if (sd->driver->get_bitmaps || sd->driver->get_text) {
|
||||
if (sh->sub_data)
|
||||
read_sub_data(sub, sh->sub_data);
|
||||
return;
|
||||
}
|
||||
init_sd = (struct sd) {
|
||||
.codec = sd->output_codec,
|
||||
.extradata = sd->output_extradata,
|
||||
|
|
2
sub/sd.h
2
sub/sd.h
|
@ -59,4 +59,6 @@ struct demux_packet *sd_conv_def_get_converted(struct sd *sd);
|
|||
void sd_conv_def_reset(struct sd *sd);
|
||||
void sd_conv_def_uninit(struct sd *sd);
|
||||
|
||||
#define SD_MAX_LINE_LEN 1000
|
||||
|
||||
#endif
|
||||
|
|
38
sub/sd_ass.c
38
sub/sd_ass.c
|
@ -27,12 +27,10 @@
|
|||
#include "core/options.h"
|
||||
#include "core/mp_common.h"
|
||||
#include "core/mp_msg.h"
|
||||
#include "demux/stheader.h"
|
||||
#include "sub.h"
|
||||
#include "dec_sub.h"
|
||||
#include "ass_mp.h"
|
||||
#include "sd.h"
|
||||
#include "subassconvert.h"
|
||||
|
||||
struct sd_ass_priv {
|
||||
struct ass_track *ass_track;
|
||||
|
@ -43,22 +41,17 @@ struct sd_ass_priv {
|
|||
char last_text[500];
|
||||
};
|
||||
|
||||
static bool is_ass_sub(const char *t)
|
||||
static bool is_native_ass(const char *t)
|
||||
{
|
||||
return t && (strcmp(t, "ass") == 0 ||
|
||||
strcmp(t, "ssa") == 0);
|
||||
}
|
||||
|
||||
static bool is_text_sub(const char *t)
|
||||
{
|
||||
return t && (is_ass_sub(t) ||
|
||||
strcmp(t, "text") == 0 ||
|
||||
strcmp(t, "subrip") == 0);
|
||||
return strcmp(t, "ass") == 0 || strcmp(t, "ssa") == 0;
|
||||
}
|
||||
|
||||
static bool supports_format(const char *format)
|
||||
{
|
||||
return is_text_sub(format);
|
||||
// ass-text is produced by converters and the subreader.c ssa parser; this
|
||||
// format has ASS tags, but doesn't start with any prelude, nor does it
|
||||
// have extradata.
|
||||
return format && (is_native_ass(format) || strcmp(format, "ass-text") == 0);
|
||||
}
|
||||
|
||||
static void free_last_event(ASS_Track *track)
|
||||
|
@ -73,19 +66,21 @@ static int init(struct sd *sd)
|
|||
if (!sd->ass_library || !sd->ass_renderer)
|
||||
return -1;
|
||||
|
||||
bool ass = is_ass_sub(sd->codec);
|
||||
bool ass = is_native_ass(sd->codec);
|
||||
struct sd_ass_priv *ctx = talloc_zero(NULL, struct sd_ass_priv);
|
||||
sd->priv = ctx;
|
||||
if (sd->ass_track) {
|
||||
ctx->ass_track = sd->ass_track;
|
||||
} else if (ass) {
|
||||
ctx->ass_track = ass_new_track(sd->ass_library);
|
||||
if (sd->extradata)
|
||||
ass_process_codec_private(ctx->ass_track, sd->extradata,
|
||||
sd->extradata_len);
|
||||
} else
|
||||
ctx->ass_track = mp_ass_default_track(sd->ass_library, sd->opts);
|
||||
|
||||
if (sd->extradata) {
|
||||
ass_process_codec_private(ctx->ass_track, sd->extradata,
|
||||
sd->extradata_len);
|
||||
}
|
||||
|
||||
ctx->vsfilter_aspect = ass;
|
||||
return 0;
|
||||
}
|
||||
|
@ -99,8 +94,7 @@ static void decode(struct sd *sd, struct demux_packet *packet)
|
|||
unsigned char *text = data;
|
||||
struct sd_ass_priv *ctx = sd->priv;
|
||||
ASS_Track *track = ctx->ass_track;
|
||||
|
||||
if (is_ass_sub(sd->codec)) {
|
||||
if (is_native_ass(sd->codec)) {
|
||||
if (bstr_startswith0((bstr){data, data_len}, "Dialogue: ")) {
|
||||
// broken ffmpeg ASS packet format
|
||||
ctx->flush_on_seek = true;
|
||||
|
@ -138,12 +132,10 @@ static void decode(struct sd *sd, struct demux_packet *packet)
|
|||
return;
|
||||
}
|
||||
not_all_whitespace:;
|
||||
char buf[500];
|
||||
subassconvert_subrip(text, buf, sizeof(buf));
|
||||
for (int i = 0; i < track->n_events; i++)
|
||||
if (track->events[i].Start == ipts
|
||||
&& (duration <= 0 || track->events[i].Duration == iduration)
|
||||
&& strcmp(track->events[i].Text, buf) == 0)
|
||||
&& strcmp(track->events[i].Text, text) == 0)
|
||||
return; // We've already added this subtitle
|
||||
if (duration <= 0) {
|
||||
iduration = 10000;
|
||||
|
@ -154,7 +146,7 @@ static void decode(struct sd *sd, struct demux_packet *packet)
|
|||
event->Start = ipts;
|
||||
event->Duration = iduration;
|
||||
event->Style = track->default_style;
|
||||
event->Text = strdup(buf);
|
||||
event->Text = strdup(text);
|
||||
}
|
||||
|
||||
static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, double pts,
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <libavutil/common.h>
|
||||
|
||||
#include "core/mp_msg.h"
|
||||
#include "subassconvert.h"
|
||||
#include "core/bstr.h"
|
||||
#include "libavutil/common.h"
|
||||
#include "sd.h"
|
||||
|
||||
struct line {
|
||||
char *buf;
|
||||
|
@ -61,7 +61,6 @@ static int indexof(const char *s, int c)
|
|||
return f ? (f - s) : -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MicroDVD
|
||||
*
|
||||
|
@ -283,7 +282,7 @@ static void microdvd_close_no_persistent_tags(struct line *new_line,
|
|||
}
|
||||
}
|
||||
|
||||
void subassconvert_microdvd(const char *orig, char *dest, int dest_buffer_size)
|
||||
static void convert_microdvd(const char *orig, char *dest, int dest_buffer_size)
|
||||
{
|
||||
/* line is not const to avoid warnings with strtol, etc.
|
||||
* orig content won't be changed */
|
||||
|
@ -309,3 +308,30 @@ void subassconvert_microdvd(const char *orig, char *dest, int dest_buffer_size)
|
|||
}
|
||||
new_line.buf[new_line.len] = 0;
|
||||
}
|
||||
|
||||
static bool supports_format(const char *format)
|
||||
{
|
||||
return format && strcmp(format, "microdvd") == 0;
|
||||
}
|
||||
|
||||
static int init(struct sd *sd)
|
||||
{
|
||||
sd->output_codec = "ass-text";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode(struct sd *sd, struct demux_packet *packet)
|
||||
{
|
||||
char dest[SD_MAX_LINE_LEN];
|
||||
// Assume input buffer is padded with 0
|
||||
convert_microdvd(packet->buffer, dest, sizeof(dest));
|
||||
sd_conv_add_packet(sd, dest, strlen(dest), packet->pts, packet->duration);
|
||||
}
|
||||
|
||||
const struct sd_functions sd_microdvd = {
|
||||
.supports_format = supports_format,
|
||||
.init = init,
|
||||
.decode = decode,
|
||||
.get_converted = sd_conv_def_get_converted,
|
||||
.reset = sd_conv_def_reset,
|
||||
};
|
||||
|
|
34
sub/sd_srt.c
34
sub/sd_srt.c
|
@ -25,11 +25,11 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <libavutil/common.h>
|
||||
|
||||
#include "core/mp_msg.h"
|
||||
#include "subassconvert.h"
|
||||
#include "core/bstr.h"
|
||||
#include "libavutil/common.h"
|
||||
#include "sd.h"
|
||||
|
||||
struct line {
|
||||
char *buf;
|
||||
|
@ -273,7 +273,7 @@ static int read_attr(char **s, struct bstr *attr, struct bstr *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size)
|
||||
static void convert_subrip(const char *orig, char *dest, int dest_buffer_size)
|
||||
{
|
||||
/* line is not const to avoid warnings with strtol, etc.
|
||||
* orig content won't be changed */
|
||||
|
@ -436,3 +436,31 @@ void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size)
|
|||
}
|
||||
new_line.buf[new_line.len] = 0;
|
||||
}
|
||||
|
||||
static bool supports_format(const char *format)
|
||||
{
|
||||
return format && (strcmp(format, "subrip") == 0 ||
|
||||
strcmp(format, "text") == 0);
|
||||
}
|
||||
|
||||
static int init(struct sd *sd)
|
||||
{
|
||||
sd->output_codec = "ass-text";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode(struct sd *sd, struct demux_packet *packet)
|
||||
{
|
||||
char dest[SD_MAX_LINE_LEN];
|
||||
// Assume input buffer is padded with 0
|
||||
convert_subrip(packet->buffer, dest, sizeof(dest));
|
||||
sd_conv_add_packet(sd, dest, strlen(dest), packet->pts, packet->duration);
|
||||
}
|
||||
|
||||
const struct sd_functions sd_srt = {
|
||||
.supports_format = supports_format,
|
||||
.init = init,
|
||||
.decode = decode,
|
||||
.get_converted = sd_conv_def_get_converted,
|
||||
.reset = sd_conv_def_reset,
|
||||
};
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Header for subtitles converter to SSA/ASS
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_SUBASSCONVERT_H
|
||||
#define MPLAYER_SUBASSCONVERT_H
|
||||
|
||||
void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size);
|
||||
void subassconvert_microdvd(const char *orig, char *dest, int dest_buffer_size);
|
||||
|
||||
#endif
|
100
sub/subreader.c
100
sub/subreader.c
|
@ -32,7 +32,6 @@
|
|||
#include "core/mp_msg.h"
|
||||
#include "subreader.h"
|
||||
#include "core/mp_common.h"
|
||||
#include "subassconvert.h"
|
||||
#include "core/options.h"
|
||||
#include "stream/stream.h"
|
||||
#include "libavutil/common.h"
|
||||
|
@ -299,7 +298,6 @@ static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current,
|
|||
int utf16 = args->utf16;
|
||||
char line[LINE_LEN+1];
|
||||
char line2[LINE_LEN+1];
|
||||
char *p;
|
||||
|
||||
do {
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
|
@ -310,13 +308,7 @@ static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current,
|
|||
"{%ld}{%ld}%[^\r\n]",
|
||||
&(current->start), &(current->end), line2) < 3));
|
||||
|
||||
if (args->opts->ass_enabled) {
|
||||
subassconvert_microdvd(line2, line, LINE_LEN + 1);
|
||||
p = line;
|
||||
} else
|
||||
p = line2;
|
||||
|
||||
return set_multiline_text(current, p, 0);
|
||||
return set_multiline_text(current, line2, 0);
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current,
|
||||
|
@ -370,8 +362,8 @@ static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current,
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_ass_read_line_subviewer(stream_t *st, subtitle *current,
|
||||
struct readline_args *args)
|
||||
static subtitle *sub_read_line_subviewer(stream_t *st, subtitle *current,
|
||||
struct readline_args *args)
|
||||
{
|
||||
int utf16 = args->utf16;
|
||||
int a1, a2, a3, a4, b1, b2, b3, b4, j = 0;
|
||||
|
@ -417,74 +409,14 @@ static subtitle *sub_ass_read_line_subviewer(stream_t *st, subtitle *current,
|
|||
j += len;
|
||||
}
|
||||
|
||||
/* Use the ASS/SSA converter to transform the whole lines */
|
||||
if (full_line[0]) {
|
||||
char converted_line[LINE_LEN + 1];
|
||||
subassconvert_subrip(full_line, converted_line, LINE_LEN + 1);
|
||||
current->text[0] = strdup(converted_line);
|
||||
current->text[0] = strdup(full_line);
|
||||
current->lines = 1;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current,
|
||||
struct readline_args *args)
|
||||
{
|
||||
int utf16 = args->utf16;
|
||||
char line[LINE_LEN+1];
|
||||
int a1,a2,a3,a4,b1,b2,b3,b4;
|
||||
char *p=NULL;
|
||||
int i,len;
|
||||
|
||||
if (args->opts->ass_enabled)
|
||||
return sub_ass_read_line_subviewer(st, current, args);
|
||||
while (!current->text[0]) {
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
if ((len=sscanf (line, "%d:%d:%d%*1[,.:]%d --> %d:%d:%d%*1[,.:]%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8)
|
||||
continue;
|
||||
current->start = a1*360000+a2*6000+a3*100+a4/10;
|
||||
current->end = b1*360000+b2*6000+b3*100+b4/10;
|
||||
for (i=0; i<SUB_MAX_TEXT;) {
|
||||
int blank = 1;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) break;
|
||||
len=0;
|
||||
for (p=line; *p!='\n' && *p!='\r' && *p; p++,len++)
|
||||
if (*p != ' ' && *p != '\t')
|
||||
blank = 0;
|
||||
if (len && !blank) {
|
||||
int j=0,skip=0;
|
||||
char *curptr=current->text[i]=malloc (len+1);
|
||||
if (!current->text[i]) return ERR;
|
||||
//strncpy (current->text[i], line, len); current->text[i][len]='\0';
|
||||
for(; j<len; j++) {
|
||||
/* let's filter html tags ::atmos */
|
||||
if(line[j]=='>') {
|
||||
skip=0;
|
||||
continue;
|
||||
}
|
||||
if(line[j]=='<') {
|
||||
skip=1;
|
||||
continue;
|
||||
}
|
||||
if(skip) {
|
||||
continue;
|
||||
}
|
||||
*curptr=line[j];
|
||||
curptr++;
|
||||
}
|
||||
*curptr='\0';
|
||||
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
current->lines=i;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current,
|
||||
struct readline_args *args)
|
||||
{
|
||||
|
@ -675,20 +607,6 @@ static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current,
|
|||
return current;
|
||||
}
|
||||
|
||||
static void sub_pp_ssa(subtitle *sub)
|
||||
{
|
||||
for (int i = 0; i < sub->lines; i++) {
|
||||
char *s, *d;
|
||||
s = d = sub->text[i];
|
||||
while (1) {
|
||||
while (*s == '{')
|
||||
while (*s && *s++ != '}');
|
||||
if (!(*d++ = *s++))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PJS subtitles reader.
|
||||
* That's the "Phoenix Japanimation Society" format.
|
||||
|
@ -1238,6 +1156,7 @@ struct subreader {
|
|||
struct readline_args *args);
|
||||
void (*post)(subtitle *dest);
|
||||
const char *name;
|
||||
const char *codec_name;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ENCA
|
||||
|
@ -1313,13 +1232,13 @@ sub_data* sub_read_file(char *filename, float fps, struct MPOpts *opts)
|
|||
int uses_time = 0, sub_num = 0, sub_errs = 0;
|
||||
static const struct subreader sr[]=
|
||||
{
|
||||
{ sub_read_line_microdvd, NULL, "microdvd" },
|
||||
{ sub_read_line_microdvd, NULL, "microdvd", "microdvd" },
|
||||
{ sub_read_line_subrip, NULL, "subviewer" },
|
||||
{ sub_read_line_subviewer, NULL, "subrip" },
|
||||
{ sub_read_line_subviewer, NULL, "subrip", "subrip" },
|
||||
{ sub_read_line_sami, NULL, "sami" },
|
||||
{ sub_read_line_vplayer, NULL, "vplayer" },
|
||||
{ sub_read_line_rt, NULL, "rt" },
|
||||
{ sub_read_line_ssa, sub_pp_ssa, "ssa" },
|
||||
{ sub_read_line_ssa, NULL, "ssa", "ass-text" },
|
||||
{ sub_read_line_pjs, NULL, "pjs" },
|
||||
{ sub_read_line_mpsub, NULL, "mpsub" },
|
||||
{ sub_read_line_aqt, NULL, "aqt" },
|
||||
|
@ -1678,12 +1597,13 @@ if ((opts->suboverlap_enabled == 2) ||
|
|||
if (return_sub == NULL) return NULL;
|
||||
subt_data = talloc_zero(NULL, sub_data);
|
||||
talloc_set_destructor(subt_data, sub_destroy);
|
||||
subt_data->codec = "text"; //srp->name;
|
||||
subt_data->codec = srp->codec_name ? srp->codec_name : "text";
|
||||
subt_data->filename = strdup(filename);
|
||||
subt_data->sub_uses_time = uses_time;
|
||||
subt_data->sub_num = sub_num;
|
||||
subt_data->sub_errs = sub_errs;
|
||||
subt_data->subtitles = return_sub;
|
||||
subt_data->fallback_fps = fps;
|
||||
return subt_data;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ typedef struct sub_data {
|
|||
int sub_uses_time;
|
||||
int sub_num; // number of subtitle structs
|
||||
int sub_errs;
|
||||
double fallback_fps;
|
||||
} sub_data;
|
||||
|
||||
struct MPOpts;
|
||||
|
|
Loading…
Reference in New Issue