[MPlayer-dev-eng] [PATCH] Simplify and factorize EOSD code
Nicolas George
nicolas.george at normalesup.org
Thu Feb 26 16:17:31 CET 2009
L'octidi 8 ventôse, an CCXVII, Nicolas George a écrit :
> Here is a new version of my proposal. What this patch does:
There was a small mistake, an else on the wrong if which made sub_visibility
toggle a little bogus. Updated version attached. Sorry.
Regards,
--
Nicolas George
-------------- next part --------------
Makefile | 1 +
eosd.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++
eosd.h | 67 +++++++++++++++
libmpcodecs/vf_ass.c | 35 +++-----
libmpcodecs/vf_vo.c | 58 +++++--------
5 files changed, 322 insertions(+), 57 deletions(-)
diff --git a/Makefile b/Makefile
index 449b058..fa52118 100644
--- a/Makefile
+++ b/Makefile
@@ -37,6 +37,7 @@ SRCS_COMMON = asxparser.c \
codec-cfg.c \
cpudetect.c \
edl.c \
+ eosd.c \
find_sub.c \
fmt-conversion.c \
get_path.c \
diff --git a/eosd.c b/eosd.c
new file mode 100644
index 0000000..0846520
--- /dev/null
+++ b/eosd.c
@@ -0,0 +1,218 @@
+/*
+ * EOSD subsystem
+ *
+ * Copyright (C) 2009 Nicolas George
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MPlayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "eosd.h"
+#include "libass/ass_mp.h"
+#include "libvo/sub.h"
+#include "libmpcodecs/vf.h"
+#include "mpcommon.h"
+
+extern float sub_delay; /* urgh */
+
+/* List of EOSD clients */
+enum {
+ EOSDC_ASS,
+ EOSDC_BOUNCING,
+ EOSDC_NUM /* number of clients */
+};
+
+struct eosd_environment {
+ ass_renderer_t *ass_renderer;
+ ass_image_t *images[EOSDC_NUM];
+ ass_image_t *images_prev[EOSDC_NUM];
+ ass_image_t **images_tail[EOSDC_NUM];
+ int images_changed;
+ int coords_changed;
+};
+
+/* CIGAES -- ANNOYING BOUNCING BALL */
+
+#include "eosd.h"
+
+static int bouncing_ball_twidth, bouncing_ball_y;
+static ass_image_t bouncing_ball_image;
+
+static void
+bouncing_ball_configure(int width, int height)
+{
+ bouncing_ball_twidth = width - 16;
+ bouncing_ball_y = (height - 16) / 2;
+}
+
+static void
+bouncing_ball_render(eosd_environment_t *eosd, double pts)
+{
+ int x;
+
+ pts /= 8;
+ x = (pts - (int)pts) * bouncing_ball_twidth;
+ bouncing_ball_image.dst_x = x;
+ bouncing_ball_image.dst_y = bouncing_ball_y;
+ eosd->images[EOSDC_BOUNCING] = &bouncing_ball_image;
+ eosd->images_changed = 1;
+}
+
+static void
+bouncing_ball_init(void)
+{
+ int x, y, r;
+
+ bouncing_ball_image.w = 16;
+ bouncing_ball_image.h = 16;
+ bouncing_ball_image.stride = 16;
+ bouncing_ball_image.bitmap = malloc(16 * 16);
+ bouncing_ball_image.color = 0x00FFFF00;
+ bouncing_ball_image.next = NULL;
+ for(y = 0; y < 16; y++) {
+ for(x = 0; x < 16; x++) {
+ r = 255 * ((x - 7.5) * (x - 7.5) + (y - 7.5) * (y - 7.5)) / 56.25;
+ bouncing_ball_image.bitmap[x + y * 16] = r < 256 ? 255 - r : 0;
+ }
+ }
+}
+
+/* CIGAES -- ANNOYING BOUNCING BALL */
+
+static void render_ass(eosd_environment_t *eosd, double pts)
+{
+ int c;
+
+ if (eosd->ass_renderer) {
+ if (sub_visibility && ass_track && pts != MP_NOPTS_VALUE) {
+ eosd->images[EOSDC_ASS] =
+ ass_mp_render_frame(eosd->ass_renderer, ass_track,
+ (pts + sub_delay) * 1000 + .5, &c);
+ eosd->images_changed += (c >= 2);
+ eosd->coords_changed += (c >= 1);
+ } else {
+ eosd->images[EOSDC_ASS] = NULL;
+ }
+ }
+}
+
+void eosd_configure(eosd_environment_t *eosd, int width, int height,
+ int unscaled, double aspect_ratio,
+ int margin_left, int margin_right,
+ int margin_top, int margin_bottom)
+{
+ if (!eosd)
+ return;
+
+ /* EOSDC_ASS */
+ if (eosd->ass_renderer) {
+ ass_configure(eosd->ass_renderer, width, height, unscaled);
+ if (aspect_ratio)
+ ass_set_aspect_ratio(eosd->ass_renderer, aspect_ratio);
+ ass_set_margins(eosd->ass_renderer, margin_top, margin_bottom,
+ margin_left, margin_right);
+ }
+
+ /* EOSDC_BOUNCING */
+ bouncing_ball_configure(width, height);
+}
+
+void eosd_render_frame(eosd_environment_t *eosd, double pts,
+ mp_eosd_images_t *images)
+{
+ int i;
+ ass_image_t **tail, *img;
+
+ images->imgs = NULL;
+ images->changed = 0;
+ eosd->images_changed = 0;
+ eosd->coords_changed = 0;
+
+ if (!eosd)
+ return;
+
+ render_ass(eosd, pts); /* EOSDC_ASS */
+ bouncing_ball_render(eosd, pts); /* EOSDC_BOUNCING */
+
+ /* Now that we have the images of all the clients, we concatenate all
+ * the lists.
+ * But the lists belong to each client, and some will use them again, so
+ * we will need to unconcatenate them when the rendering is done, so we
+ * keep a pointer to the 'next' link of the last element.
+ * This is an ugly hack; we probably will want to change it when we use
+ * a more generic data structure for the images.
+ */
+ tail = &images->imgs;
+ for (i = 0; i < EOSDC_NUM; i++) {
+ if (eosd->images[i] == NULL && eosd->images_prev[i] != NULL)
+ eosd->images_changed++;
+ eosd->images_prev[i] = eosd->images[i];
+ *tail = eosd->images[i];
+ for (img = eosd->images[i]; img != NULL; img = img->next)
+ tail = &img->next;
+ eosd->images_tail[i] = eosd->images[i] ? tail : NULL;
+ }
+ *tail = NULL;
+ images->changed = eosd->images_changed ? 2 : eosd->coords_changed ? 1 : 0;
+}
+
+void eosd_release_frame(eosd_environment_t *eosd)
+{
+ int i;
+
+ if (!eosd)
+ return;
+ /* Remember, we have kept a pointer to the last 'next' link of each
+ * list. Now is time to reset those links to NULL.
+ */
+ for (i = 0; i < EOSDC_NUM; i++)
+ if (eosd->images_tail[i])
+ *(eosd->images_tail[i]) = NULL;
+}
+
+eosd_environment_t *eosd_environment_init(ass_library_t *ass_library)
+{
+ eosd_environment_t *eosd;
+
+ eosd = calloc(1, sizeof(eosd_environment_t));
+ if (!eosd)
+ return NULL;
+
+ /* EOSDC_ASS */
+ eosd->ass_renderer = ass_renderer_init(ass_library);
+ if (eosd->ass_renderer)
+ ass_configure_fonts(eosd->ass_renderer);
+
+ /* EOSDC_BOUNCING */
+ bouncing_ball_init();
+
+ return eosd;
+}
+
+void eosd_environment_done(eosd_environment_t *eosd)
+{
+ if (!eosd)
+ return;
+
+ /* EOSDC_ASS */
+ if (eosd->ass_renderer)
+ ass_renderer_done(eosd->ass_renderer);
+
+ /* EOSDC_BOUNCING */
+ /* nothing */
+
+ free(eosd);
+}
diff --git a/eosd.h b/eosd.h
new file mode 100644
index 0000000..797b82a
--- /dev/null
+++ b/eosd.h
@@ -0,0 +1,67 @@
+/*
+ * EOSD subsystem
+ *
+ * Copyright (C) 2009 Nicolas George
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MPlayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_EOSD_H
+#define MPLAYER_EOSD_H
+
+#include "libass/ass.h"
+#include "libass/ass_mp.h"
+
+/**
+ * Abstract structure holding the status of the EOSD subsystem
+ */
+typedef struct eosd_environment eosd_environment_t;
+
+/**
+ * Creates a new EOSD environment
+ */
+eosd_environment_t *eosd_environment_init(ass_library_t *ass_library);
+
+/**
+ * Destroys an EOSD environment and all its elements
+ * If eosd is NULL, does nothing.
+ */
+void eosd_environment_done(eosd_environment_t *eosd);
+
+/**
+ * Configures an EOSD environment for the geometry of the driver
+ * If eosd is NULL, does nothing.
+ */
+void eosd_configure(eosd_environment_t *eosd, int width, int height,
+ int unscaled, double aspect_ratio,
+ int margin_left, int margin_right,
+ int margin_top, int margin_bottom);
+
+/**
+ * Renders a frame into the images structure
+ * If eosd is NULL, returns an empty list.
+ */
+void eosd_render_frame(eosd_environment_t *eosd, double pts,
+ mp_eosd_images_t *images);
+
+/**
+ * Releases the images returned by eosd_render_frame
+ * If eosd is NULL, does nothing.
+ */
+void eosd_release_frame(eosd_environment_t *eosd);
+
+#endif /* MPLAYER_EOSD_H */
diff --git a/libmpcodecs/vf_ass.c b/libmpcodecs/vf_ass.c
index f33aba4..f84e110 100644
--- a/libmpcodecs/vf_ass.c
+++ b/libmpcodecs/vf_ass.c
@@ -41,7 +41,7 @@
#include "m_option.h"
#include "m_struct.h"
-#include "libass/ass.h"
+#include "eosd.h"
#include "libass/ass_mp.h"
#define _r(c) ((c)>>24)
@@ -62,7 +62,7 @@ static const struct vf_priv_s {
// 0 = insert always
int auto_insert;
- ass_renderer_t* ass_priv;
+ eosd_environment_t* eosd;
unsigned char* planes[3];
unsigned char* dirty_rows;
@@ -71,10 +71,6 @@ static const struct vf_priv_s {
extern int opt_screen_size_x;
extern int opt_screen_size_y;
-extern ass_track_t* ass_track;
-extern float sub_delay;
-extern int sub_visibility;
-
static int config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt)
@@ -93,10 +89,9 @@ static int config(struct vf_instance_s* vf,
vf->priv->planes[2] = malloc(vf->priv->outw * vf->priv->outh);
vf->priv->dirty_rows = malloc(vf->priv->outh);
- if (vf->priv->ass_priv) {
- ass_configure(vf->priv->ass_priv, vf->priv->outw, vf->priv->outh, 0);
- ass_set_aspect_ratio(vf->priv->ass_priv, ((double)d_width) / d_height);
- }
+ eosd_configure(vf->priv->eosd, vf->priv->outw, vf->priv->outh, 0,
+ (double)d_width / d_height,
+ 0, 0, ass_top_margin, ass_bottom_margin);
return vf_next_config(vf, vf->priv->outw, vf->priv->outh, d_width, d_height, flags, outfmt);
}
@@ -326,12 +321,11 @@ static int render_frame(struct vf_instance_s* vf, mp_image_t *mpi, const ass_ima
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts)
{
- ass_image_t* images = 0;
- if (sub_visibility && vf->priv->ass_priv && ass_track && (pts != MP_NOPTS_VALUE))
- images = ass_mp_render_frame(vf->priv->ass_priv, ass_track, (pts+sub_delay) * 1000 + .5, NULL);
-
+ mp_eosd_images_t images;
+ eosd_render_frame(vf->priv->eosd, pts, &images);
prepare_image(vf, mpi);
- if (images) render_frame(vf, mpi, images);
+ if (images.imgs) render_frame(vf, mpi, images.imgs);
+ eosd_release_frame(vf->priv->eosd);
return vf_next_put_image(vf, vf->dmpi, pts);
}
@@ -351,12 +345,11 @@ static int control(vf_instance_t *vf, int request, void *data)
{
switch (request) {
case VFCTRL_INIT_EOSD:
- vf->priv->ass_priv = ass_renderer_init((ass_library_t*)data);
- if (!vf->priv->ass_priv) return CONTROL_FALSE;
- ass_configure_fonts(vf->priv->ass_priv);
+ vf->priv->eosd = eosd_environment_init((ass_library_t*)data);
+ if (!vf->priv->eosd) return CONTROL_FALSE;
return CONTROL_TRUE;
case VFCTRL_DRAW_EOSD:
- if (vf->priv->ass_priv) return CONTROL_TRUE;
+ if (vf->priv->eosd) return CONTROL_TRUE;
break;
}
return vf_next_control(vf, request, data);
@@ -364,8 +357,8 @@ static int control(vf_instance_t *vf, int request, void *data)
static void uninit(struct vf_instance_s* vf)
{
- if (vf->priv->ass_priv)
- ass_renderer_done(vf->priv->ass_priv);
+ if (vf->priv->eosd)
+ eosd_environment_done(vf->priv->eosd);
if (vf->priv->planes[1])
free(vf->priv->planes[1]);
if (vf->priv->planes[2])
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index affffa6..0639597 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -10,11 +10,7 @@
#include "libvo/video_out.h"
-#ifdef CONFIG_ASS
-#include "libass/ass.h"
-#include "libass/ass_mp.h"
-extern ass_track_t* ass_track;
-#endif
+#include "eosd.h"
//===========================================================================//
@@ -24,10 +20,8 @@ extern float sub_delay;
struct vf_priv_s {
double pts;
const vo_functions_t *vo;
-#ifdef CONFIG_ASS
- ass_renderer_t* ass_priv;
+ eosd_environment_t *eosd;
int prev_visibility;
-#endif
};
#define video_out (vf->priv->vo)
@@ -68,8 +62,8 @@ static int config(struct vf_instance_s* vf,
return 0;
#ifdef CONFIG_ASS
- if (vf->priv->ass_priv)
- ass_configure(vf->priv->ass_priv, width, height, !!(vf->default_caps & VFCAP_EOSD_UNSCALED));
+ eosd_configure(vf->priv->eosd, width, height,
+ !!(vf->default_caps & VFCAP_EOSD_UNSCALED), 0, 0, 0, 0, 0);
#endif
++vo_config_count;
@@ -116,34 +110,29 @@ static int control(struct vf_instance_s* vf, int request, void* data)
#ifdef CONFIG_ASS
case VFCTRL_INIT_EOSD:
{
- vf->priv->ass_priv = ass_renderer_init((ass_library_t*)data);
- if (!vf->priv->ass_priv) return CONTROL_FALSE;
- ass_configure_fonts(vf->priv->ass_priv);
- vf->priv->prev_visibility = 0;
+ vf->priv->eosd = eosd_environment_init((ass_library_t*)data);
+ if (!vf->priv->eosd) return CONTROL_FALSE;
return CONTROL_TRUE;
}
case VFCTRL_DRAW_EOSD:
{
mp_eosd_images_t images = {NULL, 2};
double pts = vf->priv->pts;
- if (!vo_config_count || !vf->priv->ass_priv) return CONTROL_FALSE;
- if (sub_visibility && vf->priv->ass_priv && ass_track && (pts != MP_NOPTS_VALUE)) {
- mp_eosd_res_t res;
- memset(&res, 0, sizeof(res));
- if (video_out->control(VOCTRL_GET_EOSD_RES, &res) == VO_TRUE) {
- ass_set_frame_size(vf->priv->ass_priv, res.w, res.h);
- ass_set_margins(vf->priv->ass_priv, res.mt, res.mb, res.ml, res.mr);
- ass_set_aspect_ratio(vf->priv->ass_priv, (double)res.w / res.h);
- }
-
- images.imgs = ass_mp_render_frame(vf->priv->ass_priv, ass_track, (pts+sub_delay) * 1000 + .5, &images.changed);
- if (!vf->priv->prev_visibility)
- images.changed = 2;
- vf->priv->prev_visibility = 1;
- } else
- vf->priv->prev_visibility = 0;
- vf->priv->prev_visibility = sub_visibility;
- return (video_out->control(VOCTRL_DRAW_EOSD, &images) == VO_TRUE) ? CONTROL_TRUE : CONTROL_FALSE;
+ int r;
+ mp_eosd_res_t res;
+ if (!vo_config_count || !vf->priv->eosd) return CONTROL_FALSE;
+ memset(&res, 0, sizeof(res));
+ if (video_out->control(VOCTRL_GET_EOSD_RES, &res) == VO_TRUE) {
+ eosd_configure(vf->priv->eosd, res.w, res.h,
+ !!(vf->default_caps & VFCAP_EOSD_UNSCALED),
+ (double)res.w / res.h,
+ res.ml, res.mr, res.mt, res.mb);
+ }
+
+ eosd_render_frame(vf->priv->eosd, pts, &images);
+ r = (video_out->control(VOCTRL_DRAW_EOSD, &images) == VO_TRUE) ? CONTROL_TRUE : CONTROL_FALSE;
+ eosd_release_frame(vf->priv->eosd);
+ return r;
}
#endif
case VFCTRL_GET_PTS:
@@ -208,10 +197,7 @@ static void draw_slice(struct vf_instance_s* vf,
static void uninit(struct vf_instance_s* vf)
{
if (vf->priv) {
-#ifdef CONFIG_ASS
- if (vf->priv->ass_priv)
- ass_renderer_done(vf->priv->ass_priv);
-#endif
+ eosd_environment_done(vf->priv->eosd);
free(vf->priv);
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/attachments/20090226/9dd73d26/attachment.pgp>
More information about the MPlayer-dev-eng
mailing list