summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-01 02:12:47 +0100
committerwm4 <wm4@nowhere>2012-11-01 02:12:47 +0100
commit84829a4ea1903e5db5782b72861fabc503a589cb (patch)
tree26b4acbaf6dd4b255278dcc67f28bd83357c3b86 /libvo
parente45dd051c304dec189d0d4d792a89c2988c3fa71 (diff)
parentf4069259cf7ffd24ac2a5b64e26a386185e94c7b (diff)
downloadmpv-84829a4ea1903e5db5782b72861fabc503a589cb.tar.bz2
mpv-84829a4ea1903e5db5782b72861fabc503a589cb.tar.xz
Merge branch 'osd_changes' into master
Conflicts: DOCS/man/en/options.rst
Diffstat (limited to 'libvo')
-rw-r--r--libvo/aspect.c31
-rw-r--r--libvo/aspect.h5
-rw-r--r--libvo/bitmap_packer.c73
-rw-r--r--libvo/bitmap_packer.h19
-rw-r--r--libvo/csputils.c74
-rw-r--r--libvo/csputils.h15
-rw-r--r--libvo/eosd_packer.c255
-rw-r--r--libvo/eosd_packer.h74
-rw-r--r--libvo/fastmemcpy.h13
-rw-r--r--libvo/gl_common.c47
-rw-r--r--libvo/gl_common.h6
-rw-r--r--libvo/gl_osd.c324
-rw-r--r--libvo/gl_osd.h43
-rw-r--r--libvo/osd.c224
-rw-r--r--libvo/osd.h34
-rw-r--r--libvo/osd_template.c383
-rw-r--r--libvo/video_out.c162
-rw-r--r--libvo/video_out.h22
-rw-r--r--libvo/vo_caca.c6
-rw-r--r--libvo/vo_corevideo.m203
-rw-r--r--libvo/vo_direct3d.c520
-rw-r--r--libvo/vo_image.c3
-rw-r--r--libvo/vo_lavc.c135
-rw-r--r--libvo/vo_opengl.c412
-rw-r--r--libvo/vo_opengl_old.c411
-rw-r--r--libvo/vo_opengl_shaders.glsl7
-rw-r--r--libvo/vo_vdpau.c417
-rw-r--r--libvo/vo_x11.c86
-rw-r--r--libvo/vo_xv.c218
29 files changed, 1412 insertions, 2810 deletions
diff --git a/libvo/aspect.c b/libvo/aspect.c
index 8a26a5ac00..f3cd00a5e5 100644
--- a/libvo/aspect.c
+++ b/libvo/aspect.c
@@ -25,18 +25,13 @@
#include "video_out.h"
-void aspect_save_orig(struct vo *vo, int orgw, int orgh)
+void aspect_save_videores(struct vo *vo, int w, int h, int d_w, int d_h)
{
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect_save_orig %dx%d\n", orgw, orgh);
- vo->aspdat.orgw = orgw;
- vo->aspdat.orgh = orgh;
-}
-
-void aspect_save_prescale(struct vo *vo, int prew, int preh)
-{
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect_save_prescale %dx%d\n", prew, preh);
- vo->aspdat.prew = prew;
- vo->aspdat.preh = preh;
+ vo->aspdat.orgw = w;
+ vo->aspdat.orgh = h;
+ vo->aspdat.prew = d_w;
+ vo->aspdat.preh = d_h;
+ vo->aspdat.par = (double)d_w / d_h * h / w;
}
void aspect_save_screenres(struct vo *vo, int scrw, int scrh)
@@ -52,9 +47,9 @@ void aspect_save_screenres(struct vo *vo, int scrw, int scrh)
vo->aspdat.scrw = scrw;
vo->aspdat.scrh = scrh;
if (opts->force_monitor_aspect)
- vo->monitor_aspect = opts->force_monitor_aspect;
+ vo->monitor_par = opts->force_monitor_aspect * scrh / scrw;
else
- vo->monitor_aspect = opts->monitor_pixel_aspect * scrw / scrh;
+ vo->monitor_par = 1.0 / opts->monitor_pixel_aspect;
}
/* aspect is called with the source resolution and the
@@ -64,17 +59,17 @@ void aspect_save_screenres(struct vo *vo, int scrw, int scrh)
void aspect_fit(struct vo *vo, int *srcw, int *srch, int fitw, int fith)
{
struct aspect_data *aspdat = &vo->aspdat;
- float pixelaspect = vo->monitor_aspect * aspdat->scrh / aspdat->scrw;
+ float pixelaspect = vo->monitor_par;
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect(0) fitin: %dx%d screenaspect: %.2f\n",
- fitw, fith, vo->monitor_aspect);
+ mp_msg(MSGT_VO, MSGL_DBG2, "aspect(0) fitin: %dx%d monitor_par: %.2f\n",
+ fitw, fith, vo->monitor_par);
*srcw = fitw;
- *srch = (float)fitw / aspdat->prew * aspdat->preh * pixelaspect;
+ *srch = (float)fitw / aspdat->prew * aspdat->preh / pixelaspect;
*srch += *srch % 2; // round
mp_msg(MSGT_VO, MSGL_DBG2, "aspect(1) wh: %dx%d (org: %dx%d)\n",
*srcw, *srch, aspdat->prew, aspdat->preh);
if (*srch > fith || *srch < aspdat->orgh) {
- int tmpw = (float)fith / aspdat->preh * aspdat->prew / pixelaspect;
+ int tmpw = (float)fith / aspdat->preh * aspdat->prew * pixelaspect;
tmpw += tmpw % 2; // round
if (tmpw <= fitw) {
*srch = fith;
diff --git a/libvo/aspect.h b/libvo/aspect.h
index aa117833f3..c5247421d2 100644
--- a/libvo/aspect.h
+++ b/libvo/aspect.h
@@ -24,10 +24,7 @@ struct vo;
void panscan_init(struct vo *vo);
void panscan_calc_windowed(struct vo *vo);
-void aspect_save_orig(struct vo *vo, int orgw, int orgh);
-
-void aspect_save_prescale(struct vo *vo, int prew, int preh);
-
+void aspect_save_videores(struct vo *vo, int w, int h, int d_w, int d_h);
void aspect_save_screenres(struct vo *vo, int scrw, int scrh);
#define A_WINZOOM 2 ///< zoom to fill window size
diff --git a/libvo/bitmap_packer.c b/libvo/bitmap_packer.c
index eedc2e2242..603a6ce410 100644
--- a/libvo/bitmap_packer.c
+++ b/libvo/bitmap_packer.c
@@ -20,6 +20,7 @@
*/
#include <stdlib.h>
+#include <assert.h>
#include <libavutil/common.h>
@@ -27,9 +28,29 @@
#include "bitmap_packer.h"
#include "mp_msg.h"
#include "mpcommon.h"
-#include "sub/ass_mp.h"
#include "sub/dec_sub.h"
+#include "fastmemcpy.h"
+#define IS_POWER_OF_2(x) (((x) > 0) && !(((x) - 1) & (x)))
+
+void packer_reset(struct bitmap_packer *packer)
+{
+ struct bitmap_packer old = *packer;
+ *packer = (struct bitmap_packer) {
+ .w_max = old.w_max,
+ .h_max = old.h_max,
+ };
+ talloc_free_children(packer);
+}
+
+void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2])
+{
+ out_bb[0] = (struct pos) {0};
+ out_bb[1] = (struct pos) {
+ FFMIN(packer->used_width + packer->padding, packer->w),
+ FFMIN(packer->used_height + packer->padding, packer->h),
+ };
+}
#define HEIGHT_SORT_BITS 4
static int size_index(int s)
@@ -142,6 +163,8 @@ int packer_pack(struct bitmap_packer *packer)
// No padding at edges
packer->used_width = FFMIN(used_width, packer->w);
packer->used_height = FFMIN(y, packer->h);
+ assert(packer->w == 0 || IS_POWER_OF_2(packer->w));
+ assert(packer->h == 0 || IS_POWER_OF_2(packer->h));
return packer->w != w_orig || packer->h != h_orig;
}
if (packer->w <= packer->h && packer->w != packer->w_max)
@@ -171,36 +194,34 @@ void packer_set_size(struct bitmap_packer *packer, int size)
packer->asize + 16);
}
-static int packer_pack_from_assimg(struct bitmap_packer *packer,
- struct ass_image *imglist)
-{
- int count = 0;
- struct ass_image *img = imglist;
- while (img) {
- if (count >= packer->asize)
- packer_set_size(packer, FFMAX(packer->asize * 2, 32));
- packer->in[count].x = img->w;
- packer->in[count].y = img->h;
- img = img->next;
- count++;
- }
- packer->count = count;
- return packer_pack(packer);
-}
-
int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
- struct sub_bitmaps *b, int padding_pixels)
+ struct sub_bitmaps *b)
{
- packer->padding = 0;
packer->count = 0;
- if (b->type == SUBBITMAP_EMPTY)
+ if (b->format == SUBBITMAP_EMPTY)
return 0;
- if (b->type == SUBBITMAP_LIBASS)
- return packer_pack_from_assimg(packer, b->imgs);
- packer->padding = padding_pixels;
- packer_set_size(packer, b->part_count);
+ packer_set_size(packer, b->num_parts);
int a = packer->padding;
- for (int i = 0; i < b->part_count; i++)
+ for (int i = 0; i < b->num_parts; i++)
packer->in[i] = (struct pos){b->parts[i].w + a, b->parts[i].h + a};
return packer_pack(packer);
}
+
+void packer_copy_subbitmaps(struct bitmap_packer *packer, struct sub_bitmaps *b,
+ void *data, int pixel_stride, int stride)
+{
+ assert(packer->count == b->num_parts);
+ if (packer->padding) {
+ struct pos bb[2];
+ packer_get_bb(packer, bb);
+ memset_pic(data, 0, bb[1].x * pixel_stride, bb[1].y, stride);
+ }
+ for (int n = 0; n < packer->count; n++) {
+ struct sub_bitmap *s = &b->parts[n];
+ struct pos p = packer->result[n];
+
+ void *pdata = (uint8_t *)data + p.y * stride + p.x * pixel_stride;
+ memcpy_pic(pdata, s->bitmap, s->w * pixel_stride, s->h,
+ stride, s->stride);
+ }
+}
diff --git a/libvo/bitmap_packer.h b/libvo/bitmap_packer.h
index c7c377cbd0..b86c3ec4f9 100644
--- a/libvo/bitmap_packer.h
+++ b/libvo/bitmap_packer.h
@@ -26,6 +26,13 @@ struct bitmap_packer {
struct ass_image;
struct sub_bitmaps;
+// Clear all internal state. Leave the following fields: w_max, h_max
+void packer_reset(struct bitmap_packer *packer);
+
+// Get the bounding box used for bitmap data (including padding).
+// The bounding box doesn't exceed (0,0)-(packer->w,packer->h).
+void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2]);
+
/* Reallocate packer->in for at least to desired number of items.
* Also sets packer->count to the same value.
*/
@@ -36,6 +43,7 @@ void packer_set_size(struct bitmap_packer *packer, int size);
* Write input sizes in packer->in.
* Resulting packing will be written in packer->result.
* w and h will be increased if necessary for successful packing.
+ * There is a strong guarantee that w and h will be powers of 2 (or set to 0).
* Return value is -1 if packing failed because w and h were set to max
* values but that wasn't enough, 1 if w or h was increased, and 0 otherwise.
*/
@@ -46,6 +54,15 @@ int packer_pack(struct bitmap_packer *packer);
* given image list.
*/
int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
- struct sub_bitmaps *b, int padding_pixels);
+ struct sub_bitmaps *b);
+
+// Copy the (already packed) sub-bitmaps from b to the image in data.
+// data must point to an image that is at least (packer->w, packer->h) big.
+// The image has the given stride (bytes between (x, y) to (x, y + 1)), and the
+// pixel format used by both the sub-bitmaps and the image uses pixel_stride
+// bytes per pixel (bytes between (x, y) to (x + 1, y)).
+// If packer->padding is set, the padding borders are cleared with 0.
+void packer_copy_subbitmaps(struct bitmap_packer *packer, struct sub_bitmaps *b,
+ void *data, int pixel_stride, int stride);
#endif
diff --git a/libvo/csputils.c b/libvo/csputils.c
index ed74b9ae74..23eb099f69 100644
--- a/libvo/csputils.c
+++ b/libvo/csputils.c
@@ -3,6 +3,8 @@
*
* Copyleft (C) 2009 Reimar Döffinger <Reimar.Doeffinger@gmx.de>
*
+ * mp_invert_yuv2rgb based on DarkPlaces engine, original code (GPL2 or later)
+ *
* This file is part of MPlayer.
*
* MPlayer is free software; you can redistribute it and/or modify
@@ -37,6 +39,7 @@ char * const mp_csp_names[MP_CSP_COUNT] = {
"BT.601 (SD)",
"BT.709 (HD)",
"SMPTE-240M",
+ "RGB",
};
char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = {
@@ -54,6 +57,7 @@ enum mp_csp avcol_spc_to_mp_csp(enum AVColorSpace colorspace)
case AVCOL_SPC_BT470BG: return MP_CSP_BT_601;
case AVCOL_SPC_SMPTE170M: return MP_CSP_BT_601;
case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M;
+ case AVCOL_SPC_RGB: return MP_CSP_RGB;
default: return MP_CSP_AUTO;
}
}
@@ -73,7 +77,8 @@ enum AVColorSpace mp_csp_to_avcol_spc(enum mp_csp colorspace)
case MP_CSP_BT_709: return AVCOL_SPC_BT709;
case MP_CSP_BT_601: return AVCOL_SPC_BT470BG;
case MP_CSP_SMPTE_240M: return AVCOL_SPC_SMPTE240M;
- default: return AVCOL_SPC_RGB;
+ case MP_CSP_RGB: return AVCOL_SPC_RGB;
+ default: return AVCOL_SPC_UNSPECIFIED;
}
}
@@ -228,6 +233,16 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
m[i][COL_Y] *= params->contrast;
m[i][COL_C] += (rgblev.max-rgblev.min) * (1 - params->contrast)/2;
}
+
+ int in_bits = FFMAX(params->int_bits_in, 1);
+ int out_bits = FFMAX(params->int_bits_out, 1);
+ double in_scale = (1 << in_bits) - 1.0;
+ double out_scale = (1 << out_bits) - 1.0;
+ for (int i = 0; i < 3; i++) {
+ m[i][COL_C] *= out_scale; // constant is 1.0
+ for (int x = 0; x < 3; x++)
+ m[i][x] *= out_scale / in_scale;
+ }
}
//! size of gamma map use to avoid slow exp function in gen_yuv2rgb_map
@@ -317,3 +332,60 @@ int mp_csp_equalizer_set(struct mp_csp_equalizer *eq, const char *property,
return 1;
}
+
+void mp_invert_yuv2rgb(float out[3][4], float in[3][4])
+{
+ float m00 = in[0][0], m01 = in[0][1], m02 = in[0][2], m03 = in[0][3],
+ m10 = in[1][0], m11 = in[1][1], m12 = in[1][2], m13 = in[1][3],
+ m20 = in[2][0], m21 = in[2][1], m22 = in[2][2], m23 = in[2][3];
+
+ // calculate the adjoint
+ out[0][0] = (m11 * m22 - m21 * m12);
+ out[0][1] = -(m01 * m22 - m21 * m02);
+ out[0][2] = (m01 * m12 - m11 * m02);
+ out[1][0] = -(m10 * m22 - m20 * m12);
+ out[1][1] = (m00 * m22 - m20 * m02);
+ out[1][2] = -(m00 * m12 - m10 * m02);
+ out[2][0] = (m10 * m21 - m20 * m11);
+ out[2][1] = -(m00 * m21 - m20 * m01);
+ out[2][2] = (m00 * m11 - m10 * m01);
+
+ // calculate the determinant (as inverse == 1/det * adjoint,
+ // adjoint * m == identity * det, so this calculates the det)
+ float det = m00 * out[0][0] + m10 * out[0][1] + m20 * out[0][2];
+ det = 1.0f / det;
+
+ out[0][0] *= det;
+ out[0][1] *= det;
+ out[0][2] *= det;
+ out[1][0] *= det;
+ out[1][1] *= det;
+ out[1][2] *= det;
+ out[2][0] *= det;
+ out[2][1] *= det;
+ out[2][2] *= det;
+
+ // fix the constant coefficient
+ // rgb = M * yuv + C
+ // M^-1 * rgb = yuv + M^-1 * C
+ // yuv = M^-1 * rgb - M^-1 * C
+ // ^^^^^^^^^^
+ out[0][3] = -(out[0][0] * m03 + out[0][1] * m13 + out[0][2] * m23);
+ out[1][3] = -(out[1][0] * m03 + out[1][1] * m13 + out[1][2] * m23);
+ out[2][3] = -(out[2][0] * m03 + out[2][1] * m13 + out[2][2] * m23);
+}
+
+// Multiply the color in c with the given matrix.
+// c is {R, G, B} or {Y, U, V} (depending on input/output and matrix).
+// Output is clipped to the given number of bits.
+void mp_map_int_color(float matrix[3][4], int clip_bits, int c[3])
+{
+ int in[3] = {c[0], c[1], c[2]};
+ for (int i = 0; i < 3; i++) {
+ double val = matrix[i][3];
+ for (int x = 0; x < 3; x++)
+ val += matrix[i][x] * in[x];
+ int ival = lrint(val);
+ c[i] = av_clip(ival, 0, (1 << clip_bits) - 1);
+ }
+}
diff --git a/libvo/csputils.h b/libvo/csputils.h
index 4ec0f14ba2..d66bb86fa3 100644
--- a/libvo/csputils.h
+++ b/libvo/csputils.h
@@ -24,6 +24,7 @@
#ifndef MPLAYER_CSPUTILS_H
#define MPLAYER_CSPUTILS_H
+#include <stdbool.h>
#include <stdint.h>
#include "libavcodec/avcodec.h"
@@ -38,6 +39,7 @@ enum mp_csp {
MP_CSP_BT_601,
MP_CSP_BT_709,
MP_CSP_SMPTE_240M,
+ MP_CSP_RGB,
MP_CSP_COUNT
};
@@ -69,10 +71,20 @@ struct mp_csp_params {
float rgamma;
float ggamma;
float bgamma;
+ // texture_bits/input_bits is for rescaling fixed point input to range [0,1]
int texture_bits;
int input_bits;
+ // for scaling integer input and output (if 0, assume range [0,1])
+ int int_bits_in;
+ int int_bits_out;
};
+#define MP_CSP_PARAMS_DEFAULTS { \
+ .colorspace = MP_CSP_DETAILS_DEFAULTS, \
+ .brightness = 0, .contrast = 1, .hue = 0, .saturation = 1, \
+ .rgamma = 1, .ggamma = 1, .bgamma = 1, \
+ .texture_bits = 8, .input_bits = 8}
+
enum mp_csp_equalizer_param {
MP_CSP_EQ_BRIGHTNESS,
MP_CSP_EQ_CONTRAST,
@@ -133,4 +145,7 @@ void mp_gen_gamma_map(unsigned char *map, int size, float gamma);
void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float yuv2rgb[3][4]);
void mp_gen_yuv2rgb_map(struct mp_csp_params *params, uint8_t *map, int size);
+void mp_invert_yuv2rgb(float out[3][4], float in[3][4]);
+void mp_map_int_color(float matrix[3][4], int clip_bits, int c[3]);
+
#endif /* MPLAYER_CSPUTILS_H */
diff --git a/libvo/eosd_packer.c b/libvo/eosd_packer.c
deleted file mode 100644
index 8f831d512e..0000000000
--- a/libvo/eosd_packer.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Common code for packing EOSD images into larger surfaces.
- *
- * This file is part of mplayer2.
- *
- * mplayer2 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.
- *
- * mplayer2 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 mplayer2; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <libavutil/common.h>
-#include "talloc.h"
-#include "mp_msg.h"
-#include "eosd_packer.h"
-
-// Initial size of EOSD surface in pixels (x*x)
-#define EOSD_SURFACE_INITIAL_SIZE 256
-
-// Allocate an eosd_packer, which can be used to layout and cache the list of
-// EOSD images contained in a mp_eosd_images_t into a flat surface.
-// It can be free'd with talloc_free().
-// Don't forget to call eosd_init() before using it.
-struct eosd_packer *eosd_packer_create(void *talloc_ctx) {
- return talloc_zero(talloc_ctx, struct eosd_packer);
-}
-
-// Call this when you need to completely reinitialize the EOSD state, e.g. when
-// when your EOSD surface was deleted.
-// max_width and max_height are the maximum surface sizes that should be
-// allowed.
-void eosd_packer_reinit(struct eosd_packer *state, uint32_t max_width,
- uint32_t max_height)
-{
- state->max_surface_width = max_width;
- state->max_surface_height = max_height;
- state->surface.w = 0;
- state->surface.h = 0;
- state->targets_count = 0;
-}
-
-#define HEIGHT_SORT_BITS 4
-static int size_index(struct eosd_target *r)
-{
- unsigned int h = r->source.y1;
- int n = av_log2_16bit(h);
- return (n << HEIGHT_SORT_BITS)
- + (- 1 - (h << HEIGHT_SORT_BITS >> n) & (1 << HEIGHT_SORT_BITS) - 1);
-}
-
-/* Pack the given rectangles into an area of size w * h.
- * The size of each rectangle is read from .source.x1/.source.y1.
- * The height of each rectangle must be at least 1 and less than 65536.
- * The .source rectangle is then set corresponding to the packed position.
- * 'scratch' must point to work memory for num_rects+16 ints.
- * Return 0 on success, -1 if the rectangles did not fit in w*h.
- *
- * The rectangles are placed in rows in order approximately sorted by
- * height (the approximate sorting is simpler than a full one would be,
- * and allows the algorithm to work in linear time). Additionally, to
- * reduce wasted space when there are a few tall rectangles, empty
- * lower-right parts of rows are filled recursively when the size of
- * rectangles in the row drops past a power-of-two threshold. So if a
- * row starts with rectangles of size 3x50, 10x40 and 5x20 then the
- * free rectangle with corners (13, 20)-(w, 50) is filled recursively.
- */
-static int pack_rectangles(struct eosd_target *rects, int num_rects,
- int w, int h, int *scratch)
-{
- int bins[16 << HEIGHT_SORT_BITS];
- int sizes[16 << HEIGHT_SORT_BITS] = {};
- for (int i = 0; i < num_rects; i++)
- sizes[size_index(rects + i)]++;
- int idx = 0;
- for (int i = 0; i < 16 << HEIGHT_SORT_BITS; i += 1 << HEIGHT_SORT_BITS) {
- for (int j = 0; j < 1 << HEIGHT_SORT_BITS; j++) {
- bins[i + j] = idx;
- idx += sizes[i + j];
- }
- scratch[idx++] = -1;
- }
- for (int i = 0; i < num_rects; i++)
- scratch[bins[size_index(rects + i)]++] = i;
- for (int i = 0; i < 16; i++)
- bins[i] = bins[i << HEIGHT_SORT_BITS] - sizes[i << HEIGHT_SORT_BITS];
- struct {
- int size, x, bottom;
- } stack[16] = {{15, 0, h}}, s = {};
- int stackpos = 1;
- int y;
- while (stackpos) {
- y = s.bottom;
- s = stack[--stackpos];
- s.size++;
- while (s.size--) {
- int maxy = -1;
- int obj;
- while ((obj = scratch[bins[s.size]]) >= 0) {
- int bottom = y + rects[obj].source.y1;
- if (bottom > s.bottom)
- break;
- int right = s.x + rects[obj].source.x1;
- if (right > w)
- break;
- bins[s.size]++;
- rects[obj].source.x0 = s.x;
- rects[obj].source.x1 += s.x;
- rects[obj].source.y0 = y;
- rects[obj].source.y1 += y;
- num_rects--;
- if (maxy <= 0)
- stack[stackpos++] = s;
- s.x = right;
- maxy = FFMAX(maxy, bottom);
- }
- if (maxy > 0)
- s.bottom = maxy;
- }
- }
- return num_rects ? -1 : 0;
-}
-
-// padding to reduce interpolation artifacts when doing scaling & filtering
-#define EOSD_PADDING 0
-
-// Release all previous images, and packs the images in imgs into state. The
-// caller must check the change variables:
-// *out_need_reposition == true: sub-image positions changed
-// *out_need_upload == true: upload all sub-images again
-// *out_need_reallocate == true: resize the EOSD texture to state->surface.w/h
-// Logical implications: need_reallocate => need_upload => need_reposition
-void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs,
- bool *out_need_reposition, bool *out_need_upload,
- bool *out_need_reallocate)
-{
- int i;
- ASS_Image *img = imgs->imgs;
- ASS_Image *p;
- struct eosd_surface *sfc = &state->surface;
-
- *out_need_reposition = imgs->bitmap_pos_id != state->last_bitmap_pos_id;
- *out_need_upload = imgs->bitmap_id != state->last_bitmap_id;
- *out_need_reallocate = false;
-
- state->last_bitmap_pos_id = imgs->bitmap_pos_id;
- state->last_bitmap_id = imgs->bitmap_id;
-
- // eosd_reinit() was probably called, force full reupload.
- if (state->targets_count == 0 && img)
- *out_need_upload = true;
-
- if (!(*out_need_reposition) && !(*out_need_upload))
- return; // Nothing changed, no need to redraw
-
- state->targets_count = 0;
-
- *out_need_reposition = true;
-
- if (!img)
- return; // There's nothing to render!
-
- if (!(*out_need_upload))
- goto eosd_skip_upload;
-
- *out_need_upload = true;
- while (1) {
- for (p = img, i = 0; p; p = p->next) {
- if (p->w <= 0 || p->h <= 0)
- continue;
- // Allocate new space for surface/target arrays
- if (i >= state->targets_size) {
- state->targets_size = FFMAX(state->targets_size * 2, 512);
- state->targets =
- talloc_realloc_size(state, state->targets,
- state->targets_size
- * sizeof(*state->targets));
- state->scratch =
- talloc_realloc_size(state, state->scratch,
- (state->targets_size + 16)
- * sizeof(*state->scratch));
- }
- state->targets[i].source.x1 = p->w + EOSD_PADDING;
- state->targets[i].source.y1 = p->h + EOSD_PADDING;
- i++;
- }
- if (pack_rectangles(state->targets, i, sfc->w, sfc->h,
- state->scratch) >= 0)
- break;
- int w = FFMIN(FFMAX(sfc->w * 2, EOSD_SURFACE_INITIAL_SIZE),
- state->max_surface_width);
- int h = FFMIN(FFMAX(sfc->h * 2, EOSD_SURFACE_INITIAL_SIZE),
- state->max_surface_height);
- if (w == sfc->w && h == sfc->h) {
- mp_msg(MSGT_VO, MSGL_ERR, "[eosd] EOSD bitmaps do not fit on "
- "a surface with the maximum supported size\n");
- return;
- }
- sfc->w = w;
- sfc->h = h;
- *out_need_reallocate = true;
- }
- if (*out_need_reallocate) {
- mp_msg(MSGT_VO, MSGL_V, "[eosd] Allocate a %dx%d surface for "
- "EOSD bitmaps.\n", sfc->w, sfc->h);
- }
-
-eosd_skip_upload:
- for (p = img; p; p = p->next) {
- if (p->w <= 0 || p->h <= 0)
- continue;
- struct eosd_target *target = &state->targets[state->targets_count];
- target->source.x1 -= EOSD_PADDING;
- target->source.y1 -= EOSD_PADDING;
- target->dest.x0 = p->dst_x;
- target->dest.y0 = p->dst_y;
- target->dest.x1 = p->w + p->dst_x;
- target->dest.y1 = p->h + p->dst_y;
- target->color = p->color;
- target->ass_img = p;
- state->targets_count++;
- }
-}
-
-// Calculate the bounding box of all sub-rectangles in the EOSD surface that
-// will be used for EOSD rendering.
-// If the bounding box is empty, return false.
-bool eosd_packer_calculate_source_bb(struct eosd_packer *state,
- struct eosd_rect *out_bb)
-{
- struct eosd_rect bb = { state->surface.w, state->surface.h, 0, 0 };
-
- for (int n = 0; n < state->targets_count; n++) {
- struct eosd_rect s = state->targets[n].source;
- bb.x0 = FFMIN(bb.x0, s.x0);
- bb.y0 = FFMIN(bb.y0, s.y0);
- bb.x1 = FFMAX(bb.x1, s.x1);
- bb.y1 = FFMAX(bb.y1, s.y1);
- }
-
- // avoid degenerate bounding box if empty
- bb.x0 = FFMIN(bb.x0, bb.x1);
- bb.y0 = FFMIN(bb.y0, bb.y1);
-
- *out_bb = bb;
- return state->targets_count > 0;
-}
diff --git a/libvo/eosd_packer.h b/libvo/eosd_packer.h
deleted file mode 100644
index 228057d3c4..0000000000
--- a/libvo/eosd_packer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This file is part of mplayer2.
- *
- * mplayer2 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.
- *
- * mplayer2 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 mplayer2; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_EOSD_PACKER_H
-#define MPLAYER_EOSD_PACKER_H
-
-#include <inttypes.h>
-#include <stdbool.h>
-
-#include "sub/ass_mp.h"
-#include "sub/dec_sub.h"
-
-// Pool of surfaces
-struct eosd_surface {
- //void *native_surface;
- int w;
- int h;
-};
-
-struct eosd_rect {
- int x0, y0, x1, y1;
-};
-
-// List of surfaces to be rendered
-struct eosd_target {
- struct eosd_rect source; // position in EOSD surface
- struct eosd_rect dest; // position on screen
- uint32_t color; // libass-style color of the image
- // NOTE: This must not be accessed after you return from your VO's
- // VOCTRL_DRAW_EOSD call - libass will free or reuse the associated
- // memory. Feel free to set this to NULL to make erroneous accesses to
- // this member fail early.
- ASS_Image *ass_img;
-};
-
-struct eosd_packer {
- struct eosd_surface surface;
- struct eosd_target *targets;
- int targets_count; // number of valid elements in targets
- int targets_size; // number of allocated elements in targets
-
- uint32_t max_surface_width;
- uint32_t max_surface_height;
-
- int *scratch;
- int last_bitmap_id;
- int last_bitmap_pos_id;
-};
-
-struct eosd_packer *eosd_packer_create(void *talloc_ctx);
-void eosd_packer_reinit(struct eosd_packer *state, uint32_t max_width,
- uint32_t max_height);
-void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs,
- bool *out_need_reposition, bool *out_need_upload,
- bool *out_need_reallocate);
-bool eosd_packer_calculate_source_bb(struct eosd_packer *state,
- struct eosd_rect *out_bb);
-
-#endif /* MPLAYER_EOSD_PACKER_H */
diff --git a/libvo/fastmemcpy.h b/libvo/fastmemcpy.h
index 5d05d37043..36fada39fe 100644
--- a/libvo/fastmemcpy.h
+++ b/libvo/fastmemcpy.h
@@ -64,4 +64,17 @@ static inline void * memcpy_pic2(void * dst, const void * src,
return retval;
}
+static inline void memset_pic(void *dst, int fill, int bytesPerLine, int height,
+ int stride)
+{
+ if