dvdspu: port to 0.11

This commit is contained in:
Wim Taymans 2011-10-08 15:16:25 +02:00
parent a9fc805e36
commit 11a7e26fd8
8 changed files with 163 additions and 134 deletions

View file

@ -55,7 +55,7 @@ static GstStaticPadTemplate video_sink_factory =
GST_STATIC_PAD_TEMPLATE ("video",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, " "format = (fourcc) { I420 }, "
GST_STATIC_CAPS ("video/x-raw, " "format = (string) { I420 }, "
"width = (int) [ 16, 4096 ], " "height = (int) [ 16, 4096 ]")
/* FIXME: Can support YV12 one day too */
);
@ -63,7 +63,7 @@ GST_STATIC_PAD_TEMPLATE ("video",
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, " "format = (fourcc) { I420 }, "
GST_STATIC_CAPS ("video/x-raw, " "format = (string) { I420 }, "
"width = (int) [ 16, 4096 ], " "height = (int) [ 16, 4096 ]")
/* FIXME: Can support YV12 one day too */
);
@ -146,8 +146,6 @@ gst_dvd_spu_init (GstDVDSpu * dvdspu)
{
dvdspu->videosinkpad =
gst_pad_new_from_static_template (&video_sink_factory, "video");
gst_pad_set_setcaps_function (dvdspu->videosinkpad,
gst_dvd_spu_video_set_caps);
gst_pad_set_getcaps_function (dvdspu->videosinkpad,
gst_dvd_spu_video_proxy_getcaps);
gst_pad_set_chain_function (dvdspu->videosinkpad, gst_dvd_spu_video_chain);
@ -162,8 +160,6 @@ gst_dvd_spu_init (GstDVDSpu * dvdspu)
gst_pad_new_from_static_template (&subpic_sink_factory, "subpicture");
gst_pad_set_chain_function (dvdspu->subpic_sinkpad, gst_dvd_spu_subpic_chain);
gst_pad_set_event_function (dvdspu->subpic_sinkpad, gst_dvd_spu_subpic_event);
gst_pad_set_setcaps_function (dvdspu->subpic_sinkpad,
gst_dvd_spu_subpic_set_caps);
gst_element_add_pad (GST_ELEMENT (dvdspu), dvdspu->videosinkpad);
gst_element_add_pad (GST_ELEMENT (dvdspu), dvdspu->subpic_sinkpad);
@ -186,8 +182,8 @@ gst_dvd_spu_clear (GstDVDSpu * dvdspu)
gst_buffer_replace (&dvdspu->ref_frame, NULL);
gst_buffer_replace (&dvdspu->pending_frame, NULL);
dvdspu->spu_state.fps_n = 25;
dvdspu->spu_state.fps_d = 1;
dvdspu->spu_state.info.fps_n = 25;
dvdspu->spu_state.info.fps_d = 1;
gst_segment_init (&dvdspu->video_seg, GST_FORMAT_UNDEFINED);
}
@ -296,39 +292,21 @@ gst_dvd_spu_video_set_caps (GstPad * pad, GstCaps * caps)
{
GstDVDSpu *dvdspu = GST_DVD_SPU (gst_pad_get_parent (pad));
gboolean res = FALSE;
GstStructure *s;
gint w, h;
GstVideoInfo info;
gint i;
gint fps_n, fps_d;
SpuState *state;
s = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (s, "width", &w) ||
!gst_structure_get_int (s, "height", &h) ||
!gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) {
if (!gst_video_info_from_caps (&info, caps))
goto done;
}
DVD_SPU_LOCK (dvdspu);
state = &dvdspu->spu_state;
state->fps_n = fps_n;
state->fps_d = fps_d;
state->vid_height = h;
state->Y_height = GST_ROUND_UP_2 (h);
state->UV_height = state->Y_height / 2;
if (state->vid_width != w) {
state->vid_width = w;
state->Y_stride = GST_ROUND_UP_4 (w);
state->UV_stride = GST_ROUND_UP_4 (state->Y_stride / 2);
for (i = 0; i < 3; i++) {
state->comp_bufs[i] = g_realloc (state->comp_bufs[i],
sizeof (guint32) * state->UV_stride);
}
state->info = info;
for (i = 0; i < 3; i++) {
state->comp_bufs[i] = g_realloc (state->comp_bufs[i],
sizeof (guint32) * info.width);
}
DVD_SPU_UNLOCK (dvdspu);
@ -376,6 +354,15 @@ gst_dvd_spu_video_event (GstPad * pad, GstEvent * event)
g_return_val_if_fail (dvdspu != NULL, FALSE);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
res = gst_dvd_spu_video_set_caps (pad, caps);
gst_event_unref (event);
break;
}
case GST_EVENT_CUSTOM_DOWNSTREAM:
case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
{
@ -513,7 +500,7 @@ dvdspu_handle_vid_buffer (GstDVDSpu * dvdspu, GstBuffer * buf)
GstClockTime next_ts = dvdspu->video_seg.position;
next_ts += gst_util_uint64_scale_int (GST_SECOND,
dvdspu->spu_state.fps_d, dvdspu->spu_state.fps_n);
dvdspu->spu_state.info.fps_d, dvdspu->spu_state.info.fps_n);
/* NULL buffer was passed - use the reference frame and update the timestamp,
* or else there's nothing to draw, and just return GST_FLOW_OK */
@ -600,16 +587,21 @@ no_ref_frame:
static void
gstspu_render (GstDVDSpu * dvdspu, GstBuffer * buf)
{
GstVideoFrame frame;
gst_video_frame_map (&frame, &dvdspu->spu_state.info, buf, GST_MAP_READWRITE);
switch (dvdspu->spu_input_type) {
case SPU_INPUT_TYPE_VOBSUB:
gstspu_vobsub_render (dvdspu, buf);
gstspu_vobsub_render (dvdspu, &frame);
break;
case SPU_INPUT_TYPE_PGS:
gstspu_pgs_render (dvdspu, buf);
gstspu_pgs_render (dvdspu, &frame);
break;
default:
break;
}
gst_video_frame_unmap (&frame);
}
/* With SPU LOCK */
@ -839,6 +831,7 @@ gst_dvd_spu_subpic_chain (GstPad * pad, GstBuffer * buf)
{
GstDVDSpu *dvdspu = (GstDVDSpu *) (gst_object_get_parent (GST_OBJECT (pad)));
GstFlowReturn ret = GST_FLOW_OK;
gsize size;
g_return_val_if_fail (dvdspu != NULL, GST_FLOW_ERROR);
@ -874,30 +867,31 @@ gst_dvd_spu_subpic_chain (GstPad * pad, GstBuffer * buf)
if (dvdspu->partial_spu == NULL)
goto done;
size = gst_buffer_get_size (dvdspu->partial_spu);
switch (dvdspu->spu_input_type) {
case SPU_INPUT_TYPE_VOBSUB:
if (GST_BUFFER_SIZE (dvdspu->partial_spu) > 4) {
if (size > 4) {
guint8 *header[2];
guint16 packet_size;
guint8 *data;
data = GST_BUFFER_DATA (dvdspu->partial_spu);
packet_size = GST_READ_UINT16_BE (data);
if (packet_size == GST_BUFFER_SIZE (dvdspu->partial_spu)) {
gst_buffer_extract (dvdspu->partial_spu, 0, header, 2);
packet_size = GST_READ_UINT16_BE (header);
if (packet_size == size) {
submit_new_spu_packet (dvdspu, dvdspu->partial_spu);
dvdspu->partial_spu = NULL;
} else if (packet_size < GST_BUFFER_SIZE (dvdspu->partial_spu)) {
} else if (packet_size < size) {
/* Somehow we collected too much - something is wrong. Drop the
* packet entirely and wait for a new one */
GST_DEBUG_OBJECT (dvdspu, "Discarding invalid SPU buffer of size %u",
GST_BUFFER_SIZE (dvdspu->partial_spu));
size);
gst_buffer_unref (dvdspu->partial_spu);
dvdspu->partial_spu = NULL;
} else {
GST_LOG_OBJECT (dvdspu,
"SPU buffer claims to be of size %u. Collected %u so far.",
packet_size, GST_BUFFER_SIZE (dvdspu->partial_spu));
packet_size, size);
}
}
break;
@ -906,34 +900,42 @@ gst_dvd_spu_subpic_chain (GstPad * pad, GstBuffer * buf)
* we've collected */
guint8 packet_type;
guint16 packet_size;
guint8 *data = GST_BUFFER_DATA (dvdspu->partial_spu);
guint8 *end = data + GST_BUFFER_SIZE (dvdspu->partial_spu);
guint8 *data, *ptr, *end;
gsize size;
gboolean invalid = FALSE;
data = gst_buffer_map (dvdspu->partial_spu, &size, NULL, GST_MAP_READ);
ptr = data;
end = ptr + size;
/* FIXME: There's no need to walk the command set each time. We can set a
* marker and resume where we left off next time */
/* FIXME: Move the packet parsing and sanity checking into the format-specific modules */
while (data != end) {
if (data + 3 > end)
while (ptr != end) {
if (ptr + 3 > end)
break;
packet_type = *data++;
packet_size = GST_READ_UINT16_BE (data);
data += 2;
if (data + packet_size > end)
packet_type = *ptr++;
packet_size = GST_READ_UINT16_BE (ptr);
ptr += 2;
if (ptr + packet_size > end)
break;
data += packet_size;
ptr += packet_size;
/* 0x80 is the END command for PGS packets */
if (packet_type == 0x80 && data != end) {
if (packet_type == 0x80 && ptr != end) {
/* Extra cruft on the end of the packet -> assume invalid */
gst_buffer_unref (dvdspu->partial_spu);
dvdspu->partial_spu = NULL;
invalid = TRUE;
break;
}
}
gst_buffer_unmap (dvdspu->partial_spu, data, size);
if (dvdspu->partial_spu && data == end) {
if (invalid) {
gst_buffer_unref (dvdspu->partial_spu);
dvdspu->partial_spu = NULL;
} else if (ptr == end) {
GST_DEBUG_OBJECT (dvdspu,
"Have complete PGS packet of size %u. Enqueueing.",
GST_BUFFER_SIZE (dvdspu->partial_spu));
"Have complete PGS packet of size %u. Enqueueing.", size);
submit_new_spu_packet (dvdspu, dvdspu->partial_spu);
dvdspu->partial_spu = NULL;
}
@ -966,6 +968,15 @@ gst_dvd_spu_subpic_event (GstPad * pad, GstEvent * event)
/* Some events on the subpicture sink pad just get ignored, like
* FLUSH_START */
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
res = gst_dvd_spu_subpic_set_caps (pad, caps);
gst_event_unref (event);
break;
}
case GST_EVENT_CUSTOM_DOWNSTREAM:
case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
{

View file

@ -69,10 +69,7 @@ struct SpuState {
GstClockTime next_ts; /* Next event TS in running time */
SpuStateFlags flags;
gint fps_n, fps_d;
gint16 vid_width, vid_height;
gint16 Y_stride, UV_stride;
gint16 Y_height, UV_height;
GstVideoInfo info;
guint32 *comp_bufs[3]; /* Compositing buffers for U+V & A */
guint16 comp_left;

View file

@ -20,6 +20,7 @@
#define __GSTSPU_COMMON_H__
#include <glib.h>
#include <gst/video/video.h>
G_BEGIN_DECLS

View file

@ -171,10 +171,11 @@ dump_rle_data (GstDVDSpu * dvdspu, guint8 * data, guint32 len)
static void
pgs_composition_object_render (PgsCompositionObject * obj, SpuState * state,
GstBuffer * dest_buf)
GstVideoFrame * frame)
{
SpuColour *colour;
guint8 *planes[3]; /* YUV frame pointers */
gint strides[3];
guint8 *data, *end;
guint16 obj_w;
guint16 obj_h G_GNUC_UNUSED;
@ -195,27 +196,27 @@ pgs_composition_object_render (PgsCompositionObject * obj, SpuState * state,
* window specified by the object's window_id */
/* Store the start of each plane */
planes[0] = GST_BUFFER_DATA (dest_buf);
planes[1] = planes[0] + (state->Y_height * state->Y_stride);
planes[2] = planes[1] + (state->UV_height * state->UV_stride);
planes[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
planes[1] = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
planes[2] = GST_VIDEO_FRAME_COMP_DATA (frame, 2);
/* Sanity check */
g_return_if_fail (planes[2] + (state->UV_height * state->UV_stride) <=
GST_BUFFER_DATA (dest_buf) + GST_BUFFER_SIZE (dest_buf));
strides[0] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
strides[1] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
strides[2] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2);
y = MIN (obj->y, state->Y_height);
y = MIN (obj->y, state->info.height);
planes[0] += state->Y_stride * y;
planes[1] += state->UV_stride * (y / 2);
planes[2] += state->UV_stride * (y / 2);
planes[0] += strides[0] * y;
planes[1] += strides[1] * (y / 2);
planes[2] += strides[2] * (y / 2);
/* RLE data: */
obj_w = GST_READ_UINT16_BE (data);
obj_h = GST_READ_UINT16_BE (data + 2);
data += 4;
min_x = MIN (obj->x, state->Y_stride);
max_x = MIN (obj->x + obj_w, state->Y_stride);
min_x = MIN (obj->x, strides[0]);
max_x = MIN (obj->x + obj_w, strides[0]);
state->comp_left = x = min_x;
state->comp_right = max_x;
@ -283,17 +284,17 @@ pgs_composition_object_render (PgsCompositionObject * obj, SpuState * state,
if (!run_len || x > max_x) {
x = min_x;
planes[0] += state->Y_stride;
planes[0] += strides[0];
if (y % 2) {
gstspu_blend_comp_buffers (state, planes);
gstspu_clear_comp_buffers (state);
planes[1] += state->UV_stride;
planes[2] += state->UV_stride;
planes[1] += strides[1];
planes[2] += strides[2];
}
y++;
if (y >= state->Y_height)
if (y >= state->info.height)
return; /* Hit the bottom */
}
}
@ -678,17 +679,20 @@ parse_pgs_packet (GstDVDSpu * dvdspu, guint8 type, guint8 * payload,
gint
gstspu_exec_pgs_buffer (GstDVDSpu * dvdspu, GstBuffer * buf)
{
guint8 *pos, *end;
guint8 *data, *pos, *end;
gsize size;
guint8 type;
guint16 packet_len;
pos = GST_BUFFER_DATA (buf);
end = pos + GST_BUFFER_SIZE (buf);
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
pos = data;
end = pos + size;
/* Need at least 3 bytes */
if (pos + 3 > end) {
PGS_DUMP ("Not enough bytes to be a PGS packet\n");
return -1;
goto error;
}
PGS_DUMP ("Begin dumping command buffer of size %u ts %" GST_TIME_FORMAT "\n",
@ -699,19 +703,27 @@ gstspu_exec_pgs_buffer (GstDVDSpu * dvdspu, GstBuffer * buf)
pos += 2;
if (pos + packet_len > end) {
gst_buffer_unmap (buf, data, size);
PGS_DUMP ("Invalid packet length %u (only have %u bytes)\n", packet_len,
end - pos);
return -1;
goto error;
}
if (parse_pgs_packet (dvdspu, type, pos, packet_len))
return -1;
goto error;
pos += packet_len;
} while (pos + 3 <= end);
PGS_DUMP ("End dumping command buffer with %u bytes remaining\n", end - pos);
return (pos - GST_BUFFER_DATA (buf));
return (pos - data);
/* ERRORS */
error:
{
gst_buffer_unmap (buf, data, size);
return -1;
}
}
void
@ -746,7 +758,7 @@ gstspu_pgs_execute_event (GstDVDSpu * dvdspu)
}
void
gstspu_pgs_render (GstDVDSpu * dvdspu, GstBuffer * buf)
gstspu_pgs_render (GstDVDSpu * dvdspu, GstVideoFrame * frame)
{
SpuState *state = &dvdspu->spu_state;
PgsPresentationSegment *ps = &state->pgs.pres_seg;
@ -758,7 +770,7 @@ gstspu_pgs_render (GstDVDSpu * dvdspu, GstBuffer * buf)
for (i = 0; i < ps->objects->len; i++) {
PgsCompositionObject *cur =
&g_array_index (ps->objects, PgsCompositionObject, i);
pgs_composition_object_render (cur, state, buf);
pgs_composition_object_render (cur, state, frame);
}
}

View file

@ -99,7 +99,7 @@ struct SpuPgsState {
void gstspu_pgs_handle_new_buf (GstDVDSpu * dvdspu, GstClockTime event_ts, GstBuffer *buf);
gboolean gstspu_pgs_execute_event (GstDVDSpu *dvdspu);
void gstspu_pgs_render (GstDVDSpu *dvdspu, GstBuffer *buf);
void gstspu_pgs_render (GstDVDSpu *dvdspu, GstVideoFrame *frame);
gboolean gstspu_pgs_handle_dvd_event (GstDVDSpu *dvdspu, GstEvent *event);
void gstspu_pgs_flush (GstDVDSpu *dvdspu);

View file

@ -138,7 +138,7 @@ gstspu_vobsub_get_nibble (SpuState * state, guint16 * rle_offset)
if (G_UNLIKELY (*rle_offset >= state->vobsub.max_offset))
return 0; /* Overran the buffer */
ret = GST_BUFFER_DATA (state->vobsub.pix_buf)[(*rle_offset) / 2];
gst_buffer_extract (state->vobsub.pix_buf, (*rle_offset) / 2, &ret, 1);
/* If the offset is even, we shift the answer down 4 bits, otherwise not */
if (*rle_offset & 0x01)
@ -384,24 +384,29 @@ gstspu_vobsub_clear_comp_buffers (SpuState * state)
}
void
gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
gstspu_vobsub_render (GstDVDSpu * dvdspu, GstVideoFrame * frame)
{
SpuState *state = &dvdspu->spu_state;
guint8 *planes[3]; /* YUV frame pointers */
gint y, last_y;
gint width, height;
gint strides[3];
/* Set up our initial state */
if (G_UNLIKELY (state->vobsub.pix_buf == NULL))
return;
/* Store the start of each plane */
planes[0] = GST_BUFFER_DATA (buf);
planes[1] = planes[0] + (state->Y_height * state->Y_stride);
planes[2] = planes[1] + (state->UV_height * state->UV_stride);
planes[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
planes[1] = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
planes[2] = GST_VIDEO_FRAME_COMP_DATA (frame, 2);
/* Sanity check */
g_return_if_fail (planes[2] + (state->UV_height * state->UV_stride) <=
GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf));
strides[0] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
strides[1] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
strides[2] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2);
width = GST_VIDEO_FRAME_WIDTH (frame);
height = GST_VIDEO_FRAME_HEIGHT (frame);
GST_DEBUG_OBJECT (dvdspu,
"Rendering SPU. disp_rect %d,%d to %d,%d. hl_rect %d,%d to %d,%d",
@ -410,13 +415,12 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
state->vobsub.hl_rect.left, state->vobsub.hl_rect.top,
state->vobsub.hl_rect.right, state->vobsub.hl_rect.bottom);
GST_DEBUG_OBJECT (dvdspu, "video size %d,%d", state->vid_width,
state->vid_height);
GST_DEBUG_OBJECT (dvdspu, "video size %d,%d", width, height);
/* When reading RLE data, we track the offset in nibbles... */
state->vobsub.cur_offsets[0] = state->vobsub.pix_data[0] * 2;
state->vobsub.cur_offsets[1] = state->vobsub.pix_data[1] * 2;
state->vobsub.max_offset = GST_BUFFER_SIZE (state->vobsub.pix_buf) * 2;
state->vobsub.max_offset = gst_buffer_get_size (state->vobsub.pix_buf) * 2;
/* Update all the palette caches */
gstspu_vobsub_update_palettes (dvdspu, state);
@ -436,18 +440,18 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
state->vobsub.clip_rect.right = state->vobsub.disp_rect.right;
/* center the image when display rectangle exceeds the video width */
if (state->vid_width <= state->vobsub.disp_rect.right) {
if (width <= state->vobsub.disp_rect.right) {
gint left, disp_width;
disp_width = state->vobsub.disp_rect.right - state->vobsub.disp_rect.left
+ 1;
left = (state->vid_width - disp_width) / 2;
left = (width - disp_width) / 2;
state->vobsub.disp_rect.left = left;
state->vobsub.disp_rect.right = left + disp_width - 1;
/* if it clips to the right, shift it left, but only till zero */
if (state->vobsub.disp_rect.right >= state->vid_width) {
gint shift = state->vobsub.disp_rect.right - state->vid_width - 1;
if (state->vobsub.disp_rect.right >= width) {
gint shift = state->vobsub.disp_rect.right - width - 1;
if (shift > state->vobsub.disp_rect.left)
shift = state->vobsub.disp_rect.left;
state->vobsub.disp_rect.left -= shift;
@ -459,8 +463,8 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
state->vobsub.clip_rect.right = state->vobsub.disp_rect.right;
/* clip right after the shift */
if (state->vobsub.clip_rect.right >= state->vid_width)
state->vobsub.clip_rect.right = state->vid_width - 1;
if (state->vobsub.clip_rect.right >= width)
state->vobsub.clip_rect.right = width - 1;
GST_DEBUG_OBJECT (dvdspu,
"clipping width to %d,%d", state->vobsub.clip_rect.left,
@ -472,10 +476,10 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
* is and do something more clever. */
state->vobsub.clip_rect.top = state->vobsub.disp_rect.top;
state->vobsub.clip_rect.bottom = state->vobsub.disp_rect.bottom;
if (state->vid_height <= state->vobsub.disp_rect.bottom) {
if (height <= state->vobsub.disp_rect.bottom) {
/* shift it up, but only till zero */
gint shift = state->vobsub.disp_rect.bottom - state->vid_height - 1;
gint shift = state->vobsub.disp_rect.bottom - height - 1;
if (shift > state->vobsub.disp_rect.top)
shift = state->vobsub.disp_rect.top;
state->vobsub.disp_rect.top -= shift;
@ -492,8 +496,8 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
state->vobsub.clip_rect.bottom = state->vobsub.disp_rect.bottom;
/* clip right after the shift */
if (state->vobsub.clip_rect.bottom >= state->vid_height)
state->vobsub.clip_rect.bottom = state->vid_height - 1;
if (state->vobsub.clip_rect.bottom >= height)
state->vobsub.clip_rect.bottom = height - 1;
GST_DEBUG_OBJECT (dvdspu,
"clipping height to %d,%d", state->vobsub.clip_rect.top,
@ -508,9 +512,9 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
last_y = (state->vobsub.disp_rect.bottom - 1) & ~(0x01);
/* Update our plane references to the first line of the disp_rect */
planes[0] += state->Y_stride * y;
planes[1] += state->UV_stride * (y / 2);
planes[2] += state->UV_stride * (y / 2);
planes[0] += strides[0] * y;
planes[1] += strides[1] * (y / 2);
planes[2] += strides[2] * (y / 2);
for (state->vobsub.cur_Y = y; state->vobsub.cur_Y <= last_y;
state->vobsub.cur_Y++) {
@ -526,7 +530,7 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
if (!clip) {
/* Advance the luminance output pointer */
planes[0] += state->Y_stride;
planes[0] += strides[0];
}
state->vobsub.cur_Y++;
@ -539,9 +543,9 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
gstspu_vobsub_blend_comp_buffers (state, planes);
/* Update all the output pointers */
planes[0] += state->Y_stride;
planes[1] += state->UV_stride;
planes[2] += state->UV_stride;
planes[0] += strides[0];
planes[1] += strides[1];
planes[2] += strides[2];
}
}
if (state->vobsub.cur_Y == state->vobsub.disp_rect.bottom) {
@ -568,24 +572,22 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
guint8 *cur;
gint16 pos;
cur = GST_BUFFER_DATA (buf) + state->Y_stride * state->vobsub.disp_rect.top;
cur = GST_BUFFER_DATA (buf) + strides[0] * state->vobsub.disp_rect.top;
for (pos = state->vobsub.disp_rect.left + 1;
pos < state->vobsub.disp_rect.right; pos++)
cur[pos] = (cur[pos] / 2) + 0x8;
cur =
GST_BUFFER_DATA (buf) +
state->Y_stride * state->vobsub.disp_rect.bottom;
cur = GST_BUFFER_DATA (buf) + strides[0] * state->vobsub.disp_rect.bottom;
for (pos = state->vobsub.disp_rect.left + 1;
pos < state->vobsub.disp_rect.right; pos++)
cur[pos] = (cur[pos] / 2) + 0x8;
cur = GST_BUFFER_DATA (buf) + state->Y_stride * state->vobsub.disp_rect.top;
cur = GST_BUFFER_DATA (buf) + strides[0] * state->vobsub.disp_rect.top;
for (pos = state->vobsub.disp_rect.top;
pos <= state->vobsub.disp_rect.bottom; pos++) {
cur[state->vobsub.disp_rect.left] =
(cur[state->vobsub.disp_rect.left] / 2) + 0x8;
cur[state->vobsub.disp_rect.right] =
(cur[state->vobsub.disp_rect.right] / 2) + 0x8;
cur += state->Y_stride;
cur += strides[0];
}
} while (0);
#endif
@ -595,17 +597,17 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
guint8 *cur;
gint16 pos;
cur = GST_BUFFER_DATA (buf) + state->Y_stride * state->hl_rect.top;
cur = GST_BUFFER_DATA (buf) + strides[0] * state->hl_rect.top;
for (pos = state->hl_rect.left + 1; pos < state->hl_rect.right; pos++)
cur[pos] = (cur[pos] / 2) + 0x8;
cur = GST_BUFFER_DATA (buf) + state->Y_stride * state->hl_rect.bottom;
cur = GST_BUFFER_DATA (buf) + strides[0] * state->hl_rect.bottom;
for (pos = state->hl_rect.left + 1; pos < state->hl_rect.right; pos++)
cur[pos] = (cur[pos] / 2) + 0x8;
cur = GST_BUFFER_DATA (buf) + state->Y_stride * state->hl_rect.top;
cur = GST_BUFFER_DATA (buf) + strides[0] * state->hl_rect.top;
for (pos = state->hl_rect.top; pos <= state->hl_rect.bottom; pos++) {
cur[state->hl_rect.left] = (cur[state->hl_rect.left] / 2) + 0x8;
cur[state->hl_rect.right] = (cur[state->hl_rect.right] / 2) + 0x8;
cur += state->Y_stride;
cur += strides[0];
}
}
#endif

View file

@ -323,13 +323,14 @@ gstspu_vobsub_handle_new_buf (GstDVDSpu * dvdspu, GstClockTime event_ts,
GstBuffer * buf)
{
guint8 *start, *end;
gsize size;
SpuState *state = &dvdspu->spu_state;
#if DUMP_DCSQ
gst_dvd_spu_dump_dcsq (dvdspu, event_ts, buf);
#endif
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 4))
if (G_UNLIKELY (gst_buffer_get_size (buf) < 4))
goto invalid;
if (state->vobsub.buf != NULL) {
@ -339,8 +340,8 @@ gstspu_vobsub_handle_new_buf (GstDVDSpu * dvdspu, GstClockTime event_ts,
state->vobsub.buf = buf;
state->vobsub.base_ts = event_ts;
start = GST_BUFFER_DATA (state->vobsub.buf);
end = start + GST_BUFFER_SIZE (state->vobsub.buf);
start = gst_buffer_map (state->vobsub.buf, &size, NULL, GST_MAP_READ);
end = start + size;
/* Configure the first command block in this buffer as our initial blk */
state->vobsub.cur_cmd_blk = GST_READ_UINT16_BE (start + 2);
@ -351,6 +352,7 @@ gstspu_vobsub_handle_new_buf (GstDVDSpu * dvdspu, GstClockTime event_ts,
g_free (state->vobsub.line_ctrl_i);
state->vobsub.line_ctrl_i = NULL;
}
gst_buffer_unmap (state->vobsub.buf, start, size);
return;
invalid:
@ -363,6 +365,7 @@ gstspu_vobsub_execute_event (GstDVDSpu * dvdspu)
{
guint8 *start, *cmd_blk, *end;
guint16 next_blk;
gsize size;
SpuState *state = &dvdspu->spu_state;
if (state->vobsub.buf == NULL)
@ -372,12 +375,13 @@ gstspu_vobsub_execute_event (GstDVDSpu * dvdspu)
" @ offset %u", GST_TIME_ARGS (state->next_ts),
state->vobsub.cur_cmd_blk);
start = GST_BUFFER_DATA (state->vobsub.buf);
end = start + GST_BUFFER_SIZE (state->vobsub.buf);
start = gst_buffer_map (state->vobsub.buf, &size, NULL, GST_MAP_READ);
end = start + size;
cmd_blk = start + state->vobsub.cur_cmd_blk;
if (G_UNLIKELY (cmd_blk + 5 >= end)) {
gst_buffer_unmap (state->vobsub.buf, start, size);
/* Invalid. Finish the buffer and loop again */
gst_dvd_spu_finish_spu_buf (dvdspu);
return FALSE;
@ -392,9 +396,11 @@ gstspu_vobsub_execute_event (GstDVDSpu * dvdspu)
} else {
/* Next Block points to the current block, so we're finished with this
* SPU buffer */
gst_buffer_unmap (state->vobsub.buf, start, size);
gst_dvd_spu_finish_spu_buf (dvdspu);
return FALSE;
}
gst_buffer_unmap (state->vobsub.buf, start, size);
return TRUE;
}

View file

@ -103,7 +103,7 @@ struct SpuVobsubState {
void gstspu_vobsub_handle_new_buf (GstDVDSpu * dvdspu, GstClockTime event_ts, GstBuffer *buf);
gboolean gstspu_vobsub_execute_event (GstDVDSpu *dvdspu);
void gstspu_vobsub_render (GstDVDSpu *dvdspu, GstBuffer *buf);
void gstspu_vobsub_render (GstDVDSpu *dvdspu, GstVideoFrame *frame);
gboolean gstspu_vobsub_handle_dvd_event (GstDVDSpu *dvdspu, GstEvent *event);
void gstspu_vobsub_flush (GstDVDSpu *dvdspu);