2 * Copyright (C) 2017 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "media_omx_hidl_video_enc_test"
19 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22 #include <android-base/logging.h>
24 #include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
25 #include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
26 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
27 #include <android/hardware/graphics/mapper/2.0/types.h>
28 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
29 #include <android/hardware/media/omx/1.0/IOmx.h>
30 #include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
31 #include <android/hardware/media/omx/1.0/IOmxNode.h>
32 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
33 #include <android/hardware/media/omx/1.0/types.h>
34 #include <android/hidl/allocator/1.0/IAllocator.h>
35 #include <android/hidl/memory/1.0/IMapper.h>
36 #include <android/hidl/memory/1.0/IMemory.h>
38 using ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer;
39 using ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener;
40 using ::android::hardware::graphics::common::V1_0::BufferUsage;
41 using ::android::hardware::graphics::common::V1_0::PixelFormat;
42 using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
43 using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
44 using ::android::hardware::media::omx::V1_0::IOmx;
45 using ::android::hardware::media::omx::V1_0::IOmxObserver;
46 using ::android::hardware::media::omx::V1_0::IOmxNode;
47 using ::android::hardware::media::omx::V1_0::Message;
48 using ::android::hardware::media::omx::V1_0::CodecBuffer;
49 using ::android::hardware::media::omx::V1_0::PortMode;
50 using ::android::hidl::allocator::V1_0::IAllocator;
51 using ::android::hidl::memory::V1_0::IMemory;
52 using ::android::hidl::memory::V1_0::IMapper;
53 using ::android::hardware::Return;
54 using ::android::hardware::Void;
55 using ::android::hardware::hidl_vec;
56 using ::android::hardware::hidl_string;
59 #include <VtsHalHidlTargetTestBase.h>
61 #include <media/hardware/HardwareAPI.h>
62 #include <media_hidl_test_common.h>
63 #include <media_video_hidl_test_common.h>
64 #include <system/window.h>
67 // A class for test environment setup
68 class ComponentTestEnvironment : public ::testing::Environment {
70 virtual void SetUp() {}
71 virtual void TearDown() {}
73 ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}
75 void setInstance(const char* _instance) { instance = _instance; }
77 void setComponent(const char* _component) { component = _component; }
79 void setRole(const char* _role) { role = _role; }
81 void setRes(const char* _res) { res = _res; }
83 const hidl_string getInstance() const { return instance; }
85 const hidl_string getComponent() const { return component; }
87 const hidl_string getRole() const { return role; }
89 const hidl_string getRes() const { return res; }
91 int initFromOptions(int argc, char** argv) {
92 static struct option options[] = {
93 {"instance", required_argument, 0, 'I'},
94 {"component", required_argument, 0, 'C'},
95 {"role", required_argument, 0, 'R'},
96 {"res", required_argument, 0, 'P'},
101 int c = getopt_long(argc, argv, "I:C:R:P:", options, &index);
111 setComponent(optarg);
126 "unrecognized option: %s\n\n"
127 "usage: %s <gtest options> <test options>\n\n"
128 "test options are:\n\n"
129 "-I, --instance: HAL instance to test\n"
130 "-C, --component: OMX component to test\n"
131 "-R, --role: OMX component Role\n"
132 "-P, --res: Resource files directory location\n",
133 argv[optind ?: 1], argv[0]);
140 hidl_string instance;
141 hidl_string component;
146 static ComponentTestEnvironment* gEnv = nullptr;
148 // video encoder test fixture class
149 class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
151 typedef ::testing::VtsHalHidlTargetTestBase Super;
153 ::std::string getTestCaseInfo() const override {
154 return ::std::string() +
155 "Component: " + gEnv->getComponent().c_str() + " | " +
156 "Role: " + gEnv->getRole().c_str() + " | " +
157 "Instance: " + gEnv->getInstance().c_str() + " | " +
158 "Res: " + gEnv->getRes().c_str();
161 virtual void SetUp() override {
164 android::hardware::media::omx::V1_0::Status status;
165 omx = Super::getService<IOmx>(gEnv->getInstance());
166 ASSERT_NE(omx, nullptr);
168 new CodecObserver([this](Message msg, const BufferInfo* buffer) {
169 handleMessage(msg, buffer);
171 ASSERT_NE(observer, nullptr);
172 if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
174 EXPECT_TRUE(omx->allocateNode(
175 gEnv->getComponent(), observer,
176 [&](android::hardware::media::omx::V1_0::Status _s,
177 sp<IOmxNode> const& _nl) {
182 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
183 ASSERT_NE(omxNode, nullptr);
184 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
185 struct StringToName {
187 standardComp CompName;
189 const StringToName kStringToName[] = {
190 {"h263", h263}, {"avc", avc}, {"mpeg4", mpeg4},
191 {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
193 const size_t kNumStringToName =
194 sizeof(kStringToName) / sizeof(kStringToName[0]);
196 char substring[OMX_MAX_STRINGNAME_SIZE];
197 strcpy(substring, gEnv->getRole().c_str());
198 pch = strchr(substring, '.');
199 ASSERT_NE(pch, nullptr);
200 compName = unknown_comp;
201 for (size_t i = 0; i < kNumStringToName; ++i) {
202 if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
203 compName = kStringToName[i].CompName;
207 if (compName == unknown_comp) disableTest = true;
208 struct CompToCompression {
209 standardComp CompName;
210 OMX_VIDEO_CODINGTYPE eCompressionFormat;
212 static const CompToCompression kCompToCompression[] = {
213 {h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC},
214 {mpeg4, OMX_VIDEO_CodingMPEG4}, {hevc, OMX_VIDEO_CodingHEVC},
215 {vp8, OMX_VIDEO_CodingVP8}, {vp9, OMX_VIDEO_CodingVP9},
217 static const size_t kNumCompToCompression =
218 sizeof(kCompToCompression) / sizeof(kCompToCompression[0]);
220 for (i = 0; i < kNumCompToCompression; ++i) {
221 if (kCompToCompression[i].CompName == compName) {
222 eCompressionFormat = kCompToCompression[i].eCompressionFormat;
226 if (i == kNumCompToCompression) disableTest = true;
228 prependSPSPPS = false;
229 timestampDevTest = false;
233 size_t suffixLen = strlen(".secure");
234 if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
236 !strcmp(gEnv->getComponent().c_str() +
237 strlen(gEnv->getComponent().c_str()) - suffixLen,
240 if (isSecure) disableTest = true;
241 if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
244 virtual void TearDown() override {
245 if (omxNode != nullptr) {
246 // If you have encountered a fatal failure, it is possible that
247 // freeNode() will not go through. Instead of hanging the app.
248 // let it pass through and report errors
249 if (::testing::Test::HasFatalFailure()) return;
250 EXPECT_TRUE((omxNode->freeNode()).isOk());
256 // callback function to process messages received by onMessages() from IL
258 void handleMessage(Message msg, const BufferInfo* buffer) {
261 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
262 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
265 if (msg.data.extendedBufferData.rangeLength != 0) {
266 // Test if current timestamp is among the list of queued
268 if (timestampDevTest && ((msg.data.extendedBufferData.flags &
269 OMX_BUFFERFLAG_CODECCONFIG) == 0)) {
271 android::List<uint64_t>::iterator it =
272 timestampUslist.begin();
273 while (it != timestampUslist.end()) {
274 if (*it == msg.data.extendedBufferData.timestampUs) {
275 timestampUslist.erase(it);
281 if (tsHit == false) {
282 if (timestampUslist.empty() == false) {
283 EXPECT_EQ(tsHit, true)
284 << "TimeStamp not recognized";
286 std::cout << "[ INFO ] Received non-zero "
287 "output / TimeStamp not recognized \n";
291 #define WRITE_OUTPUT 0
293 static int count = 0;
296 ofp = fopen("out.bin", "ab");
298 ofp = fopen("out.bin", "wb");
299 if (ofp != nullptr) {
300 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
302 msg.data.extendedBufferData.rangeLength, ofp);
322 sp<CodecObserver> observer;
323 sp<IOmxNode> omxNode;
324 standardComp compName;
325 OMX_VIDEO_CODINGTYPE eCompressionFormat;
329 ::android::List<uint64_t> timestampUslist;
330 bool timestampDevTest;
332 sp<IGraphicBufferProducer> producer;
333 sp<IGraphicBufferSource> source;
336 static void description(const std::string& description) {
337 RecordProperty("description", description);
341 // CodecProducerListener class
342 struct CodecProducerListener : public IProducerListener {
344 CodecProducerListener(int a, int b)
345 : freeBuffers(a), minUnDequeuedCount(b) {}
346 virtual ::android::hardware::Return<void> onBufferReleased() override {
347 android::Mutex::Autolock autoLock(bufferLock);
351 virtual ::android::hardware::Return<bool> needsReleaseNotify() override {
355 android::Mutex::Autolock autoLock(bufferLock);
357 EXPECT_GE(freeBuffers, minUnDequeuedCount);
361 size_t minUnDequeuedCount;
362 android::Mutex bufferLock;
365 // Mock IOmxBufferSource class. GraphicBufferSource.cpp in libstagefright/omx/
366 // implements this class. Below is dummy class introduced to test if callback
367 // functions are actually being called or not
368 struct DummyBufferSource : public IOmxBufferSource {
370 DummyBufferSource(sp<IOmxNode> node) {
375 virtual Return<void> onOmxExecuting();
376 virtual Return<void> onOmxIdle();
377 virtual Return<void> onOmxLoaded();
378 virtual Return<void> onInputBufferAdded(uint32_t buffer);
379 virtual Return<void> onInputBufferEmptied(
380 uint32_t buffer, const ::android::hardware::hidl_handle& fence);
384 sp<IOmxNode> omxNode;
385 android::Vector<BufferInfo> iBuffer, oBuffer;
388 Return<void> DummyBufferSource::onOmxExecuting() {
392 // Fetch a client owned input buffer and send an EOS
393 if ((index = getEmptyBufferID(&iBuffer)) < iBuffer.size()) {
394 android::hardware::media::omx::V1_0::Status status;
395 CodecBuffer t = iBuffer[index].omxBuffer;
396 t.type = CodecBuffer::Type::ANW_BUFFER;
397 native_handle_t* fenceNh = native_handle_create(0, 0);
398 EXPECT_NE(fenceNh, nullptr);
399 status = omxNode->emptyBuffer(iBuffer[index].id, t, OMX_BUFFERFLAG_EOS,
401 native_handle_close(fenceNh);
402 native_handle_delete(fenceNh);
403 EXPECT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
404 iBuffer.editItemAt(index).owner = component;
409 Return<void> DummyBufferSource::onOmxIdle() {
415 Return<void> DummyBufferSource::onOmxLoaded() {
420 Return<void> DummyBufferSource::onInputBufferAdded(uint32_t buffer) {
422 EXPECT_EQ(executing, false);
427 Return<void> DummyBufferSource::onInputBufferEmptied(
428 uint32_t buffer, const ::android::hardware::hidl_handle& fence) {
432 for (i = 0; i < iBuffer.size(); i++) {
433 if (iBuffer[i].id == buffer) {
434 iBuffer.editItemAt(i).owner = client;
441 // request VOP refresh
442 void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
443 android::hardware::media::omx::V1_0::Status status;
444 OMX_CONFIG_INTRAREFRESHVOPTYPE param;
445 param.IntraRefreshVOP = OMX_TRUE;
446 status = setPortConfig(omxNode, OMX_IndexConfigVideoIntraVOPRefresh,
448 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
449 std::cout << "[ INFO ] unable to request IDR \n";
453 void changeBitrate(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t nBitrate) {
454 android::hardware::media::omx::V1_0::Status status;
455 OMX_VIDEO_CONFIG_BITRATETYPE param;
456 param.nEncodeBitrate = nBitrate;
458 setPortConfig(omxNode, OMX_IndexConfigVideoBitrate, portIndex, ¶m);
459 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
460 std::cout << "[ INFO ] unable to change Bitrate \n";
464 Return<android::hardware::media::omx::V1_0::Status> changeFrameRate(
465 sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t xFramerate) {
466 android::hardware::media::omx::V1_0::Status status;
467 OMX_CONFIG_FRAMERATETYPE param;
468 param.xEncodeFramerate = xFramerate;
469 status = setPortConfig(omxNode, OMX_IndexConfigVideoFramerate, portIndex,
471 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
472 std::cout << "[ INFO ] unable to change Framerate \n";
476 // modify intra refresh interval
477 void changeRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
478 uint32_t nRefreshPeriod) {
479 android::hardware::media::omx::V1_0::Status status;
480 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE param;
481 param.nRefreshPeriod = nRefreshPeriod;
482 status = setPortConfig(omxNode,
483 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
485 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
486 std::cout << "[ INFO ] unable to change Refresh Period\n";
489 // set intra refresh interval
490 void setRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
491 uint32_t nRefreshPeriod) {
492 android::hardware::media::omx::V1_0::Status status;
493 OMX_VIDEO_PARAM_INTRAREFRESHTYPE param;
494 param.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
496 if (nRefreshPeriod == 0)
499 OMX_PARAM_PORTDEFINITIONTYPE portDef;
500 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
502 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
504 ((portDef.format.video.nFrameWidth + 15) >>
505 4 * (portDef.format.video.nFrameHeight + 15) >> 4) /
509 status = setPortParam(omxNode, OMX_IndexParamVideoIntraRefresh, portIndex,
511 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
512 std::cout << "[ INFO ] unable to set Refresh Period \n";
515 void setLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t latency) {
516 android::hardware::media::omx::V1_0::Status status;
517 OMX_PARAM_U32TYPE param;
518 param.nU32 = (OMX_U32)latency;
519 status = setPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
521 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
522 std::cout << "[ INFO ] unable to set latency\n";
525 void getLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t* latency) {
526 android::hardware::media::omx::V1_0::Status status;
527 OMX_PARAM_U32TYPE param;
528 status = getPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
530 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
531 std::cout << "[ INFO ] unable to get latency\n";
533 *latency = param.nU32;
536 // Set Default port param.
537 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
538 OMX_VIDEO_CODINGTYPE eCompressionFormat,
539 OMX_U32 nFrameWidth, OMX_U32 nFrameHeight,
540 OMX_U32 nBitrate, OMX_U32 xFramerate) {
541 android::hardware::media::omx::V1_0::Status status;
542 OMX_PARAM_PORTDEFINITIONTYPE portDef;
543 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
545 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
546 portDef.format.video.nFrameWidth = nFrameWidth;
547 portDef.format.video.nFrameHeight = nFrameHeight;
548 portDef.format.video.nBitrate = nBitrate;
549 portDef.format.video.xFramerate = xFramerate;
550 portDef.format.video.bFlagErrorConcealment = OMX_TRUE;
551 portDef.format.video.eCompressionFormat = eCompressionFormat;
552 portDef.format.video.eColorFormat = OMX_COLOR_FormatUnused;
553 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
555 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
557 std::vector<int32_t> arrProfile;
558 std::vector<int32_t> arrLevel;
559 enumerateProfileAndLevel(omxNode, portIndex, &arrProfile, &arrLevel);
560 if (arrProfile.empty() == true || arrLevel.empty() == true)
562 int32_t profile = arrProfile[0];
563 int32_t level = arrLevel[0];
565 switch ((int)eCompressionFormat) {
566 case OMX_VIDEO_CodingAVC:
567 setupAVCPort(omxNode, portIndex,
568 static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile),
569 static_cast<OMX_VIDEO_AVCLEVELTYPE>(level),
572 case OMX_VIDEO_CodingHEVC:
573 setupHEVCPort(omxNode, portIndex,
574 static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile),
575 static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level));
577 case OMX_VIDEO_CodingH263:
578 setupH263Port(omxNode, portIndex,
579 static_cast<OMX_VIDEO_H263PROFILETYPE>(profile),
580 static_cast<OMX_VIDEO_H263LEVELTYPE>(level),
583 case OMX_VIDEO_CodingMPEG4:
584 setupMPEG4Port(omxNode, portIndex,
585 static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile),
586 static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level),
589 case OMX_VIDEO_CodingVP8:
590 setupVPXPort(omxNode, portIndex, xFramerate);
591 setupVP8Port(omxNode, portIndex,
592 static_cast<OMX_VIDEO_VP8PROFILETYPE>(profile),
593 static_cast<OMX_VIDEO_VP8LEVELTYPE>(level));
595 case OMX_VIDEO_CodingVP9:
596 setupVPXPort(omxNode, portIndex, xFramerate);
597 setupVP9Port(omxNode, portIndex,
598 static_cast<OMX_VIDEO_VP9PROFILETYPE>(profile),
599 static_cast<OMX_VIDEO_VP9LEVELTYPE>(level));
606 // LookUpTable of clips and metadata for component testing
607 void GetURLForComponent(char* URL) {
608 strcat(URL, "bbb_352x288_420p_30fps_32frames.yuv");
611 // blocking call to ensures application to Wait till all the inputs are consumed
612 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
613 android::Vector<BufferInfo>* iBuffer,
614 android::Vector<BufferInfo>* oBuffer,
615 bool inputDataIsMeta = false,
616 sp<CodecProducerListener> listener = nullptr) {
617 android::hardware::media::omx::V1_0::Status status;
619 int timeOut = TIMEOUT_COUNTER_Q;
624 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
626 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
627 // status == TIMED_OUT, it could be due to process time being large
628 // than DEFAULT_TIMEOUT or component needs output buffers to start
630 if (inputDataIsMeta) {
631 if (listener->freeBuffers == iBuffer->size()) break;
633 for (; i < iBuffer->size(); i++) {
634 if ((*iBuffer)[i].owner != client) break;
636 if (i == iBuffer->size()) break;
639 // Dispatch an output buffer assuming outQueue.empty() is true
641 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
642 ASSERT_NO_FATAL_FAILURE(
643 dispatchOutputBuffer(omxNode, oBuffer, index));
644 timeOut = TIMEOUT_COUNTER_Q;
649 int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
650 std::ifstream& eleStream) {
651 sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
652 android::hardware::graphics::mapper::V2_0::IMapper::getService();
653 EXPECT_NE(mapper.get(), nullptr);
654 if (mapper.get() == nullptr) return 1;
656 android::hardware::hidl_handle fence;
657 android::hardware::graphics::mapper::V2_0::IMapper::Rect rect;
658 android::hardware::graphics::mapper::V2_0::YCbCrLayout ycbcrLayout;
659 android::hardware::graphics::mapper::V2_0::Error error;
662 rect.width = buffer->omxBuffer.attr.anwBuffer.width;
663 rect.height = buffer->omxBuffer.attr.anwBuffer.height;
665 if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
666 format == PixelFormat::YCBCR_420_888) {
668 buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
669 [&](android::hardware::graphics::mapper::V2_0::Error _e,
670 android::hardware::graphics::mapper::V2_0::YCbCrLayout _n1) {
675 android::hardware::graphics::mapper::V2_0::Error::NONE);
676 if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
679 int size = ((rect.width * rect.height * 3) >> 1);
680 char* img = new char[size];
681 if (img == nullptr) return 1;
682 eleStream.read(img, size);
683 if (eleStream.gcount() != size) {
689 char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
690 for (size_t y = rect.height; y > 0; --y) {
691 memcpy(ipBuffer, imgTmp, rect.width);
692 ipBuffer += ycbcrLayout.yStride;
693 imgTmp += rect.width;
696 if (format == PixelFormat::YV12)
697 EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
698 else if (format == PixelFormat::YCRCB_420_SP)
699 EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
701 ipBuffer = static_cast<char*>(ycbcrLayout.cb);
702 for (size_t y = rect.height >> 1; y > 0; --y) {
703 for (int32_t x = 0; x < (rect.width >> 1); ++x) {
704 ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
706 ipBuffer += ycbcrLayout.cStride;
708 ipBuffer = static_cast<char*>(ycbcrLayout.cr);
709 for (size_t y = rect.height >> 1; y > 0; --y) {
710 for (int32_t x = 0; x < (rect.width >> 1); ++x) {
711 ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
713 ipBuffer += ycbcrLayout.cStride;
719 [&](android::hardware::graphics::mapper::V2_0::Error _e,
720 android::hardware::hidl_handle _n1) {
725 android::hardware::graphics::mapper::V2_0::Error::NONE);
726 if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
730 mapper->lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
731 [&](android::hardware::graphics::mapper::V2_0::Error _e,
737 android::hardware::graphics::mapper::V2_0::Error::NONE);
738 if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
741 if (format == PixelFormat::BGRA_8888) {
742 char* ipBuffer = static_cast<char*>(data);
743 for (size_t y = rect.height; y > 0; --y) {
744 eleStream.read(ipBuffer, rect.width * 4);
745 if (eleStream.gcount() != rect.width * 4) return 1;
746 ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
749 EXPECT_TRUE(false) << "un expected pixel format";
754 [&](android::hardware::graphics::mapper::V2_0::Error _e,
755 android::hardware::hidl_handle _n1) {
760 android::hardware::graphics::mapper::V2_0::Error::NONE);
761 if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
768 int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
769 std::ifstream& eleStream) {
770 sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
771 android::hardware::graphics::mapper::V2_0::IMapper::getService();
772 EXPECT_NE(mapper.get(), nullptr);
773 if (mapper.get() == nullptr) return 1;
775 void* buff = nullptr;
776 android::hardware::graphics::mapper::V2_0::Error error;
777 mapper->importBuffer(
778 buffer->omxBuffer.nativeHandle,
779 [&](android::hardware::graphics::mapper::V2_0::Error _e, void* _n1) {
783 EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
784 if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
787 if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
789 error = mapper->freeBuffer(buff);
790 EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
791 if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
797 int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
798 sp<IGraphicBufferProducer> producer,
799 sp<CodecProducerListener> listener,
800 android::Vector<BufferInfo>* buffArray,
801 OMX_U32 portIndex, std::ifstream& eleStream,
802 uint64_t timestamp) {
803 android::hardware::media::omx::V1_0::Status status;
804 OMX_PARAM_PORTDEFINITIONTYPE portDef;
806 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
808 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
809 if (status != ::android::hardware::media::omx::V1_0::Status::OK) return 1;
812 // A flag returned by dequeueBuffer when the client needs to call
813 // requestBuffer immediately thereafter.
814 BUFFER_NEEDS_REALLOCATION = 0x1,
815 // A flag returned by dequeueBuffer when all mirrored slots should be
816 // released by the client. This flag should always be processed first.
817 RELEASE_ALL_BUFFERS = 0x2,
822 ::android::hardware::hidl_handle fence;
823 IGraphicBufferProducer::FrameEventHistoryDelta outTimestamps;
824 ::android::hardware::media::V1_0::AnwBuffer AnwBuffer;
825 PixelFormat format = PixelFormat::YCBCR_420_888;
826 producer->dequeueBuffer(
827 portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
828 format, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
829 true, [&](int32_t _s, int32_t const& _n1,
830 ::android::hardware::hidl_handle const& _n2,
831 IGraphicBufferProducer::FrameEventHistoryDelta const& _n3) {
837 if (result & BUFFER_NEEDS_REALLOCATION) {
838 producer->requestBuffer(
839 slot, [&](int32_t _s,
840 ::android::hardware::media::V1_0::AnwBuffer const& _n1) {
844 EXPECT_EQ(result, 0);
845 if (result != 0) return 1;
847 for (i = 0; i < buffArray->size(); i++) {
848 if ((*buffArray)[i].slot == -1) {
849 buffArray->editItemAt(i).slot = slot;
850 buffArray->editItemAt(i).omxBuffer.nativeHandle =
851 AnwBuffer.nativeHandle;
852 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer =
857 EXPECT_NE(i, buffArray->size());
858 if (i == buffArray->size()) return 1;
860 EXPECT_EQ(result, 0);
861 if (result != 0) return 1;
866 for (i = 0; i < buffArray->size(); i++) {
867 if ((*buffArray)[i].slot == slot) {
868 buffer = (*buffArray)[i];
872 EXPECT_NE(i, buffArray->size());
873 if (i == buffArray->size()) return 1;
874 if (fillGraphicBuffer(&buffer, format, eleStream)) return 1;
877 IGraphicBufferProducer::QueueBufferOutput output;
878 IGraphicBufferProducer::QueueBufferInput input;
879 android::hardware::media::V1_0::Rect rect;
882 rect.right = buffer.omxBuffer.attr.anwBuffer.width;
883 rect.bottom = buffer.omxBuffer.attr.anwBuffer.height;
884 input.timestamp = timestamp;
885 input.isAutoTimestamp = false;
887 android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN;
889 input.scalingMode = 0;
891 input.stickyTransform = 0;
892 input.fence = android::hardware::hidl_handle();
893 input.surfaceDamage =
894 android::hardware::hidl_vec<android::hardware::media::V1_0::Rect>{rect};
895 input.getFrameTimestamps = false;
896 producer->queueBuffer(
898 [&](int32_t _s, const IGraphicBufferProducer::QueueBufferOutput& _n1) {
902 EXPECT_EQ(result, 0);
903 if (result != 0) return 1;
905 listener->reduceCount();
910 int fillByteBuffer(sp<IOmxNode> omxNode, char* ipBuffer, OMX_U32 portIndexInput,
911 std::ifstream& eleStream) {
912 android::hardware::media::omx::V1_0::Status status;
913 OMX_PARAM_PORTDEFINITIONTYPE portDef;
916 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndexInput,
918 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
920 int size = ((portDef.format.video.nFrameWidth *
921 portDef.format.video.nFrameHeight * 3) >>
923 char* img = new char[size];
924 if (img == nullptr) return 1;
925 eleStream.read(img, size);
926 if (eleStream.gcount() != size) {
933 for (j = 0; j < portDef.format.video.nFrameHeight; ++j) {
934 memcpy(Y, imgTmp, portDef.format.video.nFrameWidth);
935 Y += portDef.format.video.nStride;
936 imgTmp += portDef.format.video.nFrameWidth;
939 if (portDef.format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
940 char* Cb = ipBuffer + (portDef.format.video.nFrameHeight *
941 portDef.format.video.nStride);
943 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
944 for (i = 0; i < (portDef.format.video.nFrameWidth >> 1); ++i) {
945 Cb[2 * i] = *imgTmp++;
947 Cb += portDef.format.video.nStride;
949 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
950 for (i = 0; i < (portDef.format.video.nFrameWidth >> 1); ++i) {
951 Cr[2 * i] = *imgTmp++;
953 Cr += portDef.format.video.nStride;
955 } else if (portDef.format.video.eColorFormat ==
956 OMX_COLOR_FormatYUV420Planar) {
957 char* Cb = ipBuffer + (portDef.format.video.nFrameHeight *
958 portDef.format.video.nStride);
959 char* Cr = Cb + ((portDef.format.video.nFrameHeight *
960 portDef.format.video.nStride) >>
962 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
963 memcpy(Cb, imgTmp, (portDef.format.video.nFrameWidth >> 1));
964 Cb += (portDef.format.video.nStride >> 1);
965 imgTmp += (portDef.format.video.nFrameWidth >> 1);
967 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
968 memcpy(Cr, imgTmp, (portDef.format.video.nFrameWidth >> 1));
969 Cr += (portDef.format.video.nStride >> 1);
970 imgTmp += (portDef.format.video.nFrameWidth >> 1);
979 void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
980 OMX_U32 portIndexInput, OMX_U32 portIndexOutput,
981 android::Vector<BufferInfo>* iBuffer,
982 android::Vector<BufferInfo>* oBuffer, uint32_t nFrames,
983 uint32_t xFramerate, int bytesCount,
984 std::ifstream& eleStream,
985 ::android::List<uint64_t>* timestampUslist = nullptr,
986 bool signalEOS = true, bool inputDataIsMeta = false,
987 sp<IGraphicBufferProducer> producer = nullptr,
988 sp<CodecProducerListener> listener = nullptr) {
989 android::hardware::media::omx::V1_0::Status status;
991 uint64_t timestamp = 0;
993 int timeOut = TIMEOUT_COUNTER_Q;
994 bool iQueued, oQueued;
996 uint32_t ipCount = 0;
998 status = changeFrameRate(omxNode, portIndexOutput, (24U << 16));
999 if (status == ::android::hardware::media::omx::V1_0::Status::OK)
1000 xFramerate = (24U << 16);
1002 int32_t timestampIncr = (int)((float)1000000 / (xFramerate >> 16));
1003 if (inputDataIsMeta) timestampIncr *= 1000; // timestamp scale: Nano sec
1006 iQueued = oQueued = false;
1008 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
1009 // Port Reconfiguration
1010 if (status == android::hardware::media::omx::V1_0::Status::OK) {
1011 ASSERT_EQ(msg.type, Message::Type::EVENT);
1012 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
1013 ASSERT_EQ(msg.data.eventData.data1, portIndexOutput);
1014 ASSERT_EQ(msg.data.eventData.data2,
1015 OMX_IndexConfigAndroidIntraRefresh);
1016 } else if (msg.data.eventData.event == OMX_EventError) {
1017 ASSERT_TRUE(false) << "Received OMX_EventError, not sure why";
1018 } else if (msg.data.eventData.event == OMX_EventDataSpaceChanged) {
1019 // TODO: how am i supposed to respond now?
1020 std::cout << "[ INFO ] OMX_EventDataSpaceChanged \n";
1026 if (nFrames == 0) break;
1028 // Dispatch input buffer
1030 if (inputDataIsMeta) {
1031 if (listener->freeBuffers > listener->minUnDequeuedCount) {
1032 if (dispatchGraphicBuffer(omxNode, producer, listener, iBuffer,
1033 portIndexInput, eleStream,
1035 if (::testing::Test::HasFailure())
1040 timestamp += timestampIncr;
1046 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
1047 char* ipBuffer = static_cast<char*>(static_cast<void*>(
1048 (*iBuffer)[index].mMemory->getPointer()));
1051 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
1052 if (fillByteBuffer(omxNode, ipBuffer, portIndexInput,
1055 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1056 if (signalEOS && (nFrames == 1)) flags |= OMX_BUFFERFLAG_EOS;
1057 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
1058 omxNode, iBuffer, index, bytesCount, flags, timestamp));
1059 if (timestampUslist) timestampUslist->push_back(timestamp);
1060 timestamp += timestampIncr;
1066 // Dispatch output buffer
1067 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
1068 ASSERT_NO_FATAL_FAILURE(
1069 dispatchOutputBuffer(omxNode, oBuffer, index));
1072 // Reset Counters when either input or output buffer is dispatched
1073 if (iQueued || oQueued)
1074 timeOut = TIMEOUT_COUNTER_Q;
1078 ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
1080 // Runtime Param Configuration
1081 if (ipCount == 15) {
1082 changeBitrate(omxNode, portIndexOutput, 768000);
1083 requestIDR(omxNode, portIndexOutput);
1084 changeRefreshPeriod(omxNode, portIndexOutput, 15);
1089 // set component role
1090 TEST_F(VideoEncHidlTest, SetRole) {
1091 description("Test Set Component Role");
1092 if (disableTest) return;
1093 android::hardware::media::omx::V1_0::Status status;
1094 status = setRole(omxNode, gEnv->getRole().c_str());
1095 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1098 // port format enumeration
1099 TEST_F(VideoEncHidlTest, EnumeratePortFormat) {
1100 description("Test Component on Mandatory Port Parameters (Port Format)");
1101 if (disableTest) return;
1102 android::hardware::media::omx::V1_0::Status status;
1103 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1104 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
1105 OMX_U32 xFramerate = (30U << 16);
1106 status = setRole(omxNode, gEnv->getRole().c_str());
1107 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1108 OMX_PORT_PARAM_TYPE params;
1109 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1110 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1111 ASSERT_EQ(params.nPorts, 2U);
1112 kPortIndexInput = params.nStartPortNumber;
1113 kPortIndexOutput = kPortIndexInput + 1;
1116 setVideoPortFormat(omxNode, kPortIndexInput, OMX_VIDEO_CodingUnused,
1117 eColorFormat, xFramerate);
1118 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1120 status = setVideoPortFormat(omxNode, kPortIndexOutput, eCompressionFormat,
1121 OMX_COLOR_FormatUnused, 0U);
1122 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1125 // Test IOmxBufferSource CallBacks
1126 TEST_F(VideoEncHidlTest, BufferSourceCallBacks) {
1127 description("Test IOmxBufferSource CallBacks");
1128 if (disableTest) return;
1129 android::hardware::media::omx::V1_0::Status status;
1130 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1131 status = setRole(omxNode, gEnv->getRole().c_str());
1132 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1133 OMX_PORT_PARAM_TYPE params;
1134 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1135 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1136 ASSERT_EQ(params.nPorts, 2U);
1137 kPortIndexInput = params.nStartPortNumber;
1138 kPortIndexOutput = kPortIndexInput + 1;
1141 // Configure input port
1142 uint32_t nFrameWidth = 352;
1143 uint32_t nFrameHeight = 288;
1144 uint32_t xFramerate = (30U << 16);
1145 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
1146 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1147 xFramerate, eColorFormat);
1149 sp<DummyBufferSource> buffersource = new DummyBufferSource(omxNode);
1150 ASSERT_NE(buffersource, nullptr);
1151 status = omxNode->setInputSurface(buffersource);
1152 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1155 PortMode portMode[2];
1156 portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
1157 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1158 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1159 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1160 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1161 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1163 // set state to idle
1164 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
1165 omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
1166 kPortIndexInput, kPortIndexOutput, portMode));
1167 // set state to executing
1168 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1169 ASSERT_NO_FATAL_FAILURE(testEOS(omxNode, observer, &buffersource->iBuffer,
1170 &buffersource->oBuffer, false, eosFlag));
1171 // set state to idle
1172 ASSERT_NO_FATAL_FAILURE(changeStateExecutetoIdle(
1173 omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer));
1174 // set state to executing
1175 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(
1176 omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
1177 kPortIndexInput, kPortIndexOutput));
1178 // test for callbacks
1179 EXPECT_EQ(buffersource->callback, 31);
1182 // test raw stream encode (input is byte buffers)
1183 TEST_F(VideoEncHidlTest, EncodeTest) {
1184 description("Test Encode");
1185 if (disableTest) return;
1186 android::hardware::media::omx::V1_0::Status status;
1187 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1188 status = setRole(omxNode, gEnv->getRole().c_str());
1189 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1190 OMX_PORT_PARAM_TYPE params;
1191 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1192 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1193 ASSERT_EQ(params.nPorts, 2U);
1194 kPortIndexInput = params.nStartPortNumber;
1195 kPortIndexOutput = kPortIndexInput + 1;
1198 strcpy(mURL, gEnv->getRes().c_str());
1199 GetURLForComponent(mURL);
1201 std::ifstream eleStream;
1203 timestampDevTest = true;
1205 // Configure input port
1206 uint32_t nFrameWidth = 352;
1207 uint32_t nFrameHeight = 288;
1208 uint32_t xFramerate = (30U << 16);
1209 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1210 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
1211 portFormat.nIndex = 0;
1213 status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
1214 kPortIndexInput, &portFormat);
1215 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
1216 EXPECT_EQ(portFormat.eCompressionFormat, OMX_VIDEO_CodingUnused);
1217 if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
1218 OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat) {
1219 eColorFormat = portFormat.eColorFormat;
1222 portFormat.nIndex++;
1223 if (portFormat.nIndex == 512) break;
1225 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1226 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1227 xFramerate, eColorFormat);
1229 // Configure output port
1230 uint32_t nBitRate = 512000;
1231 ASSERT_NO_FATAL_FAILURE(
1232 setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
1233 nFrameWidth, nFrameHeight, nBitRate, xFramerate));
1234 setRefreshPeriod(omxNode, kPortIndexOutput, 0);
1237 omxNode->getExtensionIndex(
1238 "OMX.google.android.index.prependSPSPPSToIDRFrames",
1239 [&status, &index](android::hardware::media::omx::V1_0::Status _s,
1244 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1245 android::PrependSPSPPSToIDRFramesParams param;
1246 param.bEnable = OMX_TRUE;
1247 status = setParam(omxNode, static_cast<OMX_INDEXTYPE>(index), ¶m);
1249 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
1250 std::cout << "[ INFO ] unable to prependSPSPPSToIDRFrames\n";
1252 prependSPSPPS = true;
1255 PortMode portMode[2];
1256 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1257 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1258 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1259 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1260 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1262 uint32_t latency = 0;
1263 setLatency(omxNode, kPortIndexInput, latency);
1264 getLatency(omxNode, kPortIndexInput, &latency);
1266 android::Vector<BufferInfo> iBuffer, oBuffer;
1268 // set state to idle
1269 ASSERT_NO_FATAL_FAILURE(
1270 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1271 kPortIndexInput, kPortIndexOutput, portMode));
1272 // set state to executing
1273 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1275 eleStream.open(mURL, std::ifstream::binary);
1276 ASSERT_EQ(eleStream.is_open(), true);
1277 ASSERT_NO_FATAL_FAILURE(encodeNFrames(
1278 omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
1279 &oBuffer, 32, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
1280 eleStream, ×tampUslist));
1282 ASSERT_NO_FATAL_FAILURE(
1283 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer));
1284 ASSERT_NO_FATAL_FAILURE(
1285 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
1286 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
1288 // set state to idle
1289 ASSERT_NO_FATAL_FAILURE(
1290 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1291 // set state to executing
1292 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1293 &oBuffer, kPortIndexInput,
1297 // test raw stream encode (input is ANW buffers)
1298 TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
1299 description("Test Encode Input buffer metamodes");
1300 if (disableTest) return;
1301 android::hardware::media::omx::V1_0::Status status;
1302 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1303 status = setRole(omxNode, gEnv->getRole().c_str());
1304 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1305 OMX_PORT_PARAM_TYPE params;
1306 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1307 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1308 ASSERT_EQ(params.nPorts, 2U);
1309 kPortIndexInput = params.nStartPortNumber;
1310 kPortIndexOutput = kPortIndexInput + 1;
1313 // Configure input port
1314 uint32_t nFrameWidth = 352;
1315 uint32_t nFrameHeight = 288;
1316 uint32_t xFramerate = (30U << 16);
1317 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
1318 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1319 xFramerate, eColorFormat);
1321 // Configure output port
1322 uint32_t nBitRate = 512000;
1323 ASSERT_NO_FATAL_FAILURE(
1324 setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
1325 nFrameWidth, nFrameHeight, nBitRate, xFramerate));
1326 // CreateInputSurface
1327 EXPECT_TRUE(omx->createInputSurface(
1328 [&](android::hardware::media::omx::V1_0::Status _s,
1329 sp<IGraphicBufferProducer> const& _nl,
1330 sp<IGraphicBufferSource> const& _n2) {
1336 ASSERT_NE(producer, nullptr);
1337 ASSERT_NE(source, nullptr);
1339 // setMaxDequeuedBufferCount
1342 producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1343 [&returnval, &value](int32_t _s, int32_t _n1) {
1347 ASSERT_EQ(returnval, 0);
1348 OMX_PARAM_PORTDEFINITIONTYPE portDef;
1349 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
1350 kPortIndexInput, &portDef);
1351 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1352 ASSERT_EQ(::android::OK,
1353 producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
1355 // Connect :: Mock Producer Listener
1356 IGraphicBufferProducer::QueueBufferOutput qbo;
1357 sp<CodecProducerListener> listener =
1358 new CodecProducerListener(portDef.nBufferCountActual + value, value);
1360 listener, NATIVE_WINDOW_API_CPU, false,
1361 [&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
1365 ASSERT_EQ(returnval, 0);
1367 portDef.nBufferCountActual = portDef.nBufferCountActual + value;
1368 status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
1369 kPortIndexInput, &portDef);
1370 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1372 // Do setInputSurface()
1373 // enable MetaMode on input port
1374 status = source->configure(
1375 omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
1376 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1379 PortMode portMode[2];
1380 portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
1381 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1382 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1383 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1384 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1385 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1388 strcpy(mURL, gEnv->getRes().c_str());
1389 GetURLForComponent(mURL);
1391 uint32_t latency = 0;
1392 setLatency(omxNode, kPortIndexInput, latency);
1393 getLatency(omxNode, kPortIndexInput, &latency);
1395 std::ifstream eleStream;
1397 status = source->setSuspend(false, 0);
1398 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1399 status = source->setRepeatPreviousFrameDelayUs(100000);
1400 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1401 status = source->setMaxFps(24.0f);
1402 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1403 status = source->setTimeLapseConfig(24.0, 24.0);
1404 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1405 status = source->setTimeOffsetUs(-100);
1406 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1407 status = source->setStartTimeUs(10);
1408 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1409 status = source->setStopTimeUs(1000000);
1410 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1411 ::android::hardware::media::omx::V1_0::ColorAspects aspects;
1413 ::android::hardware::media::omx::V1_0::ColorAspects::Range::UNSPECIFIED;
1414 aspects.primaries = ::android::hardware::media::omx::V1_0::ColorAspects::
1415 Primaries::UNSPECIFIED;
1416 aspects.transfer = ::android::hardware::media::omx::V1_0::ColorAspects::
1417 Transfer::UNSPECIFIED;
1418 aspects.matrixCoeffs = ::android::hardware::media::omx::V1_0::ColorAspects::
1419 MatrixCoeffs::UNSPECIFIED;
1420 status = source->setColorAspects(aspects);
1421 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1422 int64_t stopTimeOffsetUs;
1423 source->getStopTimeOffsetUs(
1424 [&](android::hardware::media::omx::V1_0::Status _s, int64_t _n1) {
1426 stopTimeOffsetUs = _n1;
1428 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1430 android::Vector<BufferInfo> iBuffer, oBuffer;
1431 // set state to idle
1432 ASSERT_NO_FATAL_FAILURE(
1433 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1434 kPortIndexInput, kPortIndexOutput, portMode));
1435 // set state to executing
1436 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1438 eleStream.open(mURL, std::ifstream::binary);
1439 ASSERT_EQ(eleStream.is_open(), true);
1440 ASSERT_NO_FATAL_FAILURE(encodeNFrames(
1441 omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
1442 &oBuffer, 1024, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
1443 eleStream, nullptr, false, true, producer, listener));
1445 ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
1446 &oBuffer, true, listener));
1447 ASSERT_NO_FATAL_FAILURE(
1448 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
1450 // set state to idle
1451 ASSERT_NO_FATAL_FAILURE(
1452 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1453 EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
1454 // set state to executing
1455 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1456 &oBuffer, kPortIndexInput,
1459 returnval = producer->disconnect(
1460 NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
1461 ASSERT_EQ(returnval, 0);
1464 // Test end of stream
1465 TEST_F(VideoEncHidlTest, EncodeTestEOS) {
1466 description("Test EOS");
1467 if (disableTest) return;
1468 android::hardware::media::omx::V1_0::Status status;
1469 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1470 status = setRole(omxNode, gEnv->getRole().c_str());
1471 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1472 OMX_PORT_PARAM_TYPE params;
1473 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1474 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1475 ASSERT_EQ(params.nPorts, 2U);
1476 kPortIndexInput = params.nStartPortNumber;
1477 kPortIndexOutput = kPortIndexInput + 1;
1480 // Configure input port
1481 uint32_t nFrameWidth = 352;
1482 uint32_t nFrameHeight = 288;
1483 uint32_t xFramerate = (30U << 16);
1484 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
1485 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1486 xFramerate, eColorFormat);
1488 // CreateInputSurface
1489 EXPECT_TRUE(omx->createInputSurface(
1490 [&](android::hardware::media::omx::V1_0::Status _s,
1491 sp<IGraphicBufferProducer> const& _nl,
1492 sp<IGraphicBufferSource> const& _n2) {
1498 ASSERT_NE(producer, nullptr);
1499 ASSERT_NE(source, nullptr);
1501 // setMaxDequeuedBufferCount
1504 producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1505 [&returnval, &value](int32_t _s, int32_t _n1) {
1509 ASSERT_EQ(returnval, 0);
1510 OMX_PARAM_PORTDEFINITIONTYPE portDef;
1511 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
1512 kPortIndexInput, &portDef);
1513 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1514 ASSERT_EQ(::android::OK,
1515 producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
1517 // Connect :: Mock Producer Listener
1518 IGraphicBufferProducer::QueueBufferOutput qbo;
1519 sp<CodecProducerListener> listener =
1520 new CodecProducerListener(portDef.nBufferCountActual + value, value);
1522 listener, NATIVE_WINDOW_API_CPU, false,
1523 [&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
1527 ASSERT_EQ(returnval, 0);
1529 portDef.nBufferCountActual = portDef.nBufferCountActual + value;
1530 status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
1531 kPortIndexInput, &portDef);
1532 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1534 // Do setInputSurface()
1535 // enable MetaMode on input port
1536 status = source->configure(
1537 omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
1538 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1541 PortMode portMode[2];
1542 portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
1543 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1544 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1545 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1546 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1547 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1549 android::Vector<BufferInfo> iBuffer, oBuffer;
1550 // set state to idle
1551 ASSERT_NO_FATAL_FAILURE(
1552 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1553 kPortIndexInput, kPortIndexOutput, portMode));
1554 // set state to executing
1555 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1558 status = source->signalEndOfInputStream();
1559 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1560 ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
1561 &oBuffer, true, listener));
1562 ASSERT_NO_FATAL_FAILURE(
1563 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
1565 // set state to idle
1566 ASSERT_NO_FATAL_FAILURE(
1567 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1568 EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
1569 // set state to executing
1570 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1571 &oBuffer, kPortIndexInput,
1574 returnval = producer->disconnect(
1575 NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
1576 ASSERT_EQ(returnval, 0);
1579 int main(int argc, char** argv) {
1580 gEnv = new ComponentTestEnvironment();
1581 ::testing::AddGlobalTestEnvironment(gEnv);
1582 ::testing::InitGoogleTest(&argc, argv);
1583 int status = gEnv->initFromOptions(argc, argv);
1585 status = RUN_ALL_TESTS();
1586 ALOGI("Test result = %d", status);