• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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_NDEBUG 0
18 #define LOG_TAG "codec2_hidl_hal_video_enc_test"
19 
20 #include <android-base/logging.h>
21 #include <gtest/gtest.h>
22 #include <stdio.h>
23 #include <fstream>
24 
25 #include <codec2/hidl/client.h>
26 #include <C2AllocatorIon.h>
27 #include <C2Config.h>
28 #include <C2Debug.h>
29 #include <C2Buffer.h>
30 #include <C2BufferPriv.h>
31 
32 using android::C2AllocatorIon;
33 
34 #include <VtsHalHidlTargetTestBase.h>
35 #include "media_c2_video_hidl_test_common.h"
36 #include "media_c2_hidl_test_common.h"
37 
38 class GraphicBuffer : public C2Buffer {
39 public:
GraphicBuffer(const std::shared_ptr<C2GraphicBlock> & block)40   explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
41       : C2Buffer({block->share(C2Rect(block->width(), block->height()),
42                                ::C2Fence())}) {}
43 };
44 
45 static ComponentTestEnvironment* gEnv = nullptr;
46 
47 namespace {
48 
49 class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
50    private:
51     typedef ::testing::VtsHalHidlTargetTestBase Super;
52 
53    public:
getTestCaseInfo() const54     ::std::string getTestCaseInfo() const override {
55         return ::std::string() +
56                 "Component: " + gEnv->getComponent().c_str() + " | " +
57                 "Instance: " + gEnv->getInstance().c_str() + " | " +
58                 "Res: " + gEnv->getRes().c_str();
59     }
60 
61     // google.codec2 Video test setup
SetUp()62     virtual void SetUp() override {
63         Super::SetUp();
64         mDisableTest = false;
65         ALOGV("Codec2VideoEncHidlTest SetUp");
66         mClient = android::Codec2Client::CreateFromService(
67             gEnv->getInstance().c_str());
68         ASSERT_NE(mClient, nullptr);
69         mListener.reset(new CodecListener(
70             [this](std::list<std::unique_ptr<C2Work>>& workItems) {
71                 handleWorkDone(workItems);
72             }));
73         ASSERT_NE(mListener, nullptr);
74         for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
75             mWorkQueue.emplace_back(new C2Work);
76         }
77         mClient->createComponent(gEnv->getComponent().c_str(), mListener,
78                                  &mComponent);
79         ASSERT_NE(mComponent, nullptr);
80 
81         std::shared_ptr<C2AllocatorStore> store =
82             android::GetCodec2PlatformAllocatorStore();
83         CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC,
84                                        &mGraphicAllocator),
85                  C2_OK);
86         mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator,
87                                                            mBlockPoolId++);
88         ASSERT_NE(mGraphicPool, nullptr);
89 
90         mCompName = unknown_comp;
91         struct StringToName {
92             const char* Name;
93             standardComp CompName;
94         };
95 
96         const StringToName kStringToName[] = {
97             {"h263", h263}, {"avc", avc}, {"mpeg4", mpeg4},
98             {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
99         };
100 
101         const size_t kNumStringToName =
102             sizeof(kStringToName) / sizeof(kStringToName[0]);
103 
104         std::string substring;
105         std::string comp;
106         substring = std::string(gEnv->getComponent());
107         /* TODO: better approach to find the component */
108         /* "c2.android." => 11th position */
109         size_t pos = 11;
110         size_t len = substring.find(".encoder", pos);
111         comp = substring.substr(pos, len - pos);
112 
113         for (size_t i = 0; i < kNumStringToName; ++i) {
114             if (!strcasecmp(comp.c_str(), kStringToName[i].Name)) {
115                 mCompName = kStringToName[i].CompName;
116                 break;
117             }
118         }
119         mEos = false;
120         mCsd = false;
121         mConfig = false;
122         mFramesReceived = 0;
123         mFailedWorkReceived = 0;
124         if (mCompName == unknown_comp) mDisableTest = true;
125         if (mDisableTest) std::cout << "[   WARN   ] Test Disabled \n";
126     }
127 
TearDown()128     virtual void TearDown() override {
129         if (mComponent != nullptr) {
130             if (::testing::Test::HasFatalFailure()) return;
131             mComponent->release();
132             mComponent = nullptr;
133         }
134         Super::TearDown();
135     }
136 
137     void setupConfigParam(int32_t nWidth, int32_t nHeight);
138 
139     // callback function to process onWorkDone received by Listener
handleWorkDone(std::list<std::unique_ptr<C2Work>> & workItems)140     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
141         for (std::unique_ptr<C2Work>& work : workItems) {
142             if (!work->worklets.empty()) {
143                 if (work->result != C2_OK) mFailedWorkReceived++;
144                 workDone(mComponent, work, mFlushedIndices, mQueueLock,
145                          mQueueCondition, mWorkQueue, mEos, mCsd,
146                          mFramesReceived);
147             }
148         }
149     }
150 
151     enum standardComp {
152         h263,
153         avc,
154         mpeg4,
155         hevc,
156         vp8,
157         vp9,
158         unknown_comp,
159     };
160 
161     bool mEos;
162     bool mCsd;
163     bool mDisableTest;
164     bool mConfig;
165     standardComp mCompName;
166     uint32_t mFramesReceived;
167     uint32_t mFailedWorkReceived;
168 
169     std::list<uint64_t> mFlushedIndices;
170 
171     C2BlockPool::local_id_t mBlockPoolId;
172     std::shared_ptr<C2BlockPool> mGraphicPool;
173     std::shared_ptr<C2Allocator> mGraphicAllocator;
174 
175     std::mutex mQueueLock;
176     std::condition_variable mQueueCondition;
177     std::list<std::unique_ptr<C2Work>> mWorkQueue;
178 
179     std::shared_ptr<android::Codec2Client> mClient;
180     std::shared_ptr<android::Codec2Client::Listener> mListener;
181     std::shared_ptr<android::Codec2Client::Component> mComponent;
182 
183    protected:
description(const std::string & description)184     static void description(const std::string& description) {
185         RecordProperty("description", description);
186     }
187 };
188 
validateComponent(const std::shared_ptr<android::Codec2Client::Component> & component,Codec2VideoEncHidlTest::standardComp compName,bool & disableTest)189 void validateComponent(
190     const std::shared_ptr<android::Codec2Client::Component>& component,
191     Codec2VideoEncHidlTest::standardComp compName, bool& disableTest) {
192     // Validate its a C2 Component
193     if (component->getName().find("c2") == std::string::npos) {
194         ALOGE("Not a c2 component");
195         disableTest = true;
196         return;
197     }
198 
199     // Validate its not an encoder and the component to be tested is video
200     if (component->getName().find("decoder") != std::string::npos) {
201         ALOGE("Expected Encoder, given Decoder");
202         disableTest = true;
203         return;
204     }
205     std::vector<std::unique_ptr<C2Param>> queried;
206     c2_status_t c2err =
207         component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
208                          C2_DONT_BLOCK, &queried);
209     if (c2err != C2_OK && queried.size() == 0) {
210         ALOGE("Query media type failed => %d", c2err);
211     } else {
212         std::string inputDomain =
213             ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
214         if (inputDomain.find("video/") == std::string::npos) {
215             ALOGE("Expected Video Component");
216             disableTest = true;
217             return;
218         }
219     }
220 
221     // Validates component name
222     if (compName == Codec2VideoEncHidlTest::unknown_comp) {
223         ALOGE("Component InValid");
224         disableTest = true;
225         return;
226     }
227     ALOGV("Component Valid");
228 }
229 
230 // Set Default config param.
setupConfigParam(int32_t nWidth,int32_t nHeight)231 void Codec2VideoEncHidlTest::setupConfigParam(int32_t nWidth, int32_t nHeight) {
232     std::vector<std::unique_ptr<C2SettingResult>> failures;
233     C2VideoSizeStreamTuning::input inputSize(0u, nWidth, nHeight);
234     std::vector<C2Param*> configParam{&inputSize};
235     c2_status_t status =
236         mComponent->config(configParam, C2_DONT_BLOCK, &failures);
237     if (failures.size() == 0u ) mConfig = true;
238     ASSERT_EQ(status, C2_OK);
239 }
240 
241 // LookUpTable of clips for component testing
GetURLForComponent(char * URL)242 void GetURLForComponent(char* URL) {
243     strcat(URL, "bbb_352x288_420p_30fps_32frames.yuv");
244 }
245 
encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> & component,std::mutex & queueLock,std::condition_variable & queueCondition,std::list<std::unique_ptr<C2Work>> & workQueue,std::list<uint64_t> & flushedIndices,std::shared_ptr<C2BlockPool> & graphicPool,std::ifstream & eleStream,uint32_t frameID,uint32_t nFrames,uint32_t nWidth,int32_t nHeight,bool flushed=false,bool signalEOS=true)246 void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
247                    std::mutex &queueLock, std::condition_variable& queueCondition,
248                    std::list<std::unique_ptr<C2Work>>& workQueue,
249                    std::list<uint64_t>& flushedIndices,
250                    std::shared_ptr<C2BlockPool>& graphicPool,
251                    std::ifstream& eleStream, uint32_t frameID,
252                    uint32_t nFrames, uint32_t nWidth, int32_t nHeight,
253                    bool flushed = false,bool signalEOS = true) {
254     typedef std::unique_lock<std::mutex> ULock;
255 
256     uint32_t maxRetry = 0;
257     int bytesCount = nWidth * nHeight * 3 >> 1;
258     int32_t timestampIncr = ENCODER_TIMESTAMP_INCREMENT;
259     uint64_t timestamp = 0;
260     while (1) {
261         if (nFrames == 0) break;
262         uint32_t flags = 0;
263         std::unique_ptr<C2Work> work;
264         // Prepare C2Work
265         while (!work && (maxRetry < MAX_RETRY)) {
266             ULock l(queueLock);
267             if (!workQueue.empty()) {
268                 work.swap(workQueue.front());
269                 workQueue.pop_front();
270             } else {
271                 queueCondition.wait_for(l, TIME_OUT);
272                 maxRetry++;
273             }
274         }
275         if (!work && (maxRetry >= MAX_RETRY)) {
276             ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
277         }
278         if (signalEOS && (nFrames == 1))
279             flags |= C2FrameData::FLAG_END_OF_STREAM;
280         if (flushed) {
281             flags |= SYNC_FRAME;
282             flushed = false;
283         }
284 
285         work->input.flags = (C2FrameData::flags_t)flags;
286         work->input.ordinal.timestamp = timestamp;
287         work->input.ordinal.frameIndex = frameID;
288         {
289             ULock l(queueLock);
290             flushedIndices.emplace_back(frameID);
291         }
292         char* data = (char*)malloc(bytesCount);
293         ASSERT_NE(data, nullptr);
294         memset(data, 0, bytesCount);
295         if (eleStream.is_open()) {
296             eleStream.read(data, bytesCount);
297             ASSERT_EQ(eleStream.gcount(), bytesCount);
298         }
299         std::shared_ptr<C2GraphicBlock> block;
300         ASSERT_EQ(
301             C2_OK,
302             graphicPool->fetchGraphicBlock(
303                 nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
304                 {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
305         ASSERT_TRUE(block);
306         // Graphic View
307         C2GraphicView view = block->map().get();
308         if (view.error() != C2_OK) {
309             fprintf(stderr, "C2GraphicBlock::map() failed : %d", view.error());
310             break;
311         }
312 
313         uint8_t* pY = view.data()[C2PlanarLayout::PLANE_Y];
314         uint8_t* pU = view.data()[C2PlanarLayout::PLANE_U];
315         uint8_t* pV = view.data()[C2PlanarLayout::PLANE_V];
316 
317         memcpy(pY, data, nWidth * nHeight);
318         memcpy(pU, data + nWidth * nHeight, (nWidth * nHeight >> 2));
319         memcpy(pV, data + (nWidth * nHeight * 5 >> 2), nWidth * nHeight >> 2);
320 
321         work->input.buffers.clear();
322         work->input.buffers.emplace_back(new GraphicBuffer(block));
323         work->worklets.clear();
324         work->worklets.emplace_back(new C2Worklet);
325         free(data);
326 
327         std::list<std::unique_ptr<C2Work>> items;
328         items.push_back(std::move(work));
329 
330         // DO THE ENCODING
331         ASSERT_EQ(component->queue(&items), C2_OK);
332         ALOGV("Frame #%d size = %d queued", frameID, bytesCount);
333         nFrames--;
334         timestamp += timestampIncr;
335         frameID++;
336         maxRetry = 0;
337     }
338 }
339 
TEST_F(Codec2VideoEncHidlTest,validateCompName)340 TEST_F(Codec2VideoEncHidlTest, validateCompName) {
341     if (mDisableTest) return;
342     ALOGV("Checks if the given component is a valid video component");
343     validateComponent(mComponent, mCompName, mDisableTest);
344     ASSERT_EQ(mDisableTest, false);
345 }
346 
TEST_F(Codec2VideoEncHidlTest,EncodeTest)347 TEST_F(Codec2VideoEncHidlTest, EncodeTest) {
348     description("Encodes input file");
349     if (mDisableTest) return;
350 
351     char mURL[512];
352     int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH;
353     int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT;
354 
355     strcpy(mURL, gEnv->getRes().c_str());
356     GetURLForComponent(mURL);
357 
358     std::ifstream eleStream;
359     eleStream.open(mURL, std::ifstream::binary);
360     ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
361     ALOGV("mURL : %s", mURL);
362 
363     setupConfigParam(nWidth, nHeight);
364     if (!mConfig) {
365         std::cout << "[   WARN   ] Test Skipped \n";
366         return;
367     }
368     ASSERT_EQ(mComponent->start(), C2_OK);
369     ASSERT_NO_FATAL_FAILURE(
370         encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
371                       mFlushedIndices, mGraphicPool, eleStream,
372                       0, ENC_NUM_FRAMES, nWidth, nHeight));
373 
374     // blocking call to ensures application to Wait till all the inputs are
375     // consumed
376     ALOGD("Waiting for input consumption");
377     ASSERT_NO_FATAL_FAILURE(
378         waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
379 
380     eleStream.close();
381     if (mFramesReceived != ENC_NUM_FRAMES) {
382         ALOGE("Input buffer count and Output buffer count mismatch");
383         ALOGE("framesReceived : %d inputFrames : %d", mFramesReceived,
384               ENC_NUM_FRAMES);
385         ASSERT_TRUE(false);
386     }
387 
388     if (!mCsd && (mCompName != vp8 && mCompName != vp9)) {
389         ASSERT_TRUE(false) << "CSD Buffer not received";
390     }
391 
392     if (mCsd && (mCompName == vp8 || mCompName == vp9)) {
393         ASSERT_TRUE(false) << "CSD Buffer not expected";
394     }
395 
396     ASSERT_EQ(mComponent->stop(), C2_OK);
397 }
398 
TEST_F(Codec2VideoEncHidlTest,EOSTest)399 TEST_F(Codec2VideoEncHidlTest, EOSTest) {
400     description("Test empty input buffer with EOS flag");
401     if (mDisableTest) return;
402     ASSERT_EQ(mComponent->start(), C2_OK);
403 
404     typedef std::unique_lock<std::mutex> ULock;
405     std::unique_ptr<C2Work> work;
406     {
407         ULock l(mQueueLock);
408         if (!mWorkQueue.empty()) {
409             work.swap(mWorkQueue.front());
410             mWorkQueue.pop_front();
411         } else {
412             ALOGE("mWorkQueue Empty is not expected at the start of the test");
413             ASSERT_TRUE(false);
414         }
415     }
416     ASSERT_NE(work, nullptr);
417     work->input.flags = (C2FrameData::flags_t)C2FrameData::FLAG_END_OF_STREAM;
418     work->input.ordinal.timestamp = 0;
419     work->input.ordinal.frameIndex = 0;
420     work->input.buffers.clear();
421     work->worklets.clear();
422     work->worklets.emplace_back(new C2Worklet);
423 
424     std::list<std::unique_ptr<C2Work>> items;
425     items.push_back(std::move(work));
426     ASSERT_EQ(mComponent->queue(&items), C2_OK);
427     uint32_t queueSize;
428     {
429         ULock l(mQueueLock);
430         queueSize = mWorkQueue.size();
431         if (queueSize < MAX_INPUT_BUFFERS) {
432             mQueueCondition.wait_for(l, TIME_OUT);
433         }
434     }
435     ASSERT_EQ(mEos, true);
436     ASSERT_EQ(mComponent->stop(), C2_OK);
437 }
438 
TEST_F(Codec2VideoEncHidlTest,FlushTest)439 TEST_F(Codec2VideoEncHidlTest, FlushTest) {
440     description("Test Request for flush");
441     if (mDisableTest) return;
442     ASSERT_EQ(mComponent->start(), C2_OK);
443 
444     typedef std::unique_lock<std::mutex> ULock;
445     char mURL[512];
446     int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH;
447     int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT;
448     strcpy(mURL, gEnv->getRes().c_str());
449     GetURLForComponent(mURL);
450     setupConfigParam(nWidth, nHeight);
451 
452     // Setting default configuration
453     mFlushedIndices.clear();
454     std::ifstream eleStream;
455     uint32_t numFramesFlushed = 10;
456     uint32_t numFrames = ENC_NUM_FRAMES;
457     eleStream.open(mURL, std::ifstream::binary);
458     ASSERT_EQ(eleStream.is_open(), true);
459     ALOGV("mURL : %s", mURL);
460     ASSERT_NO_FATAL_FAILURE(
461         encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
462                       mFlushedIndices, mGraphicPool, eleStream,
463                       0, numFramesFlushed, nWidth, nHeight));
464     std::list<std::unique_ptr<C2Work>> flushedWork;
465     c2_status_t err =
466         mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
467     ASSERT_EQ(err, C2_OK);
468     ASSERT_NO_FATAL_FAILURE(
469         waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
470             (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
471     uint64_t frameIndex;
472     {
473         //Update mFlushedIndices based on the index received from flush()
474         ULock l(mQueueLock);
475         for (std::unique_ptr<C2Work>& work : flushedWork) {
476             ASSERT_NE(work, nullptr);
477             frameIndex = work->input.ordinal.frameIndex.peeku();
478             std::list<uint64_t>::iterator frameIndexIt = std::find(
479                 mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
480             if (!mFlushedIndices.empty() &&
481                 (frameIndexIt != mFlushedIndices.end())) {
482                 mFlushedIndices.erase(frameIndexIt);
483                 work->input.buffers.clear();
484                 work->worklets.clear();
485                 mWorkQueue.push_back(std::move(work));
486             }
487         }
488     }
489     mFlushedIndices.clear();
490     ASSERT_NO_FATAL_FAILURE(
491         encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
492                       mFlushedIndices, mGraphicPool, eleStream,
493                       numFramesFlushed, numFrames - numFramesFlushed,
494                       nWidth, nHeight, true));
495     eleStream.close();
496     err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
497     ASSERT_EQ(err, C2_OK);
498     ASSERT_NO_FATAL_FAILURE(
499         waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
500             (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
501     {
502         //Update mFlushedIndices based on the index received from flush()
503         ULock l(mQueueLock);
504         for (std::unique_ptr<C2Work>& work : flushedWork) {
505             ASSERT_NE(work, nullptr);
506             frameIndex = work->input.ordinal.frameIndex.peeku();
507             std::list<uint64_t>::iterator frameIndexIt = std::find(
508                 mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
509             if (!mFlushedIndices.empty() &&
510                 (frameIndexIt != mFlushedIndices.end())) {
511                 mFlushedIndices.erase(frameIndexIt);
512                 work->input.buffers.clear();
513                 work->worklets.clear();
514                 mWorkQueue.push_back(std::move(work));
515             }
516         }
517     }
518     ASSERT_EQ(mFlushedIndices.empty(), true);
519     ASSERT_EQ(mComponent->stop(), C2_OK);
520 }
521 
TEST_F(Codec2VideoEncHidlTest,InvalidBufferTest)522 TEST_F(Codec2VideoEncHidlTest, InvalidBufferTest) {
523     description("Tests feeding larger/smaller input buffer");
524     if (mDisableTest) return;
525     ASSERT_EQ(mComponent->start(), C2_OK);
526 
527     std::ifstream eleStream;
528     int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH / 2;
529     int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT / 2;
530     setupConfigParam(nWidth, nHeight);
531 
532     ASSERT_NO_FATAL_FAILURE(
533         encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
534                       mFlushedIndices, mGraphicPool, eleStream,
535                       0, 1, nWidth, nHeight, false, false));
536 
537     // Feed larger input buffer.
538     ASSERT_NO_FATAL_FAILURE(
539         encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
540                       mFlushedIndices, mGraphicPool, eleStream,
541                       1, 1, nWidth*2, nHeight*2, false, false));
542 
543     // Feed smaller input buffer.
544     ASSERT_NO_FATAL_FAILURE(
545         encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
546                       mFlushedIndices, mGraphicPool, eleStream,
547                       2, 1, nWidth/2, nHeight/2, false, true));
548 
549     // blocking call to ensures application to Wait till all the inputs are
550     // consumed
551     ALOGD("Waiting for input consumption");
552     ASSERT_NO_FATAL_FAILURE(
553         waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
554 
555     if (mFramesReceived != 3) {
556         ALOGE("Input buffer count and Output buffer count mismatch");
557         ALOGE("framesReceived : %d inputFrames : 3", mFramesReceived);
558         ASSERT_TRUE(false);
559     }
560 
561     if (mFailedWorkReceived == 0) {
562         ALOGE("Expected failed frame count mismatch");
563         ALOGE("failedFramesReceived : %d", mFailedWorkReceived);
564         ASSERT_TRUE(false);
565     }
566 
567     ASSERT_EQ(mComponent->stop(), C2_OK);
568 }
569 
570 class Codec2VideoEncResolutionTest : public Codec2VideoEncHidlTest,
571         public ::testing::WithParamInterface<std::pair<int32_t, int32_t> > {
572 };
573 
TEST_P(Codec2VideoEncResolutionTest,ResolutionTest)574 TEST_P(Codec2VideoEncResolutionTest, ResolutionTest) {
575     description("Tests encoding at different resolutions");
576     if (mDisableTest) return;
577 
578     std::ifstream eleStream;
579     int32_t nWidth = GetParam().first;
580     int32_t nHeight = GetParam().second;
581     ALOGD("Trying encode for width %d height %d", nWidth, nHeight);
582     mConfig = false;
583     mEos = false;
584     setupConfigParam(nWidth, nHeight);
585     if (!mConfig) return;
586     ASSERT_EQ(mComponent->start(), C2_OK);
587 
588     ASSERT_NO_FATAL_FAILURE(
589         encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
590                       mFlushedIndices, mGraphicPool, eleStream, 0,
591                       MAX_INPUT_BUFFERS, nWidth, nHeight));
592 
593     ALOGD("Waiting for input consumption");
594     ASSERT_NO_FATAL_FAILURE(
595         waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
596 
597     ASSERT_EQ(mEos, true);
598     ASSERT_EQ(mComponent->stop(), C2_OK);
599     ASSERT_EQ(mComponent->reset(), C2_OK);
600 }
601 INSTANTIATE_TEST_CASE_P(NonStdSizes, Codec2VideoEncResolutionTest, ::testing::Values(
602     std::make_pair(52, 18),
603     std::make_pair(365, 365),
604     std::make_pair(484, 362),
605     std::make_pair(244, 488)));
606 
607 }  // anonymous namespace
608 
main(int argc,char ** argv)609 int main(int argc, char** argv) {
610     gEnv = new ComponentTestEnvironment();
611     ::testing::AddGlobalTestEnvironment(gEnv);
612     ::testing::InitGoogleTest(&argc, argv);
613     gEnv->init(&argc, argv);
614     int status = gEnv->initFromOptions(argc, argv);
615     if (status == 0) {
616         int status = RUN_ALL_TESTS();
617         LOG(INFO) << "C2 Test result = " << status;
618     }
619     return status;
620 }
621