summaryrefslogtreecommitdiffstats
path: root/libhb/rendersub.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/rendersub.c')
-rw-r--r--libhb/rendersub.c107
1 files changed, 103 insertions, 4 deletions
diff --git a/libhb/rendersub.c b/libhb/rendersub.c
index 4b0fae6d1..8d9f7f2c1 100644
--- a/libhb/rendersub.c
+++ b/libhb/rendersub.c
@@ -188,13 +188,112 @@ static void blend( hb_buffer_t *dst, hb_buffer_t *src, int left, int top )
}
}
-// applies subtitle 'sub' YUVA420P buffer into destination 'buf'
-// 'buf' is currently YUV420P, but in future will be other formats as well
+static void blend8on1x( hb_buffer_t *dst, hb_buffer_t *src, int left, int top, int shift )
+{
+ int xx, yy;
+ int ww, hh;
+ int x0, y0;
+ int max;
+
+ uint8_t *y_in;
+ uint8_t *u_in;
+ uint8_t *v_in;
+ uint8_t *a_in;
+
+ uint16_t *y_out;
+ uint16_t *u_out;
+ uint16_t *v_out;
+ uint16_t alpha;
+
+ x0 = y0 = 0;
+ if( left < 0 )
+ {
+ x0 = -left;
+ }
+ if( top < 0 )
+ {
+ y0 = -top;
+ }
+
+ ww = src->f.width;
+ if( src->f.width - x0 > dst->f.width - left )
+ {
+ ww = dst->f.width - left + x0;
+ }
+ hh = src->f.height;
+ if( src->f.height - y0 > dst->f.height - top )
+ {
+ hh = dst->f.height - top + y0;
+ }
+
+ max = (256 << shift) -1;
+
+ // Blend luma
+ for( yy = y0; yy < hh; yy++ )
+ {
+ y_in = src->plane[0].data + yy * src->plane[0].stride;
+ y_out = (uint16_t*)(dst->plane[0].data + ( yy + top ) * dst->plane[0].stride);
+ a_in = src->plane[3].data + yy * src->plane[3].stride;
+ for( xx = x0; xx < ww; xx++ )
+ {
+ alpha = a_in[xx] << shift;
+ /*
+ * Merge the luminance and alpha with the picture
+ */
+ y_out[left + xx] =
+ ( (uint32_t)y_out[left + xx] * ( max - alpha ) +
+ ((uint32_t)y_in[xx] << shift) * alpha ) / max;
+ }
+ }
+
+ // Blend U & V
+ int hshift = 0;
+ int wshift = 0;
+ if( dst->plane[1].height < dst->plane[0].height )
+ hshift = 1;
+ if( dst->plane[1].width < dst->plane[0].width )
+ wshift = 1;
+
+ for( yy = y0 >> hshift; yy < hh >> hshift; yy++ )
+ {
+ u_in = src->plane[1].data + yy * src->plane[1].stride;
+ u_out = (uint16_t*)(dst->plane[1].data + ( yy + ( top >> hshift ) ) * dst->plane[1].stride);
+ v_in = src->plane[2].data + yy * src->plane[2].stride;
+ v_out = (uint16_t*)(dst->plane[2].data + ( yy + ( top >> hshift ) ) * dst->plane[2].stride);
+ a_in = src->plane[3].data + ( yy << hshift ) * src->plane[3].stride;
+
+ for( xx = x0 >> wshift; xx < ww >> wshift; xx++ )
+ {
+ alpha = a_in[xx << wshift] << shift;
+
+ // Blend averge U and alpha
+ u_out[(left >> wshift) + xx] =
+ ( (uint32_t)u_out[(left >> wshift) + xx] * ( max - alpha ) +
+ ((uint32_t)u_in[xx] << shift) * alpha ) / max;
+
+ // Blend V and alpha
+ v_out[(left >> wshift) + xx] =
+ ( (uint32_t)v_out[(left >> wshift) + xx] * ( max - alpha ) +
+ ((uint32_t)v_in[xx] << shift) * alpha ) / max;
+ }
+ }
+}
+
// Assumes that the input destination buffer has the same dimensions
// as the original title dimensions
static void ApplySub( hb_filter_private_t * pv, hb_buffer_t * buf, hb_buffer_t * sub )
{
- blend( buf, sub, sub->f.x, sub->f.y );
+ switch (pv->output.pix_fmt) {
+ case AV_PIX_FMT_YUV420P10:
+ blend8on1x(buf, sub, sub->f.x, sub->f.y, 2);
+ break;
+ case AV_PIX_FMT_YUV420P12:
+ blend8on1x(buf, sub, sub->f.x, sub->f.y, 4);
+ break;
+ default:
+ blend(buf, sub, sub->f.x, sub->f.y);
+ break;
+ }
}
static hb_buffer_t * ScaleSubtitle(hb_filter_private_t *pv,
@@ -604,7 +703,7 @@ static int ssa_post_init( hb_filter_object_t * filter, hb_job_t * job )
ass_set_frame_size( pv->renderer, width, height);
double par = (double)job->par.num / job->par.den;
- ass_set_aspect_ratio( pv->renderer, 1, par );
+ ass_set_pixel_aspect( pv->renderer, par );
return 0;
}