diff options
Diffstat (limited to 'libvo')
-rw-r--r-- | libvo/aspect.c | 31 | ||||
-rw-r--r-- | libvo/aspect.h | 5 | ||||
-rw-r--r-- | libvo/bitmap_packer.c | 73 | ||||
-rw-r--r-- | libvo/bitmap_packer.h | 19 | ||||
-rw-r--r-- | libvo/csputils.c | 74 | ||||
-rw-r--r-- | libvo/csputils.h | 15 | ||||
-rw-r--r-- | libvo/eosd_packer.c | 255 | ||||
-rw-r--r-- | libvo/eosd_packer.h | 74 | ||||
-rw-r--r-- | libvo/fastmemcpy.h | 13 | ||||
-rw-r--r-- | libvo/gl_common.c | 47 | ||||
-rw-r--r-- | libvo/gl_common.h | 6 | ||||
-rw-r--r-- | libvo/gl_osd.c | 324 | ||||
-rw-r--r-- | libvo/gl_osd.h | 43 | ||||
-rw-r--r-- | libvo/osd.c | 224 | ||||
-rw-r--r-- | libvo/osd.h | 34 | ||||
-rw-r--r-- | libvo/osd_template.c | 383 | ||||
-rw-r--r-- | libvo/video_out.c | 162 | ||||
-rw-r--r-- | libvo/video_out.h | 22 | ||||
-rw-r--r-- | libvo/vo_caca.c | 6 | ||||
-rw-r--r-- | libvo/vo_corevideo.m | 203 | ||||
-rw-r--r-- | libvo/vo_direct3d.c | 520 | ||||
-rw-r--r-- | libvo/vo_image.c | 3 | ||||
-rw-r--r-- | libvo/vo_lavc.c | 135 | ||||
-rw-r--r-- | libvo/vo_opengl.c | 412 | ||||
-rw-r--r-- | libvo/vo_opengl_old.c | 411 | ||||
-rw-r--r-- | libvo/vo_opengl_shaders.glsl | 7 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 417 | ||||
-rw-r--r-- | libvo/vo_x11.c | 86 | ||||
-rw-r--r-- | libvo/vo_xv.c | 218 |
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 (bytesPerLine == stride) { + memset(dst, fill, stride * height); + } else { + for (int i = 0; i < height; i++) { + memset(dst, fill, bytesPerLine); + dst = (uint8_t *)dst + stride; + } + } +} + #endif /* MPLAYER_FASTMEMCPY_H */ diff --git a/libvo/gl_common.c b/libvo/gl_common.c index 20c3d44af2..80db2eacc4 100644 --- a/libvo/gl_common.c +++ b/libvo/gl_common.c @@ -46,6 +46,8 @@ #include "aspect.h" #include "pnm_loader.h" |