Refactoring MediaCodec decoder
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <android/log.h>
|
||||
#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<MediaCodecAV1Decoder>();
|
||||
}
|
||||
|
||||
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<MediaCodecAV1Decoder> 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<std::string> 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<uint8_t> 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)";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user