diff options
author | wm4 <wm4@nowhere> | 2013-06-08 01:35:44 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-06-28 20:34:46 +0200 |
commit | 3382a6f6e48c7e093c2b7e0e4a0e28b60a084358 (patch) | |
tree | cc50df6d6ae5ffa6b1f7d3eb4e816a3afcfd1641 /video | |
parent | 823e0c511bea235be06d5e2037ef9d0b345d9405 (diff) | |
download | mpv-3382a6f6e48c7e093c2b7e0e4a0e28b60a084358.tar.bz2 mpv-3382a6f6e48c7e093c2b7e0e4a0e28b60a084358.tar.xz |
video: add a new method to configure filters and VOs
The filter chain and the video ouputs have config() functions. They are
strictly limited to transfering the video size and format. Other
parameters (like color levels) have to be transferred separately.
Improve upon this by introducing a separate set of reconfig() functions,
which use mp_image_params to carry format parameters. This struct
contains all image format related parameters from config(), plus
additional parameters such as colorspace.
Change vf_rotate to use it, as well as vo_opengl. vf_rotate is just
an example/test case, but vo_opengl will need it later.
The intention is also to get rid of VOCTRL_SET_YUV_COLORSPACE. This
information is now handed to the VOs via reconfig(). The getter,
VOCTRL_GET_YUV_COLORSPACE, will still be needed though.
Diffstat (limited to 'video')
-rw-r--r-- | video/decode/lavc.h | 1 | ||||
-rw-r--r-- | video/decode/vd.c | 50 | ||||
-rw-r--r-- | video/decode/vd.h | 2 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 22 | ||||
-rw-r--r-- | video/filter/vf.c | 92 | ||||
-rw-r--r-- | video/filter/vf.h | 21 | ||||
-rw-r--r-- | video/filter/vf_lavfi.c | 4 | ||||
-rw-r--r-- | video/filter/vf_rotate.c | 25 | ||||
-rw-r--r-- | video/filter/vf_vo.c | 21 | ||||
-rw-r--r-- | video/mp_image.c | 5 | ||||
-rw-r--r-- | video/mp_image.h | 10 | ||||
-rw-r--r-- | video/out/gl_video.c | 16 | ||||
-rw-r--r-- | video/out/gl_video.h | 2 | ||||
-rw-r--r-- | video/out/vo.c | 29 | ||||
-rw-r--r-- | video/out/vo.h | 37 | ||||
-rw-r--r-- | video/out/vo_opengl.c | 13 |
16 files changed, 211 insertions, 139 deletions
diff --git a/video/decode/lavc.h b/video/decode/lavc.h index 41701be1d6..25ed2b8ac5 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h @@ -18,6 +18,7 @@ typedef struct ffmpeg_ctx { int do_hw_dr1; int vo_initialized; int best_csp; + struct mp_image_params image_params; AVRational last_sample_aspect_ratio; enum AVDiscard skip_frame; const char *software_fallback_decoder; diff --git a/video/decode/vd.c b/video/decode/vd.c index b38d9d43d5..6f05ab334c 100644 --- a/video/decode/vd.c +++ b/video/decode/vd.c @@ -50,16 +50,22 @@ const vd_functions_t * const mpcodecs_vd_drivers[] = { NULL }; -int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) +int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params) { struct MPOpts *opts = sh->opts; vf_instance_t *vf = sh->vfilter; int vocfg_flags = 0; - - if (w) - sh->disp_w = w; - if (h) - sh->disp_h = h; + struct mp_image_params p = *params; + + if (!p.w || !p.h) { + // ideally, this should be dead code + mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown size, using container size.\n"); + p.w = sh->disp_w; + p.h = sh->disp_h; + } else { + sh->disp_w = p.w; + sh->disp_h = p.h; + } mp_msg(MSGT_DECVIDEO, MSGL_V, "VIDEO: %dx%d %5.3f fps %5.1f kbps (%4.1f kB/s)\n", @@ -67,10 +73,10 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) sh->i_bps / 1000.0); if (!sh->disp_w || !sh->disp_h) - return 0; + return -1; mp_msg(MSGT_DECVIDEO, MSGL_V, "VDec: vo config request - %d x %d (%s)\n", - w, h, vo_format_name(out_fmt)); + p.w, p.h, vo_format_name(p.imgfmt)); if (get_video_quality_max(sh) <= 0 && opts->divx_quality) { // user wants postprocess but no pp filter yet: @@ -78,17 +84,17 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) } // check if libvo and codec has common outfmt (no conversion): + int flags = 0; for (;;) { mp_msg(MSGT_VFILTER, MSGL_V, "Trying filter chain:\n"); vf_print_filter_chain(MSGL_V, vf); - int flags = vf->query_format(vf, out_fmt); + flags = vf->query_format(vf, p.imgfmt); mp_msg(MSGT_CPLAYER, MSGL_DBG2, "vo_debug: query(%s) returned 0x%X \n", - vo_format_name(out_fmt), flags); + vo_format_name(p.imgfmt), flags); if ((flags & VFCAP_CSP_SUPPORTED_BY_HW) || (flags & VFCAP_CSP_SUPPORTED)) { - sh->output_flags = flags; break; } // TODO: no match - we should use conversion... @@ -104,16 +110,13 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) mp_tmsg(MSGT_VFILTER, MSGL_WARN, "Attempted filter chain:\n"); vf_print_filter_chain(MSGL_WARN, vf); sh->vf_initialized = -1; - return 0; // failed + return -1; // failed } - sh->outfmt = out_fmt; - mp_msg(MSGT_CPLAYER, MSGL_V, "VDec: using %s as output csp\n", - vo_format_name(out_fmt)); sh->vfilter = vf; // autodetect flipping bool flip = opts->flip; - if (flip && !(sh->output_flags & VFCAP_FLIP)) { + if (flip && !(flags & VFCAP_FLIP)) { // we need to flip, but no flipping filter avail. vf_add_before_vo(&vf, "flip", NULL); sh->vfilter = vf; @@ -147,19 +150,21 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n", sh->aspect); } + p.d_w = d_w; + p.d_h = d_h; + vocfg_flags = (opts->fullscreen ? VOFLAG_FULLSCREEN : 0) | (flip ? VOFLAG_FLIPPING : 0); // Time to config libvo! mp_msg(MSGT_CPLAYER, MSGL_V, "VO Config (%dx%d->%dx%d,flags=%d,0x%X)\n", sh->disp_w, - sh->disp_h, d_w, d_h, vocfg_flags, out_fmt); + sh->disp_h, d_w, d_h, vocfg_flags, p.imgfmt); - if (vf_config_wrapper(vf, sh->disp_w, sh->disp_h, d_w, d_h, vocfg_flags, - out_fmt) == 0) { + if (vf_reconfig_wrapper(vf, &p, vocfg_flags) < 0) { mp_tmsg(MSGT_CPLAYER, MSGL_WARN, "FATAL: Cannot initialize video driver.\n"); sh->vf_initialized = -1; - return 0; + return -1; } mp_tmsg(MSGT_VFILTER, MSGL_V, "Video filter chain:\n"); @@ -167,6 +172,9 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) sh->vf_initialized = 1; + sh->colorspace = p.colorspace; + sh->color_range = p.colorlevels; + set_video_colorspace(sh); if (opts->gamma_gamma != 1000) @@ -180,5 +188,5 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) if (opts->gamma_hue != 1000) set_video_colors(sh, "hue", opts->gamma_hue); - return 1; + return 0; } diff --git a/video/decode/vd.h b/video/decode/vd.h index 0e06f7bb40..ca4107dca9 100644 --- a/video/decode/vd.h +++ b/video/decode/vd.h @@ -44,6 +44,6 @@ extern const vd_functions_t *const mpcodecs_vd_drivers[]; #define VDCTRL_QUERY_UNSEEN_FRAMES 9 // current decoder lag #define VDCTRL_REINIT_VO 10 // reinit filter/VO chain -int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int outfmt); +int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params); #endif /* MPLAYER_VD_H */ diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 1f5ae68bbf..f67e6dfbe6 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -436,10 +436,19 @@ static int init_vo(sh_video_t *sh, AVFrame *frame) ctx->pix_fmt = pix_fmt; ctx->best_csp = pixfmt2imgfmt(pix_fmt); - sh->colorspace = avcol_spc_to_mp_csp(ctx->avctx->colorspace); - sh->color_range = avcol_range_to_mp_csp_levels(ctx->avctx->color_range); + ctx->image_params = (struct mp_image_params) { + .imgfmt = ctx->best_csp, + .w = width, + .h = height, + // Ideally, we should also set aspect ratio, but we aren't there yet + // - so vd.c calculates display size from sh->aspect. + .d_w = width, + .d_h = height, + .colorspace = avcol_spc_to_mp_csp(ctx->avctx->colorspace), + .colorlevels = avcol_range_to_mp_csp_levels(ctx->avctx->color_range), + }; - if (!mpcodecs_config_vo(sh, sh->disp_w, sh->disp_h, ctx->best_csp)) + if (mpcodecs_reconfig_vo(sh, &ctx->image_params) < 0) return -1; ctx->vo_initialized = 1; @@ -690,8 +699,8 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, struct mp_image *mpi = image_from_decoder(sh); assert(mpi->planes[0]); - mpi->colorspace = sh->colorspace; - mpi->levels = sh->color_range; + mpi->colorspace = ctx->image_params.colorspace; + mpi->levels = ctx->image_params.colorlevels; *out_image = mpi; return 1; @@ -745,7 +754,8 @@ static int control(sh_video_t *sh, int cmd, void *arg) *(int *)arg = delay; return CONTROL_TRUE; case VDCTRL_REINIT_VO: - mpcodecs_config_vo(sh, sh->disp_w, sh->disp_h, ctx->best_csp); + if (ctx->vo_initialized) + mpcodecs_reconfig_vo(sh, &ctx->image_params); return true; } return CONTROL_UNKNOWN; diff --git a/video/filter/vf.c b/video/filter/vf.c index 94df76c0e1..26841f380f 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -125,16 +125,17 @@ const m_obj_list_t vf_obj_list = { // the last vf_config call. struct mp_image *vf_alloc_out_image(struct vf_instance *vf) { + struct mp_image_params *p = &vf->fmt_out.params; assert(vf->fmt_out.configured); - return mp_image_pool_get(vf->out_pool, vf->fmt_out.fmt, - vf->fmt_out.w, vf->fmt_out.h); + return mp_image_pool_get(vf->out_pool, p->imgfmt, p->w, p->h); } void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img) { + struct mp_image_params *p = &vf->fmt_out.params; assert(vf->fmt_out.configured); - assert(vf->fmt_out.fmt == img->imgfmt); - assert(vf->fmt_out.w == img->w && vf->fmt_out.h == img->h); + assert(p->imgfmt == img->imgfmt); + assert(p->w == img->w && p->h == img->h); mp_image_pool_make_writeable(vf->out_pool, img); } @@ -156,10 +157,11 @@ static struct mp_image *vf_default_filter(struct vf_instance *vf, static void print_fmt(int msglevel, struct vf_format *fmt) { if (fmt && fmt->configured) { - mp_msg(MSGT_VFILTER, msglevel, "%dx%d", fmt->w, fmt->h); - if (fmt->w != fmt->dw || fmt->h != fmt->dh) - mp_msg(MSGT_VFILTER, msglevel, "->%dx%d", fmt->dw, fmt->dh); - mp_msg(MSGT_VFILTER, msglevel, " %s %#x", mp_imgfmt_to_name(fmt->fmt), + struct mp_image_params *p = &fmt->params; + mp_msg(MSGT_VFILTER, msglevel, "%dx%d", p->w, p->h); + if (p->w != p->d_w || p->h != p->d_h) + mp_msg(MSGT_VFILTER, msglevel, "->%dx%d", p->d_w, p->d_h); + mp_msg(MSGT_VFILTER, msglevel, " %s %#x", mp_imgfmt_to_name(p->imgfmt), fmt->flags); } else { mp_msg(MSGT_VFILTER, msglevel, "???"); @@ -366,9 +368,10 @@ static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf) // Return >= 0 on success, < 0 on failure (even if output frames were produced) int vf_filter_frame(struct vf_instance *vf, struct mp_image *img) { + struct mp_image_params *p = &vf->fmt_in.params; assert(vf->fmt_in.configured); - assert(img->w == vf->fmt_in.w && img->h == vf->fmt_in.h); - assert(img->imgfmt == vf->fmt_in.fmt); + assert(img->w == p->w && img->h == p->h); + assert(img->imgfmt == p->imgfmt); if (vf->filter_ext) { return vf->filter_ext(vf, img); @@ -410,54 +413,73 @@ void vf_chain_seek_reset(struct vf_instance *vf) vf_forget_frames(cur); } -int vf_config_wrapper(struct vf_instance *vf, - int width, int height, int d_width, int d_height, - unsigned int flags, unsigned int outfmt) +int vf_reconfig_wrapper(struct vf_instance *vf, struct mp_image_params *p, + int flags) { vf_forget_frames(vf); mp_image_pool_clear(vf->out_pool); - vf->fmt_in = vf->fmt_out = (struct vf_format){0}; - - int r = vf->config(vf, width, height, d_width, d_height, flags, outfmt); - if (r) { - vf->fmt_in = (struct vf_format) { - .configured = 1, - .w = width, .h = height, - .dw = d_width, .dh = d_height, - .flags = flags, - .fmt = outfmt, - }; - vf->fmt_out = vf->next ? vf->next->fmt_in : (struct vf_format){0}; + vf->fmt_in = (struct vf_format) { + .params = *p, + .flags = flags, + }; + vf->fmt_out = (struct vf_format){0}; + + int r; + if (vf->reconfig) { + r = vf->reconfig(vf, p, flags); + } else { + r = vf->config(vf, p->w, p->h, p->d_w, p->d_h, flags, p->imgfmt); + r = r ? 0 : -1; + } + if (r >= 0) { + vf->fmt_in.configured = 1; + if (vf->next) + vf->fmt_out = vf->next->fmt_in; } return r; } -int vf_next_config(struct vf_instance *vf, - int width, int height, int d_width, int d_height, - unsigned int voflags, unsigned int outfmt) +int vf_next_reconfig(struct vf_instance *vf, struct mp_image_params *p, + int outflags) { struct MPOpts *opts = vf->opts; - int flags = vf->next->query_format(vf->next, outfmt); + int flags = vf->next->query_format(vf->next, p->imgfmt); if (!flags) { // hmm. colorspace mismatch!!! // let's insert the 'scale' filter, it does the job for us: vf_instance_t *vf2; if (vf->next->info == &vf_info_scale) - return 0; // scale->scale + return -1; // scale->scale vf2 = vf_open_filter(opts, vf->next, "scale", NULL); if (!vf2) - return 0; // shouldn't happen! + return -1; // shouldn't happen! vf->next = vf2; - flags = vf->next->query_format(vf->next, outfmt); + flags = vf->next->query_format(vf->next, p->imgfmt); if (!flags) { mp_tmsg(MSGT_VFILTER, MSGL_ERR, "Cannot find matching colorspace, " "even by inserting 'scale' :(\n"); - return 0; // FAIL + return -1; // FAIL } } - return vf_config_wrapper(vf->next, width, height, d_width, d_height, - voflags, outfmt); + return vf_reconfig_wrapper(vf->next, p, outflags); +} + +int vf_next_config(struct vf_instance *vf, + int width, int height, int d_width, int d_height, + unsigned int voflags, unsigned int outfmt) +{ + struct mp_image_params p = { + .imgfmt = outfmt, + .w = width, + .h = height, + .d_w = d_width, + .d_h = d_height, + .colorspace = vf->fmt_in.params.colorspace, + .colorlevels = vf->fmt_in.params.colorlevels, + }; + int r = vf_reconfig_wrapper(vf->next, &p, voflags); + return r < 0 ? 0 : 1; } int vf_next_control(struct vf_instance *vf, int request, void *data) diff --git a/video/filter/vf.h b/video/filter/vf.h index fd0118e152..638fc30a61 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -36,21 +36,28 @@ typedef struct vf_info { const char *author; const char *comment; int (*vf_open)(struct vf_instance *vf, char *args); - // Ptr to a struct dscribing the options + // Ptr to a struct describing the options const void *opts; } vf_info_t; struct vf_format { int configured; - int w, h, dw, dh, flags, fmt; + struct mp_image_params params; + int flags; }; typedef struct vf_instance { const vf_info_t *info; - // funcs: + int (*config)(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt); + + // Alternative to config() (can pass more image parameters) + // Note: the callee is allowed to write *params. + int (*reconfig)(struct vf_instance *vf, struct mp_image_params *params, + int flags); + int (*control)(struct vf_instance *vf, int request, void *data); int (*query_format)(struct vf_instance *vf, unsigned int fmt); @@ -131,6 +138,9 @@ int vf_next_config(struct vf_instance *vf, int vf_next_control(struct vf_instance *vf, int request, void *data); int vf_next_query_format(struct vf_instance *vf, unsigned int fmt); +int vf_next_reconfig(struct vf_instance *vf, struct mp_image_params *params, + int flags); + struct m_obj_settings; vf_instance_t *append_filters(vf_instance_t *last, struct m_obj_settings *vf_settings); @@ -140,9 +150,8 @@ vf_instance_t *vf_find_by_label(vf_instance_t *chain, const char *label); void vf_uninit_filter(vf_instance_t *vf); void vf_uninit_filter_chain(vf_instance_t *vf); -int vf_config_wrapper(struct vf_instance *vf, - int width, int height, int d_width, int d_height, - unsigned int flags, unsigned int outfmt); +int vf_reconfig_wrapper(struct vf_instance *vf, struct mp_image_params *params, + int flags); void vf_print_filter_chain(int msglevel, struct vf_instance *vf); void vf_rescale_dsize(int *d_width, int *d_height, int old_w, int old_h, diff --git a/video/filter/vf_lavfi.c b/video/filter/vf_lavfi.c index 53e22c21b9..6d5735b433 100644 --- a/video/filter/vf_lavfi.c +++ b/video/filter/vf_lavfi.c @@ -301,8 +301,8 @@ static int control(vf_instance_t *vf, int request, void *data) switch (request) { case VFCTRL_SEEK_RESET: if (p->graph) { - struct vf_format *f = &vf->fmt_in; - recreate_graph(vf, f->w, f->h, f->dw, f->dh, f->fmt); + struct mp_image_params *f = &vf->fmt_in.params; + recreate_graph(vf, f->w, f->h, f->d_w, f->d_h, f->imgfmt); } break; } diff --git a/video/filter/vf_rotate.c b/video/filter/vf_rotate.c index 0e5fbdbd37..94132848fb 100644 --- a/video/filter/vf_rotate.c +++ b/video/filter/vf_rotate.c @@ -65,21 +65,24 @@ static void rotate(unsigned char* dst,unsigned char* src,int dststride,int srcst } } -static int config(struct vf_instance *vf, int width, int height, - int d_width, int d_height, - unsigned int flags, unsigned int outfmt) +static int reconfig(struct vf_instance *vf, struct mp_image_params *p, int flags) { if (vf->priv->direction & 4) { - if (width < height) + if (p->w < p->h) vf->priv->direction &= 3; } if (vf->priv->direction & 4) - return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt); - struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(outfmt); - int a_w = MP_ALIGN_DOWN(width, desc.align_x); - int a_h = MP_ALIGN_DOWN(height, desc.align_y); - vf_rescale_dsize(&d_width, &d_height, width, height, a_w, a_h); - return vf_next_config(vf, a_h, a_w, d_height, d_width, flags, outfmt); + return vf_next_reconfig(vf, p, flags); + struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(p->imgfmt); + int a_w = MP_ALIGN_DOWN(p->w, desc.align_x); + int a_h = MP_ALIGN_DOWN(p->h, desc.align_y); + vf_rescale_dsize(&p->d_w, &p->d_h, p->w, p->h, a_w, a_h); + p->w = a_h; + p->h = a_w; + int t = p->d_w; + p->d_w = p->d_h; + p->d_h = t; + return vf_next_reconfig(vf, p, flags); } static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) @@ -113,7 +116,7 @@ static int query_format(struct vf_instance *vf, unsigned int fmt) } static int vf_open(vf_instance_t *vf, char *args){ - vf->config=config; + vf->reconfig=reconfig; vf->filter=filter; vf->query_format=query_format; vf->priv=malloc(sizeof(struct vf_priv_s)); diff --git a/video/filter/vf_vo.c b/video/filter/vf_vo.c index 5edd2956c6..22fa38f8d0 100644 --- a/video/filter/vf_vo.c +++ b/video/filter/vf_vo.c @@ -37,22 +37,18 @@ struct vf_priv_s { }; #define video_out (vf->priv->vo) -static int config(struct vf_instance *vf, - int width, int height, int d_width, int d_height, - unsigned int flags, unsigned int outfmt) +static int reconfig(struct vf_instance *vf, struct mp_image_params *p, int flags) { - - if ((width <= 0) || (height <= 0) || (d_width <= 0) || (d_height <= 0)) { + if (p->w <= 0 || p->h <= 0 || p->d_w <= 0 || p->d_h <= 0) { mp_msg(MSGT_CPLAYER, MSGL_ERR, "VO: invalid dimensions!\n"); - return 0; + return -1; } const vo_info_t *info = video_out->driver->info; mp_msg(MSGT_CPLAYER, MSGL_INFO, "VO: [%s] %dx%d => %dx%d %s %s%s\n", info->short_name, - width, height, - d_width, d_height, - vo_format_name(outfmt), + p->w, p->h, p->d_w, p->d_h, + vo_format_name(p->imgfmt), (flags & VOFLAG_FULLSCREEN) ? " [fs]" : "", (flags & VOFLAG_FLIPPING) ? " [flip]" : ""); mp_msg(MSGT_CPLAYER, MSGL_V, "VO: Description: %s\n", info->name); @@ -60,10 +56,7 @@ static int config(struct vf_instance *vf, if (info->comment && strlen(info->comment) > 0) mp_msg(MSGT_CPLAYER, MSGL_V, "VO: Comment: %s\n", info->comment); - if (vo_config(video_out, width, height, d_width, d_height, flags, outfmt)) - return 0; - - return 1; + return vo_reconfig(video_out, p, flags); } static int control(struct vf_instance *vf, int request, void *data) @@ -120,7 +113,7 @@ static void uninit(struct vf_instance *vf) static int vf_open(vf_instance_t *vf, char *args) { - vf->config = config; + vf->reconfig = reconfig; vf->control = control; vf->query_format = query_format; vf->uninit = uninit; diff --git a/video/mp_image.c b/video/mp_image.c index ec8f14fc34..85c174dfaa 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -152,15 +152,14 @@ static int mp_chroma_div_up(int size, int shift) // Caller has to make sure this doesn't exceed the allocated plane data/strides. void mp_image_set_size(struct mp_image *mpi, int w, int h) { - mpi->w = w; - mpi->h = h; + mpi->w = mpi->display_w = w; + mpi->h = mpi->display_h = h; for (int n = 0; n < mpi->num_planes; n++) { mpi->plane_w[n] = mp_chroma_div_up(mpi->w, mpi->fmt.xs[n]); mpi->plane_h[n] = mp_chroma_div_up(mpi->h, mpi->fmt.ys[n]); } mpi->chroma_width = mpi->plane_w[1]; mpi->chroma_height = mpi->plane_h[1]; - mpi->display_w = mpi->display_h = 0; } void mp_image_set_display_size(struct mp_image *mpi, int dw, int dh) diff --git a/video/mp_image.h b/video/mp_image.h index ca536a1e91..643b70b949 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -37,6 +37,14 @@ #define MP_IMGFIELD_BOTTOM 0x10 #define MP_IMGFIELD_INTERLACED 0x20 +struct mp_image_params { + enum mp_imgfmt imgfmt; // pixel format + int w, h; // image dimensions + int d_w, d_h; // define display aspect ratio (never 0/0) + enum mp_csp colorspace; + enum mp_csp_levels colorlevels; +}; + /* Memory management: * - mp_image is a light-weight reference to the actual image data (pixels). * The actual image data is reference counted and can outlive mp_image @@ -58,7 +66,7 @@ typedef struct mp_image { struct mp_imgfmt_desc fmt; // fields redundant to fmt, for convenience or compatibility - unsigned int imgfmt; + enum mp_imgfmt imgfmt; int num_planes; int chroma_x_shift; // horizontal int chroma_y_shift; // vertical diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 4d780f41d8..658c531546 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -1848,17 +1848,19 @@ bool gl_video_check_format(int mp_format) return init_format(mp_format, NULL); } -void gl_video_config(struct gl_video *p, int format, int w, int h, int dw, int dh) +void gl_video_config(struct gl_video *p, struct mp_image_params *params) { - if (p->image_format != format || p->image_w != w || p->image_h != h) { + if (p->image_format != params->imgfmt || p->image_w != params->w || + p->image_h != params->h) + { uninit_video(p); - p->image_w = w; - p->image_h = h; - init_format(format, p); + p->image_w = params->w; + p->image_h = params->h; + init_format(params->imgfmt, p); init_video(p); } - p->image_dw = dw; - p->image_dh = dh; + p->image_dw = params->d_w; + p->image_dh = params->d_h; } void gl_video_set_output_depth(struct gl_video *p, int r, int g, int b) diff --git a/video/out/gl_video.h b/video/out/gl_video.h index 0d796502bb..289ccddf52 100644 --- a/video/out/gl_video.h +++ b/video/out/gl_video.h @@ -54,7 +54,7 @@ struct gl_video; struct gl_video *gl_video_init(GL *gl); void gl_video_uninit(struct gl_video *p); void gl_video_set_options(struct gl_video *p, struct gl_video_opts *opts); -void gl_video_config(struct gl_video *p, int format, int w, int h, int dw, int dh); +void gl_video_config(struct gl_video *p, struct mp_image_params *params); void gl_video_set_output_depth(struct gl_video *p, int r, int g, int b); void gl_video_set_lut3d(struct gl_video *p, struct lut3d *lut3d); void gl_video_draw_osd(struct gl_video *p, struct osd_state *osd); diff --git a/video/out/vo.c b/video/out/vo.c index c621f37472..02d51bf7b6 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -406,21 +406,34 @@ static int event_fd_callback(void *ctx, int fd) return MP_INPUT_NOTHING; } -int vo_config(struct vo *vo, uint32_t width, uint32_t height, - uint32_t d_width, uint32_t d_height, uint32_t flags, - uint32_t format) +int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags) { - aspect_save_videores(vo, width, height, d_width, d_height); + int d_width = params->d_w; + int d_height = params->d_h; + aspect_save_videores(vo, params->w, params->h, d_width, d_height); if (vo_control(vo, VOCTRL_UPDATE_SCREENINFO, NULL) == VO_TRUE) { - determine_window_geometry(vo, d_width, d_height); + determine_window_geometry(vo, params->d_w, params->d_h); d_width = vo->dwidth; d_height = vo->dheight; } + vo->dwidth = d_width; + vo->dheight = d_height; - int ret = vo->driver->config(vo, width, height, d_width, d_height, flags, - format); - vo->config_ok = (ret == 0); + struct mp_image_params p2 = *params; + p2.d_w = vo->aspdat.prew; + p2.d_h = vo->aspdat.preh; + + int ret; + if (vo->driver->reconfig) { + ret = vo->driver->reconfig(vo, &p2, flags); + } else { + // Old config() takes window size, while reconfig() takes aspect (!) + ret = vo->driver->config(vo, p2.w, p2.h, d_width, d_height, flags, + p2.imgfmt); + ret = ret ? -1 : 0; + } + vo->config_ok = (ret >= 0); vo->config_count += vo->config_ok; if (vo->registered_fd == -1 && vo->event_fd != -1 && vo->config_ok) { mp_input_add_key_fd(vo->input_ctx, vo->event_fd, 1, event_fd_callback, diff --git a/video/out/vo.h b/video/out/vo.h index df16a01d0e..9f4d2a9060 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -47,8 +47,8 @@ enum mp_voctrl { VOCTRL_GET_PANSCAN, VOCTRL_SET_PANSCAN, - VOCTRL_SET_EQUALIZER, // struct voctrl_set_equalizer_args - VOCTRL_GET_EQUALIZER, // struct voctrl_get_equalizer_args + VOCTRL_SET_EQUALIZER, // struct voctrl_set_equalizer_args* + VOCTRL_GET_EQUALIZER, // struct voctrl_get_equalizer_args* /* for vdpau hardware decoding */ VOCTRL_HWDEC_DECODER_RENDER, // pointer to hw state @@ -62,7 +62,7 @@ enum mp_voctrl { VOCTRL_BORDER, VOCTRL_UPDATE_WINDOW_TITLE, // char* - VOCTRL_SET_CURSOR_VISIBILITY, // bool + VOCTRL_SET_CURSOR_VISIBILITY, // bool* VOCTRL_KILL_SCREENSAVER, VOCTRL_RESTORE_SCREENSAVER, @@ -72,12 +72,12 @@ enum mp_voctrl { VOCTRL_UPDATE_SCREENINFO, - VOCTRL_SET_YUV_COLORSPACE, // struct mp_csp_details - VOCTRL_GET_YUV_COLORSPACE, // struct mp_csp_details + VOCTRL_SET_YUV_COLORSPACE, // struct mp_csp_details* + VOCTRL_GET_YUV_COLORSPACE, // struct mp_csp_details* - VOCTRL_SCREENSHOT, // struct voctrl_screenshot_args + VOCTRL_SCREENSHOT, // struct voctrl_screenshot_args* - VOCTRL_SET_COMMAND_LINE, // char* + VOCTRL_SET_COMMAND_LINE, // char** }; // VOCTRL_SET_EQUALIZER @@ -139,6 +139,7 @@ typedef struct vo_info_s struct vo; struct osd_state; struct mp_image; +struct mp_image_params; struct vo_driver { // Driver buffers or adds (deinterlace) frames and will keep track @@ -164,20 +165,28 @@ struct vo_driver { int (*query_format)(struct vo *vo, uint32_t format); /* - * Initialize (means CONFIGURE) the display driver. - * params: + * Initialize or reconfigure the display driver. * width,height: image source size - * d_width,d_height: size of the requested window size, just a hint - * fullscreen: flag, 0=windowd 1=fullscreen, just a hint + * d_width,d_height: requested window size, just a hint + * flags: combination of VOFLAG_ values * title: window title, if available * format: fourcc of pixel format * returns : zero on successful initialization, non-zero on error. */ int (*config)(struct vo *vo, uint32_t width, uint32_t height, - uint32_t d_width, uint32_t d_height, uint32_t fullscreen, + uint32_t d_width, uint32_t d_height, uint32_t flags, uint32_t format); /* + * Initialize or reconfigure the display driver. Alternative to config(), + * and can carry more image parameters. + * params: video parameters, like pixel format and frame size + * flags: combination of VOFLAG_ values + * returns: < 0 on error, >= 0 on success + */ + int (*reconfig)(struct vo *vo, struct mp_image_params *params, int flags); + + /* * Control interface */ int (*control)(struct vo *vo, uint32_t request, void *data); @@ -284,9 +293,7 @@ struct vo *init_best_video_out(struct mp_vo_opts *opts, struct mp_fifo *key_fifo, struct input_ctx *input_ctx, struct encode_lavc_context *encode_lavc_ctx); -int vo_config(struct vo *vo, uint32_t width, uint32_t height, - uint32_t d_width, uint32_t d_height, uint32_t flags, - uint32_t format); +int vo_reconfig(struct vo *vo, struct mp_image_params *p, int flags); void list_video_out(void); int vo_control(struct vo *vo, uint32_t request, void *data); diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 35ea0cebb0..882689ed87 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -163,15 +163,13 @@ static void video_resize_redraw_callback(struct vo *vo, int w, int h) |