summaryrefslogtreecommitdiffstats
path: root/sub/sd_lavc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sub/sd_lavc.c')
-rw-r--r--sub/sd_lavc.c133
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);