1 /*
2  * Copyright 2024, 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 //#define LOG_NDEBUG 0
17 #define LOG_TAG "WAidlGraphicBufferSource"
18 #include <android/hardware_buffer_aidl.h>
19 #include <private/android/AHardwareBufferHelpers.h>
20 #include <utils/Log.h>
21 
22 #include <aidl/android/media/BnAidlBufferSource.h>
23 #include <aidl/android/media/IAidlNode.h>
24 
25 #include <media/stagefright/aidlpersistentsurface/AidlGraphicBufferSource.h>
26 #include <media/stagefright/aidlpersistentsurface/C2NodeDef.h>
27 #include <media/stagefright/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.h>
28 #include <media/stagefright/aidlpersistentsurface/wrapper/Conversion.h>
29 
30 namespace android::media {
31 using ::android::binder::unique_fd;
32 using ::aidl::android::hardware::graphics::common::PixelFormat;
33 using ::aidl::android::hardware::graphics::common::Dataspace;
34 using ::aidl::android::media::AidlColorAspects;
35 using ::aidl::android::media::IAidlNode;
36 using ::aidl::android::media::BnAidlBufferSource;
37 
38 // Conversion
39 using ::android::media::aidl_conversion::fromAidlStatus;
40 using ::android::media::aidl_conversion::toAidlStatus;
41 using ::android::media::aidl_conversion::compactFromAidlColorAspects;
42 using ::android::media::aidl_conversion::rawFromAidlDataspace;
43 
44 struct WAidlGraphicBufferSource::WAidlNodeWrapper : public IAidlNodeWrapper {
45     std::shared_ptr<IAidlNode> mNode;
46 
WAidlNodeWrapperandroid::media::WAidlGraphicBufferSource::WAidlNodeWrapper47     WAidlNodeWrapper(const std::shared_ptr<IAidlNode> &node): mNode(node) {
48     }
49 
submitBufferandroid::media::WAidlGraphicBufferSource::WAidlNodeWrapper50     virtual status_t submitBuffer(
51             int32_t bufferId, uint32_t flags,
52             const sp<GraphicBuffer> &buffer,
53             int64_t timestamp, int fenceFd) override {
54         ::ndk::ScopedFileDescriptor fence(fenceFd);
55         if (buffer.get()) {
56             ::aidl::android::hardware::HardwareBuffer hBuffer;
57             AHardwareBuffer *ahwBuffer = AHardwareBuffer_from_GraphicBuffer(buffer.get());
58             AHardwareBuffer_acquire(ahwBuffer);
59             hBuffer.reset(ahwBuffer);
60 
61             return fromAidlStatus(mNode->submitBuffer(
62                     bufferId,
63                     std::move(hBuffer),
64                     flags,
65                     timestamp,
66                     fence));
67         }
68 
69         return fromAidlStatus(mNode->submitBuffer(
70               bufferId,
71               {},
72               flags,
73               timestamp,
74               fence));
75     }
76 
dispatchDataSpaceChangedandroid::media::WAidlGraphicBufferSource::WAidlNodeWrapper77     virtual void dispatchDataSpaceChanged(
78             int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
79         ::ndk::ScopedAStatus err = mNode->onDataSpaceChanged(
80                 dataSpace, aspects, pixelFormat);
81         status_t status = fromAidlStatus(err);
82         if (status != NO_ERROR) {
83             ALOGE("WAidlNodeWrapper failed to change dataspace (%d): "
84                     "dataSpace = %ld, aspects = %ld, pixelFormat = %ld",
85                     static_cast<int>(status),
86                     static_cast<long>(dataSpace),
87                     static_cast<long>(aspects),
88                     static_cast<long>(pixelFormat));
89         }
90     }
91 };
92 
93 class WAidlGraphicBufferSource::WAidlBufferSource : public BnAidlBufferSource {
94     sp<AidlGraphicBufferSource> mSource;
95 
96 public:
WAidlBufferSource(const sp<AidlGraphicBufferSource> & source)97     WAidlBufferSource(const sp<AidlGraphicBufferSource> &source): mSource(source) {
98     }
99 
onStart()100     ::ndk::ScopedAStatus onStart() override {
101         mSource->onStart();
102         return ::ndk::ScopedAStatus::ok();
103     }
104 
onStop()105     ::ndk::ScopedAStatus onStop() override {
106         mSource->onStop();
107         return ::ndk::ScopedAStatus::ok();
108     }
109 
onRelease()110     ::ndk::ScopedAStatus onRelease() override {
111         mSource->onRelease();
112         return ::ndk::ScopedAStatus::ok();
113     }
114 
onInputBufferAdded(int32_t bufferId)115     ::ndk::ScopedAStatus onInputBufferAdded(int32_t bufferId) override {
116         mSource->onInputBufferAdded(bufferId);
117         return ::ndk::ScopedAStatus::ok();
118     }
119 
onInputBufferEmptied(int32_t bufferId,const::ndk::ScopedFileDescriptor & fence)120     ::ndk::ScopedAStatus onInputBufferEmptied(
121             int32_t bufferId, const ::ndk::ScopedFileDescriptor& fence) override {
122         mSource->onInputBufferEmptied(bufferId, ::dup(fence.get()));
123         return ::ndk::ScopedAStatus::ok();
124     }
125 };
126 
127 // WAidlGraphicBufferSource
WAidlGraphicBufferSource(sp<AidlGraphicBufferSource> const & base)128 WAidlGraphicBufferSource::WAidlGraphicBufferSource(
129         sp<AidlGraphicBufferSource> const& base) :
130     mBase(base),
131     mBufferSource(::ndk::SharedRefBase::make<WAidlBufferSource>(base)) {
132 }
133 
configure(const std::shared_ptr<IAidlNode> & node,Dataspace dataspace)134 ::ndk::ScopedAStatus WAidlGraphicBufferSource::configure(
135         const std::shared_ptr<IAidlNode>& node, Dataspace dataspace) {
136     if (node == NULL) {
137         return toAidlStatus(BAD_VALUE);
138     }
139 
140     // Do setInputSurface() first, the node will try to enable metadata
141     // mode on input, and does necessary error checking. If this fails,
142     // we can't use this input surface on the node.
143     ::ndk::ScopedAStatus err = node->setInputSurface(mBufferSource);
144     status_t fnStatus = fromAidlStatus(err);
145     if (fnStatus != NO_ERROR) {
146         ALOGE("Unable to set input surface: %d", fnStatus);
147         return err;
148     }
149 
150     // use consumer usage bits queried from encoder, but always add
151     // HW_VIDEO_ENCODER for backward compatibility.
152     int64_t  consumerUsage;
153     fnStatus = OK;
154     err = node->getConsumerUsage(&consumerUsage);
155     fnStatus = fromAidlStatus(err);
156     if (fnStatus != NO_ERROR) {
157         if (fnStatus == FAILED_TRANSACTION) {
158             return err;
159         }
160         consumerUsage = 0;
161     }
162 
163     IAidlNode::InputBufferParams rDef ;
164     err = node->getInputBufferParams(&rDef);
165     fnStatus = fromAidlStatus(err);
166     if (fnStatus != NO_ERROR) {
167         ALOGE("Failed to get port definition: %d", fnStatus);
168         return toAidlStatus(fnStatus);
169     }
170 
171     return toAidlStatus(mBase->configure(
172             new WAidlNodeWrapper(node),
173             rawFromAidlDataspace(dataspace),
174             rDef.bufferCountActual,
175             rDef.frameWidth,
176             rDef.frameHeight,
177             static_cast<uint64_t>(consumerUsage)));
178 }
179 
setSuspend(bool suspend,int64_t timeUs)180 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setSuspend(
181         bool suspend, int64_t timeUs) {
182     return toAidlStatus(mBase->setSuspend(suspend, timeUs));
183 }
184 
setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs)185 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setRepeatPreviousFrameDelayUs(
186         int64_t repeatAfterUs) {
187     return toAidlStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
188 }
189 
setMaxFps(float maxFps)190 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setMaxFps(float maxFps) {
191     return toAidlStatus(mBase->setMaxFps(maxFps));
192 }
193 
setTimeLapseConfig(double fps,double captureFps)194 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setTimeLapseConfig(
195         double fps, double captureFps) {
196     return toAidlStatus(mBase->setTimeLapseConfig(fps, captureFps));
197 }
198 
setStartTimeUs(int64_t startTimeUs)199 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
200     return toAidlStatus(mBase->setStartTimeUs(startTimeUs));
201 }
202 
setStopTimeUs(int64_t stopTimeUs)203 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
204     return toAidlStatus(mBase->setStopTimeUs(stopTimeUs));
205 }
206 
getStopTimeOffsetUs(int64_t * _aidl_return)207 ::ndk::ScopedAStatus WAidlGraphicBufferSource::getStopTimeOffsetUs(int64_t* _aidl_return) {
208     status_t status = mBase->getStopTimeOffsetUs(_aidl_return);
209     return toAidlStatus(status);
210 }
211 
setColorAspects(const AidlColorAspects & aspects)212 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setColorAspects(
213         const AidlColorAspects& aspects) {
214     return toAidlStatus(mBase->setColorAspects(compactFromAidlColorAspects(aspects)));
215 }
216 
setTimeOffsetUs(int64_t timeOffsetUs)217 ::ndk::ScopedAStatus WAidlGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
218     return toAidlStatus(mBase->setTimeOffsetUs(timeOffsetUs));
219 }
220 
signalEndOfInputStream()221 ::ndk::ScopedAStatus WAidlGraphicBufferSource::signalEndOfInputStream() {
222     return toAidlStatus(mBase->signalEndOfInputStream());
223 }
224 
225 
226 }  // namespace android::media
227