#include #include #include "Decoder/MediaCodecAV1Decoder.h" #include "Decoder/VideoDecoderFactory.h" #include "Common/VideoTypes.h" #define LOG_TAG "MediaCodecAV1DecoderTest" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) using namespace VavCore; class MediaCodecAV1DecoderTest : public ::testing::Test { protected: void SetUp() override { LOGI("Setting up MediaCodecAV1DecoderTest"); decoder = std::make_unique(); } void TearDown() override { LOGI("Tearing down MediaCodecAV1DecoderTest"); // NOTE: MediaCodecAV1Decoder destructor will call Cleanup() automatically // Calling Cleanup() here would cause double-cleanup and potential crashes if (decoder) { decoder.reset(); } } std::unique_ptr decoder; }; // Test 1: Basic initialization and cleanup TEST_F(MediaCodecAV1DecoderTest, InitializationAndCleanup) { LOGI("Test: InitializationAndCleanup"); ASSERT_NE(decoder, nullptr) << "Decoder should be created"; // Cleanup should not crash decoder->Cleanup(); SUCCEED() << "Decoder initialization and cleanup successful"; } // Test 2: Get available codecs TEST_F(MediaCodecAV1DecoderTest, GetAvailableCodecs) { LOGI("Test: GetAvailableCodecs"); std::vector codecs = decoder->GetAvailableCodecs(); LOGI("Found %zu MediaCodec AV1 codecs", codecs.size()); for (const auto& codec : codecs) { LOGI(" - %s", codec.c_str()); } // On most Android devices, there should be at least one AV1 codec // But we allow 0 for older devices EXPECT_GE(codecs.size(), 0) << "Should have 0 or more codecs available"; if (codecs.size() > 0) { SUCCEED() << "Found " << codecs.size() << " AV1 codec(s)"; } else { GTEST_SKIP() << "No AV1 codecs available on this device (API < 29 or no hardware support)"; } } // Test 3: Initialize with valid metadata TEST_F(MediaCodecAV1DecoderTest, InitializeWithValidMetadata) { LOGI("Test: InitializeWithValidMetadata"); // Check if any codecs are available auto codecs = decoder->GetAvailableCodecs(); if (codecs.empty()) { GTEST_SKIP() << "No AV1 codecs available for initialization test"; } VideoMetadata metadata; metadata.width = 1920; metadata.height = 1080; metadata.frame_rate = 30.0; metadata.codec_name = "av01"; bool success = decoder->Initialize(metadata); if (success) { SUCCEED() << "Decoder initialized successfully with 1920x1080@30fps"; } else { // Initialization might fail on emulators or devices without proper support LOGI("Decoder initialization failed (may be expected on emulator)"); } } // Test 4: Initialize with invalid dimensions (should fail gracefully) TEST_F(MediaCodecAV1DecoderTest, InitializeWithInvalidDimensions) { LOGI("Test: InitializeWithInvalidDimensions"); VideoMetadata metadata; metadata.width = 0; // Invalid width metadata.height = 0; // Invalid height metadata.frame_rate = 30.0; metadata.codec_name = "av01"; bool success = decoder->Initialize(metadata); EXPECT_FALSE(success) << "Initialization should fail with invalid dimensions"; if (!success) { SUCCEED() << "Correctly rejected invalid dimensions"; } } // Test 5: Decode frame without initialization (should fail) TEST_F(MediaCodecAV1DecoderTest, DecodeFrameWithoutInitialization) { LOGI("Test: DecodeFrameWithoutInitialization"); // Try to decode without initializing std::vector dummyData(100, 0); VideoFrame frame; bool success = decoder->DecodeFrame(dummyData.data(), dummyData.size(), frame); EXPECT_FALSE(success) << "DecodeFrame should fail without initialization"; if (!success) { SUCCEED() << "Correctly rejected decode attempt without initialization"; } } // Test 6: Test reset functionality TEST_F(MediaCodecAV1DecoderTest, ResetFunctionality) { LOGI("Test: ResetFunctionality"); // Initialize decoder auto codecs = decoder->GetAvailableCodecs(); if (codecs.empty()) { GTEST_SKIP() << "No AV1 codecs available for reset test"; } VideoMetadata metadata; metadata.width = 1280; metadata.height = 720; metadata.frame_rate = 30.0; metadata.codec_name = "av01"; bool initSuccess = decoder->Initialize(metadata); if (!initSuccess) { GTEST_SKIP() << "Cannot test reset without successful initialization"; } // Reset should not crash decoder->Reset(); SUCCEED() << "Decoder reset successful"; } // Test 7: Test flush functionality TEST_F(MediaCodecAV1DecoderTest, FlushFunctionality) { LOGI("Test: FlushFunctionality"); // Initialize decoder auto codecs = decoder->GetAvailableCodecs(); if (codecs.empty()) { GTEST_SKIP() << "No AV1 codecs available for flush test"; } VideoMetadata metadata; metadata.width = 1280; metadata.height = 720; metadata.frame_rate = 30.0; metadata.codec_name = "av01"; bool initSuccess = decoder->Initialize(metadata); if (!initSuccess) { GTEST_SKIP() << "Cannot test flush without successful initialization"; } // Flush should not crash decoder->Flush(); SUCCEED() << "Decoder flush successful"; } // Test 8: Test decoder statistics (skipped - GetStatistics not implemented) TEST_F(MediaCodecAV1DecoderTest, DecoderStatistics) { LOGI("Test: DecoderStatistics"); // Note: GetStatistics() method not yet implemented in MediaCodecAV1Decoder GTEST_SKIP() << "GetStatistics() method not yet implemented"; } // Test 9: Get decoder name (skipped - GetName not in interface) TEST_F(MediaCodecAV1DecoderTest, GetDecoderName) { LOGI("Test: GetDecoderName"); // Note: GetName() is not part of IVideoDecoder interface GTEST_SKIP() << "GetName() method not in IVideoDecoder interface"; } // Test 10: Multiple initialize/cleanup cycles TEST_F(MediaCodecAV1DecoderTest, MultipleInitializeCleanupCycles) { LOGI("Test: MultipleInitializeCleanupCycles"); auto codecs = decoder->GetAvailableCodecs(); if (codecs.empty()) { GTEST_SKIP() << "No AV1 codecs available for cycle test"; } VideoMetadata metadata; metadata.width = 1280; metadata.height = 720; metadata.frame_rate = 30.0; metadata.codec_name = "av01"; // Perform 3 cycles for (int i = 0; i < 3; i++) { LOGI("Cycle %d: Initializing...", i + 1); bool initSuccess = decoder->Initialize(metadata); if (initSuccess) { LOGI("Cycle %d: Cleaning up...", i + 1); decoder->Cleanup(); } else { LOGI("Cycle %d: Initialization failed (may be expected)", i + 1); } } SUCCEED() << "Multiple initialize/cleanup cycles completed"; } // Test 11: Supports codec type (skipped - SupportsCodec not in interface) TEST_F(MediaCodecAV1DecoderTest, SupportsCodecType) { LOGI("Test: SupportsCodecType"); // Note: SupportsCodec() is not part of MediaCodecAV1Decoder interface GTEST_SKIP() << "SupportsCodec() method not in MediaCodecAV1Decoder interface"; } // Test 12: Hardware acceleration detection TEST_F(MediaCodecAV1DecoderTest, HardwareAccelerationDetection) { LOGI("Test: HardwareAccelerationDetection"); bool isHardwareAccelerated = decoder->IsHardwareAccelerated(); LOGI("Hardware acceleration: %s", isHardwareAccelerated ? "YES" : "NO"); // This is informational, not an assertion if (isHardwareAccelerated) { SUCCEED() << "Decoder reports hardware acceleration available"; } else { SUCCEED() << "Decoder reports software decoding (may be emulator)"; } }