diff options
Diffstat (limited to 'sub/sd_lavc.c')
-rw-r--r-- | sub/sd_lavc.c | 133 |
1 files changed, 50 insertions, 83 deletions
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index 1da33ffca1..bee224c506 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -16,6 +16,7 @@ */ #include <stdlib.h> +#include <assert.h> #include <libavcodec/avcodec.h> @@ -23,58 +24,39 @@ #include "mp_msg.h" #include "libmpdemux/stheader.h" #include "sd.h" -#include "spudec.h" -// Current code still pushes subs directly to global spudec +#include "dec_sub.h" #include "sub.h" struct sd_lavc_priv { AVCodecContext *avctx; + AVSubtitle sub; + bool have_sub; int count; struct sub_bitmap *inbitmaps; struct sub_bitmap *outbitmaps; + struct osd_bmp_indexed *imgs; bool bitmaps_changed; double endpts; }; -static void old_avsub_to_spudec(AVSubtitleRect **rects, int num_rects, - double pts, double endpts) +static void guess_resolution(char type, int *w, int *h) { - int i, xmin = INT_MAX, ymin = INT_MAX, xmax = INT_MIN, ymax = INT_MIN; - struct spu_packet_t *packet; - - if (num_rects == 1) { - spudec_set_paletted(vo_spudec, - rects[0]->pict.data[0], - rects[0]->pict.linesize[0], - rects[0]->pict.data[1], - rects[0]->x, - rects[0]->y, - rects[0]->w, - rects[0]->h, - pts, - endpts); - return; - } - for (i = 0; i < num_rects; i++) { - xmin = FFMIN(xmin, rects[i]->x); - ymin = FFMIN(ymin, rects[i]->y); - xmax = FFMAX(xmax, rects[i]->x + rects[i]->w); - ymax = FFMAX(ymax, rects[i]->y + rects[i]->h); + if (type == 'v') { + /* XXX Although the video frame is some size, the SPU frame is + always maximum size i.e. 720 wide and 576 or 480 high */ + // For HD files in MKV the VobSub resolution can be higher though, + // see largeres_vobsub.mkv + if (*w <= 720 && *h <= 576) { + *w = 720; + *h = (*h == 480 || *h == 240) ? 480 : 576; + } + } else { + // Hope that PGS subs set these and 720/576 works for dvb subs + if (!*w) + *w = 720; + if (!*h) + *h = 576; } - packet = spudec_packet_create(xmin, ymin, xmax - xmin, ymax - ymin); - if (!packet) - return; - spudec_packet_clear(packet); - for (i = 0; i < num_rects; i++) - spudec_packet_fill(packet, - rects[i]->pict.data[0], - rects[i]->pict.linesize[0], - rects[i]->pict.data[1], - rects[i]->x - xmin, - rects[i]->y - ymin, - rects[i]->w, - rects[i]->h); - spudec_packet_send(vo_spudec, packet, pts, endpts); } static int init(struct sh_sub *sh, struct osd_state *osd) @@ -122,8 +104,13 @@ static void clear(struct sd_lavc_priv *priv) talloc_free(priv->inbitmaps); talloc_free(priv->outbitmaps); priv->inbitmaps = priv->outbitmaps = NULL; + talloc_free(priv->imgs); + priv->imgs = NULL; priv->bitmaps_changed = true; priv->endpts = MP_NOPTS_VALUE; + if (priv->have_sub) + avsubtitle_free(&priv->sub); + priv->have_sub = false; } static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, @@ -145,6 +132,8 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt); if (res < 0 || !got_sub) return; + priv->sub = sub; + priv->have_sub = true; 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; @@ -153,39 +142,27 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, double endpts = MP_NOPTS_VALUE; if (pts != MP_NOPTS_VALUE && duration >= 0) endpts = pts + duration; - if (vo_spudec && sub.num_rects == 0) - spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, pts, endpts); if (sub.num_rects > 0) { switch (sub.rects[0]->type) { case SUBTITLE_BITMAP: - // Assume resolution heuristics only work for PGS and DVB - if (!osd->support_rgba || sh->type != 'p' && sh->type != 'b') { - if (!vo_spudec) - vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, - NULL, 0); - old_avsub_to_spudec(sub.rects, sub.num_rects, pts, endpts); - vo_osd_changed(OSDTYPE_SPU); - break; - } priv->inbitmaps = talloc_array(priv, struct sub_bitmap, sub.num_rects); + priv->imgs = talloc_array(priv, struct osd_bmp_indexed, + sub.num_rects); for (int i = 0; i < sub.num_rects; i++) { struct AVSubtitleRect *r = sub.rects[i]; struct sub_bitmap *b = &priv->inbitmaps[i]; - uint32_t *outbmp = talloc_size(priv->inbitmaps, - r->w * r->h * 4); - b->bitmap = outbmp; + struct osd_bmp_indexed *img = &priv->imgs[i]; + img->bitmap = r->pict.data[0]; + assert(r->nb_colors > 0); + assert(r->nb_colors * 4 <= sizeof(img->palette)); + memcpy(img->palette, r->pict.data[1], r->nb_colors * 4); + b->bitmap = img; + b->stride = r->pict.linesize[0]; b->w = r->w; b->h = r->h; b->x = r->x; b->y = r->y; - uint8_t *inbmp = r->pict.data[0]; - uint32_t *palette = (uint32_t *) r->pict.data[1]; - for (int y = 0; y < r->h; y++) { - for (int x = 0; x < r->w; x++) - *outbmp++ = palette[*inbmp++]; - inbmp += r->pict.linesize[0] - r->w; - }; } priv->count = sub.num_rects; priv->endpts = endpts; @@ -196,50 +173,39 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, break; } } - avsubtitle_free(&sub); } static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, + struct mp_osd_res d, double pts, struct sub_bitmaps *res) { struct sd_lavc_priv *priv = sh->context; - if (priv->endpts != MP_NOPTS_VALUE && (osd->sub_pts >= priv->endpts || - osd->sub_pts < priv->endpts - 300)) + if (priv->endpts != MP_NOPTS_VALUE && (pts >= priv->endpts || + pts < priv->endpts - 300)) clear(priv); - if (!osd->support_rgba) - return; if (priv->bitmaps_changed && priv->count > 0) priv->outbitmaps = talloc_memdup(priv, priv->inbitmaps, talloc_get_size(priv->inbitmaps)); - bool pos_changed = false; - // Hope that PGS subs set these and 720/576 works for dvb subs int inw = priv->avctx->width; - if (!inw) - inw = 720; int inh = priv->avctx->height; - if (!inh) - inh = 576; - struct mp_eosd_res *d = &osd->dim; - double xscale = (double) (d->w - d->ml - d->mr) / inw; - double yscale = (double) (d->h - d->mt - d->mb) / inh; + guess_resolution(sh->type, &inw, &inh); + double xscale = (double) (d.w - d.ml - d.mr) / inw; + double yscale = (double) (d.h - d.mt - d.mb) / inh; for (int i = 0; i < priv->count; i++) { struct sub_bitmap *bi = &priv->inbitmaps[i]; struct sub_bitmap *bo = &priv->outbitmaps[i]; -#define SET(var, val) pos_changed |= var != (int)(val); var = (val) - SET(bo->x, bi->x * xscale + d->ml); - SET(bo->y, bi->y * yscale + d->mt); - SET(bo->dw, bi->w * xscale); - SET(bo->dh, bi->h * yscale); + bo->x = bi->x * xscale + d.ml; + bo->y = bi->y * yscale + d.mt; + bo->dw = bi->w * xscale; + bo->dh = bi->h * yscale; } res->parts = priv->outbitmaps; - res->part_count = priv->count; + res->num_parts = priv->count; if (priv->bitmaps_changed) res->bitmap_id = ++res->bitmap_pos_id; - else if (pos_changed) - res->bitmap_pos_id++; priv->bitmaps_changed = false; - res->type = SUBBITMAP_RGBA; + res->format = SUBBITMAP_INDEXED; res->scaled = xscale != 1 || yscale != 1; } @@ -256,6 +222,7 @@ static void uninit(struct sh_sub *sh) { struct sd_lavc_priv *priv = sh->context; + clear(priv); avcodec_close(priv->avctx); av_free(priv->avctx); talloc_free(priv); |