summaryrefslogtreecommitdiff
path: root/src/libspucc/xine_decoder.c
diff options
context:
space:
mode:
authorChristian Vogler <cvogler@users.sourceforge.net>2002-01-07 19:30:09 +0000
committerChristian Vogler <cvogler@users.sourceforge.net>2002-01-07 19:30:09 +0000
commit16be79073dc84a67b72f7e1a5cac93a5b34782aa (patch)
tree14071f2a3a8e5a59b5208ec1bd7bd684a6342df8 /src/libspucc/xine_decoder.c
parentd984be942f5a0d4601ff791683050ca36bd5c4cb (diff)
downloadxine-lib-16be79073dc84a67b72f7e1a5cac93a5b34782aa.tar.gz
xine-lib-16be79073dc84a67b72f7e1a5cac93a5b34782aa.tar.bz2
move all configuration responsibilities to xine_decoder.c.
cc decoder is now initialized only if CC events arrive. clean up cc_config_t by moving out renderer specific parts to new cc_renderer_t. fix event race conditions and simplify code by using one global lock for cc decoder that stays locked for the entire duration of a CC function call. CVS patchset: 1368 CVS date: 2002/01/07 19:30:09
Diffstat (limited to 'src/libspucc/xine_decoder.c')
-rw-r--r--src/libspucc/xine_decoder.c278
1 files changed, 235 insertions, 43 deletions
diff --git a/src/libspucc/xine_decoder.c b/src/libspucc/xine_decoder.c
index 4d5b40ef5..8bdb1f6c3 100644
--- a/src/libspucc/xine_decoder.c
+++ b/src/libspucc/xine_decoder.c
@@ -17,7 +17,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.1 2002/01/05 21:41:18 miguelfreitas Exp $
+ * $Id: xine_decoder.c,v 1.2 2002/01/07 19:30:09 cvogler Exp $
*
* closed caption spu decoder. receive data by events.
*
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include "buffer.h"
#include "events.h"
@@ -32,9 +33,8 @@
#include "xineutils.h"
#include "cc_decoder.h"
-/*
-#define LOG 1
-*/
+
+#define LOG_DEBUG 1
typedef struct spucc_decoder_s {
@@ -44,15 +44,209 @@ typedef struct spucc_decoder_s {
/* closed captioning decoder state */
cc_decoder_t *ccdec;
+ /* true if ccdec has been initialized */
+ int cc_open;
- /* closed captioning decoder configuration */
+ /* closed captioning decoder configuration and intrinsics */
cc_config_t cc_cfg;
- int cc_open;
-
+ /* video dimensions captured in frame change events */
+ int video_width;
+ int video_height;
+
+ /* big lock regulating access to the CC decoder, CC renderer, and
+ configuration changes. For CC decoding, fine-grained locking is not
+ necessary. Using just single lock for everything makes the code
+ for configuraton changes *a lot* simpler, and *much* easier to
+ debug and maintain.
+ */
+ pthread_mutex_t cc_mutex;
} spucc_decoder_t;
+/*------------------- general utility functions ----------------------------*/
+
+static void copy_str(char *d, const char *s, size_t maxbytes)
+{
+ strncpy(d, s, maxbytes - 1);
+ d[maxbytes - 1] = '\0';
+}
+
+
+/*------------------- private methods --------------------------------------*/
+
+/* CAUTION: THIS FUNCTION ASSUMES THAT THE MUTEX IS ALREADY LOCKED! */
+static void spucc_update_intrinsics(spucc_decoder_t *this)
+{
+#ifdef LOG_DEBUG
+ printf("spucc: update_intrinsics\n");
+#endif
+
+ if (this->cc_open)
+ cc_renderer_update_cfg(this->cc_cfg.renderer, this->video_width,
+ this->video_height);
+}
+
+
+/* CAUTION: THIS FUNCTION ASSUMES THAT THE MUTEX IS ALREADY LOCKED! */
+static void spucc_do_close(spucc_decoder_t *this)
+{
+ if (this->cc_open) {
+#ifdef LOG_DEBUG
+ printf("spucc: close\n");
+#endif
+ cc_decoder_close(this->ccdec);
+ cc_renderer_close(this->cc_cfg.renderer);
+ this->cc_open = 0;
+ }
+}
+
+
+/* CAUTION: THIS FUNCTION ASSUMES THAT THE MUTEX IS ALREADY LOCKED! */
+static void spucc_do_init (spucc_decoder_t *this, vo_instance_t *vo_out)
+{
+ if (! this->cc_open) {
+#ifdef LOG_DEBUG
+ printf("spucc: init\n");
+#endif
+ /* initialize caption renderer */
+ this->cc_cfg.renderer = cc_renderer_open(this->xine->osd_renderer,
+ this->xine->metronom,
+ &this->cc_cfg,
+ this->video_width,
+ this->video_height);
+ spucc_update_intrinsics(this);
+
+ /* initialize CC decoder */
+ this->ccdec = cc_decoder_open(&this->cc_cfg);
+ this->cc_open = 1;
+ }
+}
+
+
+/*----------------- configuration listeners --------------------------------*/
+
+static void spucc_cfg_enable_change(void *this_gen, cfg_entry_t *value)
+{
+ spucc_decoder_t *this = (spucc_decoder_t *) this_gen;
+ cc_config_t *cc_cfg = &this->cc_cfg;
+
+ pthread_mutex_lock(&this->cc_mutex);
+
+ cc_cfg->cc_enabled = value->num_value;
+ if (! cc_cfg->cc_enabled) {
+ /* captions were just disabled? */
+ spucc_do_close(this);
+ }
+ /* caption decoder is initialized on demand, so do nothing on open */
+
+#ifdef LOG_DEBUG
+ printf("spucc: closed captions are now %s.\n", cc_cfg->cc_enabled?
+ "enabled" : "disabled");
+#endif
+
+ pthread_mutex_unlock(&this->cc_mutex);
+}
+
+
+static void spucc_font_change(void *this_gen, cfg_entry_t *value)
+{
+ spucc_decoder_t *this = (spucc_decoder_t *) this_gen;
+ cc_config_t *cc_cfg = &this->cc_cfg;
+ char *font;
+
+ if (strcmp(value->key, "misc.cc_font") == 0)
+ font = cc_cfg->font;
+ else
+ font = cc_cfg->italic_font;
+
+ pthread_mutex_lock(&this->cc_mutex);
+
+ copy_str(font, value->str_value, CC_FONT_MAX);
+ spucc_update_intrinsics(this);
+#ifdef LOG_DEBUG
+ printf("spucc: changing %s to font %s\n", value->key, font);
+#endif
+
+ pthread_mutex_unlock(&this->cc_mutex);
+}
+
+
+static void spucc_num_change(void *this_gen, cfg_entry_t *value)
+{
+ spucc_decoder_t *this = (spucc_decoder_t *) this_gen;
+ cc_config_t *cc_cfg = &this->cc_cfg;
+ int *num;
+
+ if (strcmp(value->key, "misc.cc_font_size") == 0)
+ num = &cc_cfg->font_size;
+ else
+ num = &cc_cfg->center;
+
+ pthread_mutex_lock(&this->cc_mutex);
+
+ *num = value->num_value;
+ spucc_update_intrinsics(this);
+#ifdef LOG_DEBUG
+ printf("spucc: changing %s to %d\n", value->key, *num);
+#endif
+
+ pthread_mutex_unlock(&this->cc_mutex);
+}
+
+
+static void spucc_register_cfg_vars(spucc_decoder_t *this,
+ config_values_t *xine_cfg) {
+ cc_config_t *cc_vars = &this->cc_cfg;
+
+ cc_vars->cc_enabled = xine_cfg->register_bool(xine_cfg,
+ "misc.cc_enabled", 0,
+ "Enable closed captions in MPEG-2 streams",
+ NULL, spucc_cfg_enable_change,
+ this);
+
+ copy_str(cc_vars->font,
+ xine_cfg->register_string(xine_cfg, "misc.cc_font", "cc",
+ "Standard closed captioning font",
+ NULL, spucc_font_change, this),
+ CC_FONT_MAX);
+
+ copy_str(cc_vars->italic_font,
+ xine_cfg->register_string(xine_cfg, "misc.cc_italic_font", "cci",
+ "Italic closed captioning font",
+ NULL, spucc_font_change, this),
+ CC_FONT_MAX);
+
+ cc_vars->font_size = xine_cfg->register_num(xine_cfg, "misc.cc_font_size",
+ 24,
+ "Closed captioning font size",
+ NULL, spucc_num_change,
+ this);
+
+ cc_vars->center = xine_cfg->register_bool(xine_cfg, "misc.cc_center", 1,
+ "Center-adjust closed captions",
+ NULL, spucc_num_change,
+ this);
+}
+
+
+/* called when the video frame size changes */
+void spucc_notify_frame_change(spucc_decoder_t *this, int width, int height)
+{
+#ifdef LOG_DEBUG
+ printf("spucc: new frame size: %dx%d\n", width, height);
+#endif
+
+ pthread_mutex_lock(&this->cc_mutex);
+ this->video_width = width;
+ this->video_height = height;
+ spucc_update_intrinsics(this);
+ pthread_mutex_unlock(&this->cc_mutex);
+}
+
+
+/*------------------- implementation of spudec interface -------------------*/
+
static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) {
/*int type = buf_type & 0xFFFF0000;
return (type == BUF_SPU_TEXT); */
@@ -63,39 +257,39 @@ static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) {
static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) {
spucc_decoder_t *this = (spucc_decoder_t *) this_gen;
-
- /* initialize CC decoder */
- this->ccdec = cc_decoder_open(this->xine->osd_renderer, this->xine->metronom,
- this->xine->config, &this->cc_cfg);
- this->cc_open = 1;
+
+ pthread_mutex_lock(&this->cc_mutex);
+ spucc_do_init(this, vo_out);
+ pthread_mutex_unlock(&this->cc_mutex);
}
+
static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
spucc_decoder_t *this = (spucc_decoder_t *) this_gen;
- int do_decode;
if (buf->decoder_info[0] == 0) {
} else {
- if( !this->cc_open )
- spudec_init (this_gen, NULL);
-
- pthread_mutex_lock(&this->cc_cfg.cc_mutex);
- do_decode = this->cc_cfg.vars.cc_enabled && this->cc_cfg.vars.can_cc;
- pthread_mutex_unlock(&this->cc_cfg.cc_mutex);
+ pthread_mutex_lock(&this->cc_mutex);
+ if (this->cc_cfg.cc_enabled) {
+ if( !this->cc_open )
+ spucc_do_init (this, NULL);
- if( do_decode ) {
- decode_cc(this->ccdec, buf->content, buf->size,
- buf->PTS, buf->SCR);
+ if(this->cc_cfg.can_cc) {
+ decode_cc(this->ccdec, buf->content, buf->size,
+ buf->PTS, buf->SCR);
+ }
}
+ pthread_mutex_unlock(&this->cc_mutex);
}
}
static void spudec_close (spu_decoder_t *this_gen) {
spucc_decoder_t *this = (spucc_decoder_t *) this_gen;
-
- cc_decoder_close(this->ccdec);
- this->cc_open = 0;
+
+ pthread_mutex_lock(&this->cc_mutex);
+ spucc_do_close(this);
+ pthread_mutex_unlock(&this->cc_mutex);
}
static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
@@ -111,11 +305,8 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
xine_frame_change_event_t *frame_change =
(xine_frame_change_event_t *)event_gen;
- if( !this->cc_open )
- spudec_init (this_gen, NULL);
-
- cc_notify_frame_change( this->ccdec, frame_change->width,
- frame_change->height);
+ spucc_notify_frame_change(this, frame_change->width,
+ frame_change->height);
}
break;
@@ -123,19 +314,18 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
{
xine_closed_caption_event_t *closed_caption =
(xine_closed_caption_event_t *)event_gen;
- int do_decode;
- if( !this->cc_open )
- spudec_init (this_gen, NULL);
-
- pthread_mutex_lock(&this->cc_cfg.cc_mutex);
- do_decode = this->cc_cfg.vars.cc_enabled && this->cc_cfg.vars.can_cc;
- pthread_mutex_unlock(&this->cc_cfg.cc_mutex);
-
- if( do_decode ) {
- decode_cc(this->ccdec, closed_caption->buffer, closed_caption->buf_len,
- closed_caption->pts, closed_caption->scr);
+ pthread_mutex_lock(&this->cc_mutex);
+ if (this->cc_cfg.cc_enabled) {
+ if (!this->cc_open)
+ spucc_do_init (this, NULL);
+ if (this->cc_cfg.can_cc) {
+ decode_cc(this->ccdec, closed_caption->buffer,
+ closed_caption->buf_len, closed_caption->pts,
+ closed_caption->scr);
+ }
}
+ pthread_mutex_unlock(&this->cc_mutex);
}
break;
}
@@ -170,8 +360,10 @@ spu_decoder_t *init_spu_decoder_plugin (int iface_version, xine_t *xine) {
this->xine = xine;
this->cc_open = 0;
-
- cc_decoder_init(xine->config, &this->cc_cfg);
+
+ pthread_mutex_init(&this->cc_mutex, NULL);
+ spucc_register_cfg_vars(this, xine->config);
+ cc_decoder_init();
xine_register_event_listener(xine, spudec_event_listener, this);