[vlc-commits] vt_utils: add cvpx_pool helpers
Thomas Guillem
git at videolan.org
Fri Jun 2 18:44:12 CEST 2017
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Apr 6 13:45:01 2017 +0200| [efeb55685f90bcad9c765ec7dde93858c0550529] | committer: Thomas Guillem
vt_utils: add cvpx_pool helpers
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=efeb55685f90bcad9c765ec7dde93858c0550529
---
modules/codec/vt_utils.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++
modules/codec/vt_utils.h | 34 +++++++++
2 files changed, 229 insertions(+)
diff --git a/modules/codec/vt_utils.c b/modules/codec/vt_utils.c
index c2f8375d27..2a84618a3c 100644
--- a/modules/codec/vt_utils.c
+++ b/modules/codec/vt_utils.c
@@ -78,3 +78,198 @@ cvpxpic_get_ref(picture_t *pic)
assert(pic->context != NULL);
return ((struct cvpxpic_ctx *)pic->context)->cvpx;
}
+
+static void
+cvpxpic_destroy_mapped_ro_cb(picture_t *pic)
+{
+ CVPixelBufferRef cvpx = (void *) pic->p_sys;
+ CVPixelBufferUnlockBaseAddress(cvpx, kCVPixelBufferLock_ReadOnly);
+ CFRelease(cvpx);
+}
+
+static void
+cvpxpic_destroy_mapped_rw_cb(picture_t *pic)
+{
+ CVPixelBufferRef cvpx = (void *) pic->p_sys;
+ CVPixelBufferUnlockBaseAddress(cvpx, 0);
+ CFRelease(cvpx);
+}
+
+picture_t *
+cvpxpic_create_mapped(const video_format_t *fmt, CVPixelBufferRef cvpx,
+ bool readonly)
+{
+ unsigned planes_count;
+ switch (fmt->i_chroma)
+ {
+ case VLC_CODEC_BGRA:
+ case VLC_CODEC_UYVY: planes_count = 0; break;
+ case VLC_CODEC_NV12: planes_count = 2; break;
+ case VLC_CODEC_I420: planes_count = 3; break;
+ default: return NULL;
+ }
+
+ CVPixelBufferLockFlags lock = readonly ? kCVPixelBufferLock_ReadOnly : 0;
+ CVPixelBufferLockBaseAddress(cvpx, lock);
+ picture_resource_t rsc = {
+ .p_sys = (void *)cvpx,
+ .pf_destroy = readonly ? cvpxpic_destroy_mapped_ro_cb
+ : cvpxpic_destroy_mapped_rw_cb,
+ };
+
+#ifndef NDEBUG
+ assert(CVPixelBufferGetPlaneCount(cvpx) == planes_count);
+#endif
+
+ if (planes_count == 0)
+ {
+ rsc.p[0].p_pixels = CVPixelBufferGetBaseAddress(cvpx);
+ rsc.p[0].i_lines = CVPixelBufferGetHeight(cvpx);
+ rsc.p[0].i_pitch = CVPixelBufferGetBytesPerRow(cvpx);
+ }
+ else
+ {
+ for (unsigned i = 0; i < planes_count; ++i)
+ {
+ rsc.p[i].p_pixels = CVPixelBufferGetBaseAddressOfPlane(cvpx, i);
+ rsc.p[i].i_lines = CVPixelBufferGetHeightOfPlane(cvpx, i);
+ rsc.p[i].i_pitch = CVPixelBufferGetBytesPerRowOfPlane(cvpx, i);
+ }
+ }
+
+ picture_t *pic = picture_NewFromResource(fmt, &rsc);
+ if (pic == NULL)
+ {
+ CVPixelBufferUnlockBaseAddress(cvpx, lock);
+ CFRelease(cvpx);
+ return NULL;
+ }
+ CVPixelBufferRetain(cvpx);
+ return pic;
+}
+
+picture_t *
+cvpxpic_unmap(picture_t *mapped_pic)
+{
+ video_format_t fmt = mapped_pic->format;
+ switch (fmt.i_chroma)
+ {
+ case VLC_CODEC_UYVY: fmt.i_chroma = VLC_CODEC_CVPX_UYVY; break;
+ case VLC_CODEC_NV12: fmt.i_chroma = VLC_CODEC_CVPX_NV12; break;
+ case VLC_CODEC_I420: fmt.i_chroma = VLC_CODEC_CVPX_I420; break;
+ case VLC_CODEC_BGRA: fmt.i_chroma = VLC_CODEC_CVPX_BGRA; break;
+ default:
+ assert(!"invalid mapped_pic fmt");
+ picture_Release(mapped_pic);
+ return NULL;
+ }
+ assert(mapped_pic->p_sys != NULL);
+
+ picture_t *hw_pic = picture_NewFromFormat(&fmt);
+ if (hw_pic == NULL)
+ {
+ picture_Release(mapped_pic);
+ return NULL;
+ }
+
+ cvpxpic_attach(hw_pic, CVPixelBufferRetain((void *)mapped_pic->p_sys));
+ picture_CopyProperties(hw_pic, mapped_pic);
+ picture_Release(mapped_pic);
+ return hw_pic;
+}
+
+CVPixelBufferPoolRef
+cvpxpool_create(const video_format_t *fmt, unsigned count)
+{
+ int cvpx_format;
+ switch (fmt->i_chroma)
+ {
+ case VLC_CODEC_CVPX_UYVY:
+ cvpx_format = kCVPixelFormatType_422YpCbCr8;
+ break;
+ case VLC_CODEC_CVPX_NV12:
+ cvpx_format = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
+ break;
+ case VLC_CODEC_CVPX_I420:
+ cvpx_format = kCVPixelFormatType_420YpCbCr8Planar;
+ break;
+ case VLC_CODEC_CVPX_BGRA:
+ cvpx_format = kCVPixelFormatType_32BGRA;
+ default:
+ return NULL;
+ }
+
+ /* destination pixel buffer attributes */
+ CFMutableDictionaryRef cvpx_attrs_dict = cfdict_create(5);
+ if (unlikely(cvpx_attrs_dict == NULL))
+ return NULL;
+ CFMutableDictionaryRef pool_dict = cfdict_create(2);
+ if (unlikely(pool_dict == NULL))
+ {
+ CFRelease(cvpx_attrs_dict);
+ return NULL;
+ }
+
+#if !TARGET_OS_IPHONE
+ CFMutableDictionaryRef io_dict = cfdict_create(0);
+ if (unlikely(io_dict == NULL))
+ {
+ CFRelease(cvpx_attrs_dict);
+ CFRelease(pool_dict);
+ return NULL;
+ }
+ CFDictionarySetValue(cvpx_attrs_dict,
+ kCVPixelBufferIOSurfacePropertiesKey, io_dict);
+ CFRelease(io_dict);
+#else
+ CFDictionarySetValue(cvpx_attrs_dict,
+ kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
+#endif
+
+ cfdict_set_int32(cvpx_attrs_dict, kCVPixelBufferBytesPerRowAlignmentKey,
+ fmt->i_width);
+ cfdict_set_int32(cvpx_attrs_dict, kCVPixelBufferPixelFormatTypeKey,
+ cvpx_format);
+ cfdict_set_int32(cvpx_attrs_dict, kCVPixelBufferWidthKey, fmt->i_width);
+ cfdict_set_int32(cvpx_attrs_dict, kCVPixelBufferHeightKey, fmt->i_height);
+
+ cfdict_set_int32(pool_dict, kCVPixelBufferPoolMinimumBufferCountKey, count);
+ cfdict_set_int32(pool_dict, kCVPixelBufferPoolMaximumBufferAgeKey, 0);
+
+ CVPixelBufferPoolRef pool;
+ CVReturn err =
+ CVPixelBufferPoolCreate(NULL, pool_dict, cvpx_attrs_dict, &pool);
+ CFRelease(pool_dict);
+ CFRelease(cvpx_attrs_dict);
+ if (err != kCVReturnSuccess)
+ return NULL;
+
+ CVPixelBufferRef cvpxs[count];
+ for (unsigned i = 0; i < count; ++i)
+ {
+ err = CVPixelBufferPoolCreatePixelBuffer(NULL, pool, &cvpxs[i]);
+ if (err != kCVReturnSuccess)
+ {
+ CVPixelBufferPoolRelease(pool);
+ pool = NULL;
+ count = i;
+ break;
+ }
+ }
+ for (unsigned i = 0; i < count; ++i)
+ CFRelease(cvpxs[i]);
+
+ return pool;
+}
+
+CVPixelBufferRef
+cvpxpool_get_cvpx(CVPixelBufferPoolRef pool)
+{
+ CVPixelBufferRef cvpx;
+ CVReturn err = CVPixelBufferPoolCreatePixelBuffer(NULL, pool, &cvpx);
+
+ if (err != kCVReturnSuccess)
+ return NULL;
+
+ return cvpx;
+}
diff --git a/modules/codec/vt_utils.h b/modules/codec/vt_utils.h
index 0c82031b92..aaba4a5c5b 100644
--- a/modules/codec/vt_utils.h
+++ b/modules/codec/vt_utils.h
@@ -41,4 +41,38 @@ int cvpxpic_attach(picture_t *p_pic, CVPixelBufferRef cvpx);
*/
CVPixelBufferRef cvpxpic_get_ref(picture_t *pic);
+/*
+ * Create a picture mapped to a cvpx buffer
+ *
+ * @param fmt i_chroma must be VLC_CODEC_UYVY, VLC_CODEC_NV12 or VLC_CODEC_I420
+ * @param cvpx buffer to map
+ * @param readonly true to map read-only, false otherwise
+ * @return a valid picture, call picture_Release() or cvpxpic_unmap() to free
+ * the picture and unmap the cvpx buffer.
+ */
+picture_t *cvpxpic_create_mapped(const video_format_t *fmt,
+ CVPixelBufferRef cvpx, bool readonly);
+
+/*
+ * Create a picture attached to an unmapped cvpx buffer
+ *
+ * @param mapped_pic must be a picture created with cvpxpic_create_mapped()
+ * @return a valid picture, the pic chroma will one of VLC_CODEC_CVPX_* chromas
+ */
+picture_t *cvpxpic_unmap(picture_t *mapped_pic);
+
+/*
+ * Create a cvpx pool
+ *
+ * @param fmt i_chroma must be one of VLC_CODEC_CVPX_* chromas
+ * @param count number of pictures to alloc
+ * @return a valid cvpx pool or NULL, release it with CVPixelBufferPoolRelease()
+ */
+CVPixelBufferPoolRef cvpxpool_create(const video_format_t *fmt, unsigned count);
+
+/*
+ * Get a cvpx buffer from a pool
+ */
+CVPixelBufferRef cvpxpool_get_cvpx(CVPixelBufferPoolRef pool);
+
#endif
More information about the vlc-commits
mailing list