From 687b552db186af66e97c58792b2db40294e92bad Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 18 Dec 2015 01:54:14 +0100 Subject: sub: remove subtitle filter chain concept It was stupid. The only thing that still effectively used it was sd_lavc_conv - all other "filters" were the subtitle decoder/renderers for text (sd_ass) and bitmap (sd_lavc) subtitles. While having a subtitle filter chain was interesting (and actually worked in almost the same way as the audio/video ones), I didn't manage to use it in a meaningful way, and I couldn't e.g. factor secondary features like fixing subtitle timing into filters. Refactor the shit and drop unneeded things as it goes. --- sub/dec_sub.c | 225 +++++++++------------------------------------------------- 1 file changed, 34 insertions(+), 191 deletions(-) (limited to 'sub/dec_sub.c') diff --git a/sub/dec_sub.c b/sub/dec_sub.c index e7362e1f69..4450f577c2 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -34,19 +34,15 @@ extern const struct sd_functions sd_ass; extern const struct sd_functions sd_lavc; -extern const struct sd_functions sd_lavc_conv; static const struct sd_functions *const sd_list[] = { + &sd_lavc, #if HAVE_LIBASS &sd_ass, #endif - &sd_lavc, - &sd_lavc_conv, NULL }; -#define MAX_NUM_SD 3 - struct dec_sub { pthread_mutex_t lock; @@ -56,8 +52,7 @@ struct dec_sub { struct sh_stream *sh; - struct sd *sd[MAX_NUM_SD]; - int num_sd; + struct sd *sd; }; struct packet_list { @@ -84,6 +79,7 @@ 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; mpthread_mutex_init_recursive(&sub->lock); @@ -93,12 +89,10 @@ struct dec_sub *sub_create(struct mpv_global *global) static void sub_uninit(struct dec_sub *sub) { sub_reset(sub); - for (int n = 0; n < sub->num_sd; n++) { - if (sub->sd[n]->driver->uninit) - sub->sd[n]->driver->uninit(sub->sd[n]); - talloc_free(sub->sd[n]); - } - sub->num_sd = 0; + if (sub->sd) + sub->sd->driver->uninit(sub->sd); + talloc_free(sub->sd); + sub->sd = NULL; } void sub_destroy(struct dec_sub *sub) @@ -113,16 +107,11 @@ void sub_destroy(struct dec_sub *sub) bool sub_is_initialized(struct dec_sub *sub) { pthread_mutex_lock(&sub->lock); - bool r = !!sub->num_sd; + bool r = !!sub->sd; pthread_mutex_unlock(&sub->lock); return r; } -static struct sd *sub_get_last_sd(struct dec_sub *sub) -{ - return sub->num_sd ? sub->sd[sub->num_sd - 1] : NULL; -} - void sub_set_video_res(struct dec_sub *sub, int w, int h) { pthread_mutex_lock(&sub->lock); @@ -138,14 +127,6 @@ void sub_set_video_fps(struct dec_sub *sub, double fps) pthread_mutex_unlock(&sub->lock); } -void sub_set_extradata(struct dec_sub *sub, void *data, int data_len) -{ - pthread_mutex_lock(&sub->lock); - sub->init_sd.extradata = data_len ? talloc_memdup(sub, data, data_len) : NULL; - sub->init_sd.extradata_len = data_len; - pthread_mutex_unlock(&sub->lock); -} - void sub_set_ass_renderer(struct dec_sub *sub, struct ass_library *ass_library, struct ass_renderer *ass_renderer, pthread_mutex_t *ass_lock) @@ -157,22 +138,11 @@ void sub_set_ass_renderer(struct dec_sub *sub, struct ass_library *ass_library, pthread_mutex_unlock(&sub->lock); } -static void print_chain(struct dec_sub *sub) -{ - MP_VERBOSE(sub, "Subtitle filter chain: "); - for (int n = 0; n < sub->num_sd; n++) { - struct sd *sd = sub->sd[n]; - MP_VERBOSE(sub, "%s%s (%s)", n > 0 ? " -> " : "", - sd->driver->name, sd->codec); - } - MP_VERBOSE(sub, "\n"); -} - 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_list[n]->supports_format(sd->codec)) { + if (sd->sh->codec && sd_list[n]->supports_format(sd->sh->codec)) { sd->driver = sd_list[n]; break; } @@ -190,73 +160,30 @@ static int sub_init_decoder(struct dec_sub *sub, struct sd *sd) void sub_init_from_sh(struct dec_sub *sub, struct sh_stream *sh) { - assert(!sub->num_sd); + assert(!sub->sd); assert(sh && sh->sub); pthread_mutex_lock(&sub->lock); sub->sh = sh; - if (sh->extradata && !sub->init_sd.extradata) - sub_set_extradata(sub, sh->extradata, sh->extradata_size); struct sd init_sd = sub->init_sd; - init_sd.codec = sh->codec; init_sd.sh = sh; - while (sub->num_sd < MAX_NUM_SD) { - struct sd *sd = talloc(NULL, struct sd); - *sd = init_sd; - sd->opts = sub->opts; - if (sub_init_decoder(sub, sd) < 0) { - talloc_free(sd); - break; - } - 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) { - print_chain(sub); - pthread_mutex_unlock(&sub->lock); - return; - } - init_sd = (struct sd) { - .codec = sd->output_codec, - .converted_from = sd->codec, - .extradata = sd->output_extradata, - .extradata_len = sd->output_extradata_len, - .sh = sub->init_sd.sh, - .video_fps = sub->init_sd.video_fps, - .ass_library = sub->init_sd.ass_library, - .ass_renderer = sub->init_sd.ass_renderer, - .ass_lock = sub->init_sd.ass_lock, - }; - } + struct sd *sd = talloc(NULL, struct sd); + *sd = init_sd; - sub_uninit(sub); - MP_ERR(sub, "Could not find subtitle decoder for format '%s'.\n", - sh->codec ? sh->codec : ""); - pthread_mutex_unlock(&sub->lock); -} - -static struct demux_packet *get_decoded_packet(struct sd *sd) -{ - return sd->driver->get_converted ? sd->driver->get_converted(sd) : NULL; -} - -static void decode_chain(struct sd **sd, int num_sd, struct demux_packet *packet) -{ - if (num_sd == 0) + if (sub_init_decoder(sub, sd) < 0) { + sd->driver->uninit(sd); + talloc_free(sd); + MP_ERR(sub, "Could not find subtitle decoder for format '%s'.\n", + sh->codec ? sh->codec : ""); + pthread_mutex_unlock(&sub->lock); return; - struct sd *dec = sd[0]; - dec->driver->decode(dec, packet); - if (num_sd > 1) { - while (1) { - struct demux_packet *next = get_decoded_packet(dec); - if (!next) - break; - decode_chain(sd + 1, num_sd - 1, next); - } } + + sub->sd = sd; + pthread_mutex_unlock(&sub->lock); } static struct demux_packet *recode_packet(struct mp_log *log, @@ -283,11 +210,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->num_sd > 0) { + 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); - decode_chain(sub->sd, sub->num_sd, recoded ? recoded : packet); + sub->sd->driver->decode(sub->sd, recoded ? recoded : packet); talloc_free(recoded); } } @@ -301,9 +228,6 @@ void sub_decode(struct dec_sub *sub, struct demux_packet *packet) static void add_sub_list(struct dec_sub *sub, struct packet_list *subs) { - struct sd *sd = sub_get_last_sd(sub); - assert(sd); - for (int n = 0; n < subs->num_packets; n++) decode_chain_recode(sub, subs->packets[n]); } @@ -326,8 +250,7 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh) pthread_mutex_lock(&sub->lock); // Converters are assumed to always accept packets in advance - struct sd *sd = sub_get_last_sd(sub); - if (!(sd && sd->driver->accept_packets_in_advance)) { + if (!(sub->sd && sub->sd->driver->accept_packets_in_advance)) { pthread_mutex_unlock(&sub->lock); return false; } @@ -353,10 +276,8 @@ bool sub_accepts_packet_in_advance(struct dec_sub *sub) { bool res = true; pthread_mutex_lock(&sub->lock); - for (int n = 0; n < sub->num_sd; n++) { - if (sub->sd[n]->driver->accepts_packet) - res &= sub->sd[n]->driver->accepts_packet(sub->sd[n]); - } + if (sub->sd && sub->sd->driver->accepts_packet) + res &= sub->sd->driver->accepts_packet(sub->sd); pthread_mutex_unlock(&sub->lock); return res; } @@ -368,22 +289,10 @@ void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, double pts, struct sub_bitmaps *res) { struct MPOpts *opts = sub->opts; - struct sd *sd = sub_get_last_sd(sub); *res = (struct sub_bitmaps) {0}; - if (sd && opts->sub_visibility) { - if (sd->driver->get_bitmaps) - sd->driver->get_bitmaps(sd, dim, pts, res); - } -} - -bool sub_has_get_text(struct dec_sub *sub) -{ - pthread_mutex_lock(&sub->lock); - struct sd *sd = sub_get_last_sd(sub); - bool r = sd && sd->driver->get_text; - pthread_mutex_unlock(&sub->lock); - return r; + if (sub->sd && opts->sub_visibility && sub->sd->driver->get_bitmaps) + sub->sd->driver->get_bitmaps(sub->sd, dim, pts, res); } // See sub_get_bitmaps() for locking requirements. @@ -393,12 +302,9 @@ char *sub_get_text(struct dec_sub *sub, double pts) { pthread_mutex_lock(&sub->lock); struct MPOpts *opts = sub->opts; - struct sd *sd = sub_get_last_sd(sub); char *text = NULL; - if (sd && opts->sub_visibility) { - if (sd->driver->get_text) - text = sd->driver->get_text(sd, pts); - } + if (sub->sd && opts->sub_visibility && sub->sd->driver->get_text) + text = sub->sd->driver->get_text(sub->sd, pts); pthread_mutex_unlock(&sub->lock); return text; } @@ -406,10 +312,8 @@ char *sub_get_text(struct dec_sub *sub, double pts) void sub_reset(struct dec_sub *sub) { pthread_mutex_lock(&sub->lock); - for (int n = 0; n < sub->num_sd; n++) { - if (sub->sd[n]->driver->reset) - sub->sd[n]->driver->reset(sub->sd[n]); - } + if (sub->sd && sub->sd->driver->reset) + sub->sd->driver->reset(sub->sd); pthread_mutex_unlock(&sub->lock); } @@ -417,69 +321,8 @@ int sub_control(struct dec_sub *sub, enum sd_ctrl cmd, void *arg) { int r = CONTROL_UNKNOWN; pthread_mutex_lock(&sub->lock); - for (int n = 0; n < sub->num_sd; n++) { - if (sub->sd[n]->driver->control) { - r = sub->sd[n]->driver->control(sub->sd[n], cmd, arg); - if (r != CONTROL_UNKNOWN) - break; - } - } + if (sub->sd && sub->sd->driver->control) + r = sub->sd->driver->control(sub->sd, cmd, arg); pthread_mutex_unlock(&sub->lock); return r; } - -#define MAX_PACKETS 10 -#define MAX_BYTES 10000 - -struct sd_conv_buffer { - struct demux_packet pkt[MAX_PACKETS]; - int num_pkt; - int read_pkt; - char buffer[MAX_BYTES]; - int cur_buffer; -}; - -void sd_conv_add_packet(struct sd *sd, void *data, int data_len, double pts, - double duration, int64_t pos) -{ - if (!sd->sd_conv_buffer) - sd->sd_conv_buffer = talloc_zero(sd, struct sd_conv_buffer); - struct sd_conv_buffer *buf = sd->sd_conv_buffer; - if (buf->num_pkt >= MAX_PACKETS || buf->cur_buffer + data_len + 1 > MAX_BYTES) - goto out_of_space; - if (buf->read_pkt == buf->num_pkt) - sd_conv_def_reset(sd); - assert(buf->read_pkt == 0); // no mixing of reading/adding allowed - struct demux_packet *pkt = &buf->pkt[buf->num_pkt++]; - *pkt = (struct demux_packet) { - .buffer = &buf->buffer[buf->cur_buffer], - .len = data_len, - .pts = pts, - .duration = duration, - .pos = pos, - }; - memcpy(pkt->buffer, data, data_len); - pkt->buffer[data_len] = 0; - buf->cur_buffer += data_len + 1; - return; - -out_of_space: - MP_ERR(sd, "Subtitle too big.\n"); -} - -struct demux_packet *sd_conv_def_get_converted(struct sd *sd) -{ - struct sd_conv_buffer *buf = sd->sd_conv_buffer; - if (buf && buf->read_pkt < buf->num_pkt) - return &buf->pkt[buf->read_pkt++]; - return NULL; -} - -void sd_conv_def_reset(struct sd *sd) -{ - struct sd_conv_buffer *buf = sd->sd_conv_buffer; - if (buf) { - buf->read_pkt = buf->num_pkt = 0; - buf->cur_buffer = 0; - } -} -- cgit v1.2.3