1 /*
2  * Copyright (C) 2017 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 C_CODEC_H_
18 #define C_CODEC_H_
19 
20 #include <atomic>
21 #include <chrono>
22 #include <list>
23 #include <memory>
24 #include <set>
25 
26 #include <C2Component.h>
27 #include <codec2/hidl/client.h>
28 
29 #include <android/native_window.h>
30 #include <media/hardware/MetadataBufferType.h>
31 #include <media/stagefright/foundation/Mutexed.h>
32 #include <media/stagefright/CodecBase.h>
33 #include <media/stagefright/FrameRenderTracker.h>
34 #include <media/stagefright/MediaDefs.h>
35 #include <media/stagefright/SkipCutBuffer.h>
36 #include <utils/NativeHandle.h>
37 #include <hardware/gralloc.h>
38 #include <nativebase/nativebase.h>
39 
40 #include "CCodecConfig.h"
41 
42 namespace android {
43 
44 class CCodecBufferChannel;
45 class InputSurfaceWrapper;
46 struct MediaCodecInfo;
47 
48 class CCodec : public CodecBase {
49 public:
50     CCodec();
51 
52     virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
53     virtual void initiateAllocateComponent(const sp<AMessage> &msg) override;
54     virtual void initiateConfigureComponent(const sp<AMessage> &msg) override;
55     virtual void initiateCreateInputSurface() override;
56     virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface) override;
57     virtual void initiateStart() override;
58     virtual void initiateShutdown(bool keepComponentAllocated = false) override;
59 
60     virtual status_t setSurface(const sp<Surface> &surface) override;
61 
62     virtual void signalFlush() override;
63     virtual void signalResume() override;
64 
65     virtual void signalSetParameters(const sp<AMessage> &params) override;
66     virtual void signalEndOfInputStream() override;
67     virtual void signalRequestIDRFrame() override;
68 
69     void initiateReleaseIfStuck();
70     void onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
71     void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex);
72 
73 protected:
74     virtual ~CCodec();
75 
76     virtual void onMessageReceived(const sp<AMessage> &msg) override;
77 
78 private:
79     typedef std::chrono::steady_clock::time_point TimePoint;
80 
81     status_t tryAndReportOnError(std::function<status_t()> job);
82 
83     void initiateStop();
84     void initiateRelease(bool sendCallback = true);
85 
86     void allocate(const sp<MediaCodecInfo> &codecInfo);
87     void configure(const sp<AMessage> &msg);
88     void start();
89     void stop();
90     void flush();
91     void release(bool sendCallback);
92 
93     /**
94      * Creates an input surface for the current device configuration compatible with CCodec.
95      * This could be backed by the C2 HAL or the OMX HAL.
96      */
97     static sp<PersistentSurface> CreateCompatibleInputSurface();
98 
99     /// Creates an input surface to the OMX HAL
100     static sp<PersistentSurface> CreateOmxInputSurface();
101 
102     /// handle a create input surface call
103     void createInputSurface();
104     void setInputSurface(const sp<PersistentSurface> &surface);
105     status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
106 
107     void setDeadline(
108             const TimePoint &now,
109             const std::chrono::milliseconds &timeout,
110             const char *name);
111 
112     enum {
113         kWhatAllocate,
114         kWhatConfigure,
115         kWhatStart,
116         kWhatFlush,
117         kWhatStop,
118         kWhatRelease,
119         kWhatCreateInputSurface,
120         kWhatSetInputSurface,
121         kWhatSetParameters,
122 
123         kWhatWorkDone,
124         kWhatWatch,
125     };
126 
127     enum {
128         RELEASED,
129         ALLOCATED,
130         FLUSHED,
131         RUNNING,
132 
133         ALLOCATING,  // RELEASED -> ALLOCATED
134         STARTING,    // ALLOCATED -> RUNNING
135         STOPPING,    // RUNNING -> ALLOCATED
136         FLUSHING,    // RUNNING -> FLUSHED
137         RESUMING,    // FLUSHED -> RUNNING
138         RELEASING,   // {ANY EXCEPT RELEASED} -> RELEASED
139     };
140 
141     struct State {
StateState142         inline State() : mState(RELEASED) {}
getState143         inline int get() const { return mState; }
setState144         inline void set(int newState) { mState = newState; }
145 
146         std::shared_ptr<Codec2Client::Component> comp;
147     private:
148         int mState;
149     };
150 
151     struct NamedTimePoint {
NamedTimePointNamedTimePoint152         NamedTimePoint() : mTimePoint(TimePoint::max()), mName("") {}
153 
setNamedTimePoint154         inline void set(
155                 const TimePoint &timePoint,
156                 const char *name) {
157             mTimePoint = timePoint;
158             mName = name;
159         }
160 
getNamedTimePoint161         inline TimePoint get() const { return mTimePoint; }
getNameNamedTimePoint162         inline const char *getName() const { return mName; }
163     private:
164         TimePoint mTimePoint;
165         const char *mName;
166     };
167 
168     Mutexed<State> mState;
169     std::shared_ptr<CCodecBufferChannel> mChannel;
170 
171     std::shared_ptr<Codec2Client> mClient;
172     std::shared_ptr<Codec2Client::Listener> mClientListener;
173     struct ClientListener;
174 
175     Mutexed<NamedTimePoint> mDeadline;
176     typedef CCodecConfig Config;
177     Mutexed<Config> mConfig;
178     Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
179     std::atomic_flag mSentConfigAfterResume;
180 
181     friend class CCodecCallbackImpl;
182 
183     DISALLOW_EVIL_CONSTRUCTORS(CCodec);
184 };
185 
186 }  // namespace android
187 
188 #endif  // C_CODEC_H_
189