blob: 90f9d9421938ec2ca879a44881544f85865b1100 [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 ANDROID_MEDIA_ECO_SESSION_H_
#define ANDROID_MEDIA_ECO_SESSION_H_
#include <android/media/eco/BnECOSession.h>
#include <android/media/eco/IECOServiceStatsProvider.h>
#include <binder/BinderService.h>
#include <condition_variable>
#include <deque>
#include <list>
#include <memory>
#include <mutex>
#include <thread>
#include "ECOData.h"
#include "ECOServiceInfoListener.h"
#include "ECOServiceStatsProvider.h"
#include "ECOUtils.h"
namespace android {
namespace media {
namespace eco {
using ::android::binder::Status;
/**
* ECO Session.
*
* ECOSession is created by ECOService to manage an encoding session. Both the providers and
* listeners should interact with ECO session after obtain it from ECOService. For ECOService 1.0,
* it only supports resolution of up to 720P and only for camera recording use case. Also, it only
* supports encoder as the provider and camera as listener.
*/
class ECOSession : public BinderService<ECOSession>,
public BnECOSession,
public virtual IBinder::DeathRecipient {
friend class BinderService<ECOSession>;
public:
virtual ~ECOSession();
virtual Status addStatsProvider(const sp<IECOServiceStatsProvider>& provider,
const ECOData& statsConfig, /*out*/ bool* status);
virtual Status removeStatsProvider(const sp<IECOServiceStatsProvider>&, bool*);
virtual Status addInfoListener(const sp<IECOServiceInfoListener>&,
const ECOData& listenerConfig,
/*out*/ bool* status);
virtual Status removeInfoListener(const sp<IECOServiceInfoListener>&, bool*);
virtual Status pushNewStats(const ECOData&, bool*);
virtual Status getWidth(int32_t* _aidl_return);
virtual Status getHeight(int32_t* _aidl_return);
virtual Status getIsCameraRecording(bool*);
virtual Status getNumOfListeners(int32_t*);
virtual Status getNumOfProviders(int32_t*);
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder>& who);
// Grant permission to EcoSessionTest to run test.
friend class EcoSessionTest;
// Let ECOService create the session.
friend class ECOService;
protected:
static android::sp<ECOSession> createECOSession(int32_t width, int32_t height,
bool isCameraRecording);
private:
// Only the ECOService could create ECOSession.
ECOSession(int32_t width, int32_t height, bool isCameraRecording);
virtual status_t dump(int fd, const Vector<String16>& args);
// Start the main thread for processing the stats and pushing info to listener.
static void startThread(ECOSession* session);
void run();
bool processStats(const ECOData& stats);
// Lock guarding ECO session state
std::mutex mSessionLock;
// Process the session stats received from provider.
void processSessionStats(const ECOData& stats);
// Process the frame stats received from provider.
void processFrameStats(const ECOData& stats);
// Generate the latest session info if available.
ECOData generateLatestSessionInfoEcoData();
std::atomic<bool> mStopThread;
std::mutex mStatsQueueLock;
std::deque<ECOData> mStatsQueue; // GUARDED_BY(mStatsQueueLock)
std::condition_variable mWorkerWaitCV;
bool mNewListenerAdded = false;
constexpr static int32_t ENCODER_MIN_QP = 0;
constexpr static int32_t ENCODER_MAX_QP = 51;
// Save the QP last reported to the listener. Init to be 0.
int32_t mLastReportedQp;
typedef struct QpRange {
int32_t mQpBlocknessThreshold = 50;
int32_t mQpChangeThreshold = 50;
} QpCondition;
QpCondition mListenerQpCondition;
android::sp<IECOServiceInfoListener> mListener;
String16 mListenerName;
android::sp<IECOServiceStatsProvider> mProvider;
String16 mProviderName;
// Main thread for processing the events from provider.
std::thread mThread;
// Width of the encoding session in number of pixels.
const int32_t mWidth;
// Height of the encoding session in number of pixels.
const int32_t mHeight;
// Whether the encoding is for camera recording.
const bool mIsCameraRecording;
// Ouput width of the encoding session in number of pixels, -1 means not available.
int32_t mOutputWidth = -1;
// Output height of the encoding session in number of pixels. -1 means not available.
int32_t mOutputHeight = -1;
// Encoder codec type of the encoding session. -1 means not available.
int32_t mCodecType = -1;
// Encoder codec profile. -1 means not available.
int32_t mCodecProfile = -1;
// Encoder codec level. -1 means not available.
int32_t mCodecLevel = -1;
// Target bitrate in bits per second. This should be provided by the provider. -1 means not
// available.
int32_t mTargetBitrateBps = -1;
// Actual bitrate in bits per second. This should be provided by the provider. -1 means not
// available.
int32_t mActualBitrateBps = -1;
// Key frame interval in number of frames. -1 means not available.
int32_t mKeyFrameIntervalFrames = -1;
// Frame rate in frames per second. -1 means not available.
float mFramerateFps;
// Debug related flags.
bool mLogStats;
uint32_t mLogStatsEntries; // number of stats received from the provider.
std::list<ECOData> mStatsDebugBuffer;
// Pushes the ECOData to the debug buffer.
void logStats(const ECOData& data);
bool mLogInfo;
uint32_t mLogInfoEntries; // number of infos sent to the listener.
std::list<ECOData> mInfosDebugBuffer;
// Pushes the ECOData to the debug buffer.
void logInfos(const ECOData& data);
};
} // namespace eco
} // namespace media
} // namespace android
#endif // ANDROID_MEDIA_ECO_SESSION_H_