opencvsharp - DrumMidiEditor/DrumMidiEditorApp GitHub Wiki

mp4出力

var mp4_codec = Config.Media.OutputVideoCodec;
var fps       = Config.Media.OutputVideoFps;

// win2dで描画する為の準備
ControlAccess.UCPlayerPanel?.GetFrameStart();

// 描画サイズ取得用にフレームを取得
using var frameSize = ControlAccess.UCPlayerPanel?.GetFrame( 0 );

if ( frameSize == null )
{
     Log.Error( $"get frame failure.", true );
     return;
}

using var mp4 = new Mp4IO();

var bmp = mp4.Open
     ( 
         aFilePath, 
         mp4_codec, 
         fps, 
         (int)frameSize.Size.Width,
         (int)frameSize.Size.Height
     );

if ( bmp == null )
{
     Log.Error( $"open video file failure.", true );
     return;
}

var frameTime = 1d / fps;

await Task.Run
     (
        () => 
        { 
             for ( var time = 0D; time <= DmsControl.EndPlayTime; time += frameTime )
             {
                  // 指定時間のフレーム画像取得(CanvasBitmap)
                  using var frame = ControlAccess.UCPlayerPanel?.GetFrame( time );

                  if ( frame == null )
                  {
                        Log.Error( $"frame read error.[{time}]" );
                        continue;
                  }

                  var buffer = frame.GetPixelBytes();

                  var bmpData = bmp.LockBits
                        (
                            new( 0, 0, bmp.Width, bmp.Height ),
                            ImageLockMode.WriteOnly,
                            bmp.PixelFormat
                        );

                  // Bitmapへ書込み
                  Marshal.Copy( buffer, 0, bmpData.Scan0, buffer.Length );

                  bmp.UnlockBits( bmpData );

                  // MP4へのフレーム追加
                  mp4.AddFrame();
             }
        }
public CanvasBitmap? GetFrame( double aFrameTime )
{
    if ( _Offscreen == null )
    {
        return null;
    }

    try
    {
        // フレーム処理
        _PlayerSurface?.OnMove( aFrameTime );

        // 描画処理
        using var drawSession = _Offscreen.CreateDrawingSession();

        drawSession.Clear( DrawSet.SheetColor.Color );

        _PlayerSurface?.OnDraw( new CanvasDrawEventArgs( drawSession ) );

        // CanvasBitmap作成
        return CanvasBitmap.CreateFromBytes
            (
                drawSession,
                _Offscreen.GetPixelBytes( 0, 0, (int)_Offscreen.SizeInPixels.Width, (int)_Offscreen.SizeInPixels.Height ),
                (int)_Offscreen.SizeInPixels.Width,
                (int)_Offscreen.SizeInPixels.Height,
                DirectXPixelFormat.R8G8B8A8UIntNormalized,
                96,
                CanvasAlphaMode.Premultiplied
            );
    }
    catch ( Exception e )
    {
        Log.Error( $"{Log.GetThisMethodName}:{e.Message}" );
        return null;
    }
}
using System.Drawing;
using System.Drawing.Imaging;

using OpenCvSharp;

/// <summary>
/// MP4出力
/// </summary>
internal class Mp4IO : DisposeBaseClass
{
    /// <summary>
    /// Video書込
    /// </summary>
    private VideoWriter? _Writer = null;

    /// <summary>
    /// 画像コンバーター
    /// </summary>
    private readonly ImageConverter _Converter = new();

    /// <summary>
    /// フレーム書込用Bitmap
    /// </summary>
    private Bitmap? _Bmp = null;

    /// <summary>
    /// ファイルオープン
    /// </summary>
    /// <param name="aGeneralPath">出力ファイルパス</param>
    /// <param name="aCodec">MP4コーデック</param>
    /// <param name="aFrameRate">フレームレート</param>
    /// <param name="aWidth">映像横幅</param>
    /// <param name="aHeight">映像高さ</param>
    /// <returns>映像書込用のBitmap</returns>
    public Bitmap Open( GeneralPath aGeneralPath, string aCodec, int aFrameRate, int aWidth, int aHeight )
    {
        Close();

        // MP4出力用のストリームを作成
        _Writer = new VideoWriter
            (
                aGeneralPath.AbsoulteFilePath,
                string.IsNullOrEmpty( aCodec ) ? FourCC.Default : FourCC.FromString( aCodec ),
                aFrameRate, 
                new( aWidth, aHeight ) 
            );

        // フレーム書込み用のBitmap作成
        _Bmp = new Bitmap( aWidth, aHeight, PixelFormat.Format32bppArgb );

        return _Bmp;
    }

    /// <summary>
    /// フレーム追加
    /// </summary>
    /// <returns>True:書込成功、False:書込失敗</returns>
    public bool AddFrame()
    {
        if ( _Writer == null || _Bmp == null )
        {
            return false;
        }

        var bmpData = _Bmp.LockBits
            (
                new( 0, 0, _Bmp.Width, _Bmp.Height ), 
                ImageLockMode.ReadOnly,
                _Bmp.PixelFormat
            );

        var buffer = (byte[]?)_Converter.ConvertTo( _Bmp, typeof( byte[] ) );

        if ( buffer == null )
        {
            return false;
        }

        // 多分、ここで色情報の置き換えを行っている
        using var mat = Mat.FromImageData( buffer ).CvtColor( ColorConversionCodes.RGBA2RGB );
//      using var mat = Mat.FromImageData( buffer ).CvtColor( ColorConversionCodes.RGB2BGR );

        _Writer.Write( mat );

        _Bmp.UnlockBits( bmpData );

        return true;
    }

    /// <summary>
    /// ファイルクローズ
    /// </summary>
    public void Close()
    {
        _Writer?.Dispose();
        _Writer = null;

        _Bmp?.Dispose();
        _Bmp = null;
    }
}
⚠️ **GitHub.com Fallback** ⚠️