1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "CCodecConfig.h"
18
19 #include <set>
20
21 #include <gtest/gtest.h>
22
23 #include <codec2/hidl/1.0/Configurable.h>
24 #include <codec2/hidl/client.h>
25 #include <util/C2InterfaceHelper.h>
26
27 #include <media/stagefright/MediaCodecConstants.h>
28
29 namespace {
30
31 enum ExtendedC2ParamIndexKind : C2Param::type_index_t {
32 kParamIndexVendorInt32 = C2Param::TYPE_INDEX_VENDOR_START,
33 kParamIndexVendorInt64,
34 kParamIndexVendorString,
35 };
36
37 typedef C2PortParam<C2Info, C2Int32Value, kParamIndexVendorInt32> C2PortVendorInt32Info;
38 constexpr char C2_PARAMKEY_VENDOR_INT32[] = "example.int32";
39 constexpr char KEY_VENDOR_INT32[] = "vendor.example.int32.value";
40
41 typedef C2StreamParam<C2Info, C2Int64Value, kParamIndexVendorInt64> C2StreamVendorInt64Info;
42 constexpr char C2_PARAMKEY_VENDOR_INT64[] = "example.int64";
43 constexpr char KEY_VENDOR_INT64[] = "vendor.example.int64.value";
44
45 typedef C2PortParam<C2Info, C2StringValue, kParamIndexVendorString> C2PortVendorStringInfo;
46 constexpr char C2_PARAMKEY_VENDOR_STRING[] = "example.string";
47 constexpr char KEY_VENDOR_STRING[] = "vendor.example.string.value";
48
49 } // namespace
50
51 namespace android {
52
53 class CCodecConfigTest : public ::testing::Test {
54 public:
55 constexpr static int32_t kCodec2Int32 = 0xC0DEC2;
56 constexpr static int64_t kCodec2Int64 = 0xC0DEC2C0DEC2ll;
57 constexpr static char kCodec2Str[] = "codec2";
58
CCodecConfigTest()59 CCodecConfigTest()
60 : mReflector{std::make_shared<C2ReflectorHelper>()} {
61 }
62
init(C2Component::domain_t domain,C2Component::kind_t kind,const char * mediaType)63 void init(
64 C2Component::domain_t domain,
65 C2Component::kind_t kind,
66 const char *mediaType) {
67 sp<hardware::media::c2::V1_0::utils::CachedConfigurable> cachedConfigurable =
68 new hardware::media::c2::V1_0::utils::CachedConfigurable(
69 std::make_unique<Configurable>(mReflector, domain, kind, mediaType));
70 cachedConfigurable->init(std::make_shared<Cache>());
71 mConfigurable = std::make_shared<Codec2Client::Configurable>(cachedConfigurable);
72 }
73
74 struct Cache : public hardware::media::c2::V1_0::utils::ParameterCache {
validateandroid::CCodecConfigTest::Cache75 c2_status_t validate(const std::vector<std::shared_ptr<C2ParamDescriptor>>&) override {
76 return C2_OK;
77 }
78 };
79
80 class Configurable : public hardware::media::c2::V1_0::utils::ConfigurableC2Intf {
81 public:
Configurable(const std::shared_ptr<C2ReflectorHelper> & reflector,C2Component::domain_t domain,C2Component::kind_t kind,const char * mediaType)82 Configurable(
83 const std::shared_ptr<C2ReflectorHelper> &reflector,
84 C2Component::domain_t domain,
85 C2Component::kind_t kind,
86 const char *mediaType)
87 : ConfigurableC2Intf("name", 0u),
88 mImpl(reflector, domain, kind, mediaType) {
89 }
90
query(const std::vector<C2Param::Index> & indices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const params) const91 c2_status_t query(
92 const std::vector<C2Param::Index> &indices,
93 c2_blocking_t mayBlock,
94 std::vector<std::unique_ptr<C2Param>>* const params) const override {
95 return mImpl.query({}, indices, mayBlock, params);
96 }
97
config(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)98 c2_status_t config(
99 const std::vector<C2Param*> ¶ms,
100 c2_blocking_t mayBlock,
101 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
102 return mImpl.config(params, mayBlock, failures);
103 }
104
querySupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const105 c2_status_t querySupportedParams(
106 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const override {
107 return mImpl.querySupportedParams(params);
108 }
109
querySupportedValues(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const110 c2_status_t querySupportedValues(
111 std::vector<C2FieldSupportedValuesQuery>& fields,
112 c2_blocking_t mayBlock) const override {
113 return mImpl.querySupportedValues(fields, mayBlock);
114 }
115
116 private:
117 class Impl : public C2InterfaceHelper {
118 public:
Impl(const std::shared_ptr<C2ReflectorHelper> & reflector,C2Component::domain_t domain,C2Component::kind_t kind,const char * mediaType)119 Impl(const std::shared_ptr<C2ReflectorHelper> &reflector,
120 C2Component::domain_t domain,
121 C2Component::kind_t kind,
122 const char *mediaType)
123 : C2InterfaceHelper{reflector} {
124
125 setDerivedInstance(this);
126
127 addParameter(
128 DefineParam(mDomain, C2_PARAMKEY_COMPONENT_DOMAIN)
129 .withConstValue(new C2ComponentDomainSetting(domain))
130 .build());
131
132 addParameter(
133 DefineParam(mKind, C2_PARAMKEY_COMPONENT_KIND)
134 .withConstValue(new C2ComponentKindSetting(kind))
135 .build());
136
137 addParameter(
138 DefineParam(mInputStreamCount, C2_PARAMKEY_INPUT_STREAM_COUNT)
139 .withConstValue(new C2PortStreamCountTuning::input(1))
140 .build());
141
142 addParameter(
143 DefineParam(mOutputStreamCount, C2_PARAMKEY_OUTPUT_STREAM_COUNT)
144 .withConstValue(new C2PortStreamCountTuning::output(1))
145 .build());
146
147 const char *rawMediaType = "";
148 switch (domain) {
149 case C2Component::DOMAIN_IMAGE: [[fallthrough]];
150 case C2Component::DOMAIN_VIDEO:
151 rawMediaType = MIMETYPE_VIDEO_RAW;
152 break;
153 case C2Component::DOMAIN_AUDIO:
154 rawMediaType = MIMETYPE_AUDIO_RAW;
155 break;
156 default:
157 break;
158 }
159 bool isEncoder = kind == C2Component::KIND_ENCODER;
160 std::string inputMediaType{isEncoder ? rawMediaType : mediaType};
161 std::string outputMediaType{isEncoder ? mediaType : rawMediaType};
162
__anon8d80e32f0202(const auto ¶m, const std::string &str) 163 auto allocSharedString = [](const auto ¶m, const std::string &str) {
164 typedef typename std::remove_reference<decltype(param)>::type::element_type T;
165 std::shared_ptr<T> ret = T::AllocShared(str.length() + 1);
166 strcpy(ret->m.value, str.c_str());
167 return ret;
168 };
169
170 addParameter(
171 DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE)
172 .withConstValue(allocSharedString(mInputMediaType, inputMediaType))
173 .build());
174
175 addParameter(
176 DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE)
177 .withConstValue(allocSharedString(mOutputMediaType, outputMediaType))
178 .build());
179
180 addParameter(
181 DefineParam(mInt32Input, C2_PARAMKEY_VENDOR_INT32)
182 .withDefault(new C2PortVendorInt32Info::input(0))
183 .withFields({C2F(mInt32Input, value).any()})
184 .withSetter(Setter<decltype(mInt32Input)::element_type>)
185 .build());
186
187 addParameter(
188 DefineParam(mInt64Output, C2_PARAMKEY_VENDOR_INT64)
189 .withDefault(new C2StreamVendorInt64Info::output(0u, 0))
190 .withFields({C2F(mInt64Output, value).any()})
191 .withSetter(Setter<decltype(mInt64Output)::element_type>)
192 .build());
193
194 addParameter(
195 DefineParam(mStringInput, C2_PARAMKEY_VENDOR_STRING)
196 .withDefault(decltype(mStringInput)::element_type::AllocShared(1, ""))
197 .withFields({C2F(mStringInput, m.value).any()})
198 .withSetter(Setter<decltype(mStringInput)::element_type>)
199 .build());
200
201 addParameter(
202 DefineParam(mPixelAspectRatio, C2_PARAMKEY_PIXEL_ASPECT_RATIO)
203 .withDefault(new C2StreamPixelAspectRatioInfo::output(0u, 1, 1))
204 .withFields({
205 C2F(mPixelAspectRatio, width).any(),
206 C2F(mPixelAspectRatio, height).any(),
207 })
208 .withSetter(Setter<C2StreamPixelAspectRatioInfo::output>)
209 .build());
210
211 if (isEncoder) {
212 addParameter(
213 DefineParam(mInputBitrate, C2_PARAMKEY_BITRATE)
214 .withDefault(new C2StreamBitrateInfo::input(0u))
215 .withFields({C2F(mInputBitrate, value).any()})
216 .withSetter(Setter<C2StreamBitrateInfo::input>)
217 .build());
218
219 addParameter(
220 DefineParam(mOutputBitrate, C2_PARAMKEY_BITRATE)
221 .withDefault(new C2StreamBitrateInfo::output(0u))
222 .withFields({C2F(mOutputBitrate, value).any()})
223 .calculatedAs(
224 Copy<C2StreamBitrateInfo::output, C2StreamBitrateInfo::input>,
225 mInputBitrate)
226 .build());
227 }
228
229 // TODO: more SDK params
230 }
231 private:
232 std::shared_ptr<C2ComponentDomainSetting> mDomain;
233 std::shared_ptr<C2ComponentKindSetting> mKind;
234 std::shared_ptr<C2PortStreamCountTuning::input> mInputStreamCount;
235 std::shared_ptr<C2PortStreamCountTuning::output> mOutputStreamCount;
236 std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType;
237 std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType;
238 std::shared_ptr<C2PortVendorInt32Info::input> mInt32Input;
239 std::shared_ptr<C2StreamVendorInt64Info::output> mInt64Output;
240 std::shared_ptr<C2PortVendorStringInfo::input> mStringInput;
241 std::shared_ptr<C2StreamPixelAspectRatioInfo::output> mPixelAspectRatio;
242 std::shared_ptr<C2StreamBitrateInfo::input> mInputBitrate;
243 std::shared_ptr<C2StreamBitrateInfo::output> mOutputBitrate;
244
245 template<typename T>
Setter(bool,C2P<T> &)246 static C2R Setter(bool, C2P<T> &) {
247 return C2R::Ok();
248 }
249
250 template<typename ME, typename DEP>
Copy(bool,C2P<ME> & me,const C2P<DEP> & dep)251 static C2R Copy(bool, C2P<ME> &me, const C2P<DEP> &dep) {
252 me.set().value = dep.v.value;
253 return C2R::Ok();
254 }
255 };
256
257 Impl mImpl;
258 };
259
260 std::shared_ptr<C2ReflectorHelper> mReflector;
261 std::shared_ptr<Codec2Client::Configurable> mConfigurable;
262 CCodecConfig mConfig;
263 };
264
265 using D = CCodecConfig::Domain;
266
267 template<typename T>
FindParam(const std::vector<std::unique_ptr<C2Param>> & vec)268 T *FindParam(const std::vector<std::unique_ptr<C2Param>> &vec) {
269 for (const std::unique_ptr<C2Param> ¶m : vec) {
270 if (param->coreIndex() == T::CORE_INDEX) {
271 return static_cast<T *>(param.get());
272 }
273 }
274 return nullptr;
275 }
276
TEST_F(CCodecConfigTest,SetVendorParam)277 TEST_F(CCodecConfigTest, SetVendorParam) {
278 // Test at audio domain, as video domain has a few local parameters that
279 // interfere with the testing.
280 init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
281
282 ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
283
284 sp<AMessage> format{new AMessage};
285 format->setInt32(KEY_VENDOR_INT32, kCodec2Int32);
286 format->setInt64(KEY_VENDOR_INT64, kCodec2Int64);
287 format->setString(KEY_VENDOR_STRING, kCodec2Str);
288
289 std::vector<std::unique_ptr<C2Param>> configUpdate;
290 ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
291 mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
292
293 ASSERT_EQ(3u, configUpdate.size());
294 C2PortVendorInt32Info::input *i32 =
295 FindParam<std::remove_pointer<decltype(i32)>::type>(configUpdate);
296 ASSERT_NE(nullptr, i32);
297 ASSERT_EQ(kCodec2Int32, i32->value);
298
299 C2StreamVendorInt64Info::output *i64 =
300 FindParam<std::remove_pointer<decltype(i64)>::type>(configUpdate);
301 ASSERT_NE(nullptr, i64);
302 ASSERT_EQ(kCodec2Int64, i64->value);
303
304 C2PortVendorStringInfo::input *str =
305 FindParam<std::remove_pointer<decltype(str)>::type>(configUpdate);
306 ASSERT_NE(nullptr, str);
307 ASSERT_STREQ(kCodec2Str, str->m.value);
308 }
309
TEST_F(CCodecConfigTest,VendorParamUpdate_Unsubscribed)310 TEST_F(CCodecConfigTest, VendorParamUpdate_Unsubscribed) {
311 // Test at audio domain, as video domain has a few local parameters that
312 // interfere with the testing.
313 init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
314
315 ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
316
317 std::vector<std::unique_ptr<C2Param>> configUpdate;
318 C2PortVendorInt32Info::input i32(kCodec2Int32);
319 C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
320 std::unique_ptr<C2PortVendorStringInfo::input> str =
321 C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
322 configUpdate.push_back(C2Param::Copy(i32));
323 configUpdate.push_back(C2Param::Copy(i64));
324 configUpdate.push_back(std::move(str));
325
326 // The vendor parameters are not yet subscribed
327 ASSERT_FALSE(mConfig.updateConfiguration(configUpdate, D::ALL));
328
329 int32_t vendorInt32{0};
330 ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
331 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
332 ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
333 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
334
335 int64_t vendorInt64{0};
336 ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
337 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
338 ASSERT_FALSE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
339 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
340
341 AString vendorString;
342 ASSERT_FALSE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
343 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
344 ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
345 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
346 }
347
TEST_F(CCodecConfigTest,VendorParamUpdate_AllSubscribed)348 TEST_F(CCodecConfigTest, VendorParamUpdate_AllSubscribed) {
349 // Test at audio domain, as video domain has a few local parameters that
350 // interfere with the testing.
351 init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
352
353 ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
354
355 // Force subscribe to all vendor params
356 ASSERT_EQ(OK, mConfig.subscribeToAllVendorParams(mConfigurable, C2_MAY_BLOCK));
357
358 std::vector<std::unique_ptr<C2Param>> configUpdate;
359 C2PortVendorInt32Info::input i32(kCodec2Int32);
360 C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
361 std::unique_ptr<C2PortVendorStringInfo::input> str =
362 C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
363 configUpdate.push_back(C2Param::Copy(i32));
364 configUpdate.push_back(C2Param::Copy(i64));
365 configUpdate.push_back(std::move(str));
366
367 ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
368
369 int32_t vendorInt32{0};
370 ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
371 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
372 ASSERT_EQ(kCodec2Int32, vendorInt32);
373 ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
374 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
375
376 int64_t vendorInt64{0};
377 ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
378 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
379 ASSERT_TRUE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
380 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
381 ASSERT_EQ(kCodec2Int64, vendorInt64);
382
383 AString vendorString;
384 ASSERT_TRUE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
385 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
386 ASSERT_STREQ(kCodec2Str, vendorString.c_str());
387 ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
388 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
389 }
390
TEST_F(CCodecConfigTest,VendorParamUpdate_PartiallySubscribed)391 TEST_F(CCodecConfigTest, VendorParamUpdate_PartiallySubscribed) {
392 // Test at audio domain, as video domain has a few local parameters that
393 // interfere with the testing.
394 init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
395
396 ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
397
398 // Subscribe to example.int32 only
399 std::vector<std::unique_ptr<C2Param>> configUpdate;
400 sp<AMessage> format{new AMessage};
401 format->setInt32(KEY_VENDOR_INT32, 0);
402 configUpdate.clear();
403 ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
404 mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
405 ASSERT_EQ(OK, mConfig.setParameters(mConfigurable, configUpdate, C2_MAY_BLOCK));
406
407 C2PortVendorInt32Info::input i32(kCodec2Int32);
408 C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
409 std::unique_ptr<C2PortVendorStringInfo::input> str =
410 C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
411 configUpdate.clear();
412 configUpdate.push_back(C2Param::Copy(i32));
413 configUpdate.push_back(C2Param::Copy(i64));
414 configUpdate.push_back(std::move(str));
415
416 // Only example.i32 should be updated
417 ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
418
419 int32_t vendorInt32{0};
420 ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
421 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
422 ASSERT_EQ(kCodec2Int32, vendorInt32);
423 ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
424 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
425
426 int64_t vendorInt64{0};
427 ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
428 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
429 ASSERT_FALSE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
430 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
431
432 AString vendorString;
433 ASSERT_FALSE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
434 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
435 ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
436 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
437 }
438
TEST_F(CCodecConfigTest,SetPixelAspectRatio)439 TEST_F(CCodecConfigTest, SetPixelAspectRatio) {
440 init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC);
441
442 ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
443
444 sp<AMessage> format{new AMessage};
445 format->setInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, 12);
446 format->setInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, 11);
447
448 std::vector<std::unique_ptr<C2Param>> configUpdate;
449 ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
450 mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
451
452 ASSERT_EQ(1u, configUpdate.size());
453 C2StreamPixelAspectRatioInfo::output *par =
454 FindParam<std::remove_pointer<decltype(par)>::type>(configUpdate);
455 ASSERT_NE(nullptr, par);
456 ASSERT_EQ(12, par->width);
457 ASSERT_EQ(11, par->height);
458 }
459
TEST_F(CCodecConfigTest,PixelAspectRatioUpdate)460 TEST_F(CCodecConfigTest, PixelAspectRatioUpdate) {
461 init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC);
462
463 ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
464
465 std::vector<std::unique_ptr<C2Param>> configUpdate;
466 C2StreamPixelAspectRatioInfo::output par(0u, 12, 11);
467 configUpdate.push_back(C2Param::Copy(par));
468
469 ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
470
471 int32_t parWidth{0};
472 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth))
473 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
474 ASSERT_EQ(12, parWidth);
475 ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth))
476 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
477
478 int32_t parHeight{0};
479 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight))
480 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
481 ASSERT_EQ(11, parHeight);
482 ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight))
483 << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
484 }
485
TEST_F(CCodecConfigTest,DataspaceUpdate)486 TEST_F(CCodecConfigTest, DataspaceUpdate) {
487 init(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER, MIMETYPE_VIDEO_AVC);
488
489 ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
490 class InputSurfaceStub : public InputSurfaceWrapper {
491 public:
492 ~InputSurfaceStub() override = default;
493 status_t connect(const std::shared_ptr<Codec2Client::Component> &) override {
494 return OK;
495 }
496 void disconnect() override {}
497 status_t start() override { return OK; }
498 status_t signalEndOfInputStream() override { return OK; }
499 status_t configure(Config &) override { return OK; }
500 };
501 mConfig.mInputSurface = std::make_shared<InputSurfaceStub>();
502
503 sp<AMessage> format{new AMessage};
504 format->setInt32(KEY_COLOR_RANGE, COLOR_RANGE_LIMITED);
505 format->setInt32(KEY_COLOR_STANDARD, COLOR_STANDARD_BT709);
506 format->setInt32(KEY_COLOR_TRANSFER, COLOR_TRANSFER_SDR_VIDEO);
507 format->setInt32(KEY_BIT_RATE, 100);
508
509 std::vector<std::unique_ptr<C2Param>> configUpdate;
510 ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
511 mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
512 ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
513
514 int32_t range{0};
515 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_RANGE, &range))
516 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
517 EXPECT_EQ(COLOR_RANGE_LIMITED, range)
518 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
519
520 int32_t standard{0};
521 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_STANDARD, &standard))
522 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
523 EXPECT_EQ(COLOR_STANDARD_BT709, standard)
524 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
525
526 int32_t transfer{0};
527 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_TRANSFER, &transfer))
528 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
529 EXPECT_EQ(COLOR_TRANSFER_SDR_VIDEO, transfer)
530 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
531
532 mConfig.mInputSurface->setDataSpace(HAL_DATASPACE_BT2020_PQ);
533
534 // Dataspace from input surface should override the configured setting
535 mConfig.updateFormats(D::ALL);
536
537 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_RANGE, &range))
538 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
539 EXPECT_EQ(COLOR_RANGE_FULL, range)
540 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
541
542 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_STANDARD, &standard))
543 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
544 EXPECT_EQ(COLOR_STANDARD_BT2020, standard)
545 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
546
547 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_TRANSFER, &transfer))
548 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
549 EXPECT_EQ(COLOR_TRANSFER_ST2084, transfer)
550 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
551
552 // Simulate bitrate update
553 format = new AMessage;
554 format->setInt32(KEY_BIT_RATE, 200);
555 configUpdate.clear();
556 ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
557 mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
558 ASSERT_EQ(OK, mConfig.setParameters(mConfigurable, configUpdate, C2_MAY_BLOCK));
559
560 // Color information should remain the same
561 mConfig.updateFormats(D::ALL);
562
563 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_RANGE, &range))
564 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
565 EXPECT_EQ(COLOR_RANGE_FULL, range)
566 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
567
568 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_STANDARD, &standard))
569 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
570 EXPECT_EQ(COLOR_STANDARD_BT2020, standard)
571 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
572
573 ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_TRANSFER, &transfer))
574 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
575 EXPECT_EQ(COLOR_TRANSFER_ST2084, transfer)
576 << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
577 }
578
579 } // namespace android
580