diff options
Diffstat (limited to 'video')
68 files changed, 2369 insertions, 2170 deletions
diff --git a/video/csputils.c b/video/csputils.c index 23eb099f69..8face3164c 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -31,6 +31,7 @@ #include <math.h> #include <assert.h> #include <libavutil/common.h> +#include <libavcodec/avcodec.h> #include "csputils.h" @@ -40,6 +41,8 @@ char * const mp_csp_names[MP_CSP_COUNT] = { "BT.709 (HD)", "SMPTE-240M", "RGB", + "XYZ", + "YCgCo", }; char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = { @@ -50,39 +53,41 @@ char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = { "gamma", }; -enum mp_csp avcol_spc_to_mp_csp(enum AVColorSpace colorspace) +enum mp_csp avcol_spc_to_mp_csp(int avcolorspace) { - switch (colorspace) { + switch (avcolorspace) { case AVCOL_SPC_BT709: return MP_CSP_BT_709; case AVCOL_SPC_BT470BG: return MP_CSP_BT_601; - case AVCOL_SPC_SMPTE170M: 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; + case AVCOL_SPC_YCOCG: return MP_CSP_YCGCO; default: return MP_CSP_AUTO; } } -enum mp_csp_levels avcol_range_to_mp_csp_levels(enum AVColorRange range) +enum mp_csp_levels avcol_range_to_mp_csp_levels(int avrange) { - switch (range) { + switch (avrange) { case AVCOL_RANGE_MPEG: return MP_CSP_LEVELS_TV; case AVCOL_RANGE_JPEG: return MP_CSP_LEVELS_PC; default: return MP_CSP_LEVELS_AUTO; } } -enum AVColorSpace mp_csp_to_avcol_spc(enum mp_csp colorspace) +int mp_csp_to_avcol_spc(enum mp_csp colorspace) { switch (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; case MP_CSP_RGB: return AVCOL_SPC_RGB; + case MP_CSP_YCGCO: return AVCOL_SPC_YCOCG; default: return AVCOL_SPC_UNSPECIFIED; } } -enum AVColorRange mp_csp_levels_to_avcol_range(enum mp_csp_levels range) +int mp_csp_levels_to_avcol_range(enum mp_csp_levels range) { switch (range) { case MP_CSP_LEVELS_TV: return AVCOL_RANGE_MPEG; @@ -96,6 +101,25 @@ enum mp_csp mp_csp_guess_colorspace(int width, int height) return width >= 1280 || height > 576 ? MP_CSP_BT_709 : MP_CSP_BT_601; } +enum mp_chroma_location avchroma_location_to_mp(int avloc) +{ + switch (avloc) { + case AVCHROMA_LOC_LEFT: return MP_CHROMA_LEFT; + case AVCHROMA_LOC_CENTER: return MP_CHROMA_CENTER; + default: return MP_CHROMA_AUTO; + } +} + +// Return location of chroma samples relative to luma samples. 0/0 means +// centered. Other possible values are -1 (top/left) and +1 (right/bottom). +void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y) +{ + *x = 0; + *y = 0; + if (loc == MP_CHROMA_LEFT) + *x = -1; +} + /** * \brief little helper function to create a lookup table for gamma * \param map buffer to create map into @@ -165,10 +189,39 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4]) int format = params->colorspace.format; if (format <= MP_CSP_AUTO || format >= MP_CSP_COUNT) format = MP_CSP_BT_601; + int levels_in = params->colorspace.levels_in; + if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT) + levels_in = MP_CSP_LEVELS_TV; + switch (format) { case MP_CSP_BT_601: luma_coeffs(m, 0.299, 0.587, 0.114 ); break; case MP_CSP_BT_709: luma_coeffs(m, 0.2126, 0.7152, 0.0722); break; case MP_CSP_SMPTE_240M: luma_coeffs(m, 0.2122, 0.7013, 0.0865); break; + case MP_CSP_RGB: { + static const float ident[3][4] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + memcpy(m, ident, sizeof(ident)); + levels_in = -1; + break; + } + case MP_CSP_XYZ: { + static const float xyz_to_rgb[3][4] = { + {3.2404542, -1.5371385, -0.4985314}, + {-0.9692660, 1.8760108, 0.0415560}, + {0.0556434, -0.2040259, 1.0572252}, + }; + memcpy(m, xyz_to_rgb, sizeof(xyz_to_rgb)); + levels_in = -1; + break; + } + case MP_CSP_YCGCO: { + static const float ycgco_to_rgb[3][4] = { + {1, -1, 1}, + {1, 1, 0}, + {1, -1, -1}, + }; + memcpy(m, ycgco_to_rgb, sizeof(ycgco_to_rgb)); + break; + } default: abort(); }; @@ -183,20 +236,19 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4]) m[i][COL_V] = huesin * u + huecos * m[i][COL_V]; } - int levels_in = params->colorspace.levels_in; - if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT) - levels_in = MP_CSP_LEVELS_TV; assert(params->input_bits >= 8); assert(params->texture_bits >= params->input_bits); - double s = (1 << params->input_bits-8) / ((1<<params->texture_bits)-1.); + double s = (1 << (params->input_bits-8)) / ((1<<params->texture_bits)-1.); // The values below are written in 0-255 scale struct yuvlevels { double ymin, ymax, cmin, cmid; } yuvlim = { 16*s, 235*s, 16*s, 128*s }, yuvfull = { 0*s, 255*s, 1*s, 128*s }, // '1' for symmetry around 128 + anyfull = { 0*s, 255*s, -255*s/2, 0 }, yuvlev; switch (levels_in) { case MP_CSP_LEVELS_TV: yuvlev = yuvlim; break; case MP_CSP_LEVELS_PC: yuvlev = yuvfull; break; + case -1: yuvlev = anyfull; break; default: abort(); } diff --git a/video/csputils.h b/video/csputils.h index d66bb86fa3..7c528d1b86 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -27,8 +27,6 @@ #include <stdbool.h> #include <stdint.h> -#include "libavcodec/avcodec.h" - /* NOTE: the csp and levels AUTO values are converted to specific ones * above vf/vo level. At least vf_scale relies on all valid settings being * nonzero at vf/vo level. @@ -40,6 +38,8 @@ enum mp_csp { MP_CSP_BT_709, MP_CSP_SMPTE_240M, MP_CSP_RGB, + MP_CSP_XYZ, + MP_CSP_YCGCO, MP_CSP_COUNT }; @@ -85,6 +85,12 @@ struct mp_csp_params { .rgamma = 1, .ggamma = 1, .bgamma = 1, \ .texture_bits = 8, .input_bits = 8} +enum mp_chroma_location { + MP_CHROMA_AUTO, + MP_CHROMA_LEFT, // mpeg2/4, h264 + MP_CHROMA_CENTER, // mpeg1, jpeg +}; + enum mp_csp_equalizer_param { MP_CSP_EQ_BRIGHTNESS, MP_CSP_EQ_CONTRAST, @@ -124,16 +130,20 @@ int mp_csp_equalizer_set(struct mp_csp_equalizer *eq, const char *property, int mp_csp_equalizer_get(struct mp_csp_equalizer *eq, const char *property, int *out_value); -enum mp_csp avcol_spc_to_mp_csp(enum AVColorSpace colorspace); +enum mp_csp avcol_spc_to_mp_csp(int avcolorspace); -enum mp_csp_levels avcol_range_to_mp_csp_levels(enum AVColorRange range); +enum mp_csp_levels avcol_range_to_mp_csp_levels(int avrange); -enum AVColorSpace mp_csp_to_avcol_spc(enum mp_csp colorspace); +int mp_csp_to_avcol_spc(enum mp_csp colorspace); -enum AVColorRange mp_csp_levels_to_avcol_range(enum mp_csp_levels range); +int mp_csp_levels_to_avcol_range(enum mp_csp_levels range); enum mp_csp mp_csp_guess_colorspace(int width, int height); +enum mp_chroma_location avchroma_location_to_mp(int avloc); + +void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y); + void mp_gen_gamma_map(unsigned char *map, int size, float gamma); #define ROW_R 0 #define ROW_G 1 diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 465791a1ed..ed856e046c 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -29,7 +29,6 @@ #include "core/mp_msg.h" #include "osdep/timer.h" -#include "osdep/shmem.h" #include "stream/stream.h" #include "demux/demux.h" @@ -45,13 +44,6 @@ #include "video/decode/dec_video.h" -// =================================================================== - -#include "core/cpudetect.h" - -int field_dominance = -1; - -int divx_quality = 0; int get_video_quality_max(sh_video_t *sh_video) { @@ -162,9 +154,9 @@ void resync_video_stream(sh_video_t *sh_video) sh_video->prev_sorted_pts = MP_NOPTS_VALUE; } -void video_reset_aspect(struct sh_video *sh_video) +void video_reinit_vo(struct sh_video *sh_video) { - sh_video->vd_driver->control(sh_video, VDCTRL_RESET_ASPECT, NULL); + sh_video->vd_driver->control(sh_video, VDCTRL_REINIT_VO, NULL); } int get_current_video_decoder_lag(sh_video_t *sh_video) @@ -184,6 +176,7 @@ void uninit_video(sh_video_t *sh_video) mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video.\n"); sh_video->vd_driver->uninit(sh_video); vf_uninit_filter_chain(sh_video->vfilter); + sh_video->vfilter = NULL; talloc_free(sh_video->gsh->decoder_desc); sh_video->gsh->decoder_desc = NULL; sh_video->initialized = 0; @@ -314,22 +307,14 @@ void *decode_video(sh_video_t *sh_video, struct demux_packet *packet, //------------------------ frame decoded. -------------------- -#if HAVE_MMX - // some codecs are broken, and doesn't restore MMX state :( - // it happens usually with broken/damaged files. - if (gCpuCaps.hasMMX) { - __asm__ volatile("emms\n\t":::"memory"); - } -#endif - if (!mpi || drop_frame) { talloc_free(mpi); return NULL; // error / skipped frame } - if (field_dominance == 0) + if (opts->field_dominance == 0) mpi->fields |= MP_IMGFIELD_TOP_FIRST; - else if (field_dominance == 1) + else if (opts->field_dominance == 1) mpi->fields &= ~MP_IMGFIELD_TOP_FIRST; double prevpts = sh_video->codec_reordered_pts; diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index 94bd2bce3a..05e3c7f0a1 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -41,7 +41,7 @@ struct mp_csp_details; void get_detected_video_colorspace(struct sh_video *sh, struct mp_csp_details *csp); void set_video_colorspace(struct sh_video *sh); void resync_video_stream(sh_video_t *sh_video); -void video_reset_aspect(struct sh_video *sh_video); +void video_reinit_vo(struct sh_video *sh_video); int get_current_video_decoder_lag(sh_video_t *sh_video); extern int divx_quality; 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 0ca685e2bb..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,28 +73,28 @@ 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 && divx_quality) { + if (get_video_quality_max(sh) <= 0 && opts->divx_quality) { // user wants postprocess but no pp filter yet: sh->vfilter = vf = vf_open_filter(opts, vf, "pp", NULL); } // 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 88ce4b2f59..ca4107dca9 100644 --- a/video/decode/vd.h +++ b/video/decode/vd.h @@ -42,8 +42,8 @@ extern const vd_functions_t *const mpcodecs_vd_drivers[]; #define VDCTRL_RESYNC_STREAM 8 // reset decode state after seeking #define VDCTRL_QUERY_UNSEEN_FRAMES 9 // current decoder lag -#define VDCTRL_RESET_ASPECT 10 // reinit filter/VO chain for new aspect ratio +#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 8a989feea7..ff1565f38f 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -73,14 +73,6 @@ static void uninit(struct sh_video *sh); #define OPT_BASE_STRUCT struct MPOpts const m_option_t lavc_decode_opts_conf[] = { - OPT_INTRANGE("bug", lavc_param.workaround_bugs, 0, -1, 999999), - OPT_FLAG("gray", lavc_param.gray, 0), - OPT_INTRANGE("idct", lavc_param.idct_algo, 0, 0, 99), - OPT |