diff --git a/Makefile b/Makefile index 495a42824e..4c4027787e 100644 --- a/Makefile +++ b/Makefile @@ -252,10 +252,10 @@ SRCS_COMMON = asxparser.c \ stream/stream_mf.c \ stream/stream_null.c \ stream/url.c \ - sub/av_sub.c \ sub/dec_sub.c \ sub/find_sub.c \ sub/find_subfiles.c \ + sub/sd_lavc.c \ sub/spudec.c \ sub/sub.c \ sub/subassconvert.c \ diff --git a/mplayer.c b/mplayer.c index b17b13c9c3..497517077c 100644 --- a/mplayer.c +++ b/mplayer.c @@ -80,7 +80,6 @@ #include "screenshot.h" #include "sub/sub.h" -#include "sub/av_sub.h" #include "cpudetect.h" #ifdef CONFIG_X11 @@ -587,8 +586,6 @@ static void uninit_subs(struct demuxer *demuxer) struct sh_sub *sh = demuxer->s_streams[i]; if (sh && sh->initialized) sub_uninit(sh); - if (sh && is_av_sub(sh->type)) - reset_avsub(sh); } } @@ -1747,7 +1744,6 @@ double playing_audio_pts(struct MPContext *mpctx) static void reset_subtitles(struct MPContext *mpctx) { struct sh_sub *sh_sub = mpctx->sh_sub; - int type = sh_sub ? sh_sub->type : '\0'; if (sh_sub) sub_reset(sh_sub, mpctx->osd); @@ -1758,8 +1754,6 @@ static void reset_subtitles(struct MPContext *mpctx) spudec_reset(vo_spudec); vo_osd_changed(OSDTYPE_SPU); } - if (sh_sub && is_av_sub(type)) - reset_avsub(sh_sub); } static void update_subtitles(struct MPContext *mpctx, double refpts_tl) @@ -1836,7 +1830,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) if (track->vobsub_id_plus_one || timestamp >= 0) spudec_assemble(vo_spudec, packet, len, timestamp); } - } else if (d_sub && (is_text_sub(type) || is_av_sub(type))) { + } else if (d_sub && (is_text_sub(type) || (sh_sub && sh_sub->active))) { if (d_sub->non_interleaved) ds_get_next_pts(d_sub); @@ -1852,13 +1846,6 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) } double duration = d_sub->first->duration; len = ds_get_packet_sub(d_sub, &packet); - if (is_av_sub(type)) { - int ret = decode_avsub(sh_sub, packet, len, subpts_s, duration); - if (ret < 0) - mp_msg(MSGT_SPUDEC, MSGL_WARN, "lavc failed decoding " - "subtitle\n"); - continue; - } if (type == 'm') { if (len < 2) continue; @@ -1869,6 +1856,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) sub_decode(sh_sub, mpctx->osd, packet, len, subpts_s, duration); continue; } + // is_text_sub() case if (subpts_s != MP_NOPTS_VALUE) { if (duration < 0) sub_clear_text(&mpctx->subs, MP_NOPTS_VALUE); diff --git a/sub/av_sub.h b/sub/av_sub.h deleted file mode 100644 index ee6205c87d..0000000000 --- a/sub/av_sub.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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_AV_SUB_H -#define MPLAYER_AV_SUB_H - -#include - -struct sh_sub; - -void reset_avsub(struct sh_sub *sh); -int decode_avsub(struct sh_sub *sh, uint8_t *data, int size, - double pts, double endpts); -bool is_av_sub(int type); - -#endif /* MPLAYER_AV_SUB_H */ diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 6a6d1d77e5..7528e90e58 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -27,6 +27,7 @@ #include "options.h" extern const struct sd_functions sd_ass; +extern const struct sd_functions sd_lavc; void sub_init(struct sh_sub *sh, struct osd_state *osd) { @@ -36,8 +37,11 @@ void sub_init(struct sh_sub *sh, struct osd_state *osd) if (opts->ass_enabled && is_text_sub(sh->type)) sh->sd_driver = &sd_ass; #endif + if (strchr("bpx", sh->type)) + sh->sd_driver = &sd_lavc; if (sh->sd_driver) { - sh->sd_driver->init(sh, osd); + if (sh->sd_driver->init(sh, osd) < 0) + return; sh->initialized = true; sh->active = true; } diff --git a/sub/sd.h b/sub/sd.h index d5aea5c1a6..c36110277b 100644 --- a/sub/sd.h +++ b/sub/sd.h @@ -5,7 +5,7 @@ struct osd_state; struct sh_sub; struct sd_functions { - void (*init)(struct sh_sub *sh, struct osd_state *osd); + int (*init)(struct sh_sub *sh, struct osd_state *osd); void (*decode)(struct sh_sub *sh, struct osd_state *osd, void *data, int data_len, double pts, double duration); void (*reset)(struct sh_sub *sh, struct osd_state *osd); diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 69587646e4..b8924fbb3f 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -43,7 +43,7 @@ static void free_last_event(ASS_Track *track) track->n_events--; } -static void init(struct sh_sub *sh, struct osd_state *osd) +static int init(struct sh_sub *sh, struct osd_state *osd) { struct sd_ass_priv *ctx; @@ -65,6 +65,7 @@ static void init(struct sh_sub *sh, struct osd_state *osd) osd->ass_track = ctx->ass_track; osd->vsfilter_aspect = sh->type == 'a'; osd->ass_track_changed = true; + return 0; } static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, diff --git a/sub/av_sub.c b/sub/sd_lavc.c similarity index 67% rename from sub/av_sub.c rename to sub/sd_lavc.c index dbf349133f..a4eafff429 100644 --- a/sub/av_sub.c +++ b/sub/sd_lavc.c @@ -1,41 +1,30 @@ /* - * This file is part of MPlayer. + * This file is part of mplayer2. * - * MPlayer is free software; you can redistribute it and/or modify + * mplayer2 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, + * mplayer2 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. + * with mplayer2. If not, see . */ +#include + #include #include "mp_msg.h" #include "libmpdemux/stheader.h" -#include "sub.h" +#include "sd.h" #include "spudec.h" -#include "av_sub.h" - -bool is_av_sub(int type) -{ - return type == 'b' || type == 'p' || type == 'x'; -} - -void reset_avsub(struct sh_sub *sh) -{ - if (sh->context) { - avcodec_close(sh->context); - av_freep(&sh->context); - } -} +// Current code still pushes subs directly to global spudec +#include "sub.h" static void avsub_to_spudec(AVSubtitleRect **rects, int num_rects, double pts, double endpts) @@ -78,20 +67,9 @@ static void avsub_to_spudec(AVSubtitleRect **rects, int num_rects, spudec_packet_send(vo_spudec, packet, pts, endpts); } -/** - * Decode a subtitle packet via libavcodec. - * \return < 0 on error, > 0 if further processing is needed - */ -int decode_avsub(struct sh_sub *sh, uint8_t *data, int size, - double pts, double duration) +static int init(struct sh_sub *sh, struct osd_state *osd) { - AVCodecContext *ctx = sh->context; enum CodecID cid = CODEC_ID_NONE; - int res; - int got_sub; - AVSubtitle sub; - AVPacket pkt; - switch (sh->type) { case 'b': cid = CODEC_ID_DVB_SUBTITLE; break; @@ -100,33 +78,42 @@ int decode_avsub(struct sh_sub *sh, uint8_t *data, int size, case 'x': cid = CODEC_ID_XSUB; break; } + AVCodecContext *ctx = NULL; + AVCodec *sub_codec = avcodec_find_decoder(cid); + if (!sub_codec) + goto error; + ctx = avcodec_alloc_context3(sub_codec); + if (!ctx) + goto error; + if (avcodec_open2(ctx, sub_codec, NULL) < 0) + goto error; + sh->context = ctx; + return 0; + + error: + mp_msg(MSGT_SUBREADER, MSGL_ERR, + "Could not open libavcodec subtitle decoder\n"); + av_free(ctx); + return -1; +} + +static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, + int data_len, double pts, double duration) +{ + AVCodecContext *ctx = sh->context; + AVSubtitle sub; + AVPacket pkt; av_init_packet(&pkt); pkt.data = data; - pkt.size = size; + pkt.size = data_len; pkt.pts = pts * 1000; if (duration >= 0) pkt.convergence_duration = duration * 1000; - if (!ctx) { - AVCodec *sub_codec; - sub_codec = avcodec_find_decoder(cid); - if (!sub_codec) - goto error; - ctx = avcodec_alloc_context3(sub_codec); - if (!ctx) - goto error; - if (avcodec_open2(ctx, sub_codec, NULL) < 0) { - error: - mp_msg(MSGT_SUBREADER, MSGL_FATAL, - "Could not open subtitle decoder\n"); - av_freep(&ctx); - return -1; - } - sh->context = ctx; - } - res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt); - if (res < 0) - return res; + int got_sub; + int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt); + if (res < 0 || !got_sub) + return; if (pts != MP_NOPTS_VALUE) { if (sub.end_display_time > sub.start_display_time) duration = (sub.end_display_time - sub.start_display_time) / 1000.0; @@ -135,9 +122,9 @@ int decode_avsub(struct sh_sub *sh, uint8_t *data, int size, double endpts = MP_NOPTS_VALUE; if (pts != MP_NOPTS_VALUE && duration >= 0) endpts = pts + duration; - if (got_sub && vo_spudec && sub.num_rects == 0) + if (vo_spudec && sub.num_rects == 0) spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, pts, endpts); - if (got_sub && sub.num_rects > 0) { + if (sub.num_rects > 0) { switch (sub.rects[0]->type) { case SUBTITLE_BITMAP: if (!vo_spudec) @@ -146,13 +133,30 @@ int decode_avsub(struct sh_sub *sh, uint8_t *data, int size, vo_osd_changed(OSDTYPE_SPU); break; default: - mp_msg(MSGT_SUBREADER, MSGL_ERR, "sd_avsub: unsupported subtitle " + mp_msg(MSGT_SUBREADER, MSGL_ERR, "sd_lavc: unsupported subtitle " "type from libavcodec\n"); - res = -1; break; } } - if (got_sub) - avsubtitle_free(&sub); - return res; + avsubtitle_free(&sub); } + +static void reset(struct sh_sub *sh, struct osd_state *osd) +{ + // lavc might not do this right for all codecs; may need close+reopen + avcodec_flush_buffers(sh->context); +} + +static void uninit(struct sh_sub *sh) +{ + avcodec_close(sh->context); + av_free(sh->context); +} + +const struct sd_functions sd_lavc = { + .init = init, + .decode = decode, + .reset = reset, + .switch_off = reset, + .uninit = uninit, +};