1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_MEDIA_ECO_SESSION_H_
18 #define ANDROID_MEDIA_ECO_SESSION_H_
19 
20 #include <android/media/eco/BnECOSession.h>
21 #include <android/media/eco/IECOServiceStatsProvider.h>
22 #include <binder/BinderService.h>
23 
24 #include <condition_variable>
25 #include <deque>
26 #include <list>
27 #include <memory>
28 #include <mutex>
29 #include <thread>
30 
31 #include "ECOData.h"
32 #include "ECOServiceInfoListener.h"
33 #include "ECOServiceStatsProvider.h"
34 #include "ECOUtils.h"
35 
36 namespace android {
37 namespace media {
38 namespace eco {
39 
40 using ::android::binder::Status;
41 
42 /**
43  * ECO Session.
44  *
45  * ECOSession is created by ECOService to manage an encoding session. Both the providers and
46  * listeners should interact with ECO session after obtain it from ECOService. For ECOService 1.0,
47  * it only supports resolution of up to 720P and only for camera recording use case. Also, it only
48  * supports encoder as the provider and camera as listener.
49  */
50 class ECOSession : public BinderService<ECOSession>,
51                    public BnECOSession,
52                    public virtual IBinder::DeathRecipient {
53     friend class BinderService<ECOSession>;
54 
55 public:
56     virtual ~ECOSession();
57 
58     virtual Status addStatsProvider(const sp<IECOServiceStatsProvider>& provider,
59                                     const ECOData& statsConfig, /*out*/ bool* status);
60 
61     virtual Status removeStatsProvider(const sp<IECOServiceStatsProvider>&, bool*);
62 
63     virtual Status addInfoListener(const sp<IECOServiceInfoListener>&,
64                                    const ECOData& listenerConfig,
65                                    /*out*/ bool* status);
66 
67     virtual Status removeInfoListener(const sp<IECOServiceInfoListener>&, bool*);
68 
69     virtual Status pushNewStats(const ECOData&, bool*);
70 
71     virtual Status getWidth(int32_t* _aidl_return);
72 
73     virtual Status getHeight(int32_t* _aidl_return);
74 
75     virtual Status getIsCameraRecording(bool*);
76 
77     virtual Status getNumOfListeners(int32_t*);
78 
79     virtual Status getNumOfProviders(int32_t*);
80 
81     // IBinder::DeathRecipient implementation
82     virtual void binderDied(const wp<IBinder>& who);
83 
84     // Grant permission to EcoSessionTest to run test.
85     friend class EcoSessionTest;
86 
87     // Let ECOService create the session.
88     friend class ECOService;
89 
90 protected:
91     static android::sp<ECOSession> createECOSession(int32_t width, int32_t height,
92                                                     bool isCameraRecording);
93 
94 private:
95     // Only the  ECOService could create ECOSession.
96     ECOSession(int32_t width, int32_t height, bool isCameraRecording);
97 
98     virtual status_t dump(int fd, const Vector<String16>& args);
99 
100     // Start the main thread for processing the stats and pushing info to listener.
101     static void startThread(ECOSession* session);
102 
103     void run();
104 
105     bool processStats(const ECOData& stats);
106 
107     // Lock guarding ECO session state
108     std::mutex mSessionLock;
109 
110     // Process the session stats received from provider.
111     void processSessionStats(const ECOData& stats);
112 
113     // Process the frame stats received from provider.
114     void processFrameStats(const ECOData& stats);
115 
116     // Generate the latest session info if available.
117     ECOData generateLatestSessionInfoEcoData();
118 
119     std::atomic<bool> mStopThread;
120 
121     std::mutex mStatsQueueLock;
122     std::deque<ECOData> mStatsQueue;  // GUARDED_BY(mStatsQueueLock)
123     std::condition_variable mWorkerWaitCV;
124 
125     bool mNewListenerAdded = false;
126 
127     constexpr static int32_t ENCODER_MIN_QP = 0;
128     constexpr static int32_t ENCODER_MAX_QP = 51;
129 
130     // Save the QP last reported to the listener. Init to be 0.
131     int32_t mLastReportedQp;
132 
133     typedef struct QpRange {
134         int32_t mQpBlocknessThreshold = 50;
135         int32_t mQpChangeThreshold = 50;
136     } QpCondition;
137     QpCondition mListenerQpCondition;
138 
139     android::sp<IECOServiceInfoListener> mListener;
140     String16 mListenerName;
141 
142     android::sp<IECOServiceStatsProvider> mProvider;
143     String16 mProviderName;
144 
145     // Main thread for processing the events from provider.
146     std::thread mThread;
147 
148     // Width of the encoding session in number of pixels.
149     const int32_t mWidth;
150 
151     // Height of the encoding session in number of pixels.
152     const int32_t mHeight;
153 
154     // Whether the encoding is for camera recording.
155     const bool mIsCameraRecording;
156 
157     // Ouput width of the encoding session in number of pixels, -1 means not available.
158     int32_t mOutputWidth = -1;
159 
160     // Output height of the encoding session in number of pixels. -1 means not available.
161     int32_t mOutputHeight = -1;
162 
163     // Encoder codec type of the encoding session. -1 means not available.
164     int32_t mCodecType = -1;
165 
166     // Encoder codec profile. -1 means not available.
167     int32_t mCodecProfile = -1;
168 
169     // Encoder codec level. -1 means not available.
170     int32_t mCodecLevel = -1;
171 
172     // Target bitrate in bits per second. This should be provided by the provider. -1 means not
173     // available.
174     int32_t mTargetBitrateBps = -1;
175 
176     // Actual bitrate in bits per second. This should be provided by the provider. -1 means not
177     // available.
178     int32_t mActualBitrateBps = -1;
179 
180     // Key frame interval in number of frames. -1 means not available.
181     int32_t mKeyFrameIntervalFrames = -1;
182 
183     // Frame rate in frames per second. -1 means not available.
184     float mFramerateFps;
185 
186     // Debug related flags.
187     bool mLogStats;
188     uint32_t mLogStatsEntries;  // number of stats received from the provider.
189     std::list<ECOData> mStatsDebugBuffer;
190 
191     // Pushes the ECOData to the debug buffer.
192     void logStats(const ECOData& data);
193 
194     bool mLogInfo;
195     uint32_t mLogInfoEntries;  // number of infos sent to the listener.
196     std::list<ECOData> mInfosDebugBuffer;
197 
198     // Pushes the ECOData to the debug buffer.
199     void logInfos(const ECOData& data);
200 };
201 
202 }  // namespace eco
203 }  // namespace media
204 }  // namespace android
205 
206 #endif  // ANDROID_MEDIA_ECO_SESSION_H_
207