summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-03-10 19:30:48 +0100
committerwm4 <wm4@nowhere>2013-04-21 04:39:58 +0200
commit778e9c06336e77909a2e2bc87aec85dc8cb08811 (patch)
treec02a5b196e1bf49ba79e21669dcd1f153e7ea472 /video
parent04f1e2dc43b9d490c392751f0e812247e6609a30 (diff)
downloadmpv-778e9c06336e77909a2e2bc87aec85dc8cb08811.tar.bz2
mpv-778e9c06336e77909a2e2bc87aec85dc8cb08811.tar.xz
mp_image: provide function to convert mp_image to AVFrame
Note that this does not pass through QP information (qscale field). The only filter for which this matters is vf_pp, and we have this natively.
Diffstat (limited to 'video')
-rw-r--r--video/mp_image.c50
-rw-r--r--video/mp_image.h3
2 files changed, 53 insertions, 0 deletions
diff --git a/video/mp_image.c b/video/mp_image.c
index 54bf10c634..5b443b5ccd 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -464,6 +464,30 @@ void mp_image_copy_fields_from_av_frame(struct mp_image *dst,
#endif
}
+// 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)
+{
+ dst->format = imgfmt2pixfmt(src->imgfmt);
+ dst->width = src->w;
+ dst->height = src->h;
+
+ for (int i = 0; i < 4; i++) {
+ dst->data[i] = src->planes[i];
+ dst->linesize[i] = src->stride[i];
+ }
+ dst->extended_data = dst->data;
+
+ dst->pict_type = src->pict_type;
+ if (src->fields & MP_IMGFIELD_INTERLACED)
+ dst->interlaced_frame = 1;
+ if (src->fields & MP_IMGFIELD_TOP_FIRST)
+ dst->top_field_first = 1;
+ if (src->fields & MP_IMGFIELD_REPEAT_FIRST)
+ dst->repeat_pict = 1;
+}
+
#if HAVE_AVUTIL_REFCOUNTING
static void frame_free(void *p)
@@ -490,4 +514,30 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame)
frame_free);
}
+static void free_img(void *opaque, uint8_t *data)
+{
+ struct mp_image *img = opaque;
+ talloc_free(img);
+}
+
+// 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's done this way to allow marking the
+// resulting AVFrame as writeable if img is the only reference (in
+// other words, it's an optimization).
+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
+ talloc_free(img);
+ AVFrame *frame = av_frame_alloc();
+ mp_image_copy_fields_to_av_frame(frame, new_ref);
+ // Caveat: if img has shared references, and all other references disappear
+ // at a later point, the AVFrame will still be read-only.
+ int flags = 0;
+ if (!mp_image_is_writeable(new_ref))
+ flags |= AV_BUFFER_FLAG_READONLY;
+ frame->buf[0] = av_buffer_create(NULL, 0, free_img, new_ref, flags);
+ return frame;
+}
+
#endif /* HAVE_AVUTIL_REFCOUNTING */
diff --git a/video/mp_image.h b/video/mp_image.h
index 85adac65f0..ca536a1e91 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -130,7 +130,10 @@ void mp_image_set_colorspace_details(struct mp_image *image,
struct AVFrame;
void mp_image_copy_fields_from_av_frame(struct mp_image *dst,
struct AVFrame *src);
+void mp_image_copy_fields_to_av_frame(struct AVFrame *dst,
+ struct mp_image *src);
struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame);
+struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img);
// align must be a power of two (align >= 1), v >= 0
#define MP_ALIGN_UP(v, align) FFALIGN(v, align)