diff --git a/app/src/main/java/com/hmwl/face_sdk/FaceActivity.java b/app/src/main/java/com/hmwl/face_sdk/FaceActivity.java index 98ae4e6..0c94710 100644 --- a/app/src/main/java/com/hmwl/face_sdk/FaceActivity.java +++ b/app/src/main/java/com/hmwl/face_sdk/FaceActivity.java @@ -70,38 +70,14 @@ public class FaceActivity extends GameActivity implements FaceLandmarkerHelper.L imageAnalyzer.setAnalyzer(backgroundExecutor, new ImageAnalysis.Analyzer() { - private long lastCaptureTime = 0; private int frameCount = 0; @Override public void analyze(@NonNull ImageProxy image) { frameCount++; - long currentTime = System.currentTimeMillis(); try { - long captureTimeNs = image.getImageInfo().getTimestamp(); - long analyzeTime = System.currentTimeMillis(); - - // 简单直接的计算方法 - long captureTimeMs = TimeUnit.NANOSECONDS.toMillis(captureTimeNs); - long latency = analyzeTime - captureTimeMs; - - // 帧率计算 - if (lastCaptureTime > 0) { - long frameInterval = captureTimeMs - lastCaptureTime; - double fps = 1000.0 / frameInterval; - - if (frameCount % 10 == 0) { // 每30帧打印一次 - Log.i("TimeLatency", String.format( - "Frame %d - Latency: %d ms, FPS: %.1f", - frameCount, latency, fps - )); - } - } - - lastCaptureTime = captureTimeMs; - processImageForVulkan(image); - if(frameCount %2 == 0) + if(frameCount %3 == 0) { detectFace(image); } @@ -186,7 +162,6 @@ public class FaceActivity extends GameActivity implements FaceLandmarkerHelper.L 0.5f, 0.5f, 1, - 0, RunningMode.LIVE_STREAM, FaceActivity.this, FaceActivity.this diff --git a/app/src/main/java/com/hmwl/face_sdk/FaceLandmarkerHelper.kt b/app/src/main/java/com/hmwl/face_sdk/FaceLandmarkerHelper.kt index 1623142..c708ba5 100644 --- a/app/src/main/java/com/hmwl/face_sdk/FaceLandmarkerHelper.kt +++ b/app/src/main/java/com/hmwl/face_sdk/FaceLandmarkerHelper.kt @@ -20,8 +20,7 @@ class FaceLandmarkerHelper( var minFaceTrackingConfidence: Float = DEFAULT_FACE_TRACKING_CONFIDENCE, var minFacePresenceConfidence: Float = DEFAULT_FACE_PRESENCE_CONFIDENCE, var maxNumFaces: Int = DEFAULT_NUM_FACES, - var currentDelegate: Int = DELEGATE_CPU, - var runningMode: RunningMode = RunningMode.IMAGE, + var runningMode: RunningMode = RunningMode.LIVE_STREAM, val context: Context, // this listener is only used when running in RunningMode.LIVE_STREAM val faceLandmarkerHelperListener: LandmarkerListener? = null @@ -50,14 +49,7 @@ class FaceLandmarkerHelper( val baseOptionBuilder = BaseOptions.builder() // Use the specified hardware for running the model. Default to CPU - when (currentDelegate) { - DELEGATE_CPU -> { - baseOptionBuilder.setDelegate(Delegate.CPU) - } - DELEGATE_GPU -> { - baseOptionBuilder.setDelegate(Delegate.GPU) - } - } + baseOptionBuilder.setDelegate(Delegate.GPU) baseOptionBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK) diff --git a/example/src/main/java/com/hmwl/example/MainActivity.java b/example/src/main/java/com/hmwl/example/MainActivity.java index 8ea02ee..5b9820c 100644 --- a/example/src/main/java/com/hmwl/example/MainActivity.java +++ b/example/src/main/java/com/hmwl/example/MainActivity.java @@ -5,7 +5,9 @@ import android.os.Bundle; import com.hmwl.face_sdk.FaceActivity; public class MainActivity extends FaceActivity{ @Override - protected void onCreate(Bundle savedInstanceState){ + protected void onCreate(Bundle savedInstanceState) + { + SetInitArg("{\"action_fps\":3,\"motion\":{\"png_name\":\"demo\",\"png_num\":1,\"show_type\":\"direction\",\"step\":\"press2\",\"technique\":\"base_makeup\",\"type\":\"bottom_makeup\"},\"zoom\":1.5}"); super.onCreate(savedInstanceState); //这个是设置接口的参数,采用json传递,可以保证接口灵活性 diff --git a/vulkan/FaceApp.cpp b/vulkan/FaceApp.cpp index 555ca00..2955d65 100644 --- a/vulkan/FaceApp.cpp +++ b/vulkan/FaceApp.cpp @@ -1,6 +1,9 @@ #include "FaceApp.h" #include "hardcode_data.h" #include +#include +#include +#include @@ -24,15 +27,89 @@ void ReceiveFacePoint(float* pos, int pointCount, int width, int height) } } +// 定义帧数据结构 +struct FrameData { + uint8_t* data; + int width; + int height; + int rowStride; + size_t dataSize; + FrameData(uint8_t* d, int w, int h, int rs, size_t ds) + : data(nullptr), width(w), height(h), rowStride(rs), dataSize(ds) { + // 深拷贝数据 + if (d && ds > 0) { + data = new uint8_t[dataSize]; + memcpy(data, d, dataSize); + } + } + + ~FrameData() { + if (data) { + delete[] data; + data = nullptr; + } + } + + // 禁止拷贝构造和赋值(使用移动语义) + FrameData(const FrameData&) = delete; + FrameData& operator=(const FrameData&) = delete; + + // 移动构造 + FrameData(FrameData&& other) noexcept + : data(other.data), width(other.width), height(other.height), + rowStride(other.rowStride), dataSize(other.dataSize) { + other.data = nullptr; + } + + // 移动赋值 + FrameData& operator=(FrameData&& other) noexcept { + if (this != &other) { + if (data) delete[] data; + data = other.data; + width = other.width; + height = other.height; + rowStride = other.rowStride; + dataSize = other.dataSize; + other.data = nullptr; + } + return *this; + } +}; + +// 全局队列和互斥锁 +std::queue frameQueue; +std::mutex queueMutex; +const int MAX_QUEUE_SIZE = 4; void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize) { - if(FaceApp::Get()->isInited()) - { - Texture& tex_bg = FaceApp::Get()->tex_bg; - FaceApp::Get()->processWithVulkan(data, width, height, rowStride, dataSize, tex_bg, false); - } + if (!FaceApp::Get()->isInited()) { + return; + } + + std::lock_guard lock(queueMutex); + + // 添加新帧数据到队列 + frameQueue.emplace(data, width, height, rowStride, dataSize); + + // 如果队列大小达到阈值,开始处理最旧的一帧 + if (frameQueue.size() >= MAX_QUEUE_SIZE) { + Texture& tex_bg = FaceApp::Get()->tex_bg; + FrameData& oldestFrame = frameQueue.front(); + + FaceApp::Get()->processWithVulkan( + oldestFrame.data, + oldestFrame.width, + oldestFrame.height, + oldestFrame.rowStride, + oldestFrame.dataSize, + tex_bg, + false + ); + + frameQueue.pop(); + } } bool FaceApp::LoadOBJ(const std::string& filename, @@ -370,27 +447,31 @@ void FaceApp::create_face_pipelines() void FaceApp::setup_descriptor_pool() { - VkDescriptorPoolSize descriptor_pool_size{}; - descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_pool_size.descriptorCount = 2; + // 保守估计:假设每个描述符集可能有多个绑定 + const uint32_t setsCount = kMaxTexture; + const uint32_t multiplier = 3; // 安全系数 - VkDescriptorPoolSize descriptor_pool_image_size{}; - descriptor_pool_image_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_pool_image_size.descriptorCount = kMaxTexture + 4; + std::vector pool_sizes = { + { + .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = setsCount * multiplier + }, + { + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = setsCount * multiplier + }, + // 如果需要其他类型的描述符,在这里添加 + }; + VkDescriptorPoolCreateInfo descriptor_pool_info{}; + descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_info.poolSizeCount = static_cast(pool_sizes.size()); + descriptor_pool_info.pPoolSizes = pool_sizes.data(); + descriptor_pool_info.maxSets = setsCount * 2; // 额外预留一些集合 + descriptor_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - std::vector pool_sizes; - pool_sizes.push_back(descriptor_pool_size); - pool_sizes.push_back(descriptor_pool_image_size); + VK_CHECK(vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool)); - - VkDescriptorPoolCreateInfo descriptor_pool_info{}; - descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptor_pool_info.poolSizeCount = pool_sizes.size(); - descriptor_pool_info.pPoolSizes = pool_sizes.data(); - descriptor_pool_info.maxSets = kMaxTexture + 4 + 2; - - VK_CHECK(vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool)); } @@ -1024,7 +1105,7 @@ void FaceApp::changeMotion(Motion& motion) loadTextureExample(path_name_ex, m_texs_ex[i], true); #else loadTexture(path_name, m_texs[i], true); - loadTexture(path_name, path_name_ex[i], true); + loadTexture(path_name, m_texs_ex[i], true); #endif // _WIN32