• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // #define LOG_NDEBUG 0
6 #define LOG_TAG "C2VDAAdaptorProxy"
7 
8 #include <C2ArcVideoAcceleratorFactory.h>
9 #include <C2VDAAdaptorProxy.h>
10 
11 #include <arc/MojoProcessSupport.h>
12 #include <arc/MojoThread.h>
13 #include <base/bind.h>
14 #include <base/files/scoped_file.h>
15 #include <mojo/public/cpp/platform/platform_handle.h>
16 #include <mojo/public/cpp/system/platform_handle.h>
17 
18 #include <binder/IServiceManager.h>
19 #include <utils/Log.h>
20 
21 namespace mojo {
22 template <>
23 struct TypeConverter<::arc::VideoFramePlane, android::VideoFramePlane> {
Convertmojo::TypeConverter24     static ::arc::VideoFramePlane Convert(const android::VideoFramePlane& plane) {
25         return ::arc::VideoFramePlane{static_cast<int32_t>(plane.mOffset),
26                                       static_cast<int32_t>(plane.mStride)};
27     }
28 };
29 }  // namespace mojo
30 
31 namespace android {
32 namespace arc {
C2VDAAdaptorProxy()33 C2VDAAdaptorProxy::C2VDAAdaptorProxy()
34       : C2VDAAdaptorProxy(::arc::MojoProcessSupport::getLeakyInstance()) {}
35 
C2VDAAdaptorProxy(::arc::MojoProcessSupport * mojoProcessSupport)36 C2VDAAdaptorProxy::C2VDAAdaptorProxy(::arc::MojoProcessSupport* mojoProcessSupport)
37       : mClient(nullptr),
38         mMojoTaskRunner(mojoProcessSupport->mojo_thread().getTaskRunner()),
39         mBinding(this),
40         mRelay(new ::arc::CancellationRelay()) {}
41 
~C2VDAAdaptorProxy()42 C2VDAAdaptorProxy::~C2VDAAdaptorProxy() {}
43 
onConnectionError(const std::string & pipeName)44 void C2VDAAdaptorProxy::onConnectionError(const std::string& pipeName) {
45     ALOGE("onConnectionError (%s)", pipeName.c_str());
46     mRelay->cancel();
47     NotifyError(::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
48 }
49 
establishChannel()50 bool C2VDAAdaptorProxy::establishChannel() {
51     ALOGV("establishChannel");
52     auto future = ::arc::Future<bool>::make_shared(mRelay);
53     mMojoTaskRunner->PostTask(FROM_HERE,
54                               ::base::Bind(&C2VDAAdaptorProxy::establishChannelOnMojoThread,
55                                          ::base::Unretained(this), future));
56     return future->wait() && future->get();
57 }
58 
establishChannelOnMojoThread(std::shared_ptr<::arc::Future<bool>> future)59 void C2VDAAdaptorProxy::establishChannelOnMojoThread(std::shared_ptr<::arc::Future<bool>> future) {
60     auto& factory = ::android::GetC2ArcVideoAcceleratorFactory();
61 
62     if (!factory.createVideoDecodeAccelerator(mojo::MakeRequest(&mVDAPtr))) {
63         future->set(false);
64         return;
65     }
66     mVDAPtr.set_connection_error_handler(::base::Bind(&C2VDAAdaptorProxy::onConnectionError,
67                                                     ::base::Unretained(this),
68                                                     std::string("mVDAPtr (vda pipe)")));
69     mVDAPtr.QueryVersion(::base::Bind(&C2VDAAdaptorProxy::onVersionReady, ::base::Unretained(this),
70                                     std::move(future)));
71 }
72 
onVersionReady(std::shared_ptr<::arc::Future<bool>> future,uint32_t version)73 void C2VDAAdaptorProxy::onVersionReady(std::shared_ptr<::arc::Future<bool>> future, uint32_t version) {
74     ALOGI("VideoDecodeAccelerator ready (version=%d)", version);
75 
76     future->set(true);
77 }
78 
ProvidePictureBuffers(::arc::mojom::PictureBufferFormatPtr format)79 void C2VDAAdaptorProxy::ProvidePictureBuffers(::arc::mojom::PictureBufferFormatPtr format) {
80     ALOGV("ProvidePictureBuffers");
81     mClient->providePictureBuffers(
82             format->min_num_buffers,
83             media::Size(format->coded_size.width(), format->coded_size.height()));
84 }
PictureReady(::arc::mojom::PicturePtr picture)85 void C2VDAAdaptorProxy::PictureReady(::arc::mojom::PicturePtr picture) {
86     ALOGV("PictureReady");
87     const auto& rect = picture->crop_rect;
88     mClient->pictureReady(picture->picture_buffer_id, picture->bitstream_id,
89                           media::Rect(rect.x(), rect.y(), rect.right(), rect.bottom()));
90 }
91 
convertErrorCode(::arc::mojom::VideoDecodeAccelerator::Result error)92 static VideoDecodeAcceleratorAdaptor::Result convertErrorCode(
93         ::arc::mojom::VideoDecodeAccelerator::Result error) {
94     switch (error) {
95     case ::arc::mojom::VideoDecodeAccelerator::Result::ILLEGAL_STATE:
96         return VideoDecodeAcceleratorAdaptor::ILLEGAL_STATE;
97     case ::arc::mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT:
98         return VideoDecodeAcceleratorAdaptor::INVALID_ARGUMENT;
99     case ::arc::mojom::VideoDecodeAccelerator::Result::UNREADABLE_INPUT:
100         return VideoDecodeAcceleratorAdaptor::UNREADABLE_INPUT;
101     case ::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE:
102         return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
103     case ::arc::mojom::VideoDecodeAccelerator::Result::INSUFFICIENT_RESOURCES:
104         return VideoDecodeAcceleratorAdaptor::INSUFFICIENT_RESOURCES;
105 
106     default:
107         ALOGE("Unknown error code: %d", static_cast<int>(error));
108         return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
109     }
110 }
111 
NotifyError(::arc::mojom::VideoDecodeAccelerator::Result error)112 void C2VDAAdaptorProxy::NotifyError(::arc::mojom::VideoDecodeAccelerator::Result error) {
113     ALOGE("NotifyError %d", static_cast<int>(error));
114     mClient->notifyError(convertErrorCode(error));
115 }
116 
NotifyEndOfBitstreamBuffer(int32_t bitstream_id)117 void C2VDAAdaptorProxy::NotifyEndOfBitstreamBuffer(int32_t bitstream_id) {
118     ALOGV("NotifyEndOfBitstreamBuffer");
119     mClient->notifyEndOfBitstreamBuffer(bitstream_id);
120 }
121 
NotifyResetDone(::arc::mojom::VideoDecodeAccelerator::Result result)122 void C2VDAAdaptorProxy::NotifyResetDone(::arc::mojom::VideoDecodeAccelerator::Result result) {
123     ALOGV("NotifyResetDone");
124     // Always notify reset done to component even if result is not success. On shutdown, MediaCodec
125     // will wait on shutdown complete notification despite any error. If no notification, it will be
126     // hanging until timeout and force release.
127     if (result != ::arc::mojom::VideoDecodeAccelerator::Result::SUCCESS) {
128         ALOGE("Reset is done incorrectly.");
129         NotifyError(result);
130     }
131     mClient->notifyResetDone();
132 }
133 
NotifyFlushDone(::arc::mojom::VideoDecodeAccelerator::Result result)134 void C2VDAAdaptorProxy::NotifyFlushDone(::arc::mojom::VideoDecodeAccelerator::Result result) {
135     ALOGV("NotifyFlushDone");
136     if (result == ::arc::mojom::VideoDecodeAccelerator::Result::CANCELLED) {
137         // Flush is cancelled by a succeeding Reset(). A client expects this behavior.
138         ALOGE("Flush is canceled.");
139         return;
140     }
141     if (result != ::arc::mojom::VideoDecodeAccelerator::Result::SUCCESS) {
142         ALOGE("Flush is done incorrectly.");
143         NotifyError(result);
144         return;
145     }
146     mClient->notifyFlushDone();
147 }
148 
149 //static
GetSupportedProfiles(InputCodec inputCodec)150 media::VideoDecodeAccelerator::SupportedProfiles C2VDAAdaptorProxy::GetSupportedProfiles(
151         InputCodec inputCodec) {
152     media::VideoDecodeAccelerator::SupportedProfiles profiles(1);
153     profiles[0].min_resolution = media::Size(16, 16);
154     profiles[0].max_resolution = media::Size(4096, 4096);
155     switch (inputCodec) {
156     case InputCodec::H264:
157         profiles[0].profile = media::H264PROFILE_MAIN;
158         break;
159     case InputCodec::VP8:
160         profiles[0].profile = media::VP8PROFILE_ANY;
161         break;
162     case InputCodec::VP9:
163         profiles[0].profile = media::VP9PROFILE_PROFILE0;
164         break;
165     default:
166         ALOGE("Unknown input codec: %d", inputCodec);
167         return {};
168     }
169     return profiles;
170 }
171 
initialize(media::VideoCodecProfile profile,bool secureMode,VideoDecodeAcceleratorAdaptor::Client * client)172 VideoDecodeAcceleratorAdaptor::Result C2VDAAdaptorProxy::initialize(
173         media::VideoCodecProfile profile, bool secureMode,
174         VideoDecodeAcceleratorAdaptor::Client* client) {
175     ALOGV("initialize(profile=%d, secureMode=%d)", static_cast<int>(profile),
176           static_cast<int>(secureMode));
177     DCHECK(client);
178     DCHECK(!mClient);
179     mClient = client;
180 
181     if (!establishChannel()) {
182         ALOGE("establishChannel failed");
183         return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
184     }
185 
186     auto future = ::arc::Future<::arc::mojom::VideoDecodeAccelerator::Result>::make_shared(mRelay);
187     mMojoTaskRunner->PostTask(FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::initializeOnMojoThread,
188                                                     ::base::Unretained(this), profile, secureMode,
189                                                     ::arc::FutureCallback(future)));
190 
191     if (!future->wait()) {
192         ALOGE("Connection lost");
193         return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
194     }
195     return static_cast<VideoDecodeAcceleratorAdaptor::Result>(future->get());
196 }
197 
initializeOnMojoThread(const media::VideoCodecProfile profile,const bool secureMode,const::arc::mojom::VideoDecodeAccelerator::InitializeCallback & cb)198 void C2VDAAdaptorProxy::initializeOnMojoThread(
199         const media::VideoCodecProfile profile, const bool secureMode,
200         const ::arc::mojom::VideoDecodeAccelerator::InitializeCallback& cb) {
201     // base::Unretained is safe because we own |mBinding|.
202     mojo::InterfacePtr<::arc::mojom::VideoDecodeClient> client;
203     mBinding.Bind(mojo::MakeRequest(&client));
204     mBinding.set_connection_error_handler(::base::Bind(&C2VDAAdaptorProxy::onConnectionError,
205                                                      ::base::Unretained(this),
206                                                      std::string("mBinding (client pipe)")));
207 
208     ::arc::mojom::VideoDecodeAcceleratorConfigPtr arcConfig =
209             ::arc::mojom::VideoDecodeAcceleratorConfig::New();
210     arcConfig->secure_mode = secureMode;
211     arcConfig->profile = static_cast<::arc::mojom::VideoCodecProfile>(profile);
212     mVDAPtr->Initialize(std::move(arcConfig), std::move(client), cb);
213 }
214 
decode(int32_t bitstreamId,int handleFd,off_t offset,uint32_t size)215 void C2VDAAdaptorProxy::decode(int32_t bitstreamId, int handleFd, off_t offset, uint32_t size) {
216     ALOGV("decode");
217     mMojoTaskRunner->PostTask(
218             FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::decodeOnMojoThread, ::base::Unretained(this),
219                                   bitstreamId, handleFd, offset, size));
220 }
221 
decodeOnMojoThread(int32_t bitstreamId,int handleFd,off_t offset,uint32_t size)222 void C2VDAAdaptorProxy::decodeOnMojoThread(int32_t bitstreamId, int handleFd, off_t offset,
223                                            uint32_t size) {
224     mojo::ScopedHandle wrappedHandle =
225             mojo::WrapPlatformHandle(mojo::PlatformHandle(::base::ScopedFD(handleFd)));
226     if (!wrappedHandle.is_valid()) {
227         ALOGE("failed to wrap handle");
228         NotifyError(::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
229         return;
230     }
231     auto bufferPtr = ::arc::mojom::BitstreamBuffer::New();
232     bufferPtr->bitstream_id = bitstreamId;
233     bufferPtr->handle_fd = std::move(wrappedHandle);
234     bufferPtr->offset = offset;
235     bufferPtr->bytes_used = size;
236     mVDAPtr->Decode(std::move(bufferPtr));
237 }
238 
assignPictureBuffers(uint32_t numOutputBuffers)239 void C2VDAAdaptorProxy::assignPictureBuffers(uint32_t numOutputBuffers) {
240     ALOGV("assignPictureBuffers: %d", numOutputBuffers);
241     mMojoTaskRunner->PostTask(FROM_HERE,
242                               ::base::Bind(&C2VDAAdaptorProxy::assignPictureBuffersOnMojoThread,
243                                          ::base::Unretained(this), numOutputBuffers));
244 }
245 
assignPictureBuffersOnMojoThread(uint32_t numOutputBuffers)246 void C2VDAAdaptorProxy::assignPictureBuffersOnMojoThread(uint32_t numOutputBuffers) {
247     mVDAPtr->AssignPictureBuffers(numOutputBuffers);
248 }
249 
importBufferForPicture(int32_t pictureBufferId,HalPixelFormat format,int handleFd,const std::vector<VideoFramePlane> & planes)250 void C2VDAAdaptorProxy::importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format,
251                                                int handleFd,
252                                                const std::vector<VideoFramePlane>& planes) {
253     ALOGV("importBufferForPicture");
254     mMojoTaskRunner->PostTask(
255             FROM_HERE,
256             ::base::Bind(&C2VDAAdaptorProxy::importBufferForPictureOnMojoThread,
257                        ::base::Unretained(this), pictureBufferId, format, handleFd, planes));
258 }
259 
importBufferForPictureOnMojoThread(int32_t pictureBufferId,HalPixelFormat format,int handleFd,const std::vector<VideoFramePlane> & planes)260 void C2VDAAdaptorProxy::importBufferForPictureOnMojoThread(
261         int32_t pictureBufferId, HalPixelFormat format, int handleFd,
262         const std::vector<VideoFramePlane>& planes) {
263     mojo::ScopedHandle wrappedHandle =
264             mojo::WrapPlatformHandle(mojo::PlatformHandle(::base::ScopedFD(handleFd)));
265     if (!wrappedHandle.is_valid()) {
266         ALOGE("failed to wrap handle");
267         NotifyError(::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
268         return;
269     }
270 
271     mVDAPtr->ImportBufferForPicture(pictureBufferId,
272                                     static_cast<::arc::mojom::HalPixelFormat>(format),
273                                     std::move(wrappedHandle),
274                                     mojo::ConvertTo<std::vector<::arc::VideoFramePlane>>(planes));
275 }
276 
reusePictureBuffer(int32_t pictureBufferId)277 void C2VDAAdaptorProxy::reusePictureBuffer(int32_t pictureBufferId) {
278     ALOGV("reusePictureBuffer: %d", pictureBufferId);
279     mMojoTaskRunner->PostTask(FROM_HERE,
280                               ::base::Bind(&C2VDAAdaptorProxy::reusePictureBufferOnMojoThread,
281                                          ::base::Unretained(this), pictureBufferId));
282 }
283 
reusePictureBufferOnMojoThread(int32_t pictureBufferId)284 void C2VDAAdaptorProxy::reusePictureBufferOnMojoThread(int32_t pictureBufferId) {
285     mVDAPtr->ReusePictureBuffer(pictureBufferId);
286 }
287 
flush()288 void C2VDAAdaptorProxy::flush() {
289     ALOGV("flush");
290     mMojoTaskRunner->PostTask(
291             FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::flushOnMojoThread, ::base::Unretained(this)));
292 }
293 
flushOnMojoThread()294 void C2VDAAdaptorProxy::flushOnMojoThread() {
295     mVDAPtr->Flush(::base::Bind(&C2VDAAdaptorProxy::NotifyFlushDone, ::base::Unretained(this)));
296 }
297 
reset()298 void C2VDAAdaptorProxy::reset() {
299     ALOGV("reset");
300     mMojoTaskRunner->PostTask(
301             FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::resetOnMojoThread, ::base::Unretained(this)));
302 }
303 
resetOnMojoThread()304 void C2VDAAdaptorProxy::resetOnMojoThread() {
305     mVDAPtr->Reset(::base::Bind(&C2VDAAdaptorProxy::NotifyResetDone, ::base::Unretained(this)));
306 }
307 
destroy()308 void C2VDAAdaptorProxy::destroy() {
309     ALOGV("destroy");
310     ::arc::Future<void> future;
311     ::arc::PostTaskAndSetFutureWithResult(
312             mMojoTaskRunner.get(), FROM_HERE,
313             ::base::Bind(&C2VDAAdaptorProxy::closeChannelOnMojoThread, ::base::Unretained(this)),
314             &future);
315     future.get();
316 }
317 
closeChannelOnMojoThread()318 void C2VDAAdaptorProxy::closeChannelOnMojoThread() {
319     if (mBinding.is_bound()) mBinding.Close();
320     mVDAPtr.reset();
321 }
322 
323 }  // namespace arc
324 }  // namespace android
325