summaryrefslogtreecommitdiff
path: root/media/eco/include/eco/ECOSession.h
blob: 9fb0bdc48d9f94ebfe9387e95fadfec38db19774 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
 * 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 <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 BnECOSession,
                   public virtual IBinder::DeathRecipient {

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_