mirror of
https://github.com/mpv-player/mpv
synced 2025-02-03 05:31:34 +00:00
sub: refactor initialization
Just simplify by removing parts not needed anymore. This includes merging dec_sub allocation and initialization (since things making initialization complicated were removed), or format support queries (it simply tries to create a decoder, and if that fails, tries the next one).
This commit is contained in:
parent
50c379e2d8
commit
d85753b79e
36
player/sub.c
36
player/sub.c
@ -143,49 +143,53 @@ void update_subtitles(struct MPContext *mpctx)
|
||||
update_subtitle(mpctx, 1);
|
||||
}
|
||||
|
||||
static void reinit_subdec(struct MPContext *mpctx, struct track *track)
|
||||
static bool init_subdec(struct MPContext *mpctx, struct track *track)
|
||||
{
|
||||
struct MPOpts *opts = mpctx->opts;
|
||||
|
||||
struct dec_sub *dec_sub = track->dec_sub;
|
||||
assert(!track->dec_sub);
|
||||
|
||||
if (sub_is_initialized(dec_sub))
|
||||
return;
|
||||
if (!track->demuxer || !track->stream)
|
||||
return false;
|
||||
|
||||
sub_init(dec_sub, track->demuxer, track->stream);
|
||||
track->dec_sub = sub_create(mpctx->global, track->demuxer, track->stream);
|
||||
if (!track->dec_sub)
|
||||
return false;
|
||||
|
||||
struct sh_video *sh_video =
|
||||
mpctx->d_video ? mpctx->d_video->header->video : NULL;
|
||||
double fps = sh_video ? sh_video->fps : 25;
|
||||
sub_control(dec_sub, SD_CTRL_SET_VIDEO_DEF_FPS, &fps);
|
||||
sub_control(track->dec_sub, SD_CTRL_SET_VIDEO_DEF_FPS, &fps);
|
||||
|
||||
// Don't do this if the file has video/audio streams. Don't do it even
|
||||
// if it has only sub streams, because reading packets will change the
|
||||
// demuxer position.
|
||||
if (!track->preloaded && track->is_external && !opts->sub_clear_on_seek) {
|
||||
if (track->is_external && !opts->sub_clear_on_seek) {
|
||||
demux_seek(track->demuxer, 0, SEEK_ABSOLUTE);
|
||||
track->preloaded = sub_read_all_packets(dec_sub, track->stream);
|
||||
track->preloaded = sub_read_all_packets(track->dec_sub);
|
||||
if (track->preloaded)
|
||||
demux_stop_thread(track->demuxer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void reinit_subs(struct MPContext *mpctx, int order)
|
||||
{
|
||||
struct track *track = mpctx->current_track[order][STREAM_SUB];
|
||||
|
||||
assert(!mpctx->d_sub[order]);
|
||||
|
||||
struct sh_stream *sh = track ? track->stream : NULL;
|
||||
if (!sh)
|
||||
struct track *track = mpctx->current_track[order][STREAM_SUB];
|
||||
if (!track)
|
||||
return;
|
||||
|
||||
if (!track->dec_sub)
|
||||
track->dec_sub = sub_create(mpctx->global);
|
||||
mpctx->d_sub[order] = track->dec_sub;
|
||||
if (!track->dec_sub && !init_subdec(mpctx, track)) {
|
||||
error_on_track(mpctx, track);
|
||||
return;
|
||||
}
|
||||
|
||||
sub_select(track->dec_sub, true);
|
||||
reinit_subdec(mpctx, track);
|
||||
osd_set_sub(mpctx->osd, OSDTYPE_SUB + order, track->dec_sub);
|
||||
sub_control(track->dec_sub, SD_CTRL_SET_TOP, &(bool){!!order});
|
||||
|
||||
mpctx->d_sub[order] = track->dec_sub;
|
||||
}
|
||||
|
148
sub/dec_sub.c
148
sub/dec_sub.c
@ -48,7 +48,6 @@ struct dec_sub {
|
||||
|
||||
struct mp_log *log;
|
||||
struct MPOpts *opts;
|
||||
struct sd init_sd;
|
||||
|
||||
struct sh_stream *sh;
|
||||
|
||||
@ -71,96 +70,57 @@ void sub_unlock(struct dec_sub *sub)
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
}
|
||||
|
||||
// Thread-safety of the returned object: all functions are thread-safe,
|
||||
// except sub_get_bitmaps() and sub_get_text(). Decoder backends (sd_*)
|
||||
// do not need to acquire locks.
|
||||
struct dec_sub *sub_create(struct mpv_global *global)
|
||||
{
|
||||
struct dec_sub *sub = talloc_zero(NULL, struct dec_sub);
|
||||
sub->log = mp_log_new(sub, global->log, "sub");
|
||||
sub->opts = global->opts;
|
||||
sub->init_sd.opts = sub->opts;
|
||||
sub->init_sd.global = global;
|
||||
|
||||
mpthread_mutex_init_recursive(&sub->lock);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
static void sub_uninit(struct dec_sub *sub)
|
||||
{
|
||||
sub_reset(sub);
|
||||
if (sub->sd)
|
||||
sub->sd->driver->uninit(sub->sd);
|
||||
talloc_free(sub->sd);
|
||||
sub->sd = NULL;
|
||||
}
|
||||
|
||||
void sub_destroy(struct dec_sub *sub)
|
||||
{
|
||||
if (!sub)
|
||||
return;
|
||||
sub_uninit(sub);
|
||||
sub_reset(sub);
|
||||
sub->sd->driver->uninit(sub->sd);
|
||||
talloc_free(sub->sd);
|
||||
pthread_mutex_destroy(&sub->lock);
|
||||
talloc_free(sub);
|
||||
}
|
||||
|
||||
bool sub_is_initialized(struct dec_sub *sub)
|
||||
// Thread-safety of the returned object: all functions are thread-safe,
|
||||
// except sub_get_bitmaps() and sub_get_text(). Decoder backends (sd_*)
|
||||
// do not need to acquire locks.
|
||||
struct dec_sub *sub_create(struct mpv_global *global, struct demuxer *demuxer,
|
||||
struct sh_stream *sh)
|
||||
{
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
bool r = !!sub->sd;
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
return r;
|
||||
}
|
||||
assert(demuxer && sh && sh->sub);
|
||||
|
||||
struct mp_log *log = mp_log_new(NULL, global->log, "sub");
|
||||
|
||||
static int sub_init_decoder(struct dec_sub *sub, struct sd *sd)
|
||||
{
|
||||
sd->driver = NULL;
|
||||
for (int n = 0; sd_list[n]; n++) {
|
||||
if (sd->sh->codec && sd_list[n]->supports_format(sd->sh->codec)) {
|
||||
sd->driver = sd_list[n];
|
||||
break;
|
||||
}
|
||||
const struct sd_functions *driver = sd_list[n];
|
||||
struct dec_sub *sub = talloc_zero(NULL, struct dec_sub);
|
||||
sub->log = talloc_steal(sub, log),
|
||||
sub->opts = global->opts;
|
||||
sub->sh = sh;
|
||||
mpthread_mutex_init_recursive(&sub->lock);
|
||||
|
||||
sub->sd = talloc(NULL, struct sd);
|
||||
*sub->sd = (struct sd){
|
||||
.global = global,
|
||||
.log = mp_log_new(sub->sd, sub->log, driver->name),
|
||||
.opts = sub->opts,
|
||||
.driver = driver,
|
||||
.demuxer = demuxer,
|
||||
.sh = sh,
|
||||
};
|
||||
|
||||
if (sh->codec && sub->sd->driver->init(sub->sd) >= 0)
|
||||
return sub;
|
||||
|
||||
ta_set_parent(log, NULL);
|
||||
talloc_free(sub->sd);
|
||||
talloc_free(sub);
|
||||
}
|
||||
|
||||
if (!sd->driver)
|
||||
return -1;
|
||||
|
||||
sd->log = mp_log_new(sd, sub->log, sd->driver->name);
|
||||
if (sd->driver->init(sd) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sub_init(struct dec_sub *sub, struct demuxer *demuxer, struct sh_stream *sh)
|
||||
{
|
||||
assert(!sub->sd);
|
||||
assert(sh && sh->sub);
|
||||
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
|
||||
sub->sh = sh;
|
||||
|
||||
struct sd init_sd = sub->init_sd;
|
||||
init_sd.demuxer = demuxer;
|
||||
init_sd.sh = sh;
|
||||
|
||||
struct sd *sd = talloc(NULL, struct sd);
|
||||
*sd = init_sd;
|
||||
|
||||
if (sub_init_decoder(sub, sd) < 0) {
|
||||
if (sd->driver && sd->driver->uninit)
|
||||
sd->driver->uninit(sd);
|
||||
talloc_free(sd);
|
||||
MP_ERR(sub, "Could not find subtitle decoder for format '%s'.\n",
|
||||
sh->codec ? sh->codec : "<unknown>");
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
sub->sd = sd;
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
mp_err(log, "Could not find subtitle decoder for format '%s'.\n",
|
||||
sh->codec ? sh->codec : "<unknown>");
|
||||
talloc_free(log);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct demux_packet *recode_packet(struct mp_log *log,
|
||||
@ -187,13 +147,11 @@ static struct demux_packet *recode_packet(struct mp_log *log,
|
||||
|
||||
static void decode_chain_recode(struct dec_sub *sub, struct demux_packet *packet)
|
||||
{
|
||||
if (sub->sd) {
|
||||
struct demux_packet *recoded = NULL;
|
||||
if (sub->sh && sub->sh->sub->charset)
|
||||
recoded = recode_packet(sub->log, packet, sub->sh->sub->charset);
|
||||
sub->sd->driver->decode(sub->sd, recoded ? recoded : packet);
|
||||
talloc_free(recoded);
|
||||
}
|
||||
struct demux_packet *recoded = NULL;
|
||||
if (sub->sh->sub->charset)
|
||||
recoded = recode_packet(sub->log, packet, sub->sh->sub->charset);
|
||||
sub->sd->driver->decode(sub->sd, recoded ? recoded : packet);
|
||||
talloc_free(recoded);
|
||||
}
|
||||
|
||||
void sub_decode(struct dec_sub *sub, struct demux_packet *packet)
|
||||
@ -220,14 +178,12 @@ static void add_packet(struct packet_list *subs, struct demux_packet *pkt)
|
||||
|
||||
// Read all packets from the demuxer and decode/add them. Returns false if
|
||||
// there are circumstances which makes this not possible.
|
||||
bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh)
|
||||
bool sub_read_all_packets(struct dec_sub *sub)
|
||||
{
|
||||
assert(sh && sh->sub);
|
||||
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
|
||||
// Converters are assumed to always accept packets in advance
|
||||
if (!(sub->sd && sub->sd->driver->accept_packets_in_advance)) {
|
||||
if (!sub->sd->driver->accept_packets_in_advance) {
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
return false;
|
||||
}
|
||||
@ -235,7 +191,7 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh)
|
||||
struct packet_list *subs = talloc_zero(NULL, struct packet_list);
|
||||
|
||||
for (;;) {
|
||||
struct demux_packet *pkt = demux_read_packet(sh);
|
||||
struct demux_packet *pkt = demux_read_packet(sub->sh);
|
||||
if (!pkt)
|
||||
break;
|
||||
add_packet(subs, pkt);
|
||||
@ -253,7 +209,7 @@ bool sub_accepts_packet_in_advance(struct dec_sub *sub)
|
||||
{
|
||||
bool res = true;
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
if (sub->sd && sub->sd->driver->accepts_packet)
|
||||
if (sub->sd->driver->accepts_packet)
|
||||
res &= sub->sd->driver->accepts_packet(sub->sd);
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
return res;
|
||||
@ -268,7 +224,7 @@ void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, double pts,
|
||||
struct MPOpts *opts = sub->opts;
|
||||
|
||||
*res = (struct sub_bitmaps) {0};
|
||||
if (sub->sd && opts->sub_visibility && sub->sd->driver->get_bitmaps)
|
||||
if (opts->sub_visibility && sub->sd->driver->get_bitmaps)
|
||||
sub->sd->driver->get_bitmaps(sub->sd, dim, pts, res);
|
||||
}
|
||||
|
||||
@ -280,7 +236,7 @@ char *sub_get_text(struct dec_sub *sub, double pts)
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
struct MPOpts *opts = sub->opts;
|
||||
char *text = NULL;
|
||||
if (sub->sd && opts->sub_visibility && sub->sd->driver->get_text)
|
||||
if (opts->sub_visibility && sub->sd->driver->get_text)
|
||||
text = sub->sd->driver->get_text(sub->sd, pts);
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
return text;
|
||||
@ -289,7 +245,7 @@ char *sub_get_text(struct dec_sub *sub, double pts)
|
||||
void sub_reset(struct dec_sub *sub)
|
||||
{
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
if (sub->sd && sub->sd->driver->reset)
|
||||
if (sub->sd->driver->reset)
|
||||
sub->sd->driver->reset(sub->sd);
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
}
|
||||
@ -297,7 +253,7 @@ void sub_reset(struct dec_sub *sub)
|
||||
void sub_select(struct dec_sub *sub, bool selected)
|
||||
{
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
if (sub->sd && sub->sd->driver->select)
|
||||
if (sub->sd->driver->select)
|
||||
sub->sd->driver->select(sub->sd, selected);
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
}
|
||||
@ -306,7 +262,7 @@ int sub_control(struct dec_sub *sub, enum sd_ctrl cmd, void *arg)
|
||||
{
|
||||
int r = CONTROL_UNKNOWN;
|
||||
pthread_mutex_lock(&sub->lock);
|
||||
if (sub->sd && sub->sd->driver->control)
|
||||
if (sub->sd->driver->control)
|
||||
r = sub->sd->driver->control(sub->sd, cmd, arg);
|
||||
pthread_mutex_unlock(&sub->lock);
|
||||
return r;
|
||||
|
@ -22,16 +22,13 @@ enum sd_ctrl {
|
||||
SD_CTRL_SET_VIDEO_DEF_FPS,
|
||||
};
|
||||
|
||||
struct dec_sub *sub_create(struct mpv_global *global);
|
||||
struct dec_sub *sub_create(struct mpv_global *global, struct demuxer *demuxer,
|
||||
struct sh_stream *sh);
|
||||
void sub_destroy(struct dec_sub *sub);
|
||||
void sub_lock(struct dec_sub *sub);
|
||||
void sub_unlock(struct dec_sub *sub);
|
||||
|
||||
void sub_init(struct dec_sub *sub, struct demuxer *demuxer, struct sh_stream *sh);
|
||||
|
||||
bool sub_is_initialized(struct dec_sub *sub);
|
||||
|
||||
bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh);
|
||||
bool sub_read_all_packets(struct dec_sub *sub);
|
||||
bool sub_accepts_packet_in_advance(struct dec_sub *sub);
|
||||
void sub_decode(struct dec_sub *sub, struct demux_packet *packet);
|
||||
void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, double pts,
|
||||
|
@ -49,15 +49,6 @@ static const char *get_lavc_format(const char *format)
|
||||
return format;
|
||||
}
|
||||
|
||||
bool lavc_conv_supports_format(const char *format)
|
||||
{
|
||||
format = get_lavc_format(format);
|
||||
enum AVCodecID cid = mp_codec_to_av_codec_id(format);
|
||||
AVCodec *codec = avcodec_find_decoder(cid);
|
||||
const AVCodecDescriptor *desc = avcodec_descriptor_get(cid);
|
||||
return codec && desc && desc->type == AVMEDIA_TYPE_SUBTITLE;
|
||||
}
|
||||
|
||||
// Disable style definitions generated by the libavcodec converter.
|
||||
// We always want the user defined style instead.
|
||||
static void disable_styles(bstr header)
|
||||
|
2
sub/sd.h
2
sub/sd.h
@ -24,7 +24,6 @@ struct sd {
|
||||
struct sd_functions {
|
||||
const char *name;
|
||||
bool accept_packets_in_advance;
|
||||
bool (*supports_format)(const char *format);
|
||||
int (*init)(struct sd *sd);
|
||||
void (*decode)(struct sd *sd, struct demux_packet *packet);
|
||||
void (*reset)(struct sd *sd);
|
||||
@ -40,7 +39,6 @@ struct sd_functions {
|
||||
};
|
||||
|
||||
struct lavc_conv;
|
||||
bool lavc_conv_supports_format(const char *format);
|
||||
struct lavc_conv *lavc_conv_create(struct mp_log *log, const char *codec_name,
|
||||
char *extradata, int extradata_len);
|
||||
char *lavc_conv_get_extradata(struct lavc_conv *priv);
|
||||
|
@ -125,12 +125,6 @@ static void add_subtitle_fonts(struct sd *sd)
|
||||
}
|
||||
}
|
||||
|
||||
static bool supports_format(const char *format)
|
||||
{
|
||||
return (format && strcmp(format, "ass") == 0) ||
|
||||
lavc_conv_supports_format(format);
|
||||
}
|
||||
|
||||
static void enable_output(struct sd *sd, bool enable)
|
||||
{
|
||||
struct sd_ass_priv *ctx = sd->priv;
|
||||
@ -633,7 +627,6 @@ static int control(struct sd *sd, enum sd_ctrl cmd, void *arg)
|
||||
const struct sd_functions sd_ass = {
|
||||
.name = "ass",
|
||||
.accept_packets_in_advance = true,
|
||||
.supports_format = supports_format,
|
||||
.init = init,
|
||||
.decode = decode,
|
||||
.get_bitmaps = get_bitmaps,
|
||||
|
@ -64,21 +64,6 @@ struct sd_lavc_priv {
|
||||
int num_seekpoints;
|
||||
};
|
||||
|
||||
static bool supports_format(const char *format)
|
||||
{
|
||||
enum AVCodecID cid = mp_codec_to_av_codec_id(format);
|
||||
// Supported codecs must be known to decode to paletted bitmaps
|
||||
switch (cid) {
|
||||
case AV_CODEC_ID_DVB_SUBTITLE:
|
||||
case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
|
||||
case AV_CODEC_ID_XSUB:
|
||||
case AV_CODEC_ID_DVD_SUBTITLE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_resolution(struct sd *sd, int wh[2])
|
||||
{
|
||||
struct sd_lavc_priv *priv = sd->priv;
|
||||
@ -110,8 +95,20 @@ static void get_resolution(struct sd *sd, int wh[2])
|
||||
|
||||
static int init(struct sd *sd)
|
||||
{
|
||||
struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv);
|
||||
enum AVCodecID cid = mp_codec_to_av_codec_id(sd->sh->codec);
|
||||
|
||||
// Supported codecs must be known to decode to paletted bitmaps
|
||||
switch (cid) {
|
||||
case AV_CODEC_ID_DVB_SUBTITLE:
|
||||
case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
|
||||
case AV_CODEC_ID_XSUB:
|
||||
case AV_CODEC_ID_DVD_SUBTITLE:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv);
|
||||
AVCodecContext *ctx = NULL;
|
||||
AVCodec *sub_codec = avcodec_find_decoder(cid);
|
||||
if (!sub_codec)
|
||||
@ -467,7 +464,6 @@ static int control(struct sd *sd, enum sd_ctrl cmd, void *arg)
|
||||
|
||||
const struct sd_functions sd_lavc = {
|
||||
.name = "lavc",
|
||||
.supports_format = supports_format,
|
||||
.init = init,
|
||||
.decode = decode,
|
||||
.get_bitmaps = get_bitmaps,
|
||||
|
Loading…
Reference in New Issue
Block a user