diff --git a/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.cpp b/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.cpp index 53613dbc2463a4657fc25d078bf357fb83993d15..d6628e3f733f4ab775c2deeadbb9fb25ae5e75b1 100644 --- a/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.cpp +++ b/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.cpp @@ -384,6 +384,9 @@ static GstFlowReturn gst_consumer_surface_pool_alloc_buffer(GstBufferPool *pool, if (gst_is_consumer_surface_memory(mem)) { *surfacemem = reinterpret_cast(mem); add_buffer_info(surfacepool, *surfacemem, *buffer); + if (surfacepool->update_video_meta != nullptr) { + surfacepool->update_video_meta(surfacepool, *surfacemem, *buffer); + } } gst_consumer_surface_pool_dump_gstbuffer(surfacepool, *buffer); return GST_FLOW_OK; @@ -460,6 +463,7 @@ static void gst_consumer_surface_pool_init(GstConsumerSurfacePool *pool) pool->priv = priv; pool->buffer_available = nullptr; pool->find_buffer = nullptr; + pool->update_video_meta = nullptr; pool->get_surface_buffer = gst_consumer_surface_pool_get_surface_buffer; pool->release_surface_buffer = gst_consumer_surface_pool_release_surface_buffer; priv->available_buf_count = 0; diff --git a/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.h b/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.h index c2865be2fdfa1f687d51552ac3b0a91dac08a324..0cb9b423fcef5ab430bd7a66df3794cd07fd1820 100644 --- a/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.h +++ b/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.h @@ -18,6 +18,7 @@ #include #include +#include "gst_consumer_surface_memory.h" #include "iconsumer_surface.h" #include "surface.h" @@ -55,6 +56,7 @@ struct _GstConsumerSurfacePool { OHOS::sptr &surface_buffer, gint32 &fencefd); void (*release_surface_buffer) (GstConsumerSurfacePool *pool, OHOS::sptr &surface_buffer, gint32 &fencefd); + void (*update_video_meta) (GstConsumerSurfacePool *pool, GstConsumerSurfaceMemory *mem, GstBuffer *buffer); }; struct _GstConsumerSurfacePoolClass { diff --git a/services/engine/gstreamer/plugins/source/videocapture/include/gst_video_capture_pool.h b/services/engine/gstreamer/plugins/source/videocapture/include/gst_video_capture_pool.h index a405789e042d04aedcb0c5344a1ffd4e1ca25ede..37fb1fdc5615b304710cc87d523d2f61def4e078 100644 --- a/services/engine/gstreamer/plugins/source/videocapture/include/gst_video_capture_pool.h +++ b/services/engine/gstreamer/plugins/source/videocapture/include/gst_video_capture_pool.h @@ -39,6 +39,9 @@ struct _GstVideoCapturePool { GMutex pool_lock; gboolean cached_data; std::shared_ptr poolMgr; + guint planes = 0; + gint stride[GST_VIDEO_MAX_PLANES] = {0, 0, 0, 0}; + gsize offset[GST_VIDEO_MAX_PLANES] = {0, 0, 0, 0}; }; struct _GstVideoCapturePoolClass { diff --git a/services/engine/gstreamer/plugins/source/videocapture/src/gst_video_capture_pool.cpp b/services/engine/gstreamer/plugins/source/videocapture/src/gst_video_capture_pool.cpp index 42a90068f2b63796a355c93a1f387b9daa98a7b1..7d754a8e1aaa90bd99402db501ab9928c683c50a 100644 --- a/services/engine/gstreamer/plugins/source/videocapture/src/gst_video_capture_pool.cpp +++ b/services/engine/gstreamer/plugins/source/videocapture/src/gst_video_capture_pool.cpp @@ -16,6 +16,8 @@ #include "gst_video_capture_pool.h" #include #include "buffer_type_meta.h" +#include "display_type.h" +#include "gst/video/gstvideometa.h" #include "surface.h" #include "scope_guard.h" #include "securec.h" @@ -29,6 +31,24 @@ using namespace OHOS; GST_DEBUG_CATEGORY_STATIC(gst_video_capture_pool_debug_category); #define GST_CAT_DEFAULT gst_video_capture_pool_debug_category +namespace { + const std::unordered_map FORMAT_PLANE_MAP = { + { PIXEL_FMT_RGBA_8888, 1 }, + { PIXEL_FMT_YCRCB_420_SP, 2}, + { PIXEL_FMT_YCBCR_420_SP, 2 }, + { PIXEL_FMT_YCBCR_420_P, 3 }, + }; + const std::unordered_map TO_GST_MAP = { + { PIXEL_FMT_RGBA_8888, GST_VIDEO_FORMAT_RGBA }, + { PIXEL_FMT_YCRCB_420_SP, GST_VIDEO_FORMAT_NV21}, + { PIXEL_FMT_YCBCR_420_SP, GST_VIDEO_FORMAT_NV12 }, + { PIXEL_FMT_YCBCR_420_P, GST_VIDEO_FORMAT_I420 }, + }; + constexpr int32_t VIDEO_PLANE_0 = 0; + constexpr int32_t VIDEO_PLANE_1 = 1; + constexpr int32_t VIDEO_PLANE_2 = 2; +} + enum { PROP_0, PROP_CACHED_DATA, @@ -42,6 +62,8 @@ static GstFlowReturn gst_video_capture_pool_find_buffer(GstBufferPool *gstpool, static GstFlowReturn gst_video_capture_pool_get_buffer(GstConsumerSurfacePool *surfacepool, GstBuffer **buffer, bool *releasebuffer); static GstFlowReturn gst_video_capture_pool_release_buffer(GstConsumerSurfacePool *surfacepool, bool *releasebuffer); +static void gst_video_capture_pool_update_video_meta(GstConsumerSurfacePool *surfacepool, GstConsumerSurfaceMemory *mem, + GstBuffer *buffer); static void gst_video_capture_pool_class_init(GstVideoCapturePoolClass *klass) { @@ -63,6 +85,7 @@ static void gst_video_capture_pool_init(GstVideoCapturePool *pool) GstConsumerSurfacePool *surfacepool = GST_CONSUMER_SURFACE_POOL(pool); surfacepool->buffer_available = gst_video_capture_pool_buffer_available; surfacepool->find_buffer = gst_video_capture_pool_find_buffer; + surfacepool->update_video_meta = gst_video_capture_pool_update_video_meta; pool->cached_data = false; pool->poolMgr = nullptr; @@ -242,4 +265,57 @@ static GstFlowReturn gst_video_capture_pool_release_buffer(GstConsumerSurfacePoo surfacepool->release_surface_buffer(surfacepool, surfacebuffer, fencefd); return GST_FLOW_OK; +} + +static void gst_video_capture_pool_update_video_meta(GstConsumerSurfacePool *surfacepool, GstConsumerSurfaceMemory *mem, + GstBuffer *buffer) +{ + g_return_if_fail(surfacepool != nullptr && buffer != nullptr && mem != nullptr && mem->is_eos_frame == FALSE); + g_return_if_fail(mem->buffer_handle != nullptr && FORMAT_PLANE_MAP.count((PixelFormat)mem->pixel_format) != 0); + g_return_if_fail(mem->buffer_handle->stride > 0 && mem->buffer_handle->stride != (int32_t)mem->width); + + GstVideoCapturePool *pool = GST_VIDEO_CAPTURE_POOL_CAST(surfacepool); + g_return_if_fail(pool != nullptr); + + int32_t stride = mem->buffer_handle->stride; + if (stride != pool->stride[VIDEO_PLANE_0]) { // this judge optimize stride/offset info calculation. + switch (mem->pixel_format) { + case PIXEL_FMT_YCRCB_420_SP: // fall-through + case PIXEL_FMT_YCBCR_420_SP: + pool->stride[VIDEO_PLANE_0] = stride; + pool->stride[VIDEO_PLANE_1] = stride; + pool->offset[VIDEO_PLANE_0] = 0; + pool->offset[VIDEO_PLANE_1] = stride * mem->height; // plane 0 size is (stride * mem->height) + break; + case PIXEL_FMT_YCBCR_420_P: + pool->stride[VIDEO_PLANE_0] = stride; + pool->stride[VIDEO_PLANE_1] = stride >> 1; + pool->stride[VIDEO_PLANE_2] = stride >> 1; + pool->offset[VIDEO_PLANE_0] = 0; + pool->offset[VIDEO_PLANE_1] = stride * mem->height; // plane 0 size is (stride * mem->height) + pool->offset[VIDEO_PLANE_2] = pool->offset[VIDEO_PLANE_1] + stride * ((mem->height + 1) >> 1); + break; + case PIXEL_FMT_RGBA_8888: + pool->stride[VIDEO_PLANE_0] = stride; + pool->offset[VIDEO_PLANE_0] = 0; + break; + default: + GST_DEBUG_OBJECT(pool, "update buffer video meta ignore pixelformat %d", mem->pixel_format); + return; + } + pool->planes = FORMAT_PLANE_MAP.at((PixelFormat)mem->pixel_format); + } + GstVideoMeta *video_meta = gst_buffer_get_video_meta(buffer); + if (video_meta != nullptr) { + video_meta->n_planes = pool->planes; + video_meta->stride[VIDEO_PLANE_0] = pool->stride[VIDEO_PLANE_0]; + video_meta->stride[VIDEO_PLANE_1] = pool->stride[VIDEO_PLANE_1]; + video_meta->stride[VIDEO_PLANE_2] = pool->stride[VIDEO_PLANE_2]; + video_meta->offset[VIDEO_PLANE_0] = pool->offset[VIDEO_PLANE_0]; + video_meta->offset[VIDEO_PLANE_1] = pool->offset[VIDEO_PLANE_1]; + video_meta->offset[VIDEO_PLANE_2] = pool->offset[VIDEO_PLANE_2]; + } else { + gst_buffer_add_video_meta_full(buffer, GST_VIDEO_FRAME_FLAG_NONE, TO_GST_MAP.at((PixelFormat)mem->pixel_format), + mem->width, mem->height, pool->planes, pool->offset, pool->stride); + } } \ No newline at end of file