diff options
author | Jan Schmidt <thaytan@noraisin.net> | 2009-05-21 23:45:43 +0100 |
---|---|---|
committer | Jan Schmidt <thaytan@noraisin.net> | 2009-05-26 15:31:55 +0100 |
commit | 871287ba2adb1295fb990aa78cfb01fb5a3e3d4f (patch) | |
tree | d02de6a2ce75a6121e1d93cfdc449a21b2f27046 /gst | |
parent | 4e847cb4acd356112f56a101132d8438abe9fa03 (diff) | |
download | gstreamer-plugins-bad-871287ba2adb1295fb990aa78cfb01fb5a3e3d4f.tar.gz |
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.c | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/gst/dvdspu/gstdvdspu.c b/gst/dvdspu/gstdvdspu.c index b340f92fa..69bc3c99b 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; |