The Usage of BufferQueue in two process

Client Process:

//#include <iostream>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>

#include <iostream>
#include <array>
#include <limits>
#include <set>
#include <unordered_map>

#include <functional>
#include <memory>
#include <ostream>
#include <string>
#include <vector>
#include <map>
#include <optional>
#include <optional>

#include <chrono>
#include <mutex>
#include <thread>

#include <android/gui/IDisplayEventConnection.h>
#include <android/gui/ISurfaceComposer.h>
#include <binder/ProcessState.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SyncScreenCaptureListener.h>
#include <inttypes.h>
#include <private/gui/ComposerService.h>
#include <private/gui/ComposerServiceAIDL.h>
#include <sys/types.h>
#include <ui/BufferQueueDefs.h>
#include <ui/DisplayMode.h>
#include <ui/Rect.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <limits>
#include <thread>
#include "ColorUtils.h"
#include "MockConsumer.h"
#include <utils/Log.h>

//
typedef uint8_t u8;
typedef int32_t u32;

#include <iostream>
#include <chrono>
#include <thread>

#include <android/gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
#include <gui/Surface.h>
#include <ui/Rect.h>

#include <gui/IConsumerListener.h>

using namespace android;

int main() {
    ProcessState::self()->startThreadPool();

    sp<IGraphicBufferConsumer> mConsumer;

    const String16 PRODUCER_NAME = String16("BQTestProducer1");
    const String16 CONSUMER_NAME = String16("BQTestConsumer1");

    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);
    sp<IServiceManager> serviceManager = defaultServiceManager();
    serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
    serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));


    sp<IBinder> binderConsumer =
            serviceManager->getService(CONSUMER_NAME);
    mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);

    sp<MockConsumer> mc(new MockConsumer);
    mConsumer->consumerConnect(mc, false);

    BufferItem item;
    auto ret = mConsumer->acquireBuffer(&item, 0);


    while (ret == BufferQueue::NO_BUFFER_AVAILABLE) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        ret = mConsumer->acquireBuffer(&item, 0);
        std::cout << "acquireBuffer fails:BufferQueue::NO_BUFFER_AVAILABLE" << std::endl;

    }
    if (ret != OK) {
        std::cout << "acquireBuffer fails:" << statusToString(ret) << std::endl;
        return ret;
    }

    uint32_t *dataOut;
    ret = item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
                                    reinterpret_cast<void **>(&dataOut));

    if (ret != OK) {
        std::cout << "item.mGraphicBuffer->lock fails" << std::endl;
        return ret;
    }

    std::cout << *dataOut << std::endl;
    ret = item.mGraphicBuffer->unlock();

    if (ret != OK) {
        std::cout << "unlock fails" << std::endl;
        return ret;
    }
    std::cout << "OK" << std::endl;
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

server:

//#include <iostream>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>

#include <iostream>
#include <array>
#include <limits>
#include <set>
#include <unordered_map>

#include <functional>
#include <memory>
#include <ostream>
#include <string>
#include <vector>
#include <map>
#include <optional>
#include <optional>

#include <chrono>
#include <mutex>
#include <thread>

#include <android/gui/IDisplayEventConnection.h>
#include <android/gui/ISurfaceComposer.h>
#include <binder/ProcessState.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SyncScreenCaptureListener.h>
#include <inttypes.h>
#include <private/gui/ComposerService.h>
#include <private/gui/ComposerServiceAIDL.h>
#include <sys/types.h>
#include <ui/BufferQueueDefs.h>
#include <ui/DisplayMode.h>
#include <ui/Rect.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <limits>
#include <thread>
#include "ColorUtils.h"
#include "MockConsumer.h"
#include <utils/Log.h>

//
typedef uint8_t u8;
typedef int32_t u32;

#include <iostream>
#include <chrono>
#include <thread>

#include <android/gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
#include <gui/Surface.h>
#include <ui/Rect.h>

#include <gui/IConsumerListener.h>

using namespace android;

static const uint32_t TEST_DATA = 1234567;

const uint32_t DEFAULT_WIDTH = 1;

const uint32_t DEFAULT_HEIGHT = 1;

// Default format before setDefaultBufferFormat is called
const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;

// Default transform hint before setTransformHint is called
//const uint32_t DEFAULT_TRANSFORM_HINT = 0;

// TODO: Make these constants in header
//const int DEFAULT_CONSUMER_USAGE_BITS = 0;

#define TEST_PRODUCER_USAGE_BITS (0)

// Parameters for a generic "valid" input for queueBuffer.
const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
const uint32_t QUEUE_BUFFER_INPUT_STICKY_TRANSFORM = 0;
const bool QUEUE_BUFFER_INPUT_GET_TIMESTAMPS = 0;
const int QUEUE_BUFFER_INPUT_SLOT = -1;

// Builder pattern to slightly vary *almost* correct input
// -- avoids copying and pasting

struct QueueBufferInputBuilder {
    QueueBufferInputBuilder() {
        timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP;
        isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP;
        dataSpace = QUEUE_BUFFER_INPUT_DATASPACE;
        crop = QUEUE_BUFFER_INPUT_RECT;
        scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
        transform = QUEUE_BUFFER_INPUT_TRANSFORM;
        fence = QUEUE_BUFFER_INPUT_FENCE;
        stickyTransform = QUEUE_BUFFER_INPUT_STICKY_TRANSFORM;
        getTimestamps = QUEUE_BUFFER_INPUT_GET_TIMESTAMPS;
        slot = QUEUE_BUFFER_INPUT_SLOT;
    }

    IGraphicBufferProducer::QueueBufferInput build() {
        return IGraphicBufferProducer::QueueBufferInput(
                timestamp,
                isAutoTimestamp,
                dataSpace,
                crop,
                scalingMode,
                transform,
                fence,
                stickyTransform,
                getTimestamps,
                slot);
    }

private:
    int64_t timestamp;
    bool isAutoTimestamp;
    android_dataspace dataSpace;
    Rect crop;
    int scalingMode;
    uint32_t transform;
    sp<Fence> fence;
    uint32_t stickyTransform;
    bool getTimestamps;
    int slot;

};

// Create a generic "valid" input for queueBuffer
// -- uses the default buffer format, width, etc.
static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
    return QueueBufferInputBuilder().build();
}


int main() {
    sp<IGraphicBufferProducer> mProducer;

    const String16 PRODUCER_NAME = String16("BQTestProducer1");

    sp<IServiceManager> serviceManager = defaultServiceManager();
    ProcessState::self()->startThreadPool();

    sp<IBinder> binderProducer =
            serviceManager->getService(PRODUCER_NAME);
    mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);

    IGraphicBufferProducer::QueueBufferOutput output;
    auto ret = mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output);

    if (ret != NO_ERROR) {
        std::cout << "mProducer->connect fails:" << statusToString(ret) << std::endl;
        return ret;
    }

    int slot = -1;
    sp<Fence> fence;
    sp<GraphicBuffer> buffer;

    ret = mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
                                   DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
                                   nullptr, nullptr);

    if (ret < 0) {
        std::cout << "mProducer->dequeueBuffer  fails: " << ret << std::endl;
        return ret;
    }

    if (slot == -1) {
        std::cout << "slot is -1" << ret << std::endl;
        return -1;
    }

    ret = mProducer->requestBuffer(slot, &buffer);
    if (buffer == nullptr) {
        std::cout << "mProducer->requestBuffer fails " << ret << std::endl;
        return -1;
    }

    uint32_t *dataIn;

    ret = buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
                       reinterpret_cast<void **>(&dataIn));

    if (ret != OK) {
        std::cout << "buffer->lock fails" << std::endl;
        return ret;
    }

    *dataIn = TEST_DATA;
    ret = buffer->unlock();

    if (ret != OK) {
        std::cout << "unlock fails" << std::endl;
        return ret;
    }

    std::cout << "slot is:" << slot << std::endl;

    IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    IGraphicBufferProducer::QueueBufferOutput output2;
    ret = mProducer->queueBuffer(slot, input, &output2);

    if (ret != NO_ERROR) {
        std::cout << "queueBuffer fails: " << statusToString(ret) << std::endl;
        return ret;
    }

    std::cout << "OK 2" << std::endl;
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值