summaryrefslogtreecommitdiff
path: root/src/libspudec/xine_decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libspudec/xine_decoder.c')
-rw-r--r--src/libspudec/xine_decoder.c259
1 files changed, 167 insertions, 92 deletions
diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c
index 406c0cc9d..0d3a0836d 100644
--- a/src/libspudec/xine_decoder.c
+++ b/src/libspudec/xine_decoder.c
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_decoder.c,v 1.7 2001/08/05 08:24:56 ehasenle Exp $
+ * $Id: xine_decoder.c,v 1.8 2001/08/13 12:52:33 ehasenle Exp $
*
* stuff needed to turn libspu into a xine decoder plugin
*/
@@ -38,31 +38,48 @@
#include "spu.h"
#include "buffer.h"
+#include "events.h"
#include "xine_internal.h"
-#define FRAME_SIZE 4096
-
+static clut_t __default_clut[] = {
+ {y: 0x00, cr: 0x80, cb:0x80},
+ {y: 0xbf, cr: 0x80, cb:0x80},
+ {y: 0x10, cr: 0x80, cb:0x80},
+ {y: 0x28, cr: 0x6d, cb:0xef},
+ {y: 0x51, cr: 0xef, cb:0x5a},
+ {y: 0xbf, cr: 0x80, cb:0x80},
+ {y: 0x36, cr: 0x80, cb:0x80},
+ {y: 0x28, cr: 0x6d, cb:0xef},
+ {y: 0xbf, cr: 0x80, cb:0x80},
+ {y: 0x51, cr: 0x80, cb:0x80},
+ {y: 0xbf, cr: 0x80, cb:0x80},
+ {y: 0x10, cr: 0x80, cb:0x80},
+ {y: 0x28, cr: 0x6d, cb:0xef},
+ {y: 0x5c, cr: 0x80, cb:0x80},
+ {y: 0xbf, cr: 0x80, cb:0x80},
+ {y: 0x1c, cr: 0x80, cb:0x80},
+ {y: 0x28, cr: 0x6d, cb:0xef}
+};
+
+#define NUM_SEQ_BUFFERS 5
typedef struct spudec_decoder_s {
spu_decoder_t spu_decoder;
+ ovl_src_t ovl_src;
- uint32_t pts;
+ spu_seq_t seq_list[NUM_SEQ_BUFFERS];
+ spu_seq_t *cur_seq;
+ spu_seq_t *ra_seq;
+ int ra_complete;
- uint8_t frame_buffer[FRAME_SIZE];
- uint8_t *frame_ptr;
- int sync_todo;
- int frame_length, frame_todo;
- uint16_t syncword;
+ uint32_t ovl_pts;
+ uint32_t buf_pts;
+ spu_state_t state;
vo_instance_t *vo_out;
- vo_overlay_t *spu;
- uint32_t *clut;
- int spu_caps;
- int bypass_mode;
- int max_num_channels;
- int output_sampling_rate;
+ vo_overlay_t ovl;
+ int ovl_caps;
int output_open;
- int output_mode;
} spudec_decoder_t;
@@ -71,107 +88,155 @@ int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) {
return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT) ;
}
+static void spudec_reset (spudec_decoder_t *this) {
+ int i;
+
+ this->ovl_pts = 0;
+ this->buf_pts = 0;
+
+ this->state.visible = 0;
+
+ for (i = 0; i < NUM_SEQ_BUFFERS; i++) {
+ this->seq_list[i].finished = 1;
+ }
+ this->ra_complete = 1;
+ this->cur_seq = this->ra_seq = this->seq_list;
+}
+
void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
+
this->vo_out = vo_out;
- this->spu_caps = vo_out->get_capabilities(vo_out);
- this->syncword = 0;
- this->sync_todo = 6;
+ this->ovl_caps = vo_out->get_capabilities(vo_out);
this->output_open = 0;
-}
-
-/* overlay_txt is just for test purposes */
-u_int *overlay_txt (vo_overlay_t *spu, float o1)
-{
- u_int x, y;
- u_char tmp;
- /* u_char *clr_ptr1 = (u_char *) img1; */
- u_char *clr_ptr2;
- u_char *spu_data_ptr = (u_char *) spu->data;
- float o;
-
- /* don't know why this can happen - but it does happen */
- if ((spu->width <= 0) || (spu->height <= 0) ||
- (spu->width > 1024) || (spu->height > 1024)) {
- fprintf (stderr, "width || height out of range.\n");
- return NULL;
- }
-
- for (y = spu->y; y < (spu->height + spu->y); y++) {
- // clr_ptr1 = (u_char *) (img1 + y * 720 + spu->x);
- for (x = spu->x; x < (spu->width + spu->x); x++) {
- o = ((float) (*spu_data_ptr>>4) / 15.0) * o1;
- //clr_ptr2 = (u_char *) &spu_clut[*spu_data_ptr&0x0f];
- *clr_ptr2 = *spu_data_ptr&0x0f;
- tmp=*spu_data_ptr;
- //printf("%X%X",tmp&0x0f,((tmp>>4)&0x0f));
- spu_data_ptr ++;
-
- // printf("%d ",(*clr_ptr2++));
- // printf("%d ",(*clr_ptr2++));
- // printf("%d ",(*clr_ptr2++));
- // printf("%d \n",(*clr_ptr2++));
- }
- printf("\n");
- }
-
- return 0;
+ spudec_reset(this);
+ memcpy(this->state.clut, __default_clut, sizeof(this->state.clut));
+ vo_out->register_ovl_src(vo_out, &this->ovl_src);
}
void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
- uint8_t *current = buf->content;
-
if (buf->type == BUF_SPU_CLUT) {
- if (this->clut == NULL)
- this->clut = malloc(sizeof(clut_t)*16);
-
- memcpy(this->clut, buf->content, sizeof(clut_t)*16);
+ memcpy(this->state.clut, buf->content, sizeof(int32_t)*16);
return;
}
-
- if (!this->spu) {
- this->spu = this->vo_out->get_overlay (this->vo_out);
- }
- /* FIXME: shouldn't happen, but get_overlay function isn't implemented yet */
- if (!this->spu)
- return;
+ if (buf->PTS) {
+ metronom_t *metronom = this->ovl_src.metronom;
+ uint32_t pts = metronom->got_spu_packet(metronom, buf->PTS, 0);
+ if (pts < this->buf_pts)
+ spudec_reset(this);
- this->spu->PTS = buf->PTS;
- if (this->clut)
- this->spu->clut_tbl = this->clut;
-
- if (!spuParseHdr (this->spu, current, buf->size)) {
- spuParseData (this->spu);
- /* overlay_txt(this->spu,1.0); Just for test purposes */
- this->vo_out->queue_overlay (this->vo_out, this->spu);
- this->spu = NULL;
- } else {
- this->spu->data=NULL;
- this->vo_out->queue_overlay (this->vo_out, this->spu);
- this->spu = NULL;
+ this->buf_pts = pts;
+ }
+
+ if (this->ra_complete) {
+ spu_seq_t *tmp_seq = this->ra_seq + 1;
+ if (tmp_seq >= this->seq_list + NUM_SEQ_BUFFERS)
+ tmp_seq = this->seq_list;
+
+ if (tmp_seq->finished) {
+ this->ra_seq = tmp_seq;
+ this->ra_seq->PTS = this->buf_pts;
+ }
}
+ this->ra_complete =
+ spuReassembly(this->ra_seq, this->ra_complete, buf->content, buf->size);
}
void spudec_close (spu_decoder_t *this_gen) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
+
+ this->vo_out->unregister_ovl_src(this->vo_out, &this->ovl_src);
+}
- if (this->clut) {
- free(this->clut);
- this->clut = 0;
+static void spudec_nextseq(spudec_decoder_t* this) {
+ spu_seq_t *tmp_seq = this->cur_seq + 1;
+ if (tmp_seq >= this->seq_list + NUM_SEQ_BUFFERS)
+ tmp_seq = this->seq_list;
+
+ if (!tmp_seq->finished) { /* is the next seq ready for process? */
+ this->cur_seq = tmp_seq;
+ this->state.cmd_ptr = this->cur_seq->buf + this->cur_seq->cmd_offs;
+ this->state.next_pts = -1; /* invalidate timestamp */
+ this->state.modified = 1;
+ this->state.visible = 0;
+ this->state.menu = 0;
}
+}
+
+static vo_overlay_t* spudec_get_overlay(ovl_src_t *ovl_src, int pts) {
+ spudec_decoder_t *this = (spudec_decoder_t*) ovl_src->src_gen;
+ int pending = 0;
-/* FIXME not implemented */
-// if (this->output_open)
-// this->spu_out->close (this->spu_out);
+ if (this->ovl_pts > pts)
+ spudec_reset(this);
- /* close (spufile); */
+ this->ovl_pts = pts;
+
+ do {
+ if (this->cur_seq->finished)
+ spudec_nextseq(this);
+
+ if (!this->cur_seq->finished) {
+ pending = spuNextEvent(&this->state, this->cur_seq, pts);
+
+ if (pending)
+ spuDoCommands(&this->state, this->cur_seq, &this->ovl);
+ } else
+ pending = 0;
+
+ } while (pending);
+
+ if (this->state.visible) {
+ if (this->state.modified) {
+ spuDrawPicture(&this->state, this->cur_seq, &this->ovl);
+ }
+
+ return &this->ovl;
+ }
+
+ return NULL;
+}
+
+static void spudec_event(spu_decoder_t *this_gen, spu_event_t *event) {
+ spudec_decoder_t *this = (spudec_decoder_t*) this_gen;
+
+ switch (event->sub_type) {
+ case SPU_EVENT_BUTTON:
+ {
+ spu_button_t *but = event->data;
+ if (!this->state.menu) return;
+
+ if (but->show) {
+ int i;
+ for (i = 0; i < 4; i++) {
+ this->ovl.color[i] = this->state.clut[but->color[i]];
+ this->ovl.trans[i] = but->trans[i];
+ }
+
+ this->state.b_left = but->left;
+ this->state.b_right = but->right;
+ this->state.b_top = but->top;
+ this->state.b_bottom = but->bottom;
+ }
+
+ this->state.b_show = but->show;
+ spuUpdateMenu(&this->state, &this->ovl);
+ }
+ break;
+ case SPU_EVENT_CLUT:
+ {
+ spu_cltbl_t *clut = event->data;
+ memcpy(this->state.clut, clut->clut, sizeof(int32_t)*16);
+ }
+ break;
+ }
}
static char *spudec_get_id(void) {
@@ -182,18 +247,28 @@ spu_decoder_t *init_spu_decoder_plugin (int iface_version, config_values_t *cfg)
spudec_decoder_t *this ;
- if (iface_version != 2)
+ if (iface_version != 3) {
+ fprintf(stderr,
+ "libspudec: Doesn't support plugin API version %d.\n"
+ "libspudec: This means there is a version mismatch between XINE and\n"
+ "libspudec: this plugin.\n", iface_version);
return NULL;
+ }
this = (spudec_decoder_t *) malloc (sizeof (spudec_decoder_t));
+ memset (this, 0, sizeof(*this));
- this->spu_decoder.interface_version = 2;
+ this->spu_decoder.interface_version = 3;
this->spu_decoder.can_handle = spudec_can_handle;
this->spu_decoder.init = spudec_init;
this->spu_decoder.decode_data = spudec_decode_data;
+ this->spu_decoder.event = spudec_event;
this->spu_decoder.close = spudec_close;
this->spu_decoder.get_identifier = spudec_get_id;
this->spu_decoder.priority = 1;
+
+ this->ovl_src.src_gen = this;
+ this->ovl_src.get_overlay = spudec_get_overlay;
return (spu_decoder_t *) this;
}