summaryrefslogtreecommitdiffstats
path: root/video/mp_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/mp_image.c')
-rw-r--r--video/mp_image.c86
1 files changed, 54 insertions, 32 deletions
diff --git a/video/mp_image.c b/video/mp_image.c
index 565de18ca6..d5b97481e8 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -81,12 +81,13 @@ 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)
@@ -94,6 +95,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)
@@ -119,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,
@@ -163,17 +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;
- }
+ *dst = *src;
+
+ *src = (struct mp_image){0};
talloc_free(src);
}
@@ -199,6 +195,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;
@@ -229,9 +230,10 @@ 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;
return new;
}
@@ -539,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)
@@ -566,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 &&
@@ -660,16 +663,25 @@ 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
// 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);
+ 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];
dst->stride[i] = src->linesize[i];
@@ -688,13 +700,16 @@ 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;
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];
@@ -720,34 +735,41 @@ 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);
}
// 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); // ensure it's refcounted
- talloc_free(img);
- if (!new_ref)
- return NULL;
+ struct mp_image *new_ref = mp_image_new_ref(img);
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);
- 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 = (struct mp_image){0};
talloc_free(new_ref);
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)
{