• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (C) 2025 Huawei Device Co., Ltd.
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 #include <iostream>
17 #include <cstdio>
18 #include <string>
19 
20 #include "gtest/gtest.h"
21 #include "avcodec_common.h"
22 #include "meta/format.h"
23 #include "avcodec_video_encoder.h"
24 #include "videoenc_inner_sample.h"
25 #include "native_avcapability.h"
26 #include "avcodec_info.h"
27 #include "avcodec_list.h"
28 
29 using namespace std;
30 using namespace OHOS;
31 using namespace OHOS::MediaAVCodec;
32 using namespace testing::ext;
33 
34 namespace {
35 class HwEncInnerFunc2NdkTest : public testing::Test {
36 public:
37     // SetUpTestCase: Called before all test cases
38     static void SetUpTestCase(void);
39     // TearDownTestCase: Called after all test case
40     static void TearDownTestCase(void);
41     // SetUp: Called before each test cases
42     void SetUp() override;
43     // TearDown: Called after each test cases
44     void TearDown() override;
45 };
46 
47 std::string g_codecMime = "video/avc";
48 std::string g_codecName = "";
49 std::string g_codecMimeHevc = "video/hevc";
50 std::string g_codecNameHevc = "";
51 OH_AVCapability *cap = nullptr;
52 OH_AVCapability *cap_Hevc = nullptr;
53 fileInfo file_640_480_rgba{"/data/test/media/640_480.rgba", GRAPHIC_PIXEL_FMT_RGBA_8888, 640, 480 };
54 fileInfo file_1280_536_nv21{"/data/test/media/1280_536_nv21.yuv", GRAPHIC_PIXEL_FMT_YCRCB_420_SP, 1280, 536 };
55 fileInfo file_1280_720_nv12{"/data/test/media/1280_720_nv12.yuv", GRAPHIC_PIXEL_FMT_YCBCR_420_SP, 1280, 720 };
56 fileInfo file_1920_816_rgba{"/data/test/media/1920_816.rgba", GRAPHIC_PIXEL_FMT_RGBA_8888, 1920, 816 };
57 fileInfo file_1920_1080_nv21{"/data/test/media/1920_1080_nv21.yuv", GRAPHIC_PIXEL_FMT_YCRCB_420_SP, 1920, 1080 };
58 fileInfo file_3840_2160_nv12{"/data/test/media/3840_2160_nv12.yuv", GRAPHIC_PIXEL_FMT_YCBCR_420_SP, 3840, 2160 };
59 
SetUpTestCase()60 void HwEncInnerFunc2NdkTest::SetUpTestCase()
61 {
62     cap = OH_AVCodec_GetCapabilityByCategory(g_codecMime.c_str(), true, HARDWARE);
63     const char *tmpCodecName = OH_AVCapability_GetName(cap);
64     g_codecName = tmpCodecName;
65     cout << "g_codecName: " << g_codecName << endl;
66 
67     cap_Hevc = OH_AVCodec_GetCapabilityByCategory(g_codecMimeHevc.c_str(), true, HARDWARE);
68     const char *tmpCodecNameHevc = OH_AVCapability_GetName(cap_Hevc);
69     g_codecNameHevc = tmpCodecNameHevc;
70     cout << "g_codecNameHevc: " << g_codecNameHevc << endl;
71 }
72 
TearDownTestCase()73 void HwEncInnerFunc2NdkTest::TearDownTestCase() {}
74 
SetUp()75 void HwEncInnerFunc2NdkTest::SetUp()
76 {
77 }
78 
TearDown()79 void HwEncInnerFunc2NdkTest::TearDown()
80 {
81 }
82 } // namespace
83 
84 namespace {
85 /**
86  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0010
87  * @tc.name      : 264 video cq sync encode
88  * @tc.desc      : function test
89  */
90 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0010, TestSize.Level2)
91 {
92     if (cap != nullptr) {
93         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap, VIDEO_ENCODER_B_FRAME);
94         if (format != nullptr) {
95             OH_AVFormat_Destroy(format);
96             format = nullptr;
97             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
98             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
99             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0010.h264";
100             vEncInnerSample->enbleSyncMode = 1;
101             vEncInnerSample->enbleBFrameMode = true;
102             vEncInnerSample->DEFAULT_BITRATE_MODE = CQ;
103             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecName));
104             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
105             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
106             vEncInnerSample->WaitForEOS();
107             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
108         }
109     }
110 }
111 
112 /**
113  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0020
114  * @tc.name      : 264 video cbr sync encode
115  * @tc.desc      : function test
116  */
117 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0020, TestSize.Level2)
118 {
119     if (cap != nullptr) {
120         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap, VIDEO_ENCODER_B_FRAME);
121         if (format != nullptr) {
122             OH_AVFormat_Destroy(format);
123             format = nullptr;
124             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
125             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
126             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0020.h264";
127             vEncInnerSample->enbleSyncMode = 1;
128             vEncInnerSample->enbleBFrameMode = true;
129             vEncInnerSample->DEFAULT_BITRATE_MODE = CBR;
130             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecName));
131             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
132             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
133             vEncInnerSample->WaitForEOS();
134             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
135         }
136     }
137 }
138 
139 /**
140  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0030
141  * @tc.name      : 264 video sqr sync encode
142  * @tc.desc      : function test
143  */
144 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0030, TestSize.Level2)
145 {
146     if (cap != nullptr) {
147         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap, VIDEO_ENCODER_B_FRAME);
148         if (format != nullptr) {
149             OH_AVFormat_Destroy(format);
150             format = nullptr;
151             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
152             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
153             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0030.h264";
154             vEncInnerSample->enbleSyncMode = 1;
155             vEncInnerSample->enbleBFrameMode = true;
156             vEncInnerSample->DEFAULT_BITRATE_MODE = SQR;
157             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecName));
158             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
159             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
160             vEncInnerSample->WaitForEOS();
161             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
162         }
163     }
164 }
165 
166 /**
167  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0040
168  * @tc.name      : 264 video vbr sync encode
169  * @tc.desc      : function test
170  */
171 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0040, TestSize.Level0)
172 {
173     if (cap != nullptr) {
174         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap, VIDEO_ENCODER_B_FRAME);
175         if (format != nullptr) {
176             OH_AVFormat_Destroy(format);
177             format = nullptr;
178             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
179             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
180             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0040.h264";
181             vEncInnerSample->enbleSyncMode = 1;
182             vEncInnerSample->enbleBFrameMode = true;
183             vEncInnerSample->DEFAULT_BITRATE_MODE = VBR;
184             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecName));
185             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
186             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
187             vEncInnerSample->WaitForEOS();
188             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
189         }
190     }
191 }
192 
193 /**
194  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0050
195  * @tc.name      : 264 video surface sync encode
196  * @tc.desc      : function test
197  */
198 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0050, TestSize.Level0)
199 {
200     if (cap != nullptr) {
201         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap, VIDEO_ENCODER_B_FRAME);
202         if (format != nullptr) {
203             OH_AVFormat_Destroy(format);
204             format = nullptr;
205             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
206             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
207             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0050.h264";
208             vEncInnerSample->enbleSyncMode = 1;
209             vEncInnerSample->enbleBFrameMode = true;
210             vEncInnerSample->surfaceInput = true;
211             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecName));
212             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
213             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
214             vEncInnerSample->WaitForEOS();
215             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
216         }
217     }
218 }
219 
220 /**
221  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0060
222  * @tc.name      : 264 video resolution change sync encode
223  * @tc.desc      : function test
224  */
225 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0060, TestSize.Level2)
226 {
227     if (cap != nullptr) {
228         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap, VIDEO_ENCODER_B_FRAME);
229         if (format != nullptr) {
230             OH_AVFormat_Destroy(format);
231             format = nullptr;
232             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
233             vEncInnerSample->DEFAULT_WIDTH = 3840;
234             vEncInnerSample->DEFAULT_HEIGHT = 2160;
235             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_MULTIFILE_0070.264";
236             vEncInnerSample->surfaceInput = true;
237             vEncInnerSample->readMultiFiles = true;
238             vEncInnerSample->enbleSyncMode = 1;
239             vEncInnerSample->enbleBFrameMode = true;
240             vEncInnerSample->fileInfos.push_back(file_640_480_rgba);
241             vEncInnerSample->fileInfos.push_back(file_1280_536_nv21);
242             vEncInnerSample->fileInfos.push_back(file_1280_720_nv12);
243             vEncInnerSample->fileInfos.push_back(file_1920_816_rgba);
244             vEncInnerSample->fileInfos.push_back(file_1920_1080_nv21);
245             vEncInnerSample->fileInfos.push_back(file_3840_2160_nv12);
246             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecName));
247             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
248             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
249             vEncInnerSample->WaitForEOS();
250         }
251     }
252 }
253 
254 /**
255  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0070
256  * @tc.name      : 265 video CBR sync encode
257  * @tc.desc      : function test
258  */
259 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0070, TestSize.Level2)
260 {
261     if (cap_Hevc != nullptr) {
262         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap_Hevc, VIDEO_ENCODER_B_FRAME);
263         if (format != nullptr) {
264             OH_AVFormat_Destroy(format);
265             format = nullptr;
266             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
267             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
268             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0070.h265";
269             vEncInnerSample->enbleSyncMode = 1;
270             vEncInnerSample->enbleBFrameMode = true;
271             vEncInnerSample->DEFAULT_BITRATE_MODE = CBR;
272             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecNameHevc));
273             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
274             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
275             vEncInnerSample->WaitForEOS();
276             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
277         }
278     }
279 }
280 
281 /**
282  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0080
283  * @tc.name      : 265 video CQ sync encode
284  * @tc.desc      : function test
285  */
286 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0080, TestSize.Level2)
287 {
288     if (cap_Hevc != nullptr) {
289         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap_Hevc, VIDEO_ENCODER_B_FRAME);
290         if (format != nullptr) {
291             OH_AVFormat_Destroy(format);
292             format = nullptr;
293             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
294             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
295             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0080.h265";
296             vEncInnerSample->enbleSyncMode = 1;
297             vEncInnerSample->enbleBFrameMode = true;
298             vEncInnerSample->DEFAULT_BITRATE_MODE = CQ;
299             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecNameHevc));
300             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
301             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
302             vEncInnerSample->WaitForEOS();
303             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
304         }
305     }
306 }
307 
308 /**
309  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0090
310  * @tc.name      : 265 video sqr sync encode
311  * @tc.desc      : function test
312  */
313 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0090, TestSize.Level2)
314 {
315     if (cap_Hevc != nullptr) {
316         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap_Hevc, VIDEO_ENCODER_B_FRAME);
317         if (format != nullptr) {
318             OH_AVFormat_Destroy(format);
319             format = nullptr;
320             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
321             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
322             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0090.h265";
323             vEncInnerSample->enbleSyncMode = 1;
324             vEncInnerSample->enbleBFrameMode = true;
325             vEncInnerSample->DEFAULT_BITRATE_MODE = SQR;
326             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecNameHevc));
327             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
328             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
329             vEncInnerSample->WaitForEOS();
330             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
331         }
332     }
333 }
334 
335 /**
336  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0100
337  * @tc.name      : 265 video vbr sync encode
338  * @tc.desc      : function test
339  */
340 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0100, TestSize.Level0)
341 {
342     if (cap_Hevc != nullptr) {
343         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap_Hevc, VIDEO_ENCODER_B_FRAME);
344         if (format != nullptr) {
345             OH_AVFormat_Destroy(format);
346             format = nullptr;
347             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
348             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
349             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0100.h265";
350             vEncInnerSample->enbleSyncMode = 1;
351             vEncInnerSample->enbleBFrameMode = true;
352             vEncInnerSample->DEFAULT_BITRATE_MODE = VBR;
353             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecNameHevc));
354             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
355             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
356             vEncInnerSample->WaitForEOS();
357             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
358         }
359     }
360 }
361 
362 /**
363  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0110
364  * @tc.name      : 265 video surface sync encode
365  * @tc.desc      : function test
366  */
367 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0110, TestSize.Level0)
368 {
369     if (cap_Hevc != nullptr) {
370         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap_Hevc, VIDEO_ENCODER_B_FRAME);
371         if (format != nullptr) {
372             OH_AVFormat_Destroy(format);
373             format = nullptr;
374             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
375             vEncInnerSample->INP_DIR = "/data/test/media/1280_720_nv.yuv";
376             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0110.h265";
377             vEncInnerSample->enbleSyncMode = 1;
378             vEncInnerSample->enbleBFrameMode = true;
379             vEncInnerSample->surfaceInput = true;
380             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecNameHevc));
381             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
382             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
383             vEncInnerSample->WaitForEOS();
384             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->errCount);
385         }
386     }
387 }
388 
389 /**
390  * @tc.number    : VIDEO_ENCODE_BFRAME_INNER_SYNC_0120
391  * @tc.name      : 265 video resolution change sync encode
392  * @tc.desc      : function test
393  */
394 HWTEST_F(HwEncInnerFunc2NdkTest, VIDEO_ENCODE_BFRAME_INNER_SYNC_0120, TestSize.Level2)
395 {
396     if (cap_Hevc != nullptr) {
397         OH_AVFormat *format =  OH_AVCapability_GetFeatureProperties(cap_Hevc, VIDEO_ENCODER_B_FRAME);
398         if (format != nullptr) {
399             OH_AVFormat_Destroy(format);
400             format = nullptr;
401             auto vEncInnerSample = make_unique<VEncNdkInnerSample>();
402             vEncInnerSample->DEFAULT_WIDTH = 3840;
403             vEncInnerSample->DEFAULT_HEIGHT = 2160;
404             vEncInnerSample->OUT_DIR = "/data/test/media/VIDEO_ENCODE_BFRAME_INNER_SYNC_0120.h265";
405             vEncInnerSample->surfaceInput = true;
406             vEncInnerSample->readMultiFiles = true;
407             vEncInnerSample->enbleSyncMode = 1;
408             vEncInnerSample->enbleBFrameMode = true;
409             vEncInnerSample->fileInfos.push_back(file_640_480_rgba);
410             vEncInnerSample->fileInfos.push_back(file_1280_536_nv21);
411             vEncInnerSample->fileInfos.push_back(file_1280_720_nv12);
412             vEncInnerSample->fileInfos.push_back(file_1920_816_rgba);
413             vEncInnerSample->fileInfos.push_back(file_1920_1080_nv21);
414             vEncInnerSample->fileInfos.push_back(file_3840_2160_nv12);
415             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->CreateByName(g_codecNameHevc));
416             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->Configure());
417             ASSERT_EQ(AV_ERR_OK, vEncInnerSample->StartVideoEncoder());
418             vEncInnerSample->WaitForEOS();
419         }
420     }
421 }
422 } // namespace