| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1 | /* | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 2 |  * Copyright 2018 The Android Open Source Project | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 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 | //#define LOG_NDEBUG 0 | 
 | 18 | #define LOG_TAG "Codec2Client" | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 19 | #include <android-base/logging.h> | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 20 |  | 
 | 21 | #include <codec2/hidl/client.h> | 
 | 22 |  | 
 | 23 | #include <deque> | 
 | 24 | #include <limits> | 
 | 25 | #include <map> | 
 | 26 | #include <type_traits> | 
 | 27 | #include <vector> | 
 | 28 |  | 
 | 29 | #include <android-base/properties.h> | 
 | 30 | #include <bufferpool/ClientManager.h> | 
 | 31 | #include <cutils/native_handle.h> | 
 | 32 | #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h> | 
 | 33 | #include <hidl/HidlSupport.h> | 
 | 34 | #include <media/stagefright/bqhelper/WGraphicBufferProducer.h> | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 35 |  | 
| Sungtak Lee | d331808 | 2018-09-07 15:52:43 -0700 | [diff] [blame] | 36 | #include <android/hardware/media/bufferpool/2.0/IClientManager.h> | 
| Pawin Vongmasa | d0f0e14 | 2018-11-15 03:36:28 -0800 | [diff] [blame] | 37 | #include <android/hardware/media/c2/1.0/IComponent.h> | 
 | 38 | #include <android/hardware/media/c2/1.0/IComponentInterface.h> | 
 | 39 | #include <android/hardware/media/c2/1.0/IComponentListener.h> | 
 | 40 | #include <android/hardware/media/c2/1.0/IComponentStore.h> | 
 | 41 | #include <android/hardware/media/c2/1.0/IConfigurable.h> | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 42 |  | 
 | 43 | #include <C2Debug.h> | 
 | 44 | #include <C2BufferPriv.h> | 
 | 45 | #include <C2PlatformSupport.h> | 
 | 46 |  | 
 | 47 | namespace android { | 
 | 48 |  | 
 | 49 | using ::android::hardware::hidl_vec; | 
 | 50 | using ::android::hardware::hidl_string; | 
 | 51 | using ::android::hardware::Return; | 
 | 52 | using ::android::hardware::Void; | 
 | 53 | using ::android::TWGraphicBufferProducer; | 
 | 54 |  | 
| Pawin Vongmasa | d0f0e14 | 2018-11-15 03:36:28 -0800 | [diff] [blame] | 55 | using namespace ::android::hardware::media::c2::V1_0; | 
 | 56 | using namespace ::android::hardware::media::c2::V1_0::utils; | 
| Sungtak Lee | d331808 | 2018-09-07 15:52:43 -0700 | [diff] [blame] | 57 | using namespace ::android::hardware::media::bufferpool::V2_0; | 
 | 58 | using namespace ::android::hardware::media::bufferpool::V2_0::implementation; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 59 |  | 
 | 60 | namespace /* unnamed */ { | 
 | 61 |  | 
 | 62 | // c2_status_t value that corresponds to hwbinder transaction failure. | 
 | 63 | constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED; | 
 | 64 |  | 
 | 65 | // List of known IComponentStore services in the decreasing order of preference. | 
 | 66 | constexpr const char* kClientNames[] = { | 
 | 67 |         "default", | 
 | 68 |         "software", | 
 | 69 |     }; | 
 | 70 |  | 
 | 71 | // Number of known IComponentStore services. | 
 | 72 | constexpr size_t kNumClients = std::extent<decltype(kClientNames)>::value; | 
 | 73 |  | 
 | 74 | typedef std::array<std::shared_ptr<Codec2Client>, kNumClients> ClientList; | 
 | 75 |  | 
 | 76 | // Convenience methods to obtain known clients. | 
 | 77 | std::shared_ptr<Codec2Client> getClient(size_t index) { | 
| Pawin Vongmasa | e55ed3f | 2018-11-28 03:39:57 -0800 | [diff] [blame] | 78 |     uint32_t serviceMask = ::android::base::GetUintProperty( | 
 | 79 |             "debug.media.codec2", uint32_t(0)); | 
 | 80 |     return Codec2Client::CreateFromService( | 
 | 81 |             kClientNames[index], | 
 | 82 |             (serviceMask & (1 << index)) != 0); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 83 | } | 
 | 84 |  | 
 | 85 | ClientList getClientList() { | 
 | 86 |     ClientList list; | 
 | 87 |     for (size_t i = 0; i < list.size(); ++i) { | 
 | 88 |         list[i] = getClient(i); | 
 | 89 |     } | 
 | 90 |     return list; | 
 | 91 | } | 
 | 92 |  | 
 | 93 | } // unnamed | 
 | 94 |  | 
 | 95 | // Codec2ConfigurableClient | 
 | 96 |  | 
 | 97 | const C2String& Codec2ConfigurableClient::getName() const { | 
 | 98 |     return mName; | 
 | 99 | } | 
 | 100 |  | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 101 | Codec2ConfigurableClient::Codec2ConfigurableClient( | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 102 |         const sp<IConfigurable>& base) | 
 | 103 |       : mBase{base}, | 
 | 104 |         mName{[base]() -> C2String { | 
 | 105 |                 C2String outName; | 
 | 106 |                 Return<void> transStatus = base->getName( | 
 | 107 |                         [&outName](const hidl_string& name) { | 
 | 108 |                             outName = name.c_str(); | 
 | 109 |                         }); | 
 | 110 |                 return transStatus.isOk() ? outName : ""; | 
 | 111 |             }()} { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 112 | } | 
 | 113 |  | 
 | 114 | c2_status_t Codec2ConfigurableClient::query( | 
 | 115 |         const std::vector<C2Param*> &stackParams, | 
 | 116 |         const std::vector<C2Param::Index> &heapParamIndices, | 
 | 117 |         c2_blocking_t mayBlock, | 
 | 118 |         std::vector<std::unique_ptr<C2Param>>* const heapParams) const { | 
 | 119 |     hidl_vec<ParamIndex> indices( | 
 | 120 |             stackParams.size() + heapParamIndices.size()); | 
 | 121 |     size_t numIndices = 0; | 
 | 122 |     for (C2Param* const& stackParam : stackParams) { | 
 | 123 |         if (!stackParam) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 124 |             LOG(WARNING) << "query -- null stack param encountered."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 125 |             continue; | 
 | 126 |         } | 
 | 127 |         indices[numIndices++] = static_cast<ParamIndex>(stackParam->index()); | 
 | 128 |     } | 
 | 129 |     size_t numStackIndices = numIndices; | 
 | 130 |     for (const C2Param::Index& index : heapParamIndices) { | 
 | 131 |         indices[numIndices++] = | 
 | 132 |                 static_cast<ParamIndex>(static_cast<uint32_t>(index)); | 
 | 133 |     } | 
 | 134 |     indices.resize(numIndices); | 
 | 135 |     if (heapParams) { | 
 | 136 |         heapParams->reserve(heapParams->size() + numIndices); | 
 | 137 |     } | 
 | 138 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 139 |     Return<void> transStatus = mBase->query( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 140 |             indices, | 
 | 141 |             mayBlock == C2_MAY_BLOCK, | 
 | 142 |             [&status, &numStackIndices, &stackParams, heapParams]( | 
 | 143 |                     Status s, const Params& p) { | 
 | 144 |                 status = static_cast<c2_status_t>(s); | 
 | 145 |                 if (status != C2_OK && status != C2_BAD_INDEX) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 146 |                     LOG(DEBUG) << "query -- call failed: " | 
 | 147 |                                << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 148 |                     return; | 
 | 149 |                 } | 
 | 150 |                 std::vector<C2Param*> paramPointers; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 151 |                 if (!parseParamsBlob(¶mPointers, p)) { | 
 | 152 |                     LOG(ERROR) << "query -- error while parsing params."; | 
 | 153 |                     status = C2_CORRUPTED; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 154 |                     return; | 
 | 155 |                 } | 
 | 156 |                 size_t i = 0; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 157 |                 for (auto it = paramPointers.begin(); | 
 | 158 |                         it != paramPointers.end(); ) { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 159 |                     C2Param* paramPointer = *it; | 
 | 160 |                     if (numStackIndices > 0) { | 
 | 161 |                         --numStackIndices; | 
 | 162 |                         if (!paramPointer) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 163 |                             LOG(WARNING) << "query -- null stack param."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 164 |                             ++it; | 
 | 165 |                             continue; | 
 | 166 |                         } | 
 | 167 |                         for (; i < stackParams.size() && !stackParams[i]; ) { | 
 | 168 |                             ++i; | 
 | 169 |                         } | 
 | 170 |                         if (i >= stackParams.size()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 171 |                             LOG(ERROR) << "query -- unexpected error."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 172 |                             status = C2_CORRUPTED; | 
 | 173 |                             return; | 
 | 174 |                         } | 
 | 175 |                         if (stackParams[i]->index() != paramPointer->index()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 176 |                             LOG(WARNING) << "query -- param skipped: " | 
 | 177 |                                             "index = " | 
 | 178 |                                          << stackParams[i]->index() << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 179 |                             stackParams[i++]->invalidate(); | 
 | 180 |                             continue; | 
 | 181 |                         } | 
 | 182 |                         if (!stackParams[i++]->updateFrom(*paramPointer)) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 183 |                             LOG(WARNING) << "query -- param update failed: " | 
 | 184 |                                             "index = " | 
 | 185 |                                          << paramPointer->index() << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 186 |                         } | 
 | 187 |                     } else { | 
 | 188 |                         if (!paramPointer) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 189 |                             LOG(WARNING) << "query -- null heap param."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 190 |                             ++it; | 
 | 191 |                             continue; | 
 | 192 |                         } | 
 | 193 |                         if (!heapParams) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 194 |                             LOG(WARNING) << "query -- " | 
 | 195 |                                             "unexpected extra stack param."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 196 |                         } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 197 |                             heapParams->emplace_back( | 
 | 198 |                                     C2Param::Copy(*paramPointer)); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 199 |                         } | 
 | 200 |                     } | 
 | 201 |                     ++it; | 
 | 202 |                 } | 
 | 203 |             }); | 
 | 204 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 205 |         LOG(ERROR) << "query -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 206 |         return C2_TRANSACTION_FAILED; | 
 | 207 |     } | 
 | 208 |     return status; | 
 | 209 | } | 
 | 210 |  | 
 | 211 | c2_status_t Codec2ConfigurableClient::config( | 
 | 212 |         const std::vector<C2Param*> ¶ms, | 
 | 213 |         c2_blocking_t mayBlock, | 
 | 214 |         std::vector<std::unique_ptr<C2SettingResult>>* const failures) { | 
 | 215 |     Params hidlParams; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 216 |     if (!createParamsBlob(&hidlParams, params)) { | 
 | 217 |         LOG(ERROR) << "config -- bad input."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 218 |         return C2_TRANSACTION_FAILED; | 
 | 219 |     } | 
 | 220 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 221 |     Return<void> transStatus = mBase->config( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 222 |             hidlParams, | 
 | 223 |             mayBlock == C2_MAY_BLOCK, | 
 | 224 |             [&status, ¶ms, failures]( | 
 | 225 |                     Status s, | 
 | 226 |                     const hidl_vec<SettingResult> f, | 
 | 227 |                     const Params& o) { | 
 | 228 |                 status = static_cast<c2_status_t>(s); | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 229 |                 if (status != C2_OK && status != C2_BAD_INDEX) { | 
 | 230 |                     LOG(DEBUG) << "config -- call failed: " | 
 | 231 |                                << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 232 |                 } | 
 | 233 |                 size_t i = failures->size(); | 
 | 234 |                 failures->resize(i + f.size()); | 
 | 235 |                 for (const SettingResult& sf : f) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 236 |                     if (!objcpy(&(*failures)[i++], sf)) { | 
 | 237 |                         LOG(ERROR) << "config -- " | 
 | 238 |                                    << "invalid SettingResult returned."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 239 |                         return; | 
 | 240 |                     } | 
 | 241 |                 } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 242 |                 if (!updateParamsFromBlob(params, o)) { | 
 | 243 |                     LOG(ERROR) << "config -- " | 
 | 244 |                                << "failed to parse returned params."; | 
 | 245 |                     status = C2_CORRUPTED; | 
 | 246 |                 } | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 247 |             }); | 
 | 248 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 249 |         LOG(ERROR) << "config -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 250 |         return C2_TRANSACTION_FAILED; | 
 | 251 |     } | 
 | 252 |     return status; | 
 | 253 | } | 
 | 254 |  | 
 | 255 | c2_status_t Codec2ConfigurableClient::querySupportedParams( | 
 | 256 |         std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const { | 
 | 257 |     // TODO: Cache and query properly! | 
 | 258 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 259 |     Return<void> transStatus = mBase->querySupportedParams( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 260 |             std::numeric_limits<uint32_t>::min(), | 
 | 261 |             std::numeric_limits<uint32_t>::max(), | 
 | 262 |             [&status, params]( | 
 | 263 |                     Status s, | 
 | 264 |                     const hidl_vec<ParamDescriptor>& p) { | 
 | 265 |                 status = static_cast<c2_status_t>(s); | 
 | 266 |                 if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 267 |                     LOG(DEBUG) << "querySupportedParams -- call failed: " | 
 | 268 |                                << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 269 |                     return; | 
 | 270 |                 } | 
 | 271 |                 size_t i = params->size(); | 
 | 272 |                 params->resize(i + p.size()); | 
 | 273 |                 for (const ParamDescriptor& sp : p) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 274 |                     if (!objcpy(&(*params)[i++], sp)) { | 
 | 275 |                         LOG(ERROR) << "querySupportedParams -- " | 
 | 276 |                                    << "invalid returned ParamDescriptor."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 277 |                         return; | 
 | 278 |                     } | 
 | 279 |                 } | 
 | 280 |             }); | 
 | 281 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 282 |         LOG(ERROR) << "querySupportedParams -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 283 |         return C2_TRANSACTION_FAILED; | 
 | 284 |     } | 
 | 285 |     return status; | 
 | 286 | } | 
 | 287 |  | 
 | 288 | c2_status_t Codec2ConfigurableClient::querySupportedValues( | 
 | 289 |         std::vector<C2FieldSupportedValuesQuery>& fields, | 
 | 290 |         c2_blocking_t mayBlock) const { | 
 | 291 |     hidl_vec<FieldSupportedValuesQuery> inFields(fields.size()); | 
 | 292 |     for (size_t i = 0; i < fields.size(); ++i) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 293 |         if (!objcpy(&inFields[i], fields[i])) { | 
 | 294 |             LOG(ERROR) << "querySupportedValues -- bad input"; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 295 |             return C2_TRANSACTION_FAILED; | 
 | 296 |         } | 
 | 297 |     } | 
 | 298 |  | 
 | 299 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 300 |     Return<void> transStatus = mBase->querySupportedValues( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 301 |             inFields, | 
 | 302 |             mayBlock == C2_MAY_BLOCK, | 
 | 303 |             [&status, &inFields, &fields]( | 
 | 304 |                     Status s, | 
 | 305 |                     const hidl_vec<FieldSupportedValuesQueryResult>& r) { | 
 | 306 |                 status = static_cast<c2_status_t>(s); | 
 | 307 |                 if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 308 |                     LOG(DEBUG) << "querySupportedValues -- call failed: " | 
 | 309 |                                << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 310 |                     return; | 
 | 311 |                 } | 
 | 312 |                 if (r.size() != fields.size()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 313 |                     LOG(ERROR) << "querySupportedValues -- " | 
 | 314 |                                   "input and output lists " | 
 | 315 |                                   "have different sizes."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 316 |                     status = C2_CORRUPTED; | 
 | 317 |                     return; | 
 | 318 |                 } | 
 | 319 |                 for (size_t i = 0; i < fields.size(); ++i) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 320 |                     if (!objcpy(&fields[i], inFields[i], r[i])) { | 
 | 321 |                         LOG(ERROR) << "querySupportedValues -- " | 
 | 322 |                                       "invalid returned value."; | 
 | 323 |                         status = C2_CORRUPTED; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 324 |                         return; | 
 | 325 |                     } | 
 | 326 |                 } | 
 | 327 |             }); | 
 | 328 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 329 |         LOG(ERROR) << "querySupportedValues -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 330 |         return C2_TRANSACTION_FAILED; | 
 | 331 |     } | 
 | 332 |     return status; | 
 | 333 | } | 
 | 334 |  | 
 | 335 | // Codec2Client::Component::HidlListener | 
 | 336 | struct Codec2Client::Component::HidlListener : public IComponentListener { | 
 | 337 |     std::weak_ptr<Component> component; | 
 | 338 |     std::weak_ptr<Listener> base; | 
 | 339 |  | 
 | 340 |     virtual Return<void> onWorkDone(const WorkBundle& workBundle) override { | 
 | 341 |         std::list<std::unique_ptr<C2Work>> workItems; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 342 |         if (!objcpy(&workItems, workBundle)) { | 
 | 343 |             LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 344 |             return Void(); | 
 | 345 |         } | 
 | 346 |         // release input buffers potentially held by the component from queue | 
 | 347 |         size_t numDiscardedInputBuffers = 0; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 348 |         std::shared_ptr<Codec2Client::Component> strongComponent = | 
 | 349 |                 component.lock(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 350 |         if (strongComponent) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 351 |             numDiscardedInputBuffers = | 
 | 352 |                     strongComponent->handleOnWorkDone(workItems); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 353 |         } | 
 | 354 |         if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 355 |             listener->onWorkDone(component, | 
 | 356 |                                  workItems, | 
 | 357 |                                  numDiscardedInputBuffers); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 358 |         } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 359 |             LOG(DEBUG) << "onWorkDone -- listener died."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 360 |         } | 
 | 361 |         return Void(); | 
 | 362 |     } | 
 | 363 |  | 
 | 364 |     virtual Return<void> onTripped( | 
 | 365 |             const hidl_vec<SettingResult>& settingResults) override { | 
 | 366 |         std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults( | 
 | 367 |                 settingResults.size()); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 368 |         for (size_t i = 0; i < settingResults.size(); ++i) { | 
 | 369 |             std::unique_ptr<C2SettingResult> c2SettingResult; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 370 |             if (!objcpy(&c2SettingResult, settingResults[i])) { | 
 | 371 |                 LOG(DEBUG) << "onTripped -- received corrupted SettingResult."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 372 |                 return Void(); | 
 | 373 |             } | 
 | 374 |             c2SettingResults[i] = std::move(c2SettingResult); | 
 | 375 |         } | 
 | 376 |         if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) { | 
 | 377 |             listener->onTripped(component, c2SettingResults); | 
 | 378 |         } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 379 |             LOG(DEBUG) << "onTripped -- listener died."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 380 |         } | 
 | 381 |         return Void(); | 
 | 382 |     } | 
 | 383 |  | 
 | 384 |     virtual Return<void> onError(Status s, uint32_t errorCode) override { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 385 |         LOG(DEBUG) << "onError --" | 
 | 386 |                    << " status = " << s | 
 | 387 |                    << ", errorCode = " << errorCode | 
 | 388 |                    << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 389 |         if (std::shared_ptr<Listener> listener = base.lock()) { | 
 | 390 |             listener->onError(component, s == Status::OK ? | 
 | 391 |                     errorCode : static_cast<c2_status_t>(s)); | 
 | 392 |         } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 393 |             LOG(DEBUG) << "onError -- listener died."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 394 |         } | 
 | 395 |         return Void(); | 
 | 396 |     } | 
 | 397 |  | 
 | 398 |     virtual Return<void> onFramesRendered( | 
 | 399 |             const hidl_vec<RenderedFrame>& renderedFrames) override { | 
 | 400 |         std::shared_ptr<Listener> listener = base.lock(); | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 401 |         if (!listener) { | 
 | 402 |             LOG(DEBUG) << "onFramesRendered -- listener died."; | 
 | 403 |             return Void(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 404 |         } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 405 |         for (const RenderedFrame& renderedFrame : renderedFrames) { | 
 | 406 |             listener->onFrameRendered( | 
 | 407 |                     renderedFrame.bufferQueueId, | 
 | 408 |                     renderedFrame.slotId, | 
 | 409 |                     renderedFrame.timestampNs); | 
 | 410 |         } | 
 | 411 |         return Void(); | 
 | 412 |     } | 
 | 413 |  | 
 | 414 |     virtual Return<void> onInputBuffersReleased( | 
 | 415 |             const hidl_vec<InputBuffer>& inputBuffers) override { | 
 | 416 |         std::shared_ptr<Listener> listener = base.lock(); | 
 | 417 |         if (!listener) { | 
 | 418 |             LOG(DEBUG) << "onInputBuffersReleased -- listener died."; | 
 | 419 |             return Void(); | 
 | 420 |         } | 
 | 421 |         std::shared_ptr<Codec2Client::Component> strongComponent = | 
 | 422 |                 component.lock(); | 
 | 423 |         if (!strongComponent) { | 
 | 424 |             LOG(DEBUG) << "onInputBuffersReleased -- component died."; | 
 | 425 |             return Void(); | 
 | 426 |         } | 
 | 427 |         for (const InputBuffer& inputBuffer : inputBuffers) { | 
 | 428 |             std::shared_ptr<C2Buffer> buffer = | 
 | 429 |                     strongComponent->freeInputBuffer( | 
 | 430 |                         inputBuffer.frameIndex, | 
 | 431 |                         inputBuffer.arrayIndex); | 
 | 432 |             LOG(VERBOSE) << "onInputBuffersReleased --" | 
 | 433 |                             " received death notification of" | 
 | 434 |                             " input buffer:" | 
 | 435 |                             " frameIndex = " << inputBuffer.frameIndex | 
 | 436 |                          << ", bufferIndex = " << inputBuffer.arrayIndex | 
 | 437 |                          << "."; | 
 | 438 |             if (buffer) { | 
 | 439 |                 listener->onInputBufferDone(buffer); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 440 |             } | 
 | 441 |         } | 
 | 442 |         return Void(); | 
 | 443 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 444 |  | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 445 | }; | 
 | 446 |  | 
 | 447 | // Codec2Client | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 448 | Codec2Client::Codec2Client(const sp<IComponentStore>& base, | 
 | 449 |                            std::string serviceName) | 
 | 450 |       : Configurable{ | 
 | 451 |             [base]() -> sp<IConfigurable> { | 
 | 452 |                 Return<sp<IConfigurable>> transResult = | 
 | 453 |                         base->getConfigurable(); | 
 | 454 |                 return transResult.isOk() ? | 
 | 455 |                         static_cast<sp<IConfigurable>>(transResult) : | 
 | 456 |                         nullptr; | 
 | 457 |             }() | 
 | 458 |         }, | 
 | 459 |         mBase{base}, | 
 | 460 |         mListed{false}, | 
 | 461 |         mServiceName{serviceName} { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 462 |     Return<sp<IClientManager>> transResult = base->getPoolClientManager(); | 
 | 463 |     if (!transResult.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 464 |         LOG(ERROR) << "getPoolClientManager -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 465 |     } else { | 
 | 466 |         mHostPoolManager = static_cast<sp<IClientManager>>(transResult); | 
 | 467 |     } | 
 | 468 | } | 
 | 469 |  | 
 | 470 | c2_status_t Codec2Client::createComponent( | 
 | 471 |         const C2String& name, | 
 | 472 |         const std::shared_ptr<Codec2Client::Listener>& listener, | 
 | 473 |         std::shared_ptr<Codec2Client::Component>* const component) { | 
 | 474 |  | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 475 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 476 |     sp<Component::HidlListener> hidlListener = new Component::HidlListener{}; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 477 |     hidlListener->base = listener; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 478 |     Return<void> transStatus = mBase->createComponent( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 479 |             name, | 
 | 480 |             hidlListener, | 
 | 481 |             ClientManager::getInstance(), | 
 | 482 |             [&status, component, hidlListener]( | 
 | 483 |                     Status s, | 
 | 484 |                     const sp<IComponent>& c) { | 
 | 485 |                 status = static_cast<c2_status_t>(s); | 
 | 486 |                 if (status != C2_OK) { | 
 | 487 |                     return; | 
 | 488 |                 } | 
 | 489 |                 *component = std::make_shared<Codec2Client::Component>(c); | 
 | 490 |                 hidlListener->component = *component; | 
 | 491 |             }); | 
 | 492 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 493 |         LOG(ERROR) << "createComponent(" << name.c_str() | 
 | 494 |                    << ") -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 495 |         return C2_TRANSACTION_FAILED; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 496 |     } else if (status != C2_OK) { | 
 | 497 |         LOG(ERROR) << "createComponent(" << name.c_str() | 
 | 498 |                    << ") -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 499 |         return status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 500 |     } else if (!*component) { | 
 | 501 |         LOG(ERROR) << "createComponent(" << name.c_str() | 
 | 502 |                    << ") -- null component."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 503 |         return C2_CORRUPTED; | 
 | 504 |     } | 
 | 505 |  | 
 | 506 |     status = (*component)->setDeathListener(*component, listener); | 
 | 507 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 508 |         LOG(ERROR) << "createComponent(" << name.c_str() | 
 | 509 |                    << ") -- failed to set up death listener: " | 
 | 510 |                    << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 511 |     } | 
 | 512 |  | 
 | 513 |     (*component)->mBufferPoolSender.setReceiver(mHostPoolManager); | 
 | 514 |     return status; | 
 | 515 | } | 
 | 516 |  | 
 | 517 | c2_status_t Codec2Client::createInterface( | 
 | 518 |         const C2String& name, | 
 | 519 |         std::shared_ptr<Codec2Client::Interface>* const interface) { | 
 | 520 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 521 |     Return<void> transStatus = mBase->createInterface( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 522 |             name, | 
 | 523 |             [&status, interface]( | 
 | 524 |                     Status s, | 
 | 525 |                     const sp<IComponentInterface>& i) { | 
 | 526 |                 status = static_cast<c2_status_t>(s); | 
 | 527 |                 if (status != C2_OK) { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 528 |                     return; | 
 | 529 |                 } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 530 |                 *interface = std::make_shared<Interface>(i); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 531 |             }); | 
 | 532 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 533 |         LOG(ERROR) << "createInterface(" << name.c_str() | 
 | 534 |                    << ") -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 535 |         return C2_TRANSACTION_FAILED; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 536 |     } else if (status != C2_OK) { | 
 | 537 |         LOG(ERROR) << "createComponent(" << name.c_str() | 
 | 538 |                    << ") -- call failed: " << status << "."; | 
 | 539 |         return status; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 540 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 541 |  | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 542 |     return status; | 
 | 543 | } | 
 | 544 |  | 
 | 545 | c2_status_t Codec2Client::createInputSurface( | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 546 |         std::shared_ptr<InputSurface>* const inputSurface) { | 
 | 547 |     c2_status_t status; | 
 | 548 |     Return<void> transStatus = mBase->createInputSurface( | 
 | 549 |             [&status, inputSurface]( | 
 | 550 |                     Status s, | 
 | 551 |                     const sp<IInputSurface>& i) { | 
 | 552 |                 status = static_cast<c2_status_t>(s); | 
 | 553 |                 if (status != C2_OK) { | 
 | 554 |                     return; | 
 | 555 |                 } | 
 | 556 |                 *inputSurface = std::make_shared<InputSurface>(i); | 
 | 557 |             }); | 
 | 558 |     if (!transStatus.isOk()) { | 
 | 559 |         LOG(ERROR) << "createInputSurface -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 560 |         return C2_TRANSACTION_FAILED; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 561 |     } else if (status != C2_OK) { | 
 | 562 |         LOG(DEBUG) << "createInputSurface -- call failed: " | 
 | 563 |                    << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 564 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 565 |     return status; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 566 | } | 
 | 567 |  | 
 | 568 | const std::vector<C2Component::Traits>& Codec2Client::listComponents() const { | 
 | 569 |     std::lock_guard<std::mutex> lock(mMutex); | 
 | 570 |     if (mListed) { | 
 | 571 |         return mTraitsList; | 
 | 572 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 573 |     Return<void> transStatus = mBase->listComponents( | 
 | 574 |             [this](Status s, | 
 | 575 |                    const hidl_vec<IComponentStore::ComponentTraits>& t) { | 
 | 576 |                 if (s != Status::OK) { | 
 | 577 |                     LOG(DEBUG) << "listComponents -- call failed: " | 
 | 578 |                                << static_cast<c2_status_t>(s) << "."; | 
 | 579 |                     return; | 
 | 580 |                 } | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 581 |                 mTraitsList.resize(t.size()); | 
 | 582 |                 mAliasesBuffer.resize(t.size()); | 
 | 583 |                 for (size_t i = 0; i < t.size(); ++i) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 584 |                     if (!objcpy(&mTraitsList[i], &mAliasesBuffer[i], t[i])) { | 
 | 585 |                         LOG(ERROR) << "listComponents -- corrupted output."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 586 |                         return; | 
 | 587 |                     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 588 |                     mTraitsList[i].owner = mServiceName; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 589 |                 } | 
 | 590 |             }); | 
 | 591 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 592 |         LOG(ERROR) << "listComponents -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 593 |     } | 
 | 594 |     mListed = true; | 
 | 595 |     return mTraitsList; | 
 | 596 | } | 
 | 597 |  | 
 | 598 | c2_status_t Codec2Client::copyBuffer( | 
 | 599 |         const std::shared_ptr<C2Buffer>& src, | 
 | 600 |         const std::shared_ptr<C2Buffer>& dst) { | 
 | 601 |     // TODO: Implement? | 
 | 602 |     (void)src; | 
 | 603 |     (void)dst; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 604 |     LOG(ERROR) << "copyBuffer not implemented"; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 605 |     return C2_OMITTED; | 
 | 606 | } | 
 | 607 |  | 
 | 608 | std::shared_ptr<C2ParamReflector> | 
 | 609 |         Codec2Client::getParamReflector() { | 
 | 610 |     // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it | 
 | 611 |     // should reflect the HAL API. | 
 | 612 |     struct SimpleParamReflector : public C2ParamReflector { | 
 | 613 |         virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const { | 
 | 614 |             hidl_vec<ParamIndex> indices(1); | 
 | 615 |             indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex()); | 
 | 616 |             std::unique_ptr<C2StructDescriptor> descriptor; | 
 | 617 |             Return<void> transStatus = mBase->getStructDescriptors( | 
 | 618 |                     indices, | 
 | 619 |                     [&descriptor]( | 
 | 620 |                             Status s, | 
 | 621 |                             const hidl_vec<StructDescriptor>& sd) { | 
 | 622 |                         c2_status_t status = static_cast<c2_status_t>(s); | 
 | 623 |                         if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 624 |                             LOG(DEBUG) << "SimpleParamReflector -- " | 
 | 625 |                                           "getStructDescriptors() failed: " | 
 | 626 |                                        << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 627 |                             descriptor.reset(); | 
 | 628 |                             return; | 
 | 629 |                         } | 
 | 630 |                         if (sd.size() != 1) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 631 |                             LOG(DEBUG) << "SimpleParamReflector -- " | 
 | 632 |                                           "getStructDescriptors() " | 
 | 633 |                                           "returned vector of size " | 
 | 634 |                                        << sd.size() << ". " | 
 | 635 |                                           "It should be 1."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 636 |                             descriptor.reset(); | 
 | 637 |                             return; | 
 | 638 |                         } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 639 |                         if (!objcpy(&descriptor, sd[0])) { | 
 | 640 |                             LOG(DEBUG) << "SimpleParamReflector -- " | 
 | 641 |                                           "getStructDescriptors() returned " | 
 | 642 |                                           "corrupted data."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 643 |                             descriptor.reset(); | 
 | 644 |                             return; | 
 | 645 |                         } | 
 | 646 |                     }); | 
 | 647 |             return descriptor; | 
 | 648 |         } | 
 | 649 |  | 
 | 650 |         SimpleParamReflector(sp<Base> base) | 
 | 651 |             : mBase(base) { } | 
 | 652 |  | 
 | 653 |         sp<Base> mBase; | 
 | 654 |     }; | 
 | 655 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 656 |     return std::make_shared<SimpleParamReflector>(mBase); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 657 | }; | 
 | 658 |  | 
 | 659 | std::shared_ptr<Codec2Client> Codec2Client::CreateFromService( | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 660 |         const char* serviceName, bool waitForService) { | 
 | 661 |     if (!serviceName) { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 662 |         return nullptr; | 
 | 663 |     } | 
 | 664 |     sp<Base> baseStore = waitForService ? | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 665 |             Base::getService(serviceName) : | 
 | 666 |             Base::tryGetService(serviceName); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 667 |     if (!baseStore) { | 
 | 668 |         if (waitForService) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 669 |             LOG(WARNING) << "Codec2.0 service \"" << serviceName << "\"" | 
 | 670 |                             " inaccessible. Check the device manifest."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 671 |         } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 672 |             LOG(DEBUG) << "Codec2.0 service \"" << serviceName << "\"" | 
 | 673 |                           " unavailable at the moment. " | 
 | 674 |                           " Wait or check the device manifest."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 675 |         } | 
 | 676 |         return nullptr; | 
 | 677 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 678 |     return std::make_shared<Codec2Client>(baseStore, serviceName); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 679 | } | 
 | 680 |  | 
 | 681 | c2_status_t Codec2Client::ForAllStores( | 
 | 682 |         const std::string &key, | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 683 |         std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)> | 
 | 684 |             predicate) { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 685 |     c2_status_t status = C2_NO_INIT;  // no IComponentStores present | 
 | 686 |  | 
 | 687 |     // Cache the mapping key -> index of Codec2Client in getClient(). | 
 | 688 |     static std::mutex key2IndexMutex; | 
 | 689 |     static std::map<std::string, size_t> key2Index; | 
 | 690 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 691 |     // By default try all stores. However, try the last known client first. If | 
 | 692 |     // the last known client fails, retry once. We do this by pushing the last | 
 | 693 |     // known client in front of the list of all clients. | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 694 |     std::deque<size_t> indices; | 
 | 695 |     for (size_t index = kNumClients; index > 0; ) { | 
 | 696 |         indices.push_front(--index); | 
 | 697 |     } | 
 | 698 |  | 
 | 699 |     bool wasMapped = false; | 
 | 700 |     std::unique_lock<std::mutex> lock(key2IndexMutex); | 
 | 701 |     auto it = key2Index.find(key); | 
 | 702 |     if (it != key2Index.end()) { | 
 | 703 |         indices.push_front(it->second); | 
 | 704 |         wasMapped = true; | 
 | 705 |     } | 
 | 706 |     lock.unlock(); | 
 | 707 |  | 
 | 708 |     for (size_t index : indices) { | 
 | 709 |         std::shared_ptr<Codec2Client> client = getClient(index); | 
 | 710 |         if (client) { | 
 | 711 |             status = predicate(client); | 
 | 712 |             if (status == C2_OK) { | 
 | 713 |                 lock.lock(); | 
 | 714 |                 key2Index[key] = index; // update last known client index | 
 | 715 |                 return status; | 
 | 716 |             } | 
 | 717 |         } | 
 | 718 |         if (wasMapped) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 719 |             LOG(INFO) << "Could not find \"" << key << "\"" | 
 | 720 |                          " in the last instance. Retrying..."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 721 |             wasMapped = false; | 
 | 722 |         } | 
 | 723 |     } | 
 | 724 |     return status;  // return the last status from a valid client | 
 | 725 | } | 
 | 726 |  | 
 | 727 | std::shared_ptr<Codec2Client::Component> | 
 | 728 |         Codec2Client::CreateComponentByName( | 
 | 729 |         const char* componentName, | 
 | 730 |         const std::shared_ptr<Listener>& listener, | 
 | 731 |         std::shared_ptr<Codec2Client>* owner) { | 
 | 732 |     std::shared_ptr<Component> component; | 
 | 733 |     c2_status_t status = ForAllStores( | 
 | 734 |             componentName, | 
 | 735 |             [owner, &component, componentName, &listener]( | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 736 |                     const std::shared_ptr<Codec2Client> &client) | 
 | 737 |                         -> c2_status_t { | 
 | 738 |                 c2_status_t status = client->createComponent(componentName, | 
 | 739 |                                                              listener, | 
 | 740 |                                                              &component); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 741 |                 if (status == C2_OK) { | 
 | 742 |                     if (owner) { | 
 | 743 |                         *owner = client; | 
 | 744 |                     } | 
 | 745 |                 } else if (status != C2_NOT_FOUND) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 746 |                     LOG(DEBUG) << "IComponentStore(" | 
 | 747 |                                    << client->getServiceName() | 
 | 748 |                                << ")::createComponent(\"" << componentName | 
 | 749 |                                << "\") returned status = " | 
 | 750 |                                << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 751 |                 } | 
 | 752 |                 return status; | 
 | 753 |             }); | 
 | 754 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 755 |         LOG(DEBUG) << "Could not create component \"" << componentName << "\". " | 
 | 756 |                       "Status = " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 757 |     } | 
 | 758 |     return component; | 
 | 759 | } | 
 | 760 |  | 
 | 761 | std::shared_ptr<Codec2Client::Interface> | 
 | 762 |         Codec2Client::CreateInterfaceByName( | 
 | 763 |         const char* interfaceName, | 
 | 764 |         std::shared_ptr<Codec2Client>* owner) { | 
 | 765 |     std::shared_ptr<Interface> interface; | 
 | 766 |     c2_status_t status = ForAllStores( | 
 | 767 |             interfaceName, | 
 | 768 |             [owner, &interface, interfaceName]( | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 769 |                     const std::shared_ptr<Codec2Client> &client) | 
 | 770 |                         -> c2_status_t { | 
 | 771 |                 c2_status_t status = client->createInterface(interfaceName, | 
 | 772 |                                                              &interface); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 773 |                 if (status == C2_OK) { | 
 | 774 |                     if (owner) { | 
 | 775 |                         *owner = client; | 
 | 776 |                     } | 
 | 777 |                 } else if (status != C2_NOT_FOUND) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 778 |                     LOG(DEBUG) << "IComponentStore(" | 
 | 779 |                                    << client->getServiceName() | 
 | 780 |                                << ")::createInterface(\"" << interfaceName | 
 | 781 |                                << "\") returned status = " | 
 | 782 |                                << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 783 |                 } | 
 | 784 |                 return status; | 
 | 785 |             }); | 
 | 786 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 787 |         LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". " | 
 | 788 |                       "Status = " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 789 |     } | 
 | 790 |     return interface; | 
 | 791 | } | 
 | 792 |  | 
 | 793 | std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() { | 
 | 794 |     uint32_t serviceMask = ::android::base::GetUintProperty( | 
 | 795 |             "debug.stagefright.c2inputsurface", uint32_t(0)); | 
 | 796 |     for (size_t i = 0; i < kNumClients; ++i) { | 
 | 797 |         if ((1 << i) & serviceMask) { | 
 | 798 |             std::shared_ptr<Codec2Client> client = getClient(i); | 
 | 799 |             std::shared_ptr<Codec2Client::InputSurface> inputSurface; | 
 | 800 |             if (client && | 
 | 801 |                     client->createInputSurface(&inputSurface) == C2_OK && | 
 | 802 |                     inputSurface) { | 
 | 803 |                 return inputSurface; | 
 | 804 |             } | 
 | 805 |         } | 
 | 806 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 807 |     LOG(INFO) << "Could not create an input surface " | 
 | 808 |                  "from any Codec2.0 services."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 809 |     return nullptr; | 
 | 810 | } | 
 | 811 |  | 
 | 812 | const std::vector<C2Component::Traits>& Codec2Client::ListComponents() { | 
 | 813 |     static std::vector<C2Component::Traits> traitsList = [](){ | 
 | 814 |         std::vector<C2Component::Traits> list; | 
 | 815 |         size_t listSize = 0; | 
 | 816 |         ClientList clientList = getClientList(); | 
 | 817 |         for (const std::shared_ptr<Codec2Client>& client : clientList) { | 
 | 818 |             if (!client) { | 
 | 819 |                 continue; | 
 | 820 |             } | 
 | 821 |             listSize += client->listComponents().size(); | 
 | 822 |         } | 
 | 823 |         list.reserve(listSize); | 
 | 824 |         for (const std::shared_ptr<Codec2Client>& client : clientList) { | 
 | 825 |             if (!client) { | 
 | 826 |                 continue; | 
 | 827 |             } | 
 | 828 |             list.insert( | 
 | 829 |                     list.end(), | 
 | 830 |                     client->listComponents().begin(), | 
 | 831 |                     client->listComponents().end()); | 
 | 832 |         } | 
 | 833 |         return list; | 
 | 834 |     }(); | 
 | 835 |  | 
 | 836 |     return traitsList; | 
 | 837 | } | 
 | 838 |  | 
 | 839 | // Codec2Client::Listener | 
 | 840 |  | 
 | 841 | Codec2Client::Listener::~Listener() { | 
 | 842 | } | 
 | 843 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 844 | // Codec2Client::Interface | 
 | 845 | Codec2Client::Interface::Interface(const sp<Base>& base) | 
 | 846 |       : Configurable{ | 
 | 847 |             [base]() -> sp<IConfigurable> { | 
 | 848 |                 Return<sp<IConfigurable>> transResult = | 
 | 849 |                         base->getConfigurable(); | 
 | 850 |                 return transResult.isOk() ? | 
 | 851 |                         static_cast<sp<IConfigurable>>(transResult) : | 
 | 852 |                         nullptr; | 
 | 853 |             }() | 
 | 854 |         }, | 
 | 855 |         mBase{base} { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 856 | } | 
 | 857 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 858 | // Codec2Client::Component | 
 | 859 | Codec2Client::Component::Component(const sp<Base>& base) | 
 | 860 |       : Configurable{ | 
 | 861 |             [base]() -> sp<IConfigurable> { | 
 | 862 |                 Return<sp<IComponentInterface>> transResult1 = | 
 | 863 |                         base->getInterface(); | 
 | 864 |                 if (!transResult1.isOk()) { | 
 | 865 |                     return nullptr; | 
 | 866 |                 } | 
 | 867 |                 Return<sp<IConfigurable>> transResult2 = | 
 | 868 |                         static_cast<sp<IComponentInterface>>(transResult1)-> | 
 | 869 |                         getConfigurable(); | 
 | 870 |                 return transResult2.isOk() ? | 
 | 871 |                         static_cast<sp<IConfigurable>>(transResult2) : | 
 | 872 |                         nullptr; | 
 | 873 |             }() | 
 | 874 |         }, | 
 | 875 |         mBase{base}, | 
 | 876 |         mBufferPoolSender{nullptr} { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 877 | } | 
 | 878 |  | 
 | 879 | Codec2Client::Component::~Component() { | 
 | 880 | } | 
 | 881 |  | 
 | 882 | c2_status_t Codec2Client::Component::createBlockPool( | 
 | 883 |         C2Allocator::id_t id, | 
 | 884 |         C2BlockPool::local_id_t* blockPoolId, | 
 | 885 |         std::shared_ptr<Codec2Client::Configurable>* configurable) { | 
 | 886 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 887 |     Return<void> transStatus = mBase->createBlockPool( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 888 |             static_cast<uint32_t>(id), | 
 | 889 |             [&status, blockPoolId, configurable]( | 
 | 890 |                     Status s, | 
 | 891 |                     uint64_t pId, | 
 | 892 |                     const sp<IConfigurable>& c) { | 
 | 893 |                 status = static_cast<c2_status_t>(s); | 
 | 894 |                 configurable->reset(); | 
 | 895 |                 if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 896 |                     LOG(DEBUG) << "createBlockPool -- call failed: " | 
 | 897 |                                << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 898 |                     return; | 
 | 899 |                 } | 
 | 900 |                 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId); | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 901 |                 *configurable = std::make_shared<Configurable>(c); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 902 |             }); | 
 | 903 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 904 |         LOG(ERROR) << "createBlockPool -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 905 |         return C2_TRANSACTION_FAILED; | 
 | 906 |     } | 
 | 907 |     return status; | 
 | 908 | } | 
 | 909 |  | 
 | 910 | c2_status_t Codec2Client::Component::destroyBlockPool( | 
 | 911 |         C2BlockPool::local_id_t localId) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 912 |     Return<Status> transResult = mBase->destroyBlockPool( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 913 |             static_cast<uint64_t>(localId)); | 
 | 914 |     if (!transResult.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 915 |         LOG(ERROR) << "destroyBlockPool -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 916 |         return C2_TRANSACTION_FAILED; | 
 | 917 |     } | 
 | 918 |     return static_cast<c2_status_t>(static_cast<Status>(transResult)); | 
 | 919 | } | 
 | 920 |  | 
 | 921 | size_t Codec2Client::Component::handleOnWorkDone( | 
 | 922 |         const std::list<std::unique_ptr<C2Work>> &workItems) { | 
 | 923 |     // Input buffers' lifetime management | 
 | 924 |     std::vector<uint64_t> inputDone; | 
 | 925 |     for (const std::unique_ptr<C2Work> &work : workItems) { | 
 | 926 |         if (work) { | 
 | 927 |             if (work->worklets.empty() | 
 | 928 |                     || !work->worklets.back() | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 929 |                     || (work->worklets.back()->output.flags & | 
 | 930 |                         C2FrameData::FLAG_INCOMPLETE) == 0) { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 931 |                 // input is complete | 
 | 932 |                 inputDone.emplace_back(work->input.ordinal.frameIndex.peeku()); | 
 | 933 |             } | 
 | 934 |         } | 
 | 935 |     } | 
 | 936 |  | 
 | 937 |     size_t numDiscardedInputBuffers = 0; | 
 | 938 |     { | 
 | 939 |         std::lock_guard<std::mutex> lock(mInputBuffersMutex); | 
 | 940 |         for (uint64_t inputIndex : inputDone) { | 
 | 941 |             auto it = mInputBuffers.find(inputIndex); | 
 | 942 |             if (it == mInputBuffers.end()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 943 |                 LOG(VERBOSE) << "onWorkDone -- returned consumed/unknown " | 
 | 944 |                                 "input frame: index = " | 
 | 945 |                              << inputIndex << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 946 |             } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 947 |                 LOG(VERBOSE) << "onWorkDone -- processed input frame: " | 
 | 948 |                              << inputIndex | 
 | 949 |                              << " (containing " << it->second.size() | 
 | 950 |                                  << " buffers)."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 951 |                 mInputBuffers.erase(it); | 
 | 952 |                 mInputBufferCount.erase(inputIndex); | 
 | 953 |                 ++numDiscardedInputBuffers; | 
 | 954 |             } | 
 | 955 |         } | 
 | 956 |     } | 
 | 957 |  | 
 | 958 |     // Output bufferqueue-based blocks' lifetime management | 
 | 959 |     mOutputBufferQueueMutex.lock(); | 
 | 960 |     sp<IGraphicBufferProducer> igbp = mOutputIgbp; | 
 | 961 |     uint64_t bqId = mOutputBqId; | 
 | 962 |     uint32_t generation = mOutputGeneration; | 
 | 963 |     mOutputBufferQueueMutex.unlock(); | 
 | 964 |  | 
 | 965 |     if (igbp) { | 
 | 966 |         holdBufferQueueBlocks(workItems, igbp, bqId, generation); | 
 | 967 |     } | 
 | 968 |     return numDiscardedInputBuffers; | 
 | 969 | } | 
 | 970 |  | 
 | 971 | std::shared_ptr<C2Buffer> Codec2Client::Component::freeInputBuffer( | 
 | 972 |         uint64_t frameIndex, | 
 | 973 |         size_t bufferIndex) { | 
 | 974 |     std::shared_ptr<C2Buffer> buffer; | 
 | 975 |     std::lock_guard<std::mutex> lock(mInputBuffersMutex); | 
 | 976 |     auto it = mInputBuffers.find(frameIndex); | 
 | 977 |     if (it == mInputBuffers.end()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 978 |         LOG(INFO) << "freeInputBuffer -- Unrecognized input frame index " | 
 | 979 |                   << frameIndex << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 980 |         return nullptr; | 
 | 981 |     } | 
 | 982 |     if (bufferIndex >= it->second.size()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 983 |         LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex | 
 | 984 |                   << " is not valid in input with frame index " << frameIndex | 
 | 985 |                   << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 986 |         return nullptr; | 
 | 987 |     } | 
 | 988 |     buffer = it->second[bufferIndex]; | 
 | 989 |     if (!buffer) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 990 |         LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex | 
 | 991 |                   << " in input with frame index " << frameIndex | 
 | 992 |                   << " has already been freed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 993 |         return nullptr; | 
 | 994 |     } | 
 | 995 |     it->second[bufferIndex] = nullptr; | 
 | 996 |     if (--mInputBufferCount[frameIndex] == 0) { | 
 | 997 |         mInputBuffers.erase(it); | 
 | 998 |         mInputBufferCount.erase(frameIndex); | 
 | 999 |     } | 
 | 1000 |     return buffer; | 
 | 1001 | } | 
 | 1002 |  | 
 | 1003 | c2_status_t Codec2Client::Component::queue( | 
 | 1004 |         std::list<std::unique_ptr<C2Work>>* const items) { | 
 | 1005 |     // remember input buffers queued to hold reference to them | 
 | 1006 |     { | 
 | 1007 |         std::lock_guard<std::mutex> lock(mInputBuffersMutex); | 
 | 1008 |         for (const std::unique_ptr<C2Work> &work : *items) { | 
 | 1009 |             if (!work) { | 
 | 1010 |                 continue; | 
 | 1011 |             } | 
 | 1012 |             if (work->input.buffers.size() == 0) { | 
 | 1013 |                 continue; | 
 | 1014 |             } | 
 | 1015 |  | 
 | 1016 |             uint64_t inputIndex = work->input.ordinal.frameIndex.peeku(); | 
 | 1017 |             auto res = mInputBuffers.emplace(inputIndex, work->input.buffers); | 
 | 1018 |             if (!res.second) { | 
 | 1019 |                 // TODO: append? - for now we are replacing | 
 | 1020 |                 res.first->second = work->input.buffers; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1021 |                 LOG(INFO) << "queue -- duplicate input frame index: " | 
 | 1022 |                           << inputIndex | 
 | 1023 |                           << ". Discarding the old input frame..."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1024 |             } | 
 | 1025 |             mInputBufferCount[inputIndex] = work->input.buffers.size(); | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1026 |             LOG(VERBOSE) << "queue -- queuing input frame: " | 
 | 1027 |                          << "index = " << inputIndex | 
 | 1028 |                          << ", number of buffers = " | 
 | 1029 |                              << work->input.buffers.size() | 
 | 1030 |                          << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1031 |         } | 
 | 1032 |     } | 
 | 1033 |  | 
 | 1034 |     WorkBundle workBundle; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1035 |     if (!objcpy(&workBundle, *items, &mBufferPoolSender)) { | 
 | 1036 |         LOG(ERROR) << "queue -- bad input."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1037 |         return C2_TRANSACTION_FAILED; | 
 | 1038 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1039 |     Return<Status> transStatus = mBase->queue(workBundle); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1040 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1041 |         LOG(ERROR) << "queue -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1042 |         return C2_TRANSACTION_FAILED; | 
 | 1043 |     } | 
 | 1044 |     c2_status_t status = | 
 | 1045 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1046 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1047 |         LOG(DEBUG) << "queue -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1048 |     } | 
 | 1049 |     return status; | 
 | 1050 | } | 
 | 1051 |  | 
 | 1052 | c2_status_t Codec2Client::Component::flush( | 
 | 1053 |         C2Component::flush_mode_t mode, | 
 | 1054 |         std::list<std::unique_ptr<C2Work>>* const flushedWork) { | 
 | 1055 |     (void)mode; // Flush mode isn't supported in HIDL yet. | 
 | 1056 |     c2_status_t status; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1057 |     Return<void> transStatus = mBase->flush( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1058 |             [&status, flushedWork]( | 
 | 1059 |                     Status s, const WorkBundle& wb) { | 
 | 1060 |                 status = static_cast<c2_status_t>(s); | 
 | 1061 |                 if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1062 |                     LOG(DEBUG) << "flush -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1063 |                     return; | 
 | 1064 |                 } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1065 |                 if (!objcpy(flushedWork, wb)) { | 
 | 1066 |                     status = C2_CORRUPTED; | 
 | 1067 |                 } else { | 
 | 1068 |                     status = C2_OK; | 
 | 1069 |                 } | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1070 |             }); | 
 | 1071 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1072 |         LOG(ERROR) << "flush -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1073 |         return C2_TRANSACTION_FAILED; | 
 | 1074 |     } | 
 | 1075 |  | 
 | 1076 |     // Indices of flushed work items. | 
 | 1077 |     std::vector<uint64_t> flushedIndices; | 
 | 1078 |     for (const std::unique_ptr<C2Work> &work : *flushedWork) { | 
 | 1079 |         if (work) { | 
 | 1080 |             if (work->worklets.empty() | 
 | 1081 |                     || !work->worklets.back() | 
 | 1082 |                     || (work->worklets.back()->output.flags & | 
 | 1083 |                         C2FrameData::FLAG_INCOMPLETE) == 0) { | 
 | 1084 |                 // input is complete | 
 | 1085 |                 flushedIndices.emplace_back( | 
 | 1086 |                         work->input.ordinal.frameIndex.peeku()); | 
 | 1087 |             } | 
 | 1088 |         } | 
 | 1089 |     } | 
 | 1090 |  | 
 | 1091 |     // Input buffers' lifetime management | 
 | 1092 |     for (uint64_t flushedIndex : flushedIndices) { | 
 | 1093 |         std::lock_guard<std::mutex> lock(mInputBuffersMutex); | 
 | 1094 |         auto it = mInputBuffers.find(flushedIndex); | 
 | 1095 |         if (it == mInputBuffers.end()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1096 |             LOG(VERBOSE) << "flush -- returned consumed/unknown input frame: " | 
 | 1097 |                             "index = " << flushedIndex << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1098 |         } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1099 |             LOG(VERBOSE) << "flush -- returned unprocessed input frame: " | 
 | 1100 |                             "index = " << flushedIndex | 
 | 1101 |                          << ", number of buffers = " | 
 | 1102 |                              << mInputBufferCount[flushedIndex] | 
 | 1103 |                          << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1104 |             mInputBuffers.erase(it); | 
 | 1105 |             mInputBufferCount.erase(flushedIndex); | 
 | 1106 |         } | 
 | 1107 |     } | 
 | 1108 |  | 
 | 1109 |     // Output bufferqueue-based blocks' lifetime management | 
 | 1110 |     mOutputBufferQueueMutex.lock(); | 
 | 1111 |     sp<IGraphicBufferProducer> igbp = mOutputIgbp; | 
 | 1112 |     uint64_t bqId = mOutputBqId; | 
 | 1113 |     uint32_t generation = mOutputGeneration; | 
 | 1114 |     mOutputBufferQueueMutex.unlock(); | 
 | 1115 |  | 
 | 1116 |     if (igbp) { | 
 | 1117 |         holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation); | 
 | 1118 |     } | 
 | 1119 |  | 
 | 1120 |     return status; | 
 | 1121 | } | 
 | 1122 |  | 
 | 1123 | c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1124 |     Return<Status> transStatus = mBase->drain( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1125 |             mode == C2Component::DRAIN_COMPONENT_WITH_EOS); | 
 | 1126 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1127 |         LOG(ERROR) << "drain -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1128 |         return C2_TRANSACTION_FAILED; | 
 | 1129 |     } | 
 | 1130 |     c2_status_t status = | 
 | 1131 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1132 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1133 |         LOG(DEBUG) << "drain -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1134 |     } | 
 | 1135 |     return status; | 
 | 1136 | } | 
 | 1137 |  | 
 | 1138 | c2_status_t Codec2Client::Component::start() { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1139 |     Return<Status> transStatus = mBase->start(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1140 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1141 |         LOG(ERROR) << "start -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1142 |         return C2_TRANSACTION_FAILED; | 
 | 1143 |     } | 
 | 1144 |     c2_status_t status = | 
 | 1145 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1146 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1147 |         LOG(DEBUG) << "start -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1148 |     } | 
 | 1149 |     return status; | 
 | 1150 | } | 
 | 1151 |  | 
 | 1152 | c2_status_t Codec2Client::Component::stop() { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1153 |     Return<Status> transStatus = mBase->stop(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1154 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1155 |         LOG(ERROR) << "stop -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1156 |         return C2_TRANSACTION_FAILED; | 
 | 1157 |     } | 
 | 1158 |     c2_status_t status = | 
 | 1159 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1160 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1161 |         LOG(DEBUG) << "stop -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1162 |     } | 
 | 1163 |     mInputBuffersMutex.lock(); | 
 | 1164 |     mInputBuffers.clear(); | 
 | 1165 |     mInputBufferCount.clear(); | 
 | 1166 |     mInputBuffersMutex.unlock(); | 
 | 1167 |     return status; | 
 | 1168 | } | 
 | 1169 |  | 
 | 1170 | c2_status_t Codec2Client::Component::reset() { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1171 |     Return<Status> transStatus = mBase->reset(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1172 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1173 |         LOG(ERROR) << "reset -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1174 |         return C2_TRANSACTION_FAILED; | 
 | 1175 |     } | 
 | 1176 |     c2_status_t status = | 
 | 1177 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1178 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1179 |         LOG(DEBUG) << "reset -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1180 |     } | 
 | 1181 |     mInputBuffersMutex.lock(); | 
 | 1182 |     mInputBuffers.clear(); | 
 | 1183 |     mInputBufferCount.clear(); | 
 | 1184 |     mInputBuffersMutex.unlock(); | 
 | 1185 |     return status; | 
 | 1186 | } | 
 | 1187 |  | 
 | 1188 | c2_status_t Codec2Client::Component::release() { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1189 |     Return<Status> transStatus = mBase->release(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1190 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1191 |         LOG(ERROR) << "release -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1192 |         return C2_TRANSACTION_FAILED; | 
 | 1193 |     } | 
 | 1194 |     c2_status_t status = | 
 | 1195 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1196 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1197 |         LOG(DEBUG) << "release -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1198 |     } | 
 | 1199 |     mInputBuffersMutex.lock(); | 
 | 1200 |     mInputBuffers.clear(); | 
 | 1201 |     mInputBufferCount.clear(); | 
 | 1202 |     mInputBuffersMutex.unlock(); | 
 | 1203 |     return status; | 
 | 1204 | } | 
 | 1205 |  | 
 | 1206 | c2_status_t Codec2Client::Component::setOutputSurface( | 
 | 1207 |         C2BlockPool::local_id_t blockPoolId, | 
 | 1208 |         const sp<IGraphicBufferProducer>& surface, | 
 | 1209 |         uint32_t generation) { | 
 | 1210 |     sp<HGraphicBufferProducer> igbp = surface->getHalInterface(); | 
 | 1211 |     if (!igbp) { | 
 | 1212 |         igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface); | 
 | 1213 |     } | 
 | 1214 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1215 |     Return<Status> transStatus = mBase->setOutputSurface( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1216 |             static_cast<uint64_t>(blockPoolId), igbp); | 
 | 1217 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1218 |         LOG(ERROR) << "setOutputSurface -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1219 |         return C2_TRANSACTION_FAILED; | 
 | 1220 |     } | 
 | 1221 |     c2_status_t status = | 
 | 1222 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1223 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1224 |         LOG(DEBUG) << "setOutputSurface -- call failed: " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1225 |     } else { | 
 | 1226 |         std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex); | 
 | 1227 |         if (mOutputIgbp != surface) { | 
 | 1228 |             mOutputIgbp = surface; | 
 | 1229 |             if (!surface) { | 
 | 1230 |                 mOutputBqId = 0; | 
 | 1231 |             } else if (surface->getUniqueId(&mOutputBqId) != OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1232 |                 LOG(ERROR) << "setOutputSurface -- " | 
 | 1233 |                               "cannot obtain bufferqueue id."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1234 |             } | 
 | 1235 |         } | 
 | 1236 |         mOutputGeneration = generation; | 
 | 1237 |     } | 
 | 1238 |     return status; | 
 | 1239 | } | 
 | 1240 |  | 
 | 1241 | status_t Codec2Client::Component::queueToOutputSurface( | 
 | 1242 |         const C2ConstGraphicBlock& block, | 
 | 1243 |         const QueueBufferInput& input, | 
 | 1244 |         QueueBufferOutput* output) { | 
 | 1245 |     uint32_t generation; | 
 | 1246 |     uint64_t bqId; | 
 | 1247 |     int32_t bqSlot; | 
 | 1248 |     if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) || | 
 | 1249 |             bqId == 0) { | 
 | 1250 |         // Block not from bufferqueue -- it must be attached before queuing. | 
 | 1251 |  | 
 | 1252 |         mOutputBufferQueueMutex.lock(); | 
 | 1253 |         sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp; | 
 | 1254 |         uint32_t outputGeneration = mOutputGeneration; | 
 | 1255 |         mOutputBufferQueueMutex.unlock(); | 
 | 1256 |  | 
| Sungtak Lee | 9b14881 | 2019-01-27 16:30:13 -0800 | [diff] [blame] | 1257 |         status_t status = attachToBufferQueue(block, | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1258 |                                                outputIgbp, | 
 | 1259 |                                                outputGeneration, | 
 | 1260 |                                                &bqSlot); | 
 | 1261 |         if (status != OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1262 |             LOG(WARNING) << "queueToOutputSurface -- attaching failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1263 |             return INVALID_OPERATION; | 
 | 1264 |         } | 
 | 1265 |  | 
 | 1266 |         status = outputIgbp->queueBuffer(static_cast<int>(bqSlot), | 
 | 1267 |                                          input, output); | 
 | 1268 |         if (status != OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1269 |             LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed " | 
 | 1270 |                           "on non-bufferqueue-based block. " | 
 | 1271 |                           "Error = " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1272 |             return status; | 
 | 1273 |         } | 
 | 1274 |         return OK; | 
 | 1275 |     } | 
 | 1276 |  | 
 | 1277 |     mOutputBufferQueueMutex.lock(); | 
 | 1278 |     sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp; | 
 | 1279 |     uint64_t outputBqId = mOutputBqId; | 
 | 1280 |     uint32_t outputGeneration = mOutputGeneration; | 
 | 1281 |     mOutputBufferQueueMutex.unlock(); | 
 | 1282 |  | 
 | 1283 |     if (!outputIgbp) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1284 |         LOG(VERBOSE) << "queueToOutputSurface -- output surface is null."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1285 |         return NO_INIT; | 
 | 1286 |     } | 
 | 1287 |  | 
| Sungtak Lee | 9b14881 | 2019-01-27 16:30:13 -0800 | [diff] [blame] | 1288 |     if (bqId != outputBqId || generation != outputGeneration) { | 
 | 1289 |         if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1290 |             LOG(ERROR) << "queueToOutputSurface -- migration failed."; | 
| Sungtak Lee | 9b14881 | 2019-01-27 16:30:13 -0800 | [diff] [blame] | 1291 |             return DEAD_OBJECT; | 
 | 1292 |         } | 
 | 1293 |         if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1294 |             LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment."; | 
| Sungtak Lee | 9b14881 | 2019-01-27 16:30:13 -0800 | [diff] [blame] | 1295 |             return UNKNOWN_ERROR; | 
 | 1296 |         } | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1297 |     } | 
 | 1298 |  | 
 | 1299 |     status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot), | 
 | 1300 |                                               input, output); | 
 | 1301 |     if (status != OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1302 |         LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed " | 
 | 1303 |                       "on bufferqueue-based block. " | 
 | 1304 |                       "Error = " << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1305 |         return status; | 
 | 1306 |     } | 
 | 1307 |     if (!yieldBufferQueueBlock(block)) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1308 |         LOG(DEBUG) << "queueToOutputSurface -- cannot yield " | 
 | 1309 |                       "bufferqueue-based block to the bufferqueue."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1310 |         return UNKNOWN_ERROR; | 
 | 1311 |     } | 
 | 1312 |     return OK; | 
 | 1313 | } | 
 | 1314 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1315 | c2_status_t Codec2Client::Component::connectToInputSurface( | 
 | 1316 |         const std::shared_ptr<InputSurface>& inputSurface, | 
 | 1317 |         std::shared_ptr<InputSurfaceConnection>* connection) { | 
 | 1318 |     c2_status_t status; | 
 | 1319 |     Return<void> transStatus = mBase->connectToInputSurface( | 
 | 1320 |             inputSurface->mBase, | 
 | 1321 |             [&status, connection]( | 
 | 1322 |                     Status s, const sp<IInputSurfaceConnection>& c) { | 
 | 1323 |                 status = static_cast<c2_status_t>(s); | 
 | 1324 |                 if (status != C2_OK) { | 
 | 1325 |                     LOG(DEBUG) << "connectToInputSurface -- call failed: " | 
 | 1326 |                                << status << "."; | 
 | 1327 |                     return; | 
 | 1328 |                 } | 
 | 1329 |                 *connection = std::make_shared<InputSurfaceConnection>(c); | 
 | 1330 |             }); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1331 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1332 |         LOG(ERROR) << "connectToInputSurface -- transaction failed"; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1333 |         return C2_TRANSACTION_FAILED; | 
 | 1334 |     } | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1335 |     return status; | 
 | 1336 | } | 
 | 1337 |  | 
 | 1338 | c2_status_t Codec2Client::Component::connectToOmxInputSurface( | 
 | 1339 |         const sp<HGraphicBufferProducer>& producer, | 
 | 1340 |         const sp<HGraphicBufferSource>& source, | 
 | 1341 |         std::shared_ptr<InputSurfaceConnection>* connection) { | 
 | 1342 |     c2_status_t status; | 
 | 1343 |     Return<void> transStatus = mBase->connectToOmxInputSurface( | 
 | 1344 |             producer, source, | 
 | 1345 |             [&status, connection]( | 
 | 1346 |                     Status s, const sp<IInputSurfaceConnection>& c) { | 
 | 1347 |                 status = static_cast<c2_status_t>(s); | 
 | 1348 |                 if (status != C2_OK) { | 
 | 1349 |                     LOG(DEBUG) << "connectToOmxInputSurface -- call failed: " | 
 | 1350 |                                << status << "."; | 
 | 1351 |                     return; | 
 | 1352 |                 } | 
 | 1353 |                 *connection = std::make_shared<InputSurfaceConnection>(c); | 
 | 1354 |             }); | 
 | 1355 |     if (!transStatus.isOk()) { | 
 | 1356 |         LOG(ERROR) << "connectToOmxInputSurface -- transaction failed."; | 
 | 1357 |         return C2_TRANSACTION_FAILED; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1358 |     } | 
 | 1359 |     return status; | 
 | 1360 | } | 
 | 1361 |  | 
 | 1362 | c2_status_t Codec2Client::Component::disconnectFromInputSurface() { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1363 |     Return<Status> transStatus = mBase->disconnectFromInputSurface(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1364 |     if (!transStatus.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1365 |         LOG(ERROR) << "disconnectToInputSurface -- transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1366 |         return C2_TRANSACTION_FAILED; | 
 | 1367 |     } | 
 | 1368 |     c2_status_t status = | 
 | 1369 |             static_cast<c2_status_t>(static_cast<Status>(transStatus)); | 
 | 1370 |     if (status != C2_OK) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1371 |         LOG(DEBUG) << "disconnectFromInputSurface -- call failed: " | 
 | 1372 |                    << status << "."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1373 |     } | 
 | 1374 |     return status; | 
 | 1375 | } | 
 | 1376 |  | 
 | 1377 | c2_status_t Codec2Client::Component::setDeathListener( | 
 | 1378 |         const std::shared_ptr<Component>& component, | 
 | 1379 |         const std::shared_ptr<Listener>& listener) { | 
 | 1380 |  | 
 | 1381 |     struct HidlDeathRecipient : public hardware::hidl_death_recipient { | 
 | 1382 |         std::weak_ptr<Component> component; | 
 | 1383 |         std::weak_ptr<Listener> base; | 
 | 1384 |  | 
 | 1385 |         virtual void serviceDied( | 
 | 1386 |                 uint64_t /* cookie */, | 
 | 1387 |                 const wp<::android::hidl::base::V1_0::IBase>& /* who */ | 
 | 1388 |                 ) override { | 
 | 1389 |             if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) { | 
 | 1390 |                 listener->onDeath(component); | 
 | 1391 |             } else { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1392 |                 LOG(DEBUG) << "onDeath -- listener died."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1393 |             } | 
 | 1394 |         } | 
 | 1395 |     }; | 
 | 1396 |  | 
 | 1397 |     sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient(); | 
 | 1398 |     deathRecipient->base = listener; | 
 | 1399 |     deathRecipient->component = component; | 
 | 1400 |  | 
 | 1401 |     component->mDeathRecipient = deathRecipient; | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1402 |     Return<bool> transResult = component->mBase->linkToDeath( | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1403 |             component->mDeathRecipient, 0); | 
 | 1404 |     if (!transResult.isOk()) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1405 |         LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1406 |         return C2_TRANSACTION_FAILED; | 
 | 1407 |     } | 
 | 1408 |     if (!static_cast<bool>(transResult)) { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1409 |         LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed."; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1410 |         return C2_CORRUPTED; | 
 | 1411 |     } | 
 | 1412 |     return C2_OK; | 
 | 1413 | } | 
 | 1414 |  | 
 | 1415 | // Codec2Client::InputSurface | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1416 | Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base) | 
 | 1417 |       : Configurable{ | 
 | 1418 |             [base]() -> sp<IConfigurable> { | 
 | 1419 |                 Return<sp<IConfigurable>> transResult = | 
 | 1420 |                         base->getConfigurable(); | 
 | 1421 |                 return transResult.isOk() ? | 
 | 1422 |                         static_cast<sp<IConfigurable>>(transResult) : | 
 | 1423 |                         nullptr; | 
 | 1424 |             }() | 
 | 1425 |         }, | 
 | 1426 |         mBase{base}, | 
 | 1427 |         mGraphicBufferProducer{new | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1428 |             ::android::hardware::graphics::bufferqueue::V1_0::utils:: | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1429 |             H2BGraphicBufferProducer([base]() -> sp<HGraphicBufferProducer> { | 
 | 1430 |                 Return<sp<HGraphicBufferProducer>> transResult = | 
 | 1431 |                         base->getGraphicBufferProducer(); | 
 | 1432 |                 return transResult.isOk() ? | 
 | 1433 |                         static_cast<sp<HGraphicBufferProducer>>(transResult) : | 
 | 1434 |                         nullptr; | 
 | 1435 |             }())} { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1436 | } | 
 | 1437 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1438 | sp<IGraphicBufferProducer> | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1439 |         Codec2Client::InputSurface::getGraphicBufferProducer() const { | 
 | 1440 |     return mGraphicBufferProducer; | 
 | 1441 | } | 
 | 1442 |  | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1443 | sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1444 |     return mBase; | 
 | 1445 | } | 
 | 1446 |  | 
 | 1447 | // Codec2Client::InputSurfaceConnection | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1448 | Codec2Client::InputSurfaceConnection::InputSurfaceConnection( | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1449 |         const sp<IInputSurfaceConnection>& base) | 
 | 1450 |       : Configurable{ | 
 | 1451 |             [base]() -> sp<IConfigurable> { | 
 | 1452 |                 Return<sp<IConfigurable>> transResult = | 
 | 1453 |                         base->getConfigurable(); | 
 | 1454 |                 return transResult.isOk() ? | 
 | 1455 |                         static_cast<sp<IConfigurable>>(transResult) : | 
 | 1456 |                         nullptr; | 
 | 1457 |             }() | 
 | 1458 |         }, | 
 | 1459 |         mBase{base} { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1460 | } | 
 | 1461 |  | 
 | 1462 | c2_status_t Codec2Client::InputSurfaceConnection::disconnect() { | 
| Pawin Vongmasa | 1c75a23 | 2019-01-09 04:41:52 -0800 | [diff] [blame] | 1463 |     Return<Status> transResult = mBase->disconnect(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1464 |     return static_cast<c2_status_t>(static_cast<Status>(transResult)); | 
 | 1465 | } | 
 | 1466 |  | 
 | 1467 | }  // namespace android | 
 | 1468 |  |