1 /* 2 * Copyright (C) 2018 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 CODEC2_HIDL_CLIENT_H_ 18 #define CODEC2_HIDL_CLIENT_H_ 19 20 #include <gui/IGraphicBufferProducer.h> 21 #include <codec2/hidl/1.0/types.h> 22 23 #include <C2PlatformSupport.h> 24 #include <C2Component.h> 25 #include <C2Buffer.h> 26 #include <C2Param.h> 27 #include <C2.h> 28 29 #include <hidl/HidlSupport.h> 30 #include <utils/StrongPointer.h> 31 32 #include <functional> 33 #include <map> 34 #include <memory> 35 #include <mutex> 36 37 /** 38 * This file contains minimal interfaces for the framework to access Codec2.0. 39 * 40 * Codec2Client is the main class that contains the following inner classes: 41 * - Listener 42 * - Configurable 43 * - Interface 44 * - Component 45 * 46 * Classes in Codec2Client, interfaces in Codec2.0, and HIDL interfaces are 47 * related as follows: 48 * - Codec2Client <==> C2ComponentStore <==> IComponentStore 49 * - Codec2Client::Listener <==> C2Component::Listener <==> IComponentListener 50 * - Codec2Client::Configurable <==> [No equivalent] <==> IConfigurable 51 * - Codec2Client::Interface <==> C2ComponentInterface <==> IComponentInterface 52 * - Codec2Client::Component <==> C2Component <==> IComponent 53 * 54 * The entry point is Codec2Client::CreateFromService(), which creates a 55 * Codec2Client object. From Codec2Client, Interface and Component objects can 56 * be created by calling createComponent() and createInterface(). 57 * 58 * createComponent() takes a Listener object, which must be implemented by the 59 * user. 60 * 61 * At the present, createBlockPool() is the only method that yields a 62 * Configurable object. Note, however, that Interface, Component and 63 * Codec2Client are all subclasses of Configurable. 64 */ 65 66 // Forward declaration of Codec2.0 HIDL interfaces 67 namespace hardware { 68 namespace google { 69 namespace media { 70 namespace c2 { 71 namespace V1_0 { 72 struct IConfigurable; 73 struct IComponentInterface; 74 struct IComponent; 75 struct IComponentStore; 76 struct IInputSurface; 77 struct IInputSurfaceConnection; 78 } // namespace V1_0 79 } // namespace c2 80 } // namespace media 81 } // namespace google 82 } // namespace hardware 83 84 namespace android { 85 namespace hardware { 86 namespace media { 87 namespace bufferpool { 88 namespace V1_0 { 89 struct IClientManager; 90 } // namespace V1_0 91 } // namespace bufferpool 92 } // namespace media 93 } // namespace hardware 94 } // namespace android 95 96 // Forward declarations of other classes 97 namespace android { 98 namespace hardware { 99 namespace graphics { 100 namespace bufferqueue { 101 namespace V1_0 { 102 struct IGraphicBufferProducer; 103 } // namespace V1_0 104 } // namespace bufferqueue 105 } // namespace graphics 106 namespace media { 107 namespace omx { 108 namespace V1_0 { 109 struct IGraphicBufferSource; 110 } // namespace V1_0 111 } // namespace omx 112 } // namespace media 113 } // namespace hardware 114 } // namespace android 115 116 namespace android { 117 118 // This class is supposed to be called Codec2Client::Configurable, but forward 119 // declaration of an inner class is not possible. 120 struct Codec2ConfigurableClient { 121 122 typedef ::hardware::google::media::c2::V1_0::IConfigurable Base; 123 124 const C2String& getName() const; 125 126 c2_status_t query( 127 const std::vector<C2Param*>& stackParams, 128 const std::vector<C2Param::Index> &heapParamIndices, 129 c2_blocking_t mayBlock, 130 std::vector<std::unique_ptr<C2Param>>* const heapParams) const; 131 132 c2_status_t config( 133 const std::vector<C2Param*> ¶ms, 134 c2_blocking_t mayBlock, 135 std::vector<std::unique_ptr<C2SettingResult>>* const failures); 136 137 c2_status_t querySupportedParams( 138 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params 139 ) const; 140 141 c2_status_t querySupportedValues( 142 std::vector<C2FieldSupportedValuesQuery>& fields, 143 c2_blocking_t mayBlock) const; 144 145 // base cannot be null. 146 Codec2ConfigurableClient(const sp<Base>& base); 147 148 protected: 149 C2String mName; 150 sp<Base> mBase; 151 152 Base* base() const; 153 154 friend struct Codec2Client; 155 }; 156 157 struct Codec2Client : public Codec2ConfigurableClient { 158 159 typedef ::hardware::google::media::c2::V1_0::IComponentStore Base; 160 161 struct Listener; 162 163 typedef Codec2ConfigurableClient Configurable; 164 165 typedef Configurable Interface; // These two types may diverge in the future. 166 167 struct Component; 168 169 struct InputSurface; 170 171 struct InputSurfaceConnection; 172 173 typedef Codec2Client Store; 174 getInstanceNameCodec2Client175 std::string getInstanceName() const { return mInstanceName; } 176 177 c2_status_t createComponent( 178 const C2String& name, 179 const std::shared_ptr<Listener>& listener, 180 std::shared_ptr<Component>* const component); 181 182 c2_status_t createInterface( 183 const C2String& name, 184 std::shared_ptr<Interface>* const interface); 185 186 c2_status_t createInputSurface( 187 std::shared_ptr<InputSurface>* const inputSurface); 188 189 const std::vector<C2Component::Traits>& listComponents() const; 190 191 c2_status_t copyBuffer( 192 const std::shared_ptr<C2Buffer>& src, 193 const std::shared_ptr<C2Buffer>& dst); 194 195 std::shared_ptr<C2ParamReflector> getParamReflector(); 196 197 static std::shared_ptr<Codec2Client> CreateFromService( 198 const char* instanceName, 199 bool waitForService = true); 200 201 // Try to create a component with a given name from all known 202 // IComponentStore services. 203 static std::shared_ptr<Component> CreateComponentByName( 204 const char* componentName, 205 const std::shared_ptr<Listener>& listener, 206 std::shared_ptr<Codec2Client>* owner = nullptr); 207 208 // Try to create a component interface with a given name from all known 209 // IComponentStore services. 210 static std::shared_ptr<Interface> CreateInterfaceByName( 211 const char* interfaceName, 212 std::shared_ptr<Codec2Client>* owner = nullptr); 213 214 // List traits from all known IComponentStore services. 215 static const std::vector<C2Component::Traits>& ListComponents(); 216 217 // Create an input surface. 218 static std::shared_ptr<InputSurface> CreateInputSurface(); 219 220 // base cannot be null. 221 Codec2Client(const sp<Base>& base, std::string instanceName); 222 223 protected: 224 Base* base() const; 225 226 // Finds the first store where the predicate returns OK, and returns the last 227 // predicate result. Uses key to remember the last store found, and if cached, 228 // it tries that store before trying all stores (one retry). 229 static c2_status_t ForAllStores( 230 const std::string& key, 231 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)> predicate); 232 233 mutable std::mutex mMutex; 234 mutable bool mListed; 235 std::string mInstanceName; 236 mutable std::vector<C2Component::Traits> mTraitsList; 237 mutable std::vector<std::unique_ptr<std::vector<std::string>>> 238 mAliasesBuffer; 239 240 sp<::android::hardware::media::bufferpool::V1_0::IClientManager> 241 mHostPoolManager; 242 }; 243 244 struct Codec2Client::Listener { 245 246 // This is called when the component produces some output. 247 // 248 // numDiscardedInputBuffers is the number of input buffers contained in 249 // workItems that have just become unused. Note that workItems may contain 250 // more input buffers than numDiscardedInputBuffers because buffers that 251 // have been previously reported by onInputBufferDone() are not counted 252 // towards numDiscardedInputBuffers, but may still show up in workItems. 253 virtual void onWorkDone( 254 const std::weak_ptr<Component>& comp, 255 std::list<std::unique_ptr<C2Work>>& workItems, 256 size_t numDiscardedInputBuffers) = 0; 257 258 // This is called when the component goes into a tripped state. 259 virtual void onTripped( 260 const std::weak_ptr<Component>& comp, 261 const std::vector<std::shared_ptr<C2SettingResult>>& settingResults 262 ) = 0; 263 264 // This is called when the component encounters an error. 265 virtual void onError( 266 const std::weak_ptr<Component>& comp, 267 uint32_t errorCode) = 0; 268 269 // This is called when the process that hosts the component shuts down 270 // unexpectedly. 271 virtual void onDeath( 272 const std::weak_ptr<Component>& comp) = 0; 273 274 // This is called when an input buffer is no longer in use by the codec. 275 // Input buffers that have been returned by onWorkDone() or flush() will not 276 // trigger a call to this function. 277 virtual void onInputBufferDone( 278 const std::shared_ptr<C2Buffer>& buffer) = 0; 279 280 // This structure is used for transporting onFramesRendered() event to the 281 // client in the case where the output buffers are obtained from a 282 // bufferqueue. 283 struct RenderedFrame { 284 // The id of the bufferqueue. 285 uint64_t bufferQueueId; 286 // The slot of the buffer inside the bufferqueue. 287 int32_t slotId; 288 // The timestamp. 289 int64_t timestampNs; 290 RenderedFrameListener::RenderedFrame291 RenderedFrame(uint64_t bufferQueueId, int32_t slotId, 292 int64_t timestampNs) 293 : bufferQueueId(bufferQueueId), 294 slotId(slotId), 295 timestampNs(timestampNs) {} 296 RenderedFrame(const RenderedFrame&) = default; 297 }; 298 299 // This is called when the component becomes aware of frames being rendered. 300 virtual void onFramesRendered( 301 const std::vector<RenderedFrame>& renderedFrames) = 0; 302 303 virtual ~Listener(); 304 305 }; 306 307 struct Codec2Client::Component : public Codec2Client::Configurable { 308 309 typedef ::hardware::google::media::c2::V1_0::IComponent Base; 310 311 c2_status_t createBlockPool( 312 C2Allocator::id_t id, 313 C2BlockPool::local_id_t* blockPoolId, 314 std::shared_ptr<Configurable>* configurable); 315 316 c2_status_t destroyBlockPool( 317 C2BlockPool::local_id_t localId); 318 319 c2_status_t queue( 320 std::list<std::unique_ptr<C2Work>>* const items); 321 322 c2_status_t flush( 323 C2Component::flush_mode_t mode, 324 std::list<std::unique_ptr<C2Work>>* const flushedWork); 325 326 c2_status_t drain(C2Component::drain_mode_t mode); 327 328 c2_status_t start(); 329 330 c2_status_t stop(); 331 332 c2_status_t reset(); 333 334 c2_status_t release(); 335 336 typedef ::android:: 337 IGraphicBufferProducer IGraphicBufferProducer; 338 typedef IGraphicBufferProducer:: 339 QueueBufferInput QueueBufferInput; 340 typedef IGraphicBufferProducer:: 341 QueueBufferOutput QueueBufferOutput; 342 343 typedef ::android::hardware::graphics::bufferqueue::V1_0:: 344 IGraphicBufferProducer HGraphicBufferProducer; 345 typedef ::android::hardware::media::omx::V1_0:: 346 IGraphicBufferSource HGraphicBufferSource; 347 348 // Set the output surface to be used with a blockpool previously created by 349 // createBlockPool(). 350 c2_status_t setOutputSurface( 351 C2BlockPool::local_id_t blockPoolId, 352 const sp<IGraphicBufferProducer>& surface, 353 uint32_t generation); 354 355 // Extract a slot number from of the block, then call 356 // IGraphicBufferProducer::queueBuffer(). 357 // 358 // If the output surface has not been set, NO_INIT will be returned. 359 // 360 // If the block does not come from a bufferqueue-based blockpool, 361 // attachBuffer() will be called, followed by queueBuffer(). 362 // 363 // If the block has a bqId that does not match the id of the output surface, 364 // DEAD_OBJECT will be returned. 365 // 366 // If the call to queueBuffer() is successful but the block cannot be 367 // associated to the output surface for automatic cancellation upon 368 // destruction, UNKNOWN_ERROR will be returned. 369 // 370 // Otherwise, the return value from queueBuffer() will be returned. 371 status_t queueToOutputSurface( 372 const C2ConstGraphicBlock& block, 373 const QueueBufferInput& input, 374 QueueBufferOutput* output); 375 376 c2_status_t connectToOmxInputSurface( 377 const sp<HGraphicBufferProducer>& producer, 378 const sp<HGraphicBufferSource>& source); 379 380 c2_status_t disconnectFromInputSurface(); 381 382 // base cannot be null. 383 Component(const sp<Base>& base); 384 385 ~Component(); 386 387 protected: 388 Base* base() const; 389 390 // Mutex for mInputBuffers and mInputBufferCount. 391 mutable std::mutex mInputBuffersMutex; 392 393 // Map: frameIndex -> vector of bufferIndices 394 // 395 // mInputBuffers[frameIndex][bufferIndex] may be null if the buffer in that 396 // slot has been freed. 397 mutable std::map<uint64_t, std::vector<std::shared_ptr<C2Buffer>>> 398 mInputBuffers; 399 400 // Map: frameIndex -> number of bufferIndices that have not been freed 401 // 402 // mInputBufferCount[frameIndex] keeps track of the number of non-null 403 // elements in mInputBuffers[frameIndex]. When mInputBufferCount[frameIndex] 404 // decreases to 0, frameIndex can be removed from both mInputBuffers and 405 // mInputBufferCount. 406 mutable std::map<uint64_t, size_t> mInputBufferCount; 407 408 ::hardware::google::media::c2::V1_0::utils::DefaultBufferPoolSender 409 mBufferPoolSender; 410 411 std::mutex mOutputBufferQueueMutex; 412 sp<IGraphicBufferProducer> mOutputIgbp; 413 uint64_t mOutputBqId; 414 uint32_t mOutputGeneration; 415 416 static c2_status_t setDeathListener( 417 const std::shared_ptr<Component>& component, 418 const std::shared_ptr<Listener>& listener); 419 sp<::android::hardware::hidl_death_recipient> mDeathRecipient; 420 421 friend struct Codec2Client; 422 423 struct HidlListener; 424 // Return the number of input buffers that should be discarded. 425 size_t handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> &workItems); 426 // Remove an input buffer from mInputBuffers and return it. 427 std::shared_ptr<C2Buffer> freeInputBuffer(uint64_t frameIndex, size_t bufferIndex); 428 429 }; 430 431 struct Codec2Client::InputSurface { 432 public: 433 typedef ::hardware::google::media::c2::V1_0::IInputSurface Base; 434 435 typedef ::hardware::google::media::c2::V1_0::IInputSurfaceConnection 436 ConnectionBase; 437 438 typedef Codec2Client::InputSurfaceConnection Connection; 439 440 typedef ::android::IGraphicBufferProducer IGraphicBufferProducer; 441 442 c2_status_t connectToComponent( 443 const std::shared_ptr<Component>& component, 444 std::shared_ptr<Connection>* connection); 445 446 std::shared_ptr<Configurable> getConfigurable() const; 447 448 const sp<IGraphicBufferProducer>& getGraphicBufferProducer() const; 449 450 // Return the underlying IInputSurface. 451 const sp<Base>& getHalInterface() const; 452 453 // base cannot be null. 454 InputSurface(const sp<Base>& base); 455 456 protected: 457 Base* base() const; 458 sp<Base> mBase; 459 460 sp<IGraphicBufferProducer> mGraphicBufferProducer; 461 462 friend struct Codec2Client; 463 friend struct Component; 464 }; 465 466 struct Codec2Client::InputSurfaceConnection { 467 468 typedef ::hardware::google::media::c2::V1_0::IInputSurfaceConnection Base; 469 470 c2_status_t disconnect(); 471 472 // base cannot be null. 473 InputSurfaceConnection(const sp<Base>& base); 474 475 protected: 476 Base* base() const; 477 sp<Base> mBase; 478 479 friend struct Codec2Client::InputSurface; 480 }; 481 482 } // namespace android 483 484 #endif // CODEC2_HIDL_CLIENT_H_ 485 486