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

Commit 789fb735 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Benchmark: add Decoder"

parents f28a06da 90f569ac
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -28,3 +28,13 @@ The path to these files on the device is required to be given for the test.
```
adb shell /data/local/tmp/extractorTest -P /sdcard/res/
```

## Decoder

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

Setup steps are same as extractor.

```
adb shell /data/local/tmp/decoderTest -P /sdcard/res/
```
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ cc_library_static {
    ],

    srcs: [
        "BenchmarkCommon.cpp",
        "Timer.cpp",
    ],

+102 −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 "BenchmarkCommon"

#include "BenchmarkCommon.h"
#include <iostream>

void CallBackHandle::ioThread() {
    ALOGV("In %s mIsDone : %d, mSawError : %d ", __func__, mIsDone, mSawError);
    while (!mIsDone && !mSawError) {
        auto task = mIOQueue.pop();
        task();
    }
}

void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index) {
    ALOGV("OnInputAvailableCB: index(%d)", index);
    CallBackHandle *self = (CallBackHandle *)userdata;
    self->getTimer()->addInputTime();
    self->mIOQueue.push([self, codec, index]() { self->onInputAvailable(codec, index); });
}

void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
                         AMediaCodecBufferInfo *bufferInfo) {
    ALOGV("OnOutputAvailableCB: index(%d), (%d, %d, %lld, 0x%x)", index, bufferInfo->offset,
          bufferInfo->size, (long long)bufferInfo->presentationTimeUs, bufferInfo->flags);
    CallBackHandle *self = (CallBackHandle *)userdata;
    self->getTimer()->addOutputTime();
    AMediaCodecBufferInfo bufferInfoCopy = *bufferInfo;
    self->mIOQueue.push([self, codec, index, bufferInfoCopy]() {
        AMediaCodecBufferInfo bc = bufferInfoCopy;
        self->onOutputAvailable(codec, index, &bc);
    });
}

void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format) {
    ALOGV("OnFormatChangedCB: format(%s)", AMediaFormat_toString(format));
    CallBackHandle *self = (CallBackHandle *)userdata;
    self->mIOQueue.push([self, codec, format]() { self->onFormatChanged(codec, format); });
}

void OnErrorCB(AMediaCodec *codec, void *userdata, media_status_t err, int32_t actionCode,
               const char *detail) {
    (void)codec;
    ALOGV("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
    CallBackHandle *self = (CallBackHandle *)userdata;
    self->mSawError = true;
}

AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
                              bool isEncoder) {
    ALOGV("In %s", __func__);
    if (!mime) {
        ALOGE("Please specify a mime type to create codec");
        return nullptr;
    }

    AMediaCodec *codec;
    if (!codecName.empty()) {
        codec = AMediaCodec_createCodecByName(codecName.c_str());
        if (!codec) {
            ALOGE("Unable to create codec by name: %s", codecName.c_str());
            return nullptr;
        }
    } else {
        if (isEncoder) {
            codec = AMediaCodec_createEncoderByType(mime);
        } else {
            codec = AMediaCodec_createDecoderByType(mime);
        }
        if (!codec) {
            ALOGE("Unable to create codec by mime: %s", mime);
            return nullptr;
        }
    }

    /* Configure codec with the given format*/
    const char *s = AMediaFormat_toString(format);
    ALOGV("Input format: %s\n", s);

    media_status_t status = AMediaCodec_configure(codec, format, nullptr, nullptr, isEncoder);
    if (status != AMEDIA_OK) {
        ALOGE("AMediaCodec_configure failed %d", status);
        return nullptr;
    }
    return codec;
}
 No newline at end of file
+96 −0
Original line number Diff line number Diff line
@@ -19,11 +19,107 @@

#include <utils/Log.h>

#include <inttypes.h>
#include <mutex>
#include <queue>
#include <thread>

#include <media/NdkMediaCodec.h>
#include <media/NdkMediaError.h>

#include "Timer.h"

using namespace std;

constexpr uint32_t kQueueDequeueTimeoutUs = 1000;
constexpr uint32_t kMaxCSDStrlen = 16;
constexpr uint32_t kMaxBufferSize = 1024 * 1024 * 16;

template <typename T>
class CallBackQueue {
  public:
    CallBackQueue() {}
    ~CallBackQueue() {}

    void push(T elem) {
        bool needsNotify = false;
        {
            lock_guard<mutex> lock(mMutex);
            needsNotify = mQueue.empty();
            mQueue.push(move(elem));
        }
        if (needsNotify) mQueueNotEmptyCondition.notify_one();
    }

    T pop() {
        unique_lock<mutex> lock(mMutex);
        if (mQueue.empty()) {
            mQueueNotEmptyCondition.wait(lock, [this]() { return !mQueue.empty(); });
        }
        auto result = mQueue.front();
        mQueue.pop();
        return result;
    }

  private:
    mutex mMutex;
    queue<T> mQueue;
    condition_variable mQueueNotEmptyCondition;
};

class CallBackHandle {
  public:
    CallBackHandle() : mSawError(false), mIsDone(false), mTimer(nullptr) {}

    virtual ~CallBackHandle() {
        if (mIOThread.joinable()) mIOThread.join();
        if (mTimer) delete mTimer;
    }

    void ioThread();

    // Implementation in child class (Decoder/Encoder)
    virtual void onInputAvailable(AMediaCodec *codec, int32_t index) {
        (void)codec;
        (void)index;
    }
    virtual void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) {
        (void)codec;
        (void)format;
    }
    virtual void onOutputAvailable(AMediaCodec *codec, int32_t index,
                                   AMediaCodecBufferInfo *bufferInfo) {
        (void)codec;
        (void)index;
        (void)bufferInfo;
    }

    virtual Timer *getTimer() { return mTimer; }

    // Keep a queue of all function callbacks.
    typedef function<void()> IOTask;
    CallBackQueue<IOTask> mIOQueue;
    thread mIOThread;
    bool mSawError;
    bool mIsDone;

  private:
    Timer *mTimer;
};

// Async API's callback
void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index);

void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
                         AMediaCodecBufferInfo *bufferInfo);

void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format);

void OnErrorCB(AMediaCodec *codec, void * /* userdata */, media_status_t err, int32_t actionCode,
               const char *detail);

// Utility to create and configure AMediaCodec
AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
                              bool isEncoder);

#endif  // __BENCHMARK_COMMON_H__
+31 −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.
 */

cc_library_static {
    name: "libbenchmark_decoder",
    defaults: [
        "libbenchmark_common-defaults",
        "libbenchmark_soft_sanitize_all-defaults",
    ],

    srcs: ["Decoder.cpp"],

    static_libs: ["libbenchmark_extractor"],

    export_include_dirs: ["."],

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