Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71a763b4 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Benchmark: Add test for Codec2 decoders"

parents 0501baaa e32d76cb
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -118,5 +118,30 @@ adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.MuxerT
The test encodes input stream and benchmarks the encoders available in SDK.
```
adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.EncoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
```

# Codec2
To run the test suite for measuring performance of the codec2 layer, follow the following steps:

The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/

To test 64-bit binary push binaries from nativetest64.
adb push $(OUT)/data/nativetest64/* /data/local/tmp/
Eg. adb push $(OUT)/data/nativetest64/C2DecoderTest/C2DecoderTest /data/local/tmp/

To test 32-bit binary push binaries from nativetest.
adb push $(OUT)/data/nativetest/* /data/local/tmp/
Eg. adb push $(OUT)/data/nativetest/C2DecoderTest/C2DecoderTest /data/local/tmp/

To get the resource files for the test follow instructions given in [NDK](#NDK)

## C2 Decoder

The test decodes input stream and benchmarks the codec2 decoders available in device.

Setup steps are same as [extractor](#extractor).

```
adb shell /data/local/tmp/C2DecoderTest -P /data/local/tmp/MediaBenchmark/res/
```
+33 −0
Original line number Diff line number Diff line
@@ -58,6 +58,39 @@ cc_defaults {
    ]
}

cc_library_static {
    name: "libmediabenchmark_codec2_common",
    defaults: [
        "libmediabenchmark_codec2_common-defaults",
    ],

    srcs: [
        "BenchmarkC2Common.cpp",
    ],

    export_include_dirs: ["."],

    ldflags: ["-Wl,-Bsymbolic"]
}

cc_defaults {
    name: "libmediabenchmark_codec2_common-defaults",

    defaults: [
        "libmediabenchmark_common-defaults",
        "libcodec2-hidl-client-defaults",
        "libmediabenchmark_soft_sanitize_all-defaults",
    ],

    include_dirs: [
        "frameworks/av/media/codec2/hidl/client/include",
    ],

    shared_libs: [
        "libcodec2_client",
    ]
}

// public dependency for native implementation
// to be used by code under media/benchmark/* only
cc_defaults {
+110 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "BenchmarkC2Common"

#include "BenchmarkC2Common.h"

int32_t BenchmarkC2Common::setupCodec2() {
    ALOGV("In %s", __func__);
    mClient = android::Codec2Client::CreateFromService("default");
    if (!mClient) return -1;

    std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
    if (!store) return -1;

    c2_status_t status = store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
    if (status != C2_OK) return status;

    mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
    if (!mLinearPool) return -1;

    status = store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator);
    if (status != C2_OK) return status;

    mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
    if (!mGraphicPool) return -1;

    for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
        mWorkQueue.emplace_back(new C2Work);
    }
    if (!mStats) mStats = new Stats();

    return status;
}

vector<string> BenchmarkC2Common::getSupportedComponentList(bool isEncoder) {
    // Get List of components from all known services
    vector<string> codecList;
    const std::vector<C2Component::Traits> listTraits = mClient->ListComponents();
    if (listTraits.size() == 0)
        ALOGE("ComponentInfo list empty.");
    else {
        for (size_t i = 0; i < listTraits.size(); i++) {
            if (isEncoder && C2Component::KIND_ENCODER == listTraits[i].kind) {
                codecList.push_back(listTraits[i].name);
            } else if (!isEncoder && C2Component::KIND_DECODER == listTraits[i].kind) {
                codecList.push_back(listTraits[i].name);
            }
        }
    }
    return codecList;
}

void BenchmarkC2Common::waitOnInputConsumption() {
    typedef std::unique_lock<std::mutex> ULock;
    uint32_t queueSize;
    uint32_t maxRetry = 0;
    {
        ULock l(mQueueLock);
        queueSize = mWorkQueue.size();
    }
    while ((maxRetry < MAX_RETRY) && (queueSize < MAX_INPUT_BUFFERS)) {
        ULock l(mQueueLock);
        if (queueSize != mWorkQueue.size()) {
            queueSize = mWorkQueue.size();
            maxRetry = 0;
        } else {
            mQueueCondition.wait_for(l, TIME_OUT);
            maxRetry++;
        }
    }
}

void BenchmarkC2Common::handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
    ALOGV("In %s", __func__);
    mStats->addOutputTime();
    for (std::unique_ptr<C2Work> &work : workItems) {
        if (!work->worklets.empty()) {
            if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
                mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) !=
                       0;
                ALOGV("WorkDone: frameID received %d , mEos : %d",
                      (int)work->worklets.front()->output.ordinal.frameIndex.peeku(), mEos);
                work->input.buffers.clear();
                work->worklets.clear();
                {
                    typedef std::unique_lock<std::mutex> ULock;
                    ULock l(mQueueLock);
                    mWorkQueue.push_back(std::move(work));
                    mQueueCondition.notify_all();
                }
            }
        }
    }
}
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __BENCHMARK_C2_COMMON_H__
#define __BENCHMARK_C2_COMMON_H__

#include "codec2/hidl/client.h"

#include <C2Component.h>
#include <C2Config.h>

#include <hidl/HidlSupport.h>

#include <C2AllocatorIon.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>

#include "BenchmarkCommon.h"

#define MAX_RETRY 20
#define TIME_OUT 400ms
#define MAX_INPUT_BUFFERS 8

using android::C2AllocatorIon;

class LinearBuffer : public C2Buffer {
  public:
    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block)
        : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}

    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block, size_t size)
        : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
};

class GraphicBuffer : public C2Buffer {
  public:
    explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
        : C2Buffer({block->share(C2Rect(block->width(), block->height()), ::C2Fence())}) {}
};

/**
 * Handle Callback functions onWorkDone(), onTripped(),
 * onError(), onDeath(), onFramesRendered() for C2 Components
 */
struct CodecListener : public android::Codec2Client::Listener {
  public:
    CodecListener(
            const std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> fn = nullptr)
        : callBack(fn) {}
    virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component> &comp,
                            std::list<std::unique_ptr<C2Work>> &workItems) override {
        ALOGV("onWorkDone called");
        (void)comp;
        if (callBack) callBack(workItems);
    }

    virtual void onTripped(
            const std::weak_ptr<android::Codec2Client::Component> &comp,
            const std::vector<std::shared_ptr<C2SettingResult>> &settingResults) override {
        (void)comp;
        (void)settingResults;
    }

    virtual void onError(const std::weak_ptr<android::Codec2Client::Component> &comp,
                         uint32_t errorCode) override {
        (void)comp;
        ALOGV("onError called");
        if (errorCode != 0) ALOGE("Error : %u", errorCode);
    }

    virtual void onDeath(const std::weak_ptr<android::Codec2Client::Component> &comp) override {
        (void)comp;
    }

    virtual void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) override {
        (void)frameIndex;
        (void)arrayIndex;
    }

    virtual void onFrameRendered(uint64_t bufferQueueId, int32_t slotId,
                                 int64_t timestampNs) override {
        (void)bufferQueueId;
        (void)slotId;
        (void)timestampNs;
    }

    std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> callBack;
};

class BenchmarkC2Common {
  public:
    BenchmarkC2Common()
        : mEos(false),
          mStats(nullptr),
          mClient(nullptr),
          mBlockPoolId(0),
          mLinearPool(nullptr),
          mGraphicPool(nullptr),
          mLinearAllocator(nullptr),
          mGraphicAllocator(nullptr) {}

    int32_t setupCodec2();

    vector<string> getSupportedComponentList(bool isEncoder);

    void waitOnInputConsumption();

    // callback function to process onWorkDone received by Listener
    void handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);

    bool mEos;
  protected:
    Stats *mStats;

    std::shared_ptr<android::Codec2Client> mClient;

    C2BlockPool::local_id_t mBlockPoolId;
    std::shared_ptr<C2BlockPool> mLinearPool;
    std::shared_ptr<C2BlockPool> mGraphicPool;
    std::shared_ptr<C2Allocator> mLinearAllocator;
    std::shared_ptr<C2Allocator> mGraphicAllocator;

    std::mutex mQueueLock;
    std::condition_variable mQueueCondition;
    std::list<std::unique_ptr<C2Work>> mWorkQueue;
};

#endif  // __BENCHMARK_C2_COMMON_H__
+19 −0
Original line number Diff line number Diff line
@@ -29,3 +29,22 @@ cc_library_static {

    ldflags: ["-Wl,-Bsymbolic"]
}

cc_library_static {
    name: "libmediabenchmark_codec2_decoder",
    defaults: [
        "libmediabenchmark_common-defaults",
        "libmediabenchmark_codec2_common-defaults",
    ],

    srcs: ["C2Decoder.cpp"],

    static_libs: [
        "libmediabenchmark_codec2_common",
        "libmediabenchmark_extractor",
    ],

    export_include_dirs: ["."],

    ldflags: ["-Wl,-Bsymbolic"]
}
Loading