blob: df16baf608c7ff6e21d1f2e5572f89464976158e [file] [log] [blame]
/*
* 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_COMMON_H__
#define __BENCHMARK_COMMON_H__
#include <utils/Log.h>
#include <inttypes.h>
#include <mutex>
#include <queue>
#include <thread>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaError.h>
#include "Stats.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), mStats(nullptr) {
mStats = new Stats();
}
virtual ~CallBackHandle() {
if (mIOThread.joinable()) mIOThread.join();
if (mStats) delete mStats;
}
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;
}
Stats *getStats() { return mStats; }
// Keep a queue of all function callbacks.
typedef function<void()> IOTask;
CallBackQueue<IOTask> mIOQueue;
thread mIOThread;
bool mSawError;
bool mIsDone;
protected:
Stats *mStats;
};
// 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__