diff --git a/DOCS/interface-changes/vf-format-stereo-in.txt b/DOCS/interface-changes/vf-format-stereo-in.txt new file mode 100644 index 0000000000000..e1dae20eff173 --- /dev/null +++ b/DOCS/interface-changes/vf-format-stereo-in.txt @@ -0,0 +1 @@ +change `--vf=format:stereo-in=no` to keep the source stereo 3D mode, `--vf=format:stereo-in=mono` now overrides it with 2D diff --git a/DOCS/man/vf.rst b/DOCS/man/vf.rst index 086295d40ca5d..ea560c8fd4d84 100644 --- a/DOCS/man/vf.rst +++ b/DOCS/man/vf.rst @@ -361,7 +361,8 @@ Available mpv-only filters are: ```` Set the stereo mode the video is assumed to be encoded in. Use ``--vf=format:stereo-in=help`` to list all available modes. Check with - the ``stereo3d`` filter documentation to see what the names mean. + the ``stereo3d`` filter documentation to see what the names mean. The + default ``no`` keeps the mode signaled by the source. ```` Set the rotation the video is assumed to be encoded with in degrees. diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c index 2b76b26b14bb7..2397c855fcae4 100644 --- a/filters/f_decoder_wrapper.c +++ b/filters/f_decoder_wrapper.c @@ -678,7 +678,8 @@ static void fix_image_params(struct priv *p, if (m.p_w <= 0 || m.p_h <= 0) m.p_w = m.p_h = 1; - m.stereo3d = p->codec->stereo_mode; + if (!m.stereo3d) + m.stereo3d = p->codec->stereo_mode; if (!mp_rect_equals(&p->codec->crop, &(struct mp_rect){0})) { struct mp_rect crop = p->codec->crop; diff --git a/video/csputils.c b/video/csputils.c index bd942ce4c790c..58c008a943080 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -130,12 +130,12 @@ const struct m_opt_choice_alternatives pl_alpha_names[] = { {0} }; -// The short name _must_ match with what vf_stereo3d accepts (if supported). +// The short names follow the input format names of the vf_stereo3d. // The long name in comments is closer to the Matroska spec (StereoMode element). // The numeric index matches the Matroska StereoMode value. If you add entries // that don't match Matroska, make sure demux_mkv.c rejects them properly. const struct m_opt_choice_alternatives mp_stereo3d_names[] = { - {"no", -1}, // disable/invalid + {"no", -1}, // unset, vf_format keeps the source mode {"mono", 0}, {"sbs2l", 1}, // "side_by_side_left" {"ab2r", 2}, // "top_bottom_right" @@ -144,8 +144,8 @@ const struct m_opt_choice_alternatives mp_stereo3d_names[] = { {"checkl", 5}, // "checkboard_left" (unsupported by vf_stereo3d) {"irr", 6}, // "row_interleaved_right" {"irl", 7}, // "row_interleaved_left" - {"icr", 8}, // "column_interleaved_right" (unsupported by vf_stereo3d) - {"icl", 9}, // "column_interleaved_left" (unsupported by vf_stereo3d) + {"icr", 8}, // "column_interleaved_right" + {"icl", 9}, // "column_interleaved_left" {"arcc", 10}, // "anaglyph_cyan_red" (Matroska: unclear which mode) {"sbs2r", 11}, // "side_by_side_right" {"agmc", 12}, // "anaglyph_green_magenta" (Matroska: unclear which mode) diff --git a/video/csputils.h b/video/csputils.h index 36e017b58568e..4ed18f1ab244f 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -49,13 +49,21 @@ extern const struct m_opt_choice_alternatives mp_csp_light_names[]; // The numeric values (except -1) match the Matroska StereoMode element value. enum mp_stereo3d_mode { MP_STEREO3D_INVALID = -1, - /* only modes explicitly referenced in the code are listed */ MP_STEREO3D_MONO = 0, MP_STEREO3D_SBS2L = 1, MP_STEREO3D_AB2R = 2, MP_STEREO3D_AB2L = 3, + MP_STEREO3D_CHECKR = 4, + MP_STEREO3D_CHECKL = 5, + MP_STEREO3D_IRR = 6, + MP_STEREO3D_IRL = 7, + MP_STEREO3D_ICR = 8, + MP_STEREO3D_ICL = 9, + MP_STEREO3D_ARCC = 10, MP_STEREO3D_SBS2R = 11, - /* no explicit enum entries for most valid values */ + MP_STEREO3D_AGMC = 12, + MP_STEREO3D_AL = 13, + MP_STEREO3D_AR = 14, MP_STEREO3D_COUNT = 15, // 14 is last valid mode }; diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index a2464a733c47c..3eebe7bc43cc2 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -100,7 +100,7 @@ static void set_params(struct vf_format_opts *p, struct mp_image_params *out, out->light = p->light; if (p->chroma_location) out->chroma_location = p->chroma_location; - if (p->stereo_in) + if (p->stereo_in >= 0) out->stereo3d = p->stereo_in; if (p->rotate >= 0) out->rotate = p->rotate; @@ -304,6 +304,7 @@ const struct mp_user_filter_entry vf_format = { .name = "format", .priv_size = sizeof(OPT_BASE_STRUCT), .priv_defaults = &(const OPT_BASE_STRUCT){ + .stereo_in = -1, .rotate = -1, .dovi = true, .enhancement_layer = true, diff --git a/video/mp_image.c b/video/mp_image.c index c0887c119be5b..5a5a84f69873a 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1079,6 +1080,29 @@ void mp_image_params_guess_csp(struct mp_image_params *params) } } +static enum mp_stereo3d_mode stereo3d_from_av(const AVStereo3D *s3d) +{ + bool inv = s3d->flags & AV_STEREO3D_FLAG_INVERT; + switch (s3d->type) { + case AV_STEREO3D_SIDEBYSIDE: + case AV_STEREO3D_SIDEBYSIDE_QUINCUNX: + return inv ? MP_STEREO3D_SBS2R : MP_STEREO3D_SBS2L; + case AV_STEREO3D_TOPBOTTOM: + return inv ? MP_STEREO3D_AB2R : MP_STEREO3D_AB2L; + case AV_STEREO3D_CHECKERBOARD: + return inv ? MP_STEREO3D_CHECKR : MP_STEREO3D_CHECKL; + case AV_STEREO3D_LINES: + return inv ? MP_STEREO3D_IRR : MP_STEREO3D_IRL; + case AV_STEREO3D_COLUMNS: + return inv ? MP_STEREO3D_ICR : MP_STEREO3D_ICL; + case AV_STEREO3D_FRAMESEQUENCE: + return inv ? MP_STEREO3D_AR : MP_STEREO3D_AL; + default: + // AV_STEREO3D_2D and types mpv has no mode for. + return MP_STEREO3D_MONO; + } +} + // Create a new mp_image reference to av_frame. struct mp_image *mp_image_from_av_frame(struct AVFrame *src) { @@ -1131,6 +1155,10 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) dst->params.chroma_location = pl_chroma_from_av(src->chroma_location); + sd = av_frame_get_side_data(src, AV_FRAME_DATA_STEREO3D); + if (sd) + dst->params.stereo3d = stereo3d_from_av((const AVStereo3D *)sd->data); + if (src->opaque_ref) { struct mp_image_params *p = (void *)src->opaque_ref->data; dst->params.stereo3d = p->stereo3d; diff --git a/video/out/gpu/osd.c b/video/out/gpu/osd.c index d6788f8c0e3d9..883dccd7eb229 100644 --- a/video/out/gpu/osd.c +++ b/video/out/gpu/osd.c @@ -53,7 +53,6 @@ struct mpgl_osd_part { struct ra_tex *texture; int w, h; int num_subparts; - int prev_num_subparts; struct sub_bitmap *subparts; int num_vertices; struct vertex *vertices; @@ -66,7 +65,6 @@ struct mpgl_osd { struct mpgl_osd_part *parts[MAX_OSD_PARTS]; const struct ra_format *fmt_table[SUBBITMAP_COUNT]; bool formats[SUBBITMAP_COUNT]; - bool change_flag; // for reporting to API user only // temporary int stereo_mode; struct mp_osd_res osd_res; @@ -81,7 +79,6 @@ struct mpgl_osd *mpgl_osd_init(struct ra *ra, struct mp_log *log, .log = log, .osd = osd, .ra = ra, - .change_flag = true, .scratch = talloc_zero_size(ctx, 1), }; @@ -194,7 +191,6 @@ static void gen_osd_cb(void *pctx, struct sub_bitmaps *imgs) ok = false; osd->change_id = imgs->change_id; - ctx->change_flag = true; } osd->num_subparts = ok ? imgs->num_parts : 0; @@ -325,15 +321,6 @@ void mpgl_osd_generate(struct mpgl_osd *ctx, struct mp_osd_res res, double pts, osd_draw(ctx->osd, ctx->osd_res, pts, draw_flags, ctx->formats, gen_osd_cb, ctx); ctx->stereo_mode = stereo_mode; - - // Parts going away does not necessarily result in gen_osd_cb() being called - // (not even with num_parts==0), so check this separately. - for (int n = 0; n < MAX_OSD_PARTS; n++) { - struct mpgl_osd_part *part = ctx->parts[n]; - if (part->num_subparts != part->prev_num_subparts) - ctx->change_flag = true; - part->prev_num_subparts = part->num_subparts; - } } // See osd_resize() for remarks. This function is an optional optimization too. @@ -342,11 +329,3 @@ void mpgl_osd_resize(struct mpgl_osd *ctx, struct mp_osd_res res, int stereo_mod set_res(ctx, res, stereo_mode); osd_resize(ctx->osd, ctx->osd_res); } - -bool mpgl_osd_check_change(struct mpgl_osd *ctx, struct mp_osd_res *res, - double pts) -{ - ctx->change_flag = false; - mpgl_osd_generate(ctx, *res, pts, 0, 0); - return ctx->change_flag; -} diff --git a/video/out/gpu/osd.h b/video/out/gpu/osd.h index 1b05e254f8146..84139ee8c3989 100644 --- a/video/out/gpu/osd.h +++ b/video/out/gpu/osd.h @@ -19,7 +19,5 @@ bool mpgl_osd_draw_prepare(struct mpgl_osd *ctx, int index, struct gl_shader_cache *sc); void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int index, struct gl_shader_cache *sc, const struct ra_fbo *fbo); -bool mpgl_osd_check_change(struct mpgl_osd *ctx, struct mp_osd_res *res, - double pts); #endif diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index b114846ba4fe9..11c4f2a4a6d86 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -3794,12 +3794,6 @@ void gl_video_set_osd_pts(struct gl_video *p, double pts) p->osd_pts = pts; } -bool gl_video_check_osd_change(struct gl_video *p, struct mp_osd_res *res, - double pts) -{ - return p->osd ? mpgl_osd_check_change(p->osd, res, pts) : false; -} - void gl_video_resize(struct gl_video *p, struct mp_rect *src, struct mp_rect *dst, struct mp_osd_res *osd) diff --git a/video/out/gpu/video.h b/video/out/gpu/video.h index a5b03adfbf7bc..d6ead086076ca 100644 --- a/video/out/gpu/video.h +++ b/video/out/gpu/video.h @@ -212,8 +212,6 @@ void gl_video_set_fb_depth(struct gl_video *p, int fb_depth); void gl_video_perfdata(struct gl_video *p, struct voctrl_performance_data *out); void gl_video_set_clear_color(struct gl_video *p, struct m_color color); void gl_video_set_osd_pts(struct gl_video *p, double pts); -bool gl_video_check_osd_change(struct gl_video *p, struct mp_osd_res *osd, - double pts); void gl_video_screenshot(struct gl_video *p, struct vo_frame *frame, struct voctrl_screenshot *args);