From bbaedfd0c5d59a22762c80c96406d5887f8ca488 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 15 Apr 2016 15:07:02 +0200 Subject: mp_image: pass through AVHWFramesContext In both directions. --- video/mp_image.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 565de18ca6..0238a102f6 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -94,6 +94,7 @@ static void mp_image_destructor(void *ptr) mp_image_t *mpi = ptr; for (int p = 0; p < MP_MAX_PLANES; p++) av_buffer_unref(&mpi->bufs[p]); + av_buffer_unref(&mpi->hwctx); } int mp_chroma_div_up(int size, int shift) @@ -174,6 +175,9 @@ void mp_image_steal_data(struct mp_image *dst, struct mp_image *src) dst->bufs[p] = src->bufs[p]; src->bufs[p] = NULL; } + av_buffer_unref(&dst->hwctx); + dst->hwctx = src->hwctx; + src->hwctx = NULL; talloc_free(src); } @@ -199,6 +203,11 @@ struct mp_image *mp_image_new_ref(struct mp_image *img) fail = true; } } + if (new->hwctx) { + new->hwctx = av_buffer_ref(new->hwctx); + if (!new->hwctx) + fail = true; + } if (!fail) return new; @@ -232,6 +241,7 @@ struct mp_image *mp_image_new_dummy_ref(struct mp_image *img) *new = *img; for (int p = 0; p < MP_MAX_PLANES; p++) new->bufs[p] = NULL; + new->hwctx = NULL; return new; } @@ -720,6 +730,9 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame) mp_image_copy_fields_from_av_frame(&t, av_frame); for (int p = 0; p < MP_MAX_PLANES; p++) t.bufs[p] = av_frame->buf[p]; +#if HAVE_AVUTIL_HAS_HWCONTEXT + t.hwctx = av_frame->hw_frames_ctx; +#endif return mp_image_new_ref(&t); } @@ -730,13 +743,12 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame) // On failure, img is only unreffed. struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img) { - struct mp_image *new_ref = mp_image_new_ref(img); // ensure it's refcounted + struct mp_image *new_ref = mp_image_new_ref(img); talloc_free(img); - if (!new_ref) - return NULL; AVFrame *frame = av_frame_alloc(); - if (!frame) { + if (!frame || !new_ref) { talloc_free(new_ref); + av_frame_free(&frame); return NULL; } mp_image_copy_fields_to_av_frame(frame, new_ref); @@ -744,6 +756,10 @@ struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img) frame->buf[p] = new_ref->bufs[p]; new_ref->bufs[p] = NULL; } +#if HAVE_AVUTIL_HAS_HWCONTEXT + frame->hw_frames_ctx = new_ref->hwctx; +#endif + new_ref->hwctx = NULL; talloc_free(new_ref); return frame; } -- cgit v1.2.3 From e6cdfdfa7446dca9b6737650e912ccd6122050b6 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 15 Apr 2016 15:11:08 +0200 Subject: mp_image: simplify mp_image_steal_data() Why was this so complex. --- video/mp_image.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 0238a102f6..05cac1b3ef 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -164,20 +164,12 @@ void mp_image_steal_data(struct mp_image *dst, struct mp_image *src) assert(dst->imgfmt == src->imgfmt && dst->w == src->w && dst->h == src->h); assert(dst->bufs[0] && src->bufs[0]); - for (int p = 0; p < MP_MAX_PLANES; p++) { - dst->planes[p] = src->planes[p]; - dst->stride[p] = src->stride[p]; - } - mp_image_copy_attributes(dst, src); + mp_image_destructor(dst); // unref old + talloc_free_children(dst); - for (int p = 0; p < MP_MAX_PLANES; p++) { - av_buffer_unref(&dst->bufs[p]); - dst->bufs[p] = src->bufs[p]; - src->bufs[p] = NULL; - } - av_buffer_unref(&dst->hwctx); - dst->hwctx = src->hwctx; - src->hwctx = NULL; + *dst = *src; + + *src = (struct mp_image){0}; talloc_free(src); } @@ -752,14 +744,12 @@ struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img) return NULL; } mp_image_copy_fields_to_av_frame(frame, new_ref); - for (int p = 0; p < MP_MAX_PLANES; p++) { + for (int p = 0; p < MP_MAX_PLANES; p++) frame->buf[p] = new_ref->bufs[p]; - new_ref->bufs[p] = NULL; - } #if HAVE_AVUTIL_HAS_HWCONTEXT frame->hw_frames_ctx = new_ref->hwctx; #endif - new_ref->hwctx = NULL; + *new_ref = (struct mp_image){0}; talloc_free(new_ref); return frame; } -- cgit v1.2.3 From d04aa5ef4e12f5bee3343e833e1209774e9204d9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 15 Apr 2016 15:33:53 +0200 Subject: mp_image: add mp_image_to_av_frame() What mp_image_to_av_frame_and_unref() should have been. (The _unref variant is still useful though.) --- video/mp_image.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 05cac1b3ef..0910bb9abc 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -729,14 +729,9 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame) } // Convert the mp_image reference to a AVFrame reference. -// Warning: img is unreferenced (i.e. free'd). This is asymmetric to -// mp_image_from_av_frame(). It was done as some sort of optimization, -// but now these semantics are pointless. -// On failure, img is only unreffed. -struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img) +struct AVFrame *mp_image_to_av_frame(struct mp_image *img) { struct mp_image *new_ref = mp_image_new_ref(img); - talloc_free(img); AVFrame *frame = av_frame_alloc(); if (!frame || !new_ref) { talloc_free(new_ref); @@ -754,6 +749,14 @@ struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img) return frame; } +// Same as mp_image_to_av_frame(), but unref img. (It does so even on failure.) +struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img) +{ + AVFrame *frame = mp_image_to_av_frame(img); + talloc_free(img); + return frame; +} + void memcpy_pic(void *dst, const void *src, int bytesPerLine, int height, int dstStride, int srcStride) { -- cgit v1.2.3 From 050b17ca9ced0811aeeb27f8ad628954d1f146cd Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 15 Apr 2016 15:48:02 +0200 Subject: mp_image: make mp_image_copy_fields_* private Future code should always use mp_image_{to,from}_av_frame(). Everything else is way too messy and fragile. --- video/mp_image.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 0910bb9abc..0ca59c62c9 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -666,8 +666,8 @@ void mp_image_params_guess_csp(struct mp_image_params *params) // Copy properties and data of the AVFrame into the mp_image, without taking // care of memory management issues. -void mp_image_copy_fields_from_av_frame(struct mp_image *dst, - struct AVFrame *src) +static void mp_image_copy_fields_from_av_frame(struct mp_image *dst, + struct AVFrame *src) { mp_image_setfmt(dst, pixfmt2imgfmt(src->format)); mp_image_set_size(dst, src->width, src->height); @@ -690,8 +690,8 @@ void mp_image_copy_fields_from_av_frame(struct mp_image *dst, // Copy properties and data of the mp_image into the AVFrame, without taking // care of memory management issues. -void mp_image_copy_fields_to_av_frame(struct AVFrame *dst, - struct mp_image *src) +static void mp_image_copy_fields_to_av_frame(struct AVFrame *dst, + struct mp_image *src) { dst->format = imgfmt2pixfmt(src->imgfmt); dst->width = src->w; -- cgit v1.2.3 From 021cb2c3870b9d0b2f2e03416702fc561f160c2b Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 25 Apr 2016 11:28:49 +0200 Subject: mp_image: allow passing NULL to mp_image_new_custom_ref() A minor simplification. Most callers don't need this, and there's no good reason why the caller should provide an "initializer" like this. (This function calls mp_image_new_dummy_ref(), which has no reason for an initializer either.) --- video/mp_image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 0ca59c62c9..5adce213e5 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -230,7 +230,7 @@ struct mp_image *mp_image_new_dummy_ref(struct mp_image *img) { struct mp_image *new = talloc_ptrtype(NULL, new); talloc_set_destructor(new, mp_image_destructor); - *new = *img; + *new = img ? *img : (struct mp_image){0}; for (int p = 0; p < MP_MAX_PLANES; p++) new->bufs[p] = NULL; new->hwctx = NULL; -- cgit v1.2.3 From 240ba92bed4e1bf083d8bae49c04a211ae848a91 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 29 May 2016 17:33:50 +0200 Subject: mp_image: don't lose pixel aspect ratio when setting format This is quite unexpected. It's caused by mp_image_set_size(), which is used to update certain fields which can be format-dependent, but which is actually also supposed to reset the pixel aspect ratio. --- video/mp_image.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 5adce213e5..52087fdf83 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -81,12 +81,14 @@ static bool mp_image_alloc_planes(struct mp_image *mpi) void mp_image_setfmt(struct mp_image *mpi, int out_fmt) { + struct mp_image_params params = mpi->params; struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(out_fmt); - mpi->params.imgfmt = fmt.id; + params.imgfmt = fmt.id; mpi->fmt = fmt; mpi->imgfmt = fmt.id; mpi->num_planes = fmt.num_planes; mp_image_set_size(mpi, mpi->w, mpi->h); + mpi->params = params; } static void mp_image_destructor(void *ptr) -- cgit v1.2.3 From 079f67268f6f5a2ecfd12277b246b1937493c092 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 30 May 2016 19:07:09 +0200 Subject: mp_image: don't reset pixel aspect with mp_image_set_size() No reason to do so. See also commit 240ba92b. Since now many mp_images will never have a pixel aspect ratio set, redefine a 0/0 aspect ratio to "undefined" instead invalid. This also brings it more in line with how decoder vs. container aspect ratios are handled. Most callers seem to be fine with the new behavior. mp_image_params_valid() in particular has to be adjusted, or some things stop working due to mp_images not becoming valid after setting size and format. --- video/mp_image.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 52087fdf83..21773ef660 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -87,7 +87,6 @@ void mp_image_setfmt(struct mp_image *mpi, int out_fmt) mpi->fmt = fmt; mpi->imgfmt = fmt.id; mpi->num_planes = fmt.num_planes; - mp_image_set_size(mpi, mpi->w, mpi->h); mpi->params = params; } @@ -122,7 +121,6 @@ void mp_image_set_size(struct mp_image *mpi, int w, int h) assert(w >= 0 && h >= 0); mpi->w = mpi->params.w = w; mpi->h = mpi->params.h = h; - mpi->params.p_w = mpi->params.p_h = 1; } void mp_image_set_params(struct mp_image *image, @@ -543,7 +541,7 @@ bool mp_image_params_valid(const struct mp_image_params *p) if (p->w <= 0 || p->h <= 0 || (p->w + 128LL) * (p->h + 128LL) >= INT_MAX / 8) return false; - if (p->p_w <= 0 || p->p_h <= 0) + if (p->p_w < 0 || p->p_h < 0) return false; if (p->rotate < 0 || p->rotate >= 360) @@ -673,6 +671,7 @@ static void mp_image_copy_fields_from_av_frame(struct mp_image *dst, { mp_image_setfmt(dst, pixfmt2imgfmt(src->format)); mp_image_set_size(dst, src->width, src->height); + dst->params.p_w = dst->params.p_h = 1; for (int i = 0; i < 4; i++) { dst->planes[i] = src->data[i]; -- cgit v1.2.3 From 4853eca8c619dfc9a942d250add5ecc22ceafa90 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 30 May 2016 19:12:41 +0200 Subject: mp_image: properly communicate aspect ratio through AVFrame No idea why this wasn't done before. In particular, this fixes playing anamorphic video through --lavfi-complex. --- video/mp_image.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index 21773ef660..ac3d4ea5e1 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -671,7 +671,9 @@ static void mp_image_copy_fields_from_av_frame(struct mp_image *dst, { mp_image_setfmt(dst, pixfmt2imgfmt(src->format)); mp_image_set_size(dst, src->width, src->height); - dst->params.p_w = dst->params.p_h = 1; + + dst->params.p_w = src->sample_aspect_ratio.num; + dst->params.p_h = src->sample_aspect_ratio.den; for (int i = 0; i < 4; i++) { dst->planes[i] = src->data[i]; @@ -698,6 +700,9 @@ static void mp_image_copy_fields_to_av_frame(struct AVFrame *dst, dst->width = src->w; dst->height = src->h; + dst->sample_aspect_ratio.num = src->params.p_w; + dst->sample_aspect_ratio.den = src->params.p_h; + for (int i = 0; i < 4; i++) { dst->data[i] = src->planes[i]; dst->linesize[i] = src->stride[i]; -- cgit v1.2.3 From 45c3e0f0d0c836158ab38db53156bb6461ad7437 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 30 May 2016 19:56:58 +0200 Subject: vo_opengl: refactor HDR mechanism Instead of doing HDR tone mapping on an ad-hoc basis inside pass_colormanage, the reference peak of an image is now part of the image params (alongside colorspace, gamma, etc.) and tone mapping is done whenever peak_src != peak_dst. To get sensible behavior when mixing HDR and SDR content and displays, target-brightness is a generic filler for "the assumed brightness of SDR content". This gets rid of the weird display_scaled hack, sets the framework for multiple HDR functions with difference reference peaks, and allows us to (in a future commit) autodetect the right source peak from the HDR metadata. (Apart from metadata, the source peak can also be controlled via vf_format. For HDR content this adjusts the overall image brightness, for SDR content it's like simulating a different exposure) --- video/mp_image.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'video/mp_image.c') diff --git a/video/mp_image.c b/video/mp_image.c index ac3d4ea5e1..d5b97481e8 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -568,6 +568,7 @@ bool mp_image_params_equal(const struct mp_image_params *p1, p1->colorlevels == p2->colorlevels && p1->primaries == p2->primaries && p1->gamma == p2->gamma && + p1->peak == p2->peak && p1->chroma_location == p2->chroma_location && p1->rotate == p2->rotate && p1->stereo_in == p2->stereo_in && @@ -662,6 +663,12 @@ void mp_image_params_guess_csp(struct mp_image_params *params) params->primaries = MP_CSP_PRIM_AUTO; params->gamma = MP_CSP_TRC_AUTO; } + + // Guess the reference peak (independent of the colorspace) + if (params->gamma == MP_CSP_TRC_SMPTE_ST2084) { + if (!params->peak) + params->peak = 10000; // As per the spec + } } // Copy properties and data of the AVFrame into the mp_image, without taking -- cgit v1.2.3