diff options
Diffstat (limited to 'gst/dvdspu/gstdvdspu.c')
-rw-r--r-- | gst/dvdspu/gstdvdspu.c | 341 |
1 files changed, 2 insertions, 339 deletions
diff --git a/gst/dvdspu/gstdvdspu.c b/gst/dvdspu/gstdvdspu.c index 69bc3c99..c9c116e8 100644 --- a/gst/dvdspu/gstdvdspu.c +++ b/gst/dvdspu/gstdvdspu.c @@ -39,18 +39,14 @@ #include <gst/gst.h> #include "gstdvdspu.h" +#include "gstspu-vobsub.h" #include "gstspu-pgs.h" -#define DUMP_DCSQ 0 - extern void gst_dvd_spu_render_spu (GstDVDSpu * dvdspu, GstBuffer * buf); GST_DEBUG_CATEGORY (dvdspu_debug); #define GST_CAT_DEFAULT dvdspu_debug -/* Convert an STM offset in the SPU sequence to a GStreamer timestamp */ -#define STM_TO_GST(stm) ((GST_MSECOND * 1024 * (stm)) / 90) - /* Filter signals and args */ enum { @@ -709,267 +705,6 @@ gst_dvd_spu_redraw_still (GstDVDSpu * dvdspu, gboolean force) } static void -gst_dvd_spu_parse_chg_colcon (GstDVDSpu * dvdspu, guint8 * data, guint8 * end) -{ - SpuState *state = &dvdspu->spu_state; - guint8 *cur; - gint16 n_entries; - gint16 i; - - /* Clear any existing chg colcon info */ - state->n_line_ctrl_i = 0; - if (state->line_ctrl_i != NULL) { - g_free (state->line_ctrl_i); - state->line_ctrl_i = NULL; - } - GST_DEBUG_OBJECT (dvdspu, "Change Color & Contrast. Pixel data = %d bytes", - (gint16) (end - data)); - - /* Count the number of entries we'll need */ - n_entries = 0; - for (cur = data; cur < end;) { - guint8 n_changes; - guint32 code; - - if (cur + 4 > end) - break; - - code = GST_READ_UINT32_BE (cur); - if (code == 0x0fffffff) - break; /* Termination code */ - - n_changes = CLAMP ((cur[2] >> 4), 1, 8); - cur += 4 + (6 * n_changes); - - if (cur > end) - break; /* Invalid entry overrunning buffer */ - - n_entries++; - } - - state->n_line_ctrl_i = n_entries; - state->line_ctrl_i = g_new (SpuLineCtrlI, n_entries); - - cur = data; - for (i = 0; i < n_entries; i++) { - SpuLineCtrlI *cur_line_ctrl = state->line_ctrl_i + i; - guint8 n_changes = CLAMP ((cur[2] >> 4), 1, 8); - guint8 c; - - cur_line_ctrl->n_changes = n_changes; - cur_line_ctrl->top = ((cur[0] << 8) & 0x300) | cur[1]; - cur_line_ctrl->bottom = ((cur[2] << 8) & 0x300) | cur[3]; - - GST_LOG_OBJECT (dvdspu, "ChgColcon Entry %d Top: %d Bottom: %d Changes: %d", - i, cur_line_ctrl->top, cur_line_ctrl->bottom, n_changes); - cur += 4; - - for (c = 0; c < n_changes; c++) { - SpuPixCtrlI *cur_pix_ctrl = cur_line_ctrl->pix_ctrl_i + c; - - cur_pix_ctrl->left = ((cur[0] << 8) & 0x300) | cur[1]; - cur_pix_ctrl->palette = GST_READ_UINT32_BE (cur + 2); - GST_LOG_OBJECT (dvdspu, " %d: left: %d palette 0x%x", c, - cur_pix_ctrl->left, cur_pix_ctrl->palette); - cur += 6; - } - } -} - -static void -gst_dvd_spu_exec_cmd_blk (GstDVDSpu * dvdspu, guint8 * data, guint8 * end) -{ - SpuState *state = &dvdspu->spu_state; - - while (data < end) { - guint8 cmd; - - cmd = data[0]; - - switch (cmd) { - case SPU_CMD_FSTA_DSP: - GST_DEBUG_OBJECT (dvdspu, " Forced Display"); - state->flags |= SPU_STATE_FORCED_DSP; - data += 1; - break; - case SPU_CMD_DSP: - GST_DEBUG_OBJECT (dvdspu, " Display On"); - state->flags |= SPU_STATE_DISPLAY; - data += 1; - break; - case SPU_CMD_STP_DSP: - GST_DEBUG_OBJECT (dvdspu, " Display Off"); - state->flags &= ~(SPU_STATE_FORCED_DSP | SPU_STATE_DISPLAY); - data += 1; - break; - case SPU_CMD_SET_COLOR:{ - if (G_UNLIKELY (data + 3 >= end)) - return; /* Invalid SET_COLOR cmd at the end of the blk */ - - state->main_idx[3] = data[1] >> 4; - state->main_idx[2] = data[1] & 0x0f; - state->main_idx[1] = data[2] >> 4; - state->main_idx[0] = data[2] & 0x0f; - - state->main_pal_dirty = TRUE; - - GST_DEBUG_OBJECT (dvdspu, - " Set Color bg %u pattern %u emph-1 %u emph-2 %u", - state->main_idx[0], state->main_idx[1], state->main_idx[2], - state->main_idx[3]); - data += 3; - break; - } - case SPU_CMD_SET_ALPHA:{ - if (G_UNLIKELY (data + 3 >= end)) - return; /* Invalid SET_ALPHA cmd at the end of the blk */ - - state->main_alpha[3] = data[1] >> 4; - state->main_alpha[2] = data[1] & 0x0f; - state->main_alpha[1] = data[2] >> 4; - state->main_alpha[0] = data[2] & 0x0f; - - state->main_pal_dirty = TRUE; - - GST_DEBUG_OBJECT (dvdspu, - " Set Alpha bg %u pattern %u emph-1 %u emph-2 %u", - state->main_alpha[0], state->main_alpha[1], state->main_alpha[2], - state->main_alpha[3]); - data += 3; - break; - } - case SPU_CMD_SET_DAREA:{ - SpuRect *r = &state->disp_rect; - - if (G_UNLIKELY (data + 7 >= end)) - return; /* Invalid SET_DAREA cmd at the end of the blk */ - - r->top = ((data[4] & 0x3f) << 4) | ((data[5] & 0xe0) >> 4); - r->left = ((data[1] & 0x3f) << 4) | ((data[2] & 0xf0) >> 4); - r->right = ((data[2] & 0x03) << 8) | data[3]; - r->bottom = ((data[5] & 0x03) << 8) | data[6]; - - GST_DEBUG_OBJECT (dvdspu, - " Set Display Area top %u left %u bottom %u right %u", r->top, - r->left, r->bottom, r->right); - - data += 7; - break; - } - case SPU_CMD_DSPXA:{ - if (G_UNLIKELY (data + 5 >= end)) - return; /* Invalid SET_DSPXE cmd at the end of the blk */ - - state->pix_data[0] = GST_READ_UINT16_BE (data + 1); - state->pix_data[1] = GST_READ_UINT16_BE (data + 3); - /* Store a reference to the current command buffer, as that's where - * we'll need to take our pixel data from */ - gst_buffer_replace (&state->pix_buf, state->buf); - - GST_DEBUG_OBJECT (dvdspu, " Set Pixel Data Offsets top: %u bot: %u", - state->pix_data[0], state->pix_data[1]); - - data += 5; - break; - } - case SPU_CMD_CHG_COLCON:{ - guint16 field_size; - - GST_DEBUG_OBJECT (dvdspu, " Set Color & Contrast Change"); - if (G_UNLIKELY (data + 3 >= end)) - return; /* Invalid CHG_COLCON cmd at the end of the blk */ - - data++; - field_size = GST_READ_UINT16_BE (data); - - if (G_UNLIKELY (data + field_size >= end)) - return; /* Invalid CHG_COLCON cmd at the end of the blk */ - - gst_dvd_spu_parse_chg_colcon (dvdspu, data + 2, data + field_size); - state->line_ctrl_i_pal_dirty = TRUE; - data += field_size; - break; - } - case SPU_CMD_END: - default: - GST_DEBUG_OBJECT (dvdspu, " END"); - data = end; - break; - } - } -} - -static void -gst_dvd_spu_finish_spu_buf (GstDVDSpu * dvdspu) -{ - SpuState *state = &dvdspu->spu_state; - - state->next_ts = state->base_ts = GST_CLOCK_TIME_NONE; - gst_buffer_replace (&state->buf, NULL); - - GST_DEBUG_OBJECT (dvdspu, "Finished SPU buffer"); -} - -static gboolean -gst_dvd_spu_setup_cmd_blk (GstDVDSpu * dvdspu, guint16 cmd_blk_offset, - guint8 * start, guint8 * end) -{ - SpuState *state = &dvdspu->spu_state; - guint16 delay; - guint8 *cmd_blk = start + cmd_blk_offset; - - if (G_UNLIKELY (cmd_blk + 5 >= end)) - return FALSE; /* No valid command block to read */ - - delay = GST_READ_UINT16_BE (cmd_blk); - state->next_ts = state->base_ts + STM_TO_GST (delay); - state->cur_cmd_blk = cmd_blk_offset; - - GST_DEBUG_OBJECT (dvdspu, "Setup CMD Block @ %u with TS %" GST_TIME_FORMAT, - state->cur_cmd_blk, GST_TIME_ARGS (state->next_ts)); - return TRUE; -} - -static void -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; - - if (state->buf != NULL) { - gst_buffer_unref (state->buf); - state->buf = NULL; - } - state->buf = packet->buf; - state->base_ts = packet->event_ts; - - start = GST_BUFFER_DATA (state->buf); - end = start + GST_BUFFER_SIZE (state->buf); - - /* Configure the first command block in this buffer as our initial blk */ - state->cur_cmd_blk = GST_READ_UINT16_BE (start + 2); - gst_dvd_spu_setup_cmd_blk (dvdspu, state->cur_cmd_blk, start, end); - /* Clear existing chg-colcon info */ - state->n_line_ctrl_i = 0; - if (state->line_ctrl_i != NULL) { - g_free (state->line_ctrl_i); - state->line_ctrl_i = NULL; - } - return; - -invalid: - /* Invalid buffer */ - gst_dvd_spu_finish_spu_buf (dvdspu); -} - -static void gst_dvd_spu_handle_dvd_event (GstDVDSpu * dvdspu, GstEvent * event) { const gchar *event_type; @@ -1055,51 +790,6 @@ gst_dvd_spu_handle_dvd_event (GstDVDSpu * dvdspu, GstEvent * event) gst_event_unref (event); } -#if DUMP_DCSQ -static void -gst_dvd_spu_dump_dcsq (GstDVDSpu * dvdspu, - GstClockTime start_ts, GstBuffer * spu_buf) -{ - guint16 cmd_blk_offset; - guint16 next_blk; - guint8 *start, *end; - - start = GST_BUFFER_DATA (spu_buf); - end = start + GST_BUFFER_SIZE (spu_buf); - - g_return_if_fail (start != NULL); - - /* First command */ - next_blk = GST_READ_UINT16_BE (start + 2); - cmd_blk_offset = 0; - - /* Loop through all commands */ - g_print ("SPU begins @ %" GST_TIME_FORMAT " offset %u\n", - GST_TIME_ARGS (start_ts), next_blk); - - while (cmd_blk_offset != next_blk) { - guint8 *data; - GstClockTime cmd_blk_ts; - - cmd_blk_offset = next_blk; - - if (G_UNLIKELY (start + cmd_blk_offset + 5 >= end)) - break; /* No valid command to read */ - - data = start + cmd_blk_offset; - - cmd_blk_ts = start_ts + STM_TO_GST (GST_READ_UINT16_BE (data)); - next_blk = GST_READ_UINT16_BE (data + 2); - - g_print ("Cmd Blk @ offset %u next %u ts %" GST_TIME_FORMAT "\n", - cmd_blk_offset, next_blk, GST_TIME_ARGS (cmd_blk_ts)); - - data += 4; - gst_dvd_spu_exec_cmd_blk (dvdspu, data, end); - } -} -#endif - /* Advance the SPU packet/command queue to a time. new_ts is in running time */ static void gst_dvd_spu_advance_spu (GstDVDSpu * dvdspu, GstClockTime new_ts) @@ -1107,9 +797,6 @@ gst_dvd_spu_advance_spu (GstDVDSpu * dvdspu, GstClockTime new_ts) SpuState *state = &dvdspu->spu_state; while (state->next_ts == GST_CLOCK_TIME_NONE || state->next_ts <= new_ts) { - guint8 *start, *cmd_blk, *end; - guint16 next_blk; - if (state->buf == NULL) { GstClockTime vid_run_ts; @@ -1159,31 +846,7 @@ gst_dvd_spu_advance_spu (GstDVDSpu * dvdspu, GstClockTime new_ts) * next cmd */ g_assert (state->buf != NULL); - GST_DEBUG_OBJECT (dvdspu, "Executing cmd blk with TS %" GST_TIME_FORMAT - " @ offset %u", GST_TIME_ARGS (state->next_ts), state->cur_cmd_blk); - - start = GST_BUFFER_DATA (state->buf); - end = start + GST_BUFFER_SIZE (state->buf); - - cmd_blk = start + state->cur_cmd_blk; - - if (G_UNLIKELY (cmd_blk + 5 >= end)) { - /* Invalid. Finish the buffer and loop again */ - gst_dvd_spu_finish_spu_buf (dvdspu); - continue; - } - - gst_dvd_spu_exec_cmd_blk (dvdspu, cmd_blk + 4, end); - - next_blk = GST_READ_UINT16_BE (cmd_blk + 2); - if (next_blk != state->cur_cmd_blk) { - /* Advance to the next block of commands */ - gst_dvd_spu_setup_cmd_blk (dvdspu, next_blk, start, end); - } else { - /* Next Block points to the current block, so we're finished with this - * SPU buffer */ - gst_dvd_spu_finish_spu_buf (dvdspu); - } + gst_dvdspu_vobsub_execute_event (dvdspu); } } |