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*> &params,
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 
__anon38026ec30202(const auto &param, const std::string &str) 163                 auto allocSharedString = [](const auto &param, 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                 // TODO: more SDK params
212             }
213         private:
214             std::shared_ptr<C2ComponentDomainSetting> mDomain;
215             std::shared_ptr<C2ComponentKindSetting> mKind;
216             std::shared_ptr<C2PortStreamCountTuning::input> mInputStreamCount;
217             std::shared_ptr<C2PortStreamCountTuning::output> mOutputStreamCount;
218             std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType;
219             std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType;
220             std::shared_ptr<C2PortVendorInt32Info::input> mInt32Input;
221             std::shared_ptr<C2StreamVendorInt64Info::output> mInt64Output;
222             std::shared_ptr<C2PortVendorStringInfo::input> mStringInput;
223             std::shared_ptr<C2StreamPixelAspectRatioInfo::output> mPixelAspectRatio;
224 
225             template<typename T>
Setter(bool,C2P<T> &)226             static C2R Setter(bool, C2P<T> &) {
227                 return C2R::Ok();
228             }
229         };
230 
231         Impl mImpl;
232     };
233 
234     std::shared_ptr<C2ReflectorHelper> mReflector;
235     std::shared_ptr<Codec2Client::Configurable> mConfigurable;
236     CCodecConfig mConfig;
237 };
238 
239 using D = CCodecConfig::Domain;
240 
241 template<typename T>
FindParam(const std::vector<std::unique_ptr<C2Param>> & vec)242 T *FindParam(const std::vector<std::unique_ptr<C2Param>> &vec) {
243     for (const std::unique_ptr<C2Param> &param : vec) {
244         if (param->coreIndex() == T::CORE_INDEX) {
245             return static_cast<T *>(param.get());
246         }
247     }
248     return nullptr;
249 }
250 
TEST_F(CCodecConfigTest,SetVendorParam)251 TEST_F(CCodecConfigTest, SetVendorParam) {
252     // Test at audio domain, as video domain has a few local parameters that
253     // interfere with the testing.
254     init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
255 
256     ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
257 
258     sp<AMessage> format{new AMessage};
259     format->setInt32(KEY_VENDOR_INT32, kCodec2Int32);
260     format->setInt64(KEY_VENDOR_INT64, kCodec2Int64);
261     format->setString(KEY_VENDOR_STRING, kCodec2Str);
262 
263     std::vector<std::unique_ptr<C2Param>> configUpdate;
264     ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
265             mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
266 
267     ASSERT_EQ(3u, configUpdate.size());
268     C2PortVendorInt32Info::input *i32 =
269         FindParam<std::remove_pointer<decltype(i32)>::type>(configUpdate);
270     ASSERT_NE(nullptr, i32);
271     ASSERT_EQ(kCodec2Int32, i32->value);
272 
273     C2StreamVendorInt64Info::output *i64 =
274         FindParam<std::remove_pointer<decltype(i64)>::type>(configUpdate);
275     ASSERT_NE(nullptr, i64);
276     ASSERT_EQ(kCodec2Int64, i64->value);
277 
278     C2PortVendorStringInfo::input *str =
279         FindParam<std::remove_pointer<decltype(str)>::type>(configUpdate);
280     ASSERT_NE(nullptr, str);
281     ASSERT_STREQ(kCodec2Str, str->m.value);
282 }
283 
TEST_F(CCodecConfigTest,VendorParamUpdate_Unsubscribed)284 TEST_F(CCodecConfigTest, VendorParamUpdate_Unsubscribed) {
285     // Test at audio domain, as video domain has a few local parameters that
286     // interfere with the testing.
287     init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
288 
289     ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
290 
291     std::vector<std::unique_ptr<C2Param>> configUpdate;
292     C2PortVendorInt32Info::input i32(kCodec2Int32);
293     C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
294     std::unique_ptr<C2PortVendorStringInfo::input> str =
295         C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
296     configUpdate.push_back(C2Param::Copy(i32));
297     configUpdate.push_back(C2Param::Copy(i64));
298     configUpdate.push_back(std::move(str));
299 
300     // The vendor parameters are not yet subscribed
301     ASSERT_FALSE(mConfig.updateConfiguration(configUpdate, D::ALL));
302 
303     int32_t vendorInt32{0};
304     ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
305             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
306     ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
307             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
308 
309     int64_t vendorInt64{0};
310     ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
311             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
312     ASSERT_FALSE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
313             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
314 
315     AString vendorString;
316     ASSERT_FALSE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
317             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
318     ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
319             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
320 }
321 
TEST_F(CCodecConfigTest,VendorParamUpdate_AllSubscribed)322 TEST_F(CCodecConfigTest, VendorParamUpdate_AllSubscribed) {
323     // Test at audio domain, as video domain has a few local parameters that
324     // interfere with the testing.
325     init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
326 
327     ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
328 
329     // Force subscribe to all vendor params
330     ASSERT_EQ(OK, mConfig.subscribeToAllVendorParams(mConfigurable, C2_MAY_BLOCK));
331 
332     std::vector<std::unique_ptr<C2Param>> configUpdate;
333     C2PortVendorInt32Info::input i32(kCodec2Int32);
334     C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
335     std::unique_ptr<C2PortVendorStringInfo::input> str =
336         C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
337     configUpdate.push_back(C2Param::Copy(i32));
338     configUpdate.push_back(C2Param::Copy(i64));
339     configUpdate.push_back(std::move(str));
340 
341     ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
342 
343     int32_t vendorInt32{0};
344     ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
345             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
346     ASSERT_EQ(kCodec2Int32, vendorInt32);
347     ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
348             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
349 
350     int64_t vendorInt64{0};
351     ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
352             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
353     ASSERT_TRUE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
354             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
355     ASSERT_EQ(kCodec2Int64, vendorInt64);
356 
357     AString vendorString;
358     ASSERT_TRUE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
359             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
360     ASSERT_STREQ(kCodec2Str, vendorString.c_str());
361     ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
362             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
363 }
364 
TEST_F(CCodecConfigTest,VendorParamUpdate_PartiallySubscribed)365 TEST_F(CCodecConfigTest, VendorParamUpdate_PartiallySubscribed) {
366     // Test at audio domain, as video domain has a few local parameters that
367     // interfere with the testing.
368     init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
369 
370     ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
371 
372     // Subscribe to example.int32 only
373     std::vector<std::unique_ptr<C2Param>> configUpdate;
374     sp<AMessage> format{new AMessage};
375     format->setInt32(KEY_VENDOR_INT32, 0);
376     configUpdate.clear();
377     ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
378             mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
379     ASSERT_EQ(OK, mConfig.setParameters(mConfigurable, configUpdate, C2_MAY_BLOCK));
380 
381     C2PortVendorInt32Info::input i32(kCodec2Int32);
382     C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
383     std::unique_ptr<C2PortVendorStringInfo::input> str =
384         C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
385     configUpdate.clear();
386     configUpdate.push_back(C2Param::Copy(i32));
387     configUpdate.push_back(C2Param::Copy(i64));
388     configUpdate.push_back(std::move(str));
389 
390     // Only example.i32 should be updated
391     ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
392 
393     int32_t vendorInt32{0};
394     ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
395             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
396     ASSERT_EQ(kCodec2Int32, vendorInt32);
397     ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
398             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
399 
400     int64_t vendorInt64{0};
401     ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
402             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
403     ASSERT_FALSE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
404             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
405 
406     AString vendorString;
407     ASSERT_FALSE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
408             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
409     ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
410             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
411 }
412 
TEST_F(CCodecConfigTest,SetPixelAspectRatio)413 TEST_F(CCodecConfigTest, SetPixelAspectRatio) {
414     init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC);
415 
416     ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
417 
418     sp<AMessage> format{new AMessage};
419     format->setInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, 12);
420     format->setInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, 11);
421 
422     std::vector<std::unique_ptr<C2Param>> configUpdate;
423     ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
424             mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
425 
426     ASSERT_EQ(1u, configUpdate.size());
427     C2StreamPixelAspectRatioInfo::output *par =
428         FindParam<std::remove_pointer<decltype(par)>::type>(configUpdate);
429     ASSERT_NE(nullptr, par);
430     ASSERT_EQ(12, par->width);
431     ASSERT_EQ(11, par->height);
432 }
433 
TEST_F(CCodecConfigTest,PixelAspectRatioUpdate)434 TEST_F(CCodecConfigTest, PixelAspectRatioUpdate) {
435     init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC);
436 
437     ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
438 
439     std::vector<std::unique_ptr<C2Param>> configUpdate;
440     C2StreamPixelAspectRatioInfo::output par(0u, 12, 11);
441     configUpdate.push_back(C2Param::Copy(par));
442 
443     ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
444 
445     int32_t parWidth{0};
446     ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth))
447             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
448     ASSERT_EQ(12, parWidth);
449     ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth))
450             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
451 
452     int32_t parHeight{0};
453     ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight))
454             << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
455     ASSERT_EQ(11, parHeight);
456     ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight))
457             << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
458 }
459 
460 } // namespace android
461