1 /*
2  * Copyright (C) 2017 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 #define LOG_TAG "media_omx_hidl_video_test_common"
18 #ifdef __LP64__
19 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
20 #endif
21 
22 #include <android-base/logging.h>
23 
24 #include <android/hardware/media/omx/1.0/IOmx.h>
25 #include <android/hardware/media/omx/1.0/IOmxNode.h>
26 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
27 #include <android/hardware/media/omx/1.0/types.h>
28 #include <android/hidl/allocator/1.0/IAllocator.h>
29 #include <android/hidl/memory/1.0/IMapper.h>
30 #include <android/hidl/memory/1.0/IMemory.h>
31 
32 using ::android::hardware::media::omx::V1_0::IOmx;
33 using ::android::hardware::media::omx::V1_0::IOmxObserver;
34 using ::android::hardware::media::omx::V1_0::IOmxNode;
35 using ::android::hardware::media::omx::V1_0::Message;
36 using ::android::hardware::media::omx::V1_0::CodecBuffer;
37 using ::android::hardware::media::omx::V1_0::PortMode;
38 using ::android::hidl::allocator::V1_0::IAllocator;
39 using ::android::hidl::memory::V1_0::IMemory;
40 using ::android::hidl::memory::V1_0::IMapper;
41 using ::android::hardware::Return;
42 using ::android::hardware::Void;
43 using ::android::hardware::hidl_vec;
44 using ::android::hardware::hidl_string;
45 using ::android::sp;
46 
47 #include <VtsHalHidlTargetTestBase.h>
48 #include <hidlmemory/mapping.h>
49 #include <media/hardware/HardwareAPI.h>
50 #include <media_hidl_test_common.h>
51 #include <media_video_hidl_test_common.h>
52 #include <memory>
53 
enumerateProfileAndLevel(sp<IOmxNode> omxNode,OMX_U32 portIndex,std::vector<int32_t> * arrProfile,std::vector<int32_t> * arrLevel)54 void enumerateProfileAndLevel(sp<IOmxNode> omxNode, OMX_U32 portIndex,
55                               std::vector<int32_t>* arrProfile,
56                               std::vector<int32_t>* arrLevel) {
57     android::hardware::media::omx::V1_0::Status status;
58     OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
59     param.nProfileIndex = 0;
60     arrProfile->clear();
61     arrLevel->clear();
62     while (1) {
63         status =
64             getPortParam(omxNode, OMX_IndexParamVideoProfileLevelQuerySupported,
65                          portIndex, &param);
66         if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
67         arrProfile->push_back(static_cast<int32_t>(param.eProfile));
68         arrLevel->push_back(static_cast<int32_t>(param.eLevel));
69         param.nProfileIndex++;
70         if (param.nProfileIndex == 512) {
71             // enumerated way too many, highly unusual for this to happen.
72             EXPECT_LE(param.nProfileIndex, 512U)
73                 << "Expecting OMX_ErrorNoMore but not received";
74             break;
75         }
76     }
77 }
78 
setupRAWPort(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_U32 nFrameWidth,OMX_U32 nFrameHeight,OMX_U32 nBitrate,OMX_U32 xFramerate,OMX_COLOR_FORMATTYPE eColorFormat)79 void setupRAWPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 nFrameWidth,
80                   OMX_U32 nFrameHeight, OMX_U32 nBitrate, OMX_U32 xFramerate,
81                   OMX_COLOR_FORMATTYPE eColorFormat) {
82     android::hardware::media::omx::V1_0::Status status;
83 
84     OMX_PARAM_PORTDEFINITIONTYPE portDef;
85     status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
86                           &portDef);
87     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
88     portDef.format.video.nFrameWidth = nFrameWidth;
89     portDef.format.video.nFrameHeight = nFrameHeight;
90     portDef.format.video.nStride = (((nFrameWidth + 15) >> 4) << 4);
91     portDef.format.video.nSliceHeight = (((nFrameHeight + 15) >> 4) << 4);
92     portDef.format.video.nBitrate = nBitrate;
93     portDef.format.video.xFramerate = xFramerate;
94     portDef.format.video.bFlagErrorConcealment = OMX_TRUE;
95     portDef.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
96     portDef.format.video.eColorFormat = eColorFormat;
97     status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
98                           &portDef);
99     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
100 }
101 
setupAVCPort(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_VIDEO_AVCPROFILETYPE eProfile,OMX_VIDEO_AVCLEVELTYPE eLevel,OMX_U32 xFramerate)102 void setupAVCPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
103                   OMX_VIDEO_AVCPROFILETYPE eProfile,
104                   OMX_VIDEO_AVCLEVELTYPE eLevel, OMX_U32 xFramerate) {
105     android::hardware::media::omx::V1_0::Status status;
106     OMX_VIDEO_PARAM_AVCTYPE param;
107     (void)xFramerate;  // necessary for intra frame spacing
108 
109     status = getPortParam(omxNode, OMX_IndexParamVideoAvc, portIndex, &param);
110     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
111     param.nSliceHeaderSpacing = 0;
112     param.nPFrames = 300;
113     param.nBFrames = 0;
114     param.bUseHadamard = OMX_TRUE;
115     param.nRefFrames = 1;
116     param.eProfile = eProfile;
117     param.eLevel = eLevel;
118     param.nAllowedPictureTypes =
119         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
120     param.bFrameMBsOnly = OMX_TRUE;
121     param.bEntropyCodingCABAC = OMX_FALSE;
122     param.bWeightedPPrediction = OMX_FALSE;
123     param.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
124     status = setPortParam(omxNode, OMX_IndexParamVideoAvc, portIndex, &param);
125     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
126 }
127 
setupHEVCPort(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_VIDEO_HEVCPROFILETYPE eProfile,OMX_VIDEO_HEVCLEVELTYPE eLevel)128 void setupHEVCPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
129                    OMX_VIDEO_HEVCPROFILETYPE eProfile,
130                    OMX_VIDEO_HEVCLEVELTYPE eLevel) {
131     android::hardware::media::omx::V1_0::Status status;
132     OMX_VIDEO_PARAM_HEVCTYPE param;
133 
134     status = getPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc,
135                           portIndex, &param);
136     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
137     (void)eProfile;
138     (void)eLevel;
139     // SPECIAL CASE; OMX.qcom.video.encoder.hevc does not support the level it
140     // enumerated in the list. Lets skip this for now
141     // param.eProfile = eProfile;
142     // param.eLevel = eLevel;
143     param.nKeyFrameInterval = 300;
144     status = setPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc,
145                           portIndex, &param);
146     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
147 }
148 
setupMPEG4Port(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_VIDEO_MPEG4PROFILETYPE eProfile,OMX_VIDEO_MPEG4LEVELTYPE eLevel,OMX_U32 xFramerate)149 void setupMPEG4Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
150                     OMX_VIDEO_MPEG4PROFILETYPE eProfile,
151                     OMX_VIDEO_MPEG4LEVELTYPE eLevel, OMX_U32 xFramerate) {
152     android::hardware::media::omx::V1_0::Status status;
153     OMX_VIDEO_PARAM_MPEG4TYPE param;
154     (void)xFramerate;  // necessary for intra frame spacing
155 
156     status = getPortParam(omxNode, OMX_IndexParamVideoMpeg4, portIndex, &param);
157     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
158 
159     param.nSliceHeaderSpacing = 0;
160     param.bSVH = OMX_FALSE;
161     param.bGov = OMX_FALSE;
162     param.nPFrames = 300;
163     param.nBFrames = 0;
164     param.nIDCVLCThreshold = 0;
165     param.bACPred = OMX_TRUE;
166     param.nMaxPacketSize = 256;
167     param.eProfile = eProfile;
168     param.eLevel = eLevel;
169     param.nAllowedPictureTypes =
170         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
171     param.nHeaderExtension = 0;
172     param.bReversibleVLC = OMX_FALSE;
173     status = setPortParam(omxNode, OMX_IndexParamVideoMpeg4, portIndex, &param);
174     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
175 }
176 
setupH263Port(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_VIDEO_H263PROFILETYPE eProfile,OMX_VIDEO_H263LEVELTYPE eLevel,OMX_U32 xFramerate)177 void setupH263Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
178                    OMX_VIDEO_H263PROFILETYPE eProfile,
179                    OMX_VIDEO_H263LEVELTYPE eLevel, OMX_U32 xFramerate) {
180     android::hardware::media::omx::V1_0::Status status;
181     OMX_VIDEO_PARAM_H263TYPE param;
182     (void)xFramerate;  // necessary for intra frame spacing
183 
184     status = getPortParam(omxNode, OMX_IndexParamVideoH263, portIndex, &param);
185     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
186 
187     param.nPFrames = 300;
188     param.nBFrames = 0;
189     param.eProfile = eProfile;
190     param.eLevel = eLevel;
191     param.nAllowedPictureTypes =
192         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
193     param.bPLUSPTYPEAllowed = OMX_FALSE;
194     param.bForceRoundingTypeToZero = OMX_FALSE;
195     param.nPictureHeaderRepetition = 0;
196     param.nGOBHeaderInterval = 0;
197     status = setPortParam(omxNode, OMX_IndexParamVideoH263, portIndex, &param);
198     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
199 }
200 
setupVPXPort(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_U32 xFramerate)201 void setupVPXPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 xFramerate) {
202     android::hardware::media::omx::V1_0::Status status;
203     OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE param;
204     (void)xFramerate;  // necessary for intra frame spacing
205 
206     status = getPortParam(omxNode,
207                           (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
208                           portIndex, &param);
209     // EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
210     // SPECIAL CASE; OMX.qcom.video.encoder.vp8 does not support this index
211     // type. Dont flag error for now
212     if (status != ::android::hardware::media::omx::V1_0::Status::OK) return;
213 
214     param.nKeyFrameInterval = 300;
215     param.eTemporalPattern = OMX_VIDEO_VPXTemporalLayerPatternNone;
216     param.nMinQuantizer = 2;
217     param.nMaxQuantizer = 63;
218     status = setPortParam(omxNode,
219                           (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
220                           portIndex, &param);
221     // EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
222     // SPECIAL CASE; OMX.qcom.video.encoder.vp8 does not support this index
223     // type. Dont flag error for now
224     if (status != ::android::hardware::media::omx::V1_0::Status::OK) return;
225 }
226 
setupVP8Port(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_VIDEO_VP8PROFILETYPE eProfile,OMX_VIDEO_VP8LEVELTYPE eLevel)227 void setupVP8Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
228                   OMX_VIDEO_VP8PROFILETYPE eProfile,
229                   OMX_VIDEO_VP8LEVELTYPE eLevel) {
230     android::hardware::media::omx::V1_0::Status status;
231     OMX_VIDEO_PARAM_VP8TYPE param;
232 
233     status = getPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoVp8,
234                           portIndex, &param);
235     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
236 
237     param.eProfile = eProfile;
238     param.eLevel = eLevel;
239     param.bErrorResilientMode = OMX_TRUE;
240     param.nDCTPartitions = 1;
241     status = setPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoVp8,
242                           portIndex, &param);
243     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
244 }
245 
setupVP9Port(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_VIDEO_VP9PROFILETYPE eProfile,OMX_VIDEO_VP9LEVELTYPE eLevel)246 void setupVP9Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
247                   OMX_VIDEO_VP9PROFILETYPE eProfile,
248                   OMX_VIDEO_VP9LEVELTYPE eLevel) {
249     android::hardware::media::omx::V1_0::Status status;
250     OMX_VIDEO_PARAM_VP9TYPE param;
251 
252     status = getPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoVp9,
253                           portIndex, &param);
254     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
255 
256     param.eProfile = eProfile;
257     param.eLevel = eLevel;
258     param.bErrorResilientMode = OMX_TRUE;
259     param.nTileRows = 1;
260     param.nTileColumns = 1;
261     param.bEnableFrameParallelDecoding = OMX_TRUE;
262     status = setPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoVp9,
263                           portIndex, &param);
264     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
265 }
266