mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
dvdspu: port to 0.11
This commit is contained in:
parent
a9fc805e36
commit
11a7e26fd8
8 changed files with 163 additions and 134 deletions
|
@ -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:
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define __GSTSPU_COMMON_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue