summaryrefslogtreecommitdiffstats
path: root/gst
diff options
context:
space:
mode:
authorJan Schmidt <thaytan@noraisin.net>2009-05-21 23:45:43 +0100
committerJan Schmidt <thaytan@noraisin.net>2009-05-26 15:31:55 +0100
commit871287ba2adb1295fb990aa78cfb01fb5a3e3d4f (patch)
treed02de6a2ce75a6121e1d93cfdc449a21b2f27046 /gst
parent4e847cb4acd356112f56a101132d8438abe9fa03 (diff)
downloadgst-plugins-bad-871287ba2adb1295fb990aa78cfb01fb5a3e3d4f.tar.gz
gst-plugins-bad-871287ba2adb1295fb990aa78cfb01fb5a3e3d4f.tar.bz2
gst-plugins-bad-871287ba2adb1295fb990aa78cfb01fb5a3e3d4f.zip
dvdspu: Collect entire PGS packets and queue as events
Collect fragmented PGS packets and submit as complete events for processing at the correct moment.
Diffstat (limited to 'gst')
-rw-r--r--gst/dvdspu/gstdvdspu.c67
1 files changed, 56 insertions, 11 deletions
diff --git a/gst/dvdspu/gstdvdspu.c b/gst/dvdspu/gstdvdspu.c
index b340f92f..69bc3c99 100644
--- a/gst/dvdspu/gstdvdspu.c
+++ b/gst/dvdspu/gstdvdspu.c
@@ -931,11 +931,15 @@ gst_dvd_spu_setup_cmd_blk (GstDVDSpu * dvdspu, guint16 cmd_blk_offset,
}
static void
-gst_dvd_spu_handle_new_spu_buf (GstDVDSpu * dvdspu, SpuPacket * packet)
+gst_dvd_spu_handle_new_vobsub_buf (GstDVDSpu * dvdspu, SpuPacket * packet)
{
guint8 *start, *end;
SpuState *state = &dvdspu->spu_state;
+#if DUMP_DCSQ
+ gst_dvd_spu_dump_dcsq (dvdspu, packet->event_ts, packet->buf);
+#endif
+
if (G_UNLIKELY (GST_BUFFER_SIZE (packet->buf) < 4))
goto invalid;
@@ -1127,12 +1131,20 @@ gst_dvd_spu_advance_spu (GstDVDSpu * dvdspu, GstClockTime new_ts)
packet->buf ? "buffer" : "event");
if (packet->buf) {
-#if DUMP_DCSQ
- gst_dvd_spu_dump_dcsq (dvdspu, packet->event_ts, packet->buf);
-#endif
- gst_dvd_spu_handle_new_spu_buf (dvdspu, packet);
- }
- if (packet->event)
+ switch (dvdspu->spu_input_type) {
+ case SPU_INPUT_TYPE_VOBSUB:
+ gst_dvd_spu_handle_new_vobsub_buf (dvdspu, packet);
+ break;
+ case SPU_INPUT_TYPE_PGS:
+ gstspu_dump_pgs_buffer (packet->buf);
+ gst_buffer_unref (packet->buf);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ g_assert (packet->event == NULL);
+ } else if (packet->event)
gst_dvd_spu_handle_dvd_event (dvdspu, packet->event);
g_free (packet);
@@ -1277,6 +1289,9 @@ gst_dvd_spu_subpic_chain (GstPad * pad, GstBuffer * buf)
}
if (dvdspu->partial_spu != NULL) {
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
+ GST_WARNING_OBJECT (dvdspu,
+ "Joining subpicture buffer with timestamp to previous");
dvdspu->partial_spu = gst_buffer_join (dvdspu->partial_spu, buf);
} else {
/* If we don't yet have a buffer, wait for one with a timestamp,
@@ -1317,11 +1332,41 @@ gst_dvd_spu_subpic_chain (GstPad * pad, GstBuffer * buf)
}
}
break;
- case SPU_INPUT_TYPE_PGS:
- gstspu_dump_pgs_buffer (dvdspu->partial_spu);
- gst_buffer_unref (dvdspu->partial_spu);
- dvdspu->partial_spu = NULL;
+ case SPU_INPUT_TYPE_PGS:{
+ /* Collect until we have a command buffer that ends exactly at the size
+ * 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);
+
+ /* 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 */
+ while (data != end) {
+ if (data + 3 > end)
+ break;
+ packet_type = *data++;
+ packet_size = GST_READ_UINT16_BE (data);
+ data += 2;
+ if (data + packet_size > end)
+ break;
+ data += packet_size;
+ if (packet_type == PGS_COMMAND_END_DISPLAY && data != end) {
+ /* Extra cruft on the end of the packet -> assume invalid */
+ gst_buffer_unref (dvdspu->partial_spu);
+ dvdspu->partial_spu = NULL;
+ break;
+ }
+ }
+
+ if (dvdspu->partial_spu && data == end) {
+ g_print ("Complete packet of size %u\n",
+ GST_BUFFER_SIZE (dvdspu->partial_spu));
+ submit_new_spu_packet (dvdspu, dvdspu->partial_spu);
+ dvdspu->partial_spu = NULL;
+ }
break;
+ }
default:
GST_ERROR_OBJECT (dvdspu, "Input type not configured before SPU passing");
goto caps_not_set;