diff options
-rw-r--r-- | demux/stheader.h | 2 | ||||
-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 |
17 files changed, 211 insertions, 141 deletions
diff --git a/demux/stheader.h b/demux/stheader.h index 58caa27dcd..ff98430a65 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -149,9 +149,7 @@ typedef struct sh_video { int colorspace; // mp_csp int color_range; // mp_csp_levels // output driver/filters: (set by libmpcodecs core) - unsigned int outfmt; struct vf_instance *vfilter; // video filter chain - int output_flags; // query_format() results for output filters+vo const struct vd_functions *vd_driver; int vf_initialized; // -1 failed, 0 not done, 1 done // win32-compatible codec parameters: 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. |