vlc fully implemented

This commit is contained in:
Elias Quinn
2025-06-11 19:01:09 +01:00
parent 7e2c8d971d
commit c8906c1471
335 changed files with 6576 additions and 333 deletions

View File

@@ -1,3 +1,5 @@
using System.Windows.Documents;
namespace ShadowStream.Obejeckte;
//Quinn
public class Catagory
@@ -20,4 +22,9 @@ public class Catagory
{
items.Clear();
}
public List<Item> getAllItems()
{
return items;
}
}

View File

@@ -20,11 +20,22 @@ public class Jason_Writer
// Save one list of locJason objects to JSON file with given name
public async Task SaveList(string listName, List<locJason> list)
{
Console.WriteLine($"Saving JSON list '{listName}' with {list.Count} items.");
foreach (var item in list)
{
Console.WriteLine($" - Path: {item.path}, Type: {item.type}, ImageData length: {(item.imageData?.Length ?? 0)}");
}
string filePath = Path.Combine(_folderPath, $"{listName}.json");
string jsonString = JsonConvert.SerializeObject(list, Formatting.Indented);
File.WriteAllText(filePath, jsonString);
await File.WriteAllTextAsync(filePath, jsonString);
Console.WriteLine($"Saved JSON to: {filePath}");
}
// Load one list of locJason objects from JSON file with given name
public List<locJason> LoadList(string listName)
{

View File

@@ -1,76 +1,96 @@
using FFMediaToolkit.Decoding;
using FFMediaToolkit.Graphics;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using LibVLCSharp.Shared;
public static class VideoFrameExtractor
{
public static Bitmap GetFrame200(string videoPath)
public static BitmapImage GetFrame200(string videoPath)
{
FFMediaToolkit.FFmpegLoader.FFmpegPath = AppDomain.CurrentDomain.BaseDirectory;
Core.Initialize();
using var libVLC = new LibVLC("--no-xlib");
using var media = new Media(libVLC, videoPath, FromType.FromPath);
using var mp = new MediaPlayer(media);
using var mediaFile = MediaFile.Open(videoPath);
mp.Play();
// Read first two frames to estimate frame rate
if (!mediaFile.Video.TryGetNextFrame(out var firstFrame))
throw new Exception("Cannot read first frame");
double firstSeconds = mediaFile.Video.Position.TotalSeconds;
while (!mp.IsPlaying)
Thread.Sleep(10);
if (!mediaFile.Video.TryGetNextFrame(out var secondFrame))
throw new Exception("Cannot read second frame");
double secondSeconds = mediaFile.Video.Position.TotalSeconds;
// Seek to ~200th frame at 30 fps
mp.Time = (long)((200.0 / 30.0) * 1000);
Thread.Sleep(500);
double frameDuration = secondSeconds - firstSeconds;
if (frameDuration <= 0)
throw new Exception("Invalid frame duration calculated");
if (!mp.IsPlaying)
mp.Play();
double frameRate = 1.0 / frameDuration;
Thread.Sleep(1000);
int totalFrames = (int)(mediaFile.Info.Duration.TotalSeconds * frameRate);
string path = Path.GetTempFileName() + ".png";
const int targetFrameIndex = 200;
if (targetFrameIndex >= totalFrames)
throw new ArgumentOutOfRangeException($"Video has only {totalFrames} frames, cannot extract frame {targetFrameIndex}");
if (!mp.TakeSnapshot(0, path, 0, 0))
throw new Exception("Snapshot failed.");
// Reopen to reset reading
mediaFile.Dispose();
using var mediaFile2 = MediaFile.Open(videoPath);
int currentFrameIndex = 0;
Bitmap targetFrameBitmap = null;
while (mediaFile2.Video.TryGetNextFrame(out var frame))
// Wait for snapshot file to be fully written and valid
int attempts = 10;
while (attempts-- > 0)
{
if (currentFrameIndex == targetFrameIndex)
{
targetFrameBitmap = ImageDataToBitmap(frame);
if (File.Exists(path) && new FileInfo(path).Length > 0)
break;
}
currentFrameIndex++;
Thread.Sleep(100);
}
if (targetFrameBitmap == null)
throw new Exception($"Failed to extract frame {targetFrameIndex}");
if (!File.Exists(path))
throw new FileNotFoundException("Snapshot file not found", path);
return targetFrameBitmap;
var fileInfo = new FileInfo(path);
if (fileInfo.Length == 0)
throw new Exception("Snapshot file is empty or corrupted.");
BitmapImage image = null;
try
{
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
if (fs == null)
throw new Exception("FileStream is null.");
image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
// Removed CreateOptions.IgnoreImageCache here to avoid ArgumentNullException
image.StreamSource = fs ?? throw new Exception("StreamSource cannot be null.");
fs.Position = 0;
image.EndInit();
image.Freeze();
}
}
catch (Exception ex)
{
Console.WriteLine($"Error loading snapshot image from {path}: {ex}");
throw new Exception("Failed to load snapshot image.", ex);
}
// Async delayed delete of temp snapshot file (after 1 minute)
DeleteFileLaterAsync(path);
return image!;
}
private static Bitmap ImageDataToBitmap(ImageData imageData)
private static async void DeleteFileLaterAsync(string path, int delayMs = 60000)
{
var bitmap = new Bitmap(imageData.ImageSize.Width, imageData.ImageSize.Height, PixelFormat.Format24bppRgb);
var bmpData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly,
bitmap.PixelFormat);
// Convert Span<byte> to byte[] for Marshal.Copy
Marshal.Copy(imageData.Data.ToArray(), 0, bmpData.Scan0, imageData.Data.Length);
bitmap.UnlockBits(bmpData);
return bitmap;
try
{
await Task.Delay(delayMs);
File.Delete(path);
}
catch (Exception ex)
{
Console.WriteLine($"[WARNING] Failed to delete temp snapshot file {path}: {ex.Message}");
}
}
}