using FluentAssertions; using Vav1Player.Video; using Vav1Player.Decoder; using Vav1Player.Container; namespace Vav1Player.Tests.Integration; public class VideoDecodingIntegrationTests { [Fact] public async Task DecodeFirstFrame_WithSampleMp4_ShouldDecodeSuccessfully() { // Arrange var sampleFilePath = Path.Combine("..", "..", "..", "..", "sample", "output.mp4"); // Skip test if sample file doesn't exist if (!File.Exists(sampleFilePath)) { return; // Skip test } using var fileReader = new VideoFileReader(sampleFilePath); using var decoder = new Dav1dDecoder(); // Act & Assert var action = async () => { // Read first chunk var chunk = await fileReader.ReadNextChunkAsync(); chunk.Should().NotBeNull(); System.Diagnostics.Debug.WriteLine($"First chunk: {chunk}"); // Parse OBUs from the chunk var obuList = Av1BitstreamParser.ParseMp4Sample(chunk!.Data); System.Diagnostics.Debug.WriteLine($"Parsed {obuList.Count} OBUs from first chunk"); obuList.Should().NotBeEmpty("First chunk should contain AV1 OBUs"); // Log OBU information for (int i = 0; i < obuList.Count; i++) { Av1BitstreamParser.LogOBUInfo(obuList[i], $"OBU #{i}: "); } // Combine OBUs for decoding var combinedData = Av1BitstreamParser.CombineOBUs(obuList); combinedData.Should().NotBeEmpty("Combined OBU data should not be empty"); System.Diagnostics.Debug.WriteLine($"Combined OBU data: {combinedData.Length} bytes"); // Initialize decoder var initResult = decoder.Initialize(); initResult.Should().BeTrue("Decoder should initialize successfully"); // Try to decode the frame var decodeResult = decoder.DecodeFrame(combinedData, out var frame); if (decodeResult && frame.HasValue) { var decodedFrame = frame.Value; System.Diagnostics.Debug.WriteLine($"Successfully decoded frame: {decodedFrame.Width}x{decodedFrame.Height}"); decodedFrame.Width.Should().BeGreaterThan(0); decodedFrame.Height.Should().BeGreaterThan(0); decodedFrame.Release(); } else { System.Diagnostics.Debug.WriteLine("Frame decoding failed or returned no frame - this might be expected for sequence headers or other non-frame OBUs"); } }; await action.Should().NotThrowAsync(); } [Fact] public async Task DecodeMultipleFrames_WithSampleMp4_ShouldDecodeSuccessfully() { // Arrange var sampleFilePath = Path.Combine("..", "..", "..", "..", "sample", "output.mp4"); // Skip test if sample file doesn't exist if (!File.Exists(sampleFilePath)) { return; // Skip test } using var fileReader = new VideoFileReader(sampleFilePath); using var decoder = new Dav1dDecoder(); // Act & Assert var action = async () => { // Initialize decoder var initResult = decoder.Initialize(); initResult.Should().BeTrue("Decoder should initialize successfully"); int decodedFrames = 0; int processedChunks = 0; int maxChunksToProcess = Math.Min(10, (int)fileReader.TotalSamples); for (int i = 0; i < maxChunksToProcess; i++) { var chunk = await fileReader.ReadNextChunkAsync(); if (chunk == null) break; processedChunks++; System.Diagnostics.Debug.WriteLine($"Processing chunk #{processedChunks}: {chunk}"); // Parse OBUs from the chunk var obuList = Av1BitstreamParser.ParseMp4Sample(chunk.Data); System.Diagnostics.Debug.WriteLine($"Chunk #{processedChunks}: Parsed {obuList.Count} OBUs"); if (obuList.Count > 0) { // Combine OBUs for decoding var combinedData = Av1BitstreamParser.CombineOBUs(obuList); // Try to decode the frame var decodeResult = decoder.DecodeFrame(combinedData, out var frame); if (decodeResult && frame.HasValue) { decodedFrames++; var decodedFrame = frame.Value; System.Diagnostics.Debug.WriteLine($"Chunk #{processedChunks}: Successfully decoded frame #{decodedFrames}: {decodedFrame.Width}x{decodedFrame.Height}"); decodedFrame.Release(); } else { System.Diagnostics.Debug.WriteLine($"Chunk #{processedChunks}: DecodeFrame failed or returned no frame (might be sequence header or metadata)"); } } } System.Diagnostics.Debug.WriteLine($"Test completed: Processed {processedChunks} chunks, decoded {decodedFrames} frames"); processedChunks.Should().BeGreaterThan(0, "Should have processed at least one chunk"); // Note: decodedFrames might be 0 if all chunks contain only sequence headers/metadata }; await action.Should().NotThrowAsync(); } }