summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmpcodecs/vf_ass.c1
-rw-r--r--libmpcodecs/vf_vo.c1
-rw-r--r--libmpcodecs/vfcap.h1
-rw-r--r--libvo/bitmap_packer.c48
-rw-r--r--libvo/bitmap_packer.h8
-rw-r--r--libvo/vo_vdpau.c111
-rw-r--r--sub/dec_sub.c3
-rw-r--r--sub/dec_sub.h19
-rw-r--r--sub/sd_ass.c1
-rw-r--r--sub/sd_lavc.c131
-rw-r--r--sub/sub.h1
11 files changed, 273 insertions, 52 deletions
diff --git a/libmpcodecs/vf_ass.c b/libmpcodecs/vf_ass.c
index ad4671fe57..f0b2e6ab77 100644
--- a/libmpcodecs/vf_ass.c
+++ b/libmpcodecs/vf_ass.c
@@ -364,6 +364,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
osd->normal_scale = vf->priv->aspect_correction;
osd->vsfilter_scale = 1;
osd->sub_pts = pts - osd->sub_offset;
+ osd->support_rgba = false;
struct sub_bitmaps b;
sub_get_bitmaps(osd, &b);
images = b.imgs;
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index 3aec40cd15..862cd63492 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -119,6 +119,7 @@ static int control(struct vf_instance *vf, int request, void *data)
}
case VFCTRL_DRAW_EOSD: {
struct osd_state *osd = data;
+ osd->support_rgba = vf->default_caps & VFCAP_EOSD_RGBA;
osd->dim = (struct mp_eosd_res){0};
if (!video_out->config_ok ||
vo_control(video_out, VOCTRL_GET_EOSD_RES, &osd->dim) != true)
diff --git a/libmpcodecs/vfcap.h b/libmpcodecs/vfcap.h
index 86c6f6e477..aef75840ae 100644
--- a/libmpcodecs/vfcap.h
+++ b/libmpcodecs/vfcap.h
@@ -48,5 +48,6 @@
#define VOCAP_NOSLICES 0x8000
#define VFCAP_OSD_FILTER 0x10000 // OSD is drawn in filter chain
#define VFCAP_EOSD_FILTER 0x20000 // EOSD is drawn in filter chain
+#define VFCAP_EOSD_RGBA 0x40000
#endif /* MPLAYER_VFCAP_H */
diff --git a/libvo/bitmap_packer.c b/libvo/bitmap_packer.c
index 2ae8a1eee0..eedc2e2242 100644
--- a/libvo/bitmap_packer.c
+++ b/libvo/bitmap_packer.c
@@ -28,6 +28,7 @@
#include "mp_msg.h"
#include "mpcommon.h"
#include "sub/ass_mp.h"
+#include "sub/dec_sub.h"
#define HEIGHT_SORT_BITS 4
@@ -55,7 +56,7 @@ static int size_index(int s)
* free rectangle with corners (13, 20)-(w, 50) is filled recursively.
*/
static int pack_rectangles(struct pos *in, struct pos *out, int num_rects,
- int w, int h, int *scratch)
+ int w, int h, int *scratch, int *used_width)
{
int bins[16 << HEIGHT_SORT_BITS];
int sizes[16 << HEIGHT_SORT_BITS] = { 0 };
@@ -100,11 +101,12 @@ static int pack_rectangles(struct pos *in, struct pos *out, int num_rects,
s.x = right;
maxy = FFMAX(maxy, bottom);
}
+ *used_width = FFMAX(*used_width, s.x);
if (maxy > 0)
s.bottom = maxy;
}
}
- return num_rects ? -1 : 0;
+ return num_rects ? -1 : y;
}
int packer_pack(struct bitmap_packer *packer)
@@ -115,7 +117,7 @@ int packer_pack(struct bitmap_packer *packer)
struct pos *in = packer->in;
int xmax = 0, ymax = 0;
for (int i = 0; i < packer->count; i++) {
- if (in[i].x == 0 || in[i].y == 0)
+ if (in[i].x <= packer->padding || in[i].y <= packer->padding)
in[i] = (struct pos){0, 0};
if (in[i].x < 0 || in [i].x > 65535 || in[i].y < 0 || in[i].y > 65535) {
mp_msg(MSGT_VO, MSGL_FATAL, "Invalid OSD / subtitle bitmap size\n");
@@ -124,20 +126,33 @@ int packer_pack(struct bitmap_packer *packer)
xmax = FFMAX(xmax, in[i].x);
ymax = FFMAX(ymax, in[i].y);
}
+ xmax = FFMAX(0, xmax - packer->padding);
+ ymax = FFMAX(0, ymax - packer->padding);
if (xmax > packer->w)
packer->w = 1 << av_log2(xmax - 1) + 1;
if (ymax > packer->h)
packer->h = 1 << av_log2(ymax - 1) + 1;
while (1) {
- if (pack_rectangles(in, packer->result, packer->count, packer->w,
- packer->h, packer->scratch) >= 0)
+ int used_width = 0;
+ int y = pack_rectangles(in, packer->result, packer->count,
+ packer->w + packer->padding,
+ packer->h + packer->padding,
+ packer->scratch, &used_width);
+ if (y >= 0) {
+ // No padding at edges
+ packer->used_width = FFMIN(used_width, packer->w);
+ packer->used_height = FFMIN(y, packer->h);
return packer->w != w_orig || packer->h != h_orig;
+ }
if (packer->w <= packer->h && packer->w != packer->w_max)
packer->w = FFMIN(packer->w * 2, packer->w_max);
else if (packer->h != packer->h_max)
packer->h = FFMIN(packer->h * 2, packer->h_max);
- else
+ else {
+ packer->w = w_orig;
+ packer->h = h_orig;
return -1;
+ }
}
}
@@ -156,8 +171,8 @@ void packer_set_size(struct bitmap_packer *packer, int size)
packer->asize + 16);
}
-int packer_pack_from_assimg(struct bitmap_packer *packer,
- struct ass_image *imglist)
+static int packer_pack_from_assimg(struct bitmap_packer *packer,
+ struct ass_image *imglist)
{
int count = 0;
struct ass_image *img = imglist;
@@ -172,3 +187,20 @@ int packer_pack_from_assimg(struct bitmap_packer *packer,
packer->count = count;
return packer_pack(packer);
}
+
+int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
+ struct sub_bitmaps *b, int padding_pixels)
+{
+ packer->padding = 0;
+ packer->count = 0;
+ if (b->type == SUBBITMAP_EMPTY)
+ return 0;
+ if (b->type == SUBBITMAP_LIBASS)
+ return packer_pack_from_assimg(packer, b->imgs);
+ packer->padding = padding_pixels;
+ packer_set_size(packer, b->part_count);
+ int a = packer->padding;
+ for (int i = 0; i < b->part_count; i++)
+ packer->in[i] = (struct pos){b->parts[i].w + a, b->parts[i].h + a};
+ return packer_pack(packer);
+}
diff --git a/libvo/bitmap_packer.h b/libvo/bitmap_packer.h
index 45b6fbc4ae..c7c377cbd0 100644
--- a/libvo/bitmap_packer.h
+++ b/libvo/bitmap_packer.h
@@ -11,9 +11,12 @@ struct bitmap_packer {
int h;
int w_max;
int h_max;
+ int padding;
int count;
struct pos *in;
struct pos *result;
+ int used_width;
+ int used_height;
// internal
int *scratch;
@@ -21,6 +24,7 @@ struct bitmap_packer {
};
struct ass_image;
+struct sub_bitmaps;
/* Reallocate packer->in for at least to desired number of items.
* Also sets packer->count to the same value.
@@ -41,7 +45,7 @@ int packer_pack(struct bitmap_packer *packer);
* packer->in will be reallocated if needed and filled from the
* given image list.
*/
-int packer_pack_from_assimg(struct bitmap_packer *packer,
- struct ass_image *imglist);
+int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
+ struct sub_bitmaps *b, int padding_pixels);
#endif
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c
index 922ec24201..594829b394 100644
--- a/libvo/vo_vdpau.c
+++ b/libvo/vo_vdpau.c
@@ -172,6 +172,7 @@ struct vdpctx {
// EOSD
struct eosd_bitmap_surface {
+ VdpRGBAFormat format;
VdpBitmapSurface surface;
uint32_t max_width;
uint32_t max_height;
@@ -1007,16 +1008,35 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs)
vc->eosd_render_count = 0;
- if (!imgs->imgs)
- return; // There's nothing to render!
+ if (imgs->type == SUBBITMAP_EMPTY)
+ return;
if (imgs->bitmap_id == vc->bitmap_id)
goto eosd_skip_upload;
need_upload = true;
+ VdpRGBAFormat format;
+ int format_size;
+ switch (imgs->type) {
+ case SUBBITMAP_LIBASS:
+ format = VDP_RGBA_FORMAT_A8;
+ format_size = 1;
+ break;
+ case SUBBITMAP_RGBA:
+ format = VDP_RGBA_FORMAT_B8G8R8A8;
+ format_size = 4;
+ break;
+ default:
+ abort();
+ };
+ if (sfc->format != format) {
+ talloc_free(sfc->packer);
+ sfc->packer = NULL;
+ };
+ sfc->format = format;
if (!sfc->packer)
- sfc->packer = make_packer(vo, VDP_RGBA_FORMAT_A8);
- int r = packer_pack_from_assimg(sfc->packer, imgs->imgs);
+ sfc->packer = make_packer(vo, format);
+ int r = packer_pack_from_subbitmaps(sfc->packer, imgs, imgs->scaled);
if (r < 0) {
mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] EOSD bitmaps do not fit on "
"a surface with the maximum supported size\n");
@@ -1028,13 +1048,21 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs)
}
mp_msg(MSGT_VO, MSGL_V, "[vdpau] Allocating a %dx%d surface for "
"EOSD bitmaps.\n", sfc->packer->w, sfc->packer->h);
- vdp_st = vdp->bitmap_surface_create(vc->vdp_device, VDP_RGBA_FORMAT_A8,
+ vdp_st = vdp->bitmap_surface_create(vc->vdp_device, format,
sfc->packer->w, sfc->packer->h,
true, &sfc->surface);
if (vdp_st != VDP_STATUS_OK)
sfc->surface = VDP_INVALID_HANDLE;
CHECK_ST_WARNING("EOSD: error when creating surface");
}
+ if (imgs->scaled) {
+ char zeros[sfc->packer->used_width * format_size];
+ memset(zeros, 0, sizeof(zeros));
+ vdp_st = vdp->bitmap_surface_put_bits_native(sfc->surface,
+ &(const void *){zeros}, &(uint32_t){0},
+ &(VdpRect){0, 0, sfc->packer->used_width,
+ sfc->packer->used_height});
+ }
eosd_skip_upload:
if (sfc->surface == VDP_INVALID_HANDLE)
@@ -1046,31 +1074,54 @@ eosd_skip_upload:
* sizeof(*vc->eosd_targets));
}
- int i = 0;
- for (ASS_Image *p = imgs->imgs; p; p = p->next, i++) {
- if (p->w == 0 || p->h == 0)
- continue;
- struct eosd_target *target = &vc->eosd_targets[vc->eosd_render_count];
- int x = sfc->packer->result[i].x;
- int y = sfc->packer->result[i].y;
- target->source = (VdpRect){x, y, x + p->w, y + p->h};
- if (need_upload) {
- vdp_st = vdp->
- bitmap_surface_put_bits_native(sfc->surface,
- (const void *) &p->bitmap,
- &p->stride, &target->source);
- CHECK_ST_WARNING("EOSD: putbits failed");
+ if (imgs->type == SUBBITMAP_LIBASS) {
+ int i = 0;
+ for (ASS_Image *p = imgs->imgs; p; p = p->next, i++) {
+ if (p->w == 0 || p->h == 0)
+ continue;
+ struct eosd_target *target = vc->eosd_targets +
+ vc->eosd_render_count;
+ int x = sfc->packer->result[i].x;
+ int y = sfc->packer->result[i].y;
+ target->source = (VdpRect){x, y, x + p->w, y + p->h};
+ if (need_upload) {
+ vdp_st = vdp->
+ bitmap_surface_put_bits_native(sfc->surface,
+ (const void *) &p->bitmap,
+ &p->stride, &target->source);
+ CHECK_ST_WARNING("EOSD: putbits failed");
+ }
+ // Render dest, color, etc.
+ target->color.alpha = 1.0 - ((p->color >> 0) & 0xff) / 255.0;
+ target->color.blue = ((p->color >> 8) & 0xff) / 255.0;
+ target->color.green = ((p->color >> 16) & 0xff) / 255.0;
+ target->color.red = ((p->color >> 24) & 0xff) / 255.0;
+ target->dest.x0 = p->dst_x;
+ target->dest.y0 = p->dst_y;
+ target->dest.x1 = p->w + p->dst_x;
+ target->dest.y1 = p->h + p->dst_y;
+ vc->eosd_render_count++;
+ }
+ } else {
+ for (int i = 0 ;i < sfc->packer->count; i++) {
+ struct sub_bitmap *b = &imgs->parts[i];
+ struct eosd_target *target = vc->eosd_targets +
+ vc->eosd_render_count;
+ int x = sfc->packer->result[i].x;
+ int y = sfc->packer->result[i].y;
+ target->source = (VdpRect){x, y, x + b->w, y + b->h};
+ if (need_upload) {
+ vdp_st = vdp->
+ bitmap_surface_put_bits_native(sfc->surface,
+ &(const void *){b->bitmap},
+ &(uint32_t){b->w * 4},
+ &target->source);
+ CHECK_ST_WARNING("EOSD: putbits failed");
+ }
+ target->color = (VdpColor){1, 1, 1, 1};
+ target->dest = (VdpRect){b->x, b->y, b->x + b->dw, b->y + b->dh};
+ vc->eosd_render_count++;
}
- // Render dest, color, etc.
- target->color.alpha = 1.0 - ((p->color >> 0) & 0xff) / 255.0;
- target->color.blue = ((p->color >> 8) & 0xff) / 255.0;
- target->color.green = ((p->color >> 16) & 0xff) / 255.0;
- target->color.red = ((p->color >> 24) & 0xff) / 255.0;
- target->dest.x0 = p->dst_x;
- target->dest.y0 = p->dst_y;
- target->dest.x1 = p->w + p->dst_x;
- target->dest.y1 = p->h + p->dst_y;
- vc->eosd_render_count++;
}
vc->bitmap_id = imgs->bitmap_id;
vc->bitmap_pos_id = imgs->bitmap_pos_id;
@@ -1529,7 +1580,7 @@ static int query_format(uint32_t format)
{
int default_flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_EOSD
- | VFCAP_EOSD_UNSCALED | VFCAP_FLIP;
+ | VFCAP_EOSD_UNSCALED | VFCAP_EOSD_RGBA | VFCAP_FLIP;
switch (format) {
case IMGFMT_YV12:
case IMGFMT_I420:
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index 3278c10d85..4a048b27a6 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -62,7 +62,8 @@ void sub_get_bitmaps(struct osd_state *osd, struct sub_bitmaps *res)
{
struct MPOpts *opts = osd->opts;
- *res = (struct sub_bitmaps){ .bitmap_id = osd->bitmap_id,
+ *res = (struct sub_bitmaps){ .type = SUBBITMAP_EMPTY,
+ .bitmap_id = osd->bitmap_id,
.bitmap_pos_id = osd->bitmap_pos_id };
if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) {
/* Change ID in case we just switched from visible subtitles
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index efbfdc9ce7..c71a2348aa 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -5,13 +5,32 @@ struct sh_sub;
struct osd_state;
struct ass_track;
+enum sub_bitmap_type {
+ SUBBITMAP_EMPTY,
+ SUBBITMAP_LIBASS,
+ SUBBITMAP_RGBA,
+};
+
typedef struct mp_eosd_res {
int w, h; // screen dimensions, including black borders
int mt, mb, ml, mr; // borders (top, bottom, left, right)
} mp_eosd_res_t;
typedef struct sub_bitmaps {
+ enum sub_bitmap_type type;
+
struct ass_image *imgs;
+
+ struct sub_bitmap {
+ int w, h;
+ int x, y;
+ // Note: not clipped, going outside the screen area is allowed
+ int dw, dh;
+ void *bitmap;
+ } *parts;
+ int part_count;
+
+ bool scaled;
int bitmap_id, bitmap_pos_id;
} mp_eosd_images_t;
diff --git a/sub/sd_ass.c b/sub/sd_ass.c
index 37c220a4b5..9295cab07d 100644
--- a/sub/sd_ass.c
+++ b/sub/sd_ass.c
@@ -147,6 +147,7 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
res->bitmap_id = ++res->bitmap_pos_id;
else if (changed)
res->bitmap_pos_id++;
+ res->type = SUBBITMAP_LIBASS;
}
static void reset(struct sh_sub *sh, struct osd_state *osd)
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index a4eafff429..1da33ffca1 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -19,6 +19,7 @@
#include <libavcodec/avcodec.h>
+#include "talloc.h"
#include "mp_msg.h"
#include "libmpdemux/stheader.h"
#include "sd.h"
@@ -26,8 +27,17 @@
// 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)
+struct sd_lavc_priv {
+ AVCodecContext *avctx;
+ int count;
+ struct sub_bitmap *inbitmaps;
+ struct sub_bitmap *outbitmaps;
+ bool bitmaps_changed;
+ double endpts;
+};
+
+static void old_avsub_to_spudec(AVSubtitleRect **rects, int num_rects,
+ double pts, double endpts)
{
int i, xmin = INT_MAX, ymin = INT_MAX, xmax = INT_MIN, ymax = INT_MIN;
struct spu_packet_t *packet;
@@ -69,6 +79,9 @@ static void avsub_to_spudec(AVSubtitleRect **rects, int num_rects,
static int init(struct sh_sub *sh, struct osd_state *osd)
{
+ if (sh->initialized)
+ return 0;
+ struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv);
enum CodecID cid = CODEC_ID_NONE;
switch (sh->type) {
case 'b':
@@ -77,6 +90,8 @@ static int init(struct sh_sub *sh, struct osd_state *osd)
cid = CODEC_ID_HDMV_PGS_SUBTITLE; break;
case 'x':
cid = CODEC_ID_XSUB; break;
+ case 'v':
+ cid = CODEC_ID_DVD_SUBTITLE; break;
}
AVCodecContext *ctx = NULL;
AVCodec *sub_codec = avcodec_find_decoder(cid);
@@ -85,25 +100,41 @@ static int init(struct sh_sub *sh, struct osd_state *osd)
ctx = avcodec_alloc_context3(sub_codec);
if (!ctx)
goto error;
+ ctx->extradata_size = sh->extradata_len;
+ ctx->extradata = sh->extradata;
if (avcodec_open2(ctx, sub_codec, NULL) < 0)
goto error;
- sh->context = ctx;
+ priv->avctx = ctx;
+ sh->context = priv;
return 0;
error:
mp_msg(MSGT_SUBREADER, MSGL_ERR,
"Could not open libavcodec subtitle decoder\n");
av_free(ctx);
+ talloc_free(priv);
return -1;
}
+static void clear(struct sd_lavc_priv *priv)
+{
+ priv->count = 0;
+ talloc_free(priv->inbitmaps);
+ talloc_free(priv->outbitmaps);
+ priv->inbitmaps = priv->outbitmaps = NULL;
+ priv->bitmaps_changed = true;
+ priv->endpts = MP_NOPTS_VALUE;
+}
+
static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
int data_len, double pts, double duration)
{
- AVCodecContext *ctx = sh->context;
+ struct sd_lavc_priv *priv = sh->context;
+ AVCodecContext *ctx = priv->avctx;
AVSubtitle sub;
AVPacket pkt;
+ clear(priv);
av_init_packet(&pkt);
pkt.data = data;
pkt.size = data_len;
@@ -127,10 +158,37 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
if (sub.num_rects > 0) {
switch (sub.rects[0]->type) {
case SUBTITLE_BITMAP:
- if (!vo_spudec)
- vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, NULL, 0);
- avsub_to_spudec(sub.rects, sub.num_rects, pts, endpts);
- vo_osd_changed(OSDTYPE_SPU);
+ // 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);
+ 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;
+ 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;
break;
default:
mp_msg(MSGT_SUBREADER, MSGL_ERR, "sd_lavc: unsupported subtitle "
@@ -141,21 +199,72 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
avsubtitle_free(&sub);
}
+static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
+ 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))
+ 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;
+ 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);
+ }
+ res->parts = priv->outbitmaps;
+ res->part_count = 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->scaled = xscale != 1 || yscale != 1;
+}
+
static void reset(struct sh_sub *sh, struct osd_state *osd)
{
+ struct sd_lavc_priv *priv = sh->context;
+
+ clear(priv);
// lavc might not do this right for all codecs; may need close+reopen
- avcodec_flush_buffers(sh->context);
+ avcodec_flush_buffers(priv->avctx);
}
static void uninit(struct sh_sub *sh)
{
- avcodec_close(sh->context);
- av_free(sh->context);
+ struct sd_lavc_priv *priv = sh->context;
+
+ avcodec_close(priv->avctx);
+ av_free(priv->avctx);
+ talloc_free(priv);
}
const struct sd_functions sd_lavc = {
.init = init,
.decode = decode,
+ .get_bitmaps = get_bitmaps,
.reset = reset,
.switch_off = reset,
.uninit = uninit,
diff --git a/sub/sub.h b/sub/sub.h
index 9fd6c5329e..fc0047bba6 100644
--- a/sub/sub.h
+++ b/sub/sub.h
@@ -71,6 +71,7 @@ struct osd_state {
double normal_scale;
double vsfilter_scale;
bool unscaled;
+ bool support_rgba;
struct ass_renderer *osd_render;
struct ass_library *osd_ass_library;