vlc | branch: master | Thomas Guillem <[email protected]> | 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 _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
