0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02: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:
wm4 2015-12-27 02:07:01 +01:00
parent 50c379e2d8
commit d85753b79e
7 changed files with 88 additions and 153 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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,

View File

@ -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,