public MF.Sample CreateSampleFromFrame(byte[] data) { MF.MediaBuffer mediaBuffer = MF.MediaFactory.CreateMemoryBuffer(data.Length); // Write all contents to the MediaBuffer for media foundation int cbMaxLength = 0; int cbCurrentLength = 0; IntPtr mediaBufferPointer = mediaBuffer.Lock(out cbMaxLength, out cbCurrentLength); try { Marshal.Copy(data, 0, mediaBufferPointer, data.Length); } finally { mediaBuffer.Unlock(); mediaBuffer.CurrentLength = data.Length; } // Create the sample (includes image and timing information) MF.Sample sample = MF.MediaFactory.CreateSample(); sample.AddBuffer(mediaBuffer); return(sample); }
public MF.Sample CreateSampleFromFrame(MemoryMappedTexture32bpp frame) { MF.MediaBuffer mediaBuffer = MF.MediaFactory.CreateMemoryBuffer((int)frame.SizeInBytes); // Write all contents to the MediaBuffer for media foundation int cbMaxLength = 0; int cbCurrentLength = 0; IntPtr mediaBufferPointer = mediaBuffer.Lock(out cbMaxLength, out cbCurrentLength); try { if (FlipY) { unsafe { int stride = videoPixelSize.Width; int *mediaBufferPointerNative = (int *)mediaBufferPointer.ToPointer(); int *targetBufferPointerNative = (int *)frame.Pointer.ToPointer(); for (int loopY = 0; loopY < videoPixelSize.Height; loopY++) { for (int loopX = 0; loopX < videoPixelSize.Width; loopX++) { int actIndexTarget = loopX + (loopY * videoPixelSize.Width); int actIndexSource = loopX + ((videoPixelSize.Height - (1 + loopY)) * videoPixelSize.Width); mediaBufferPointerNative[actIndexTarget] = targetBufferPointerNative[actIndexSource]; } } } } else { unsafe { int stride = videoPixelSize.Width; int *mediaBufferPointerNative = (int *)mediaBufferPointer.ToPointer(); int *targetBufferPointerNative = (int *)frame.Pointer.ToPointer(); for (int loopY = 0; loopY < videoPixelSize.Height; loopY++) { for (int loopX = 0; loopX < videoPixelSize.Width; loopX++) { int actIndex = loopX + (loopY * videoPixelSize.Width); mediaBufferPointerNative[actIndex] = targetBufferPointerNative[actIndex]; } } } } } finally { mediaBuffer.Unlock(); mediaBuffer.CurrentLength = (int)frame.SizeInBytes; } // Create the sample (includes image and timing information) MF.Sample sample = MF.MediaFactory.CreateSample(); sample.AddBuffer(mediaBuffer); return(sample); }
private void CleanupAndDispose() { if (currentBuffer != null) { currentBuffer.Unlock(); currentBuffer.Dispose(); currentBuffer = null; } if (currentSample != null) { currentSample.Dispose(); currentSample = null; } }
/// <summary> /// Triggers internal rendering within the resource (e. g. Render to Texture). /// </summary> /// <param name="renderState">Current render state.</param> public void Render(RenderState renderState) { D3D11.DeviceContext deviceContext = renderState.Device.DeviceImmediateContextD3D11; // Do nothing here if we have no new frame to render if (m_lastFrameTimestamp >= m_videoReader.CurrentFrameTimestamp) { return; } // Upload the last read video frame to texture buffer on the graphics device using (SeeingSharpMediaBuffer mediaBuffer = m_videoReader.GetCurrentFrame()) { MF.MediaBuffer mediaBufferNative = mediaBuffer.GetBuffer(); SharpDX.DataBox dataBox = deviceContext.MapSubresource(m_texture, 0, D3D11.MapMode.WriteDiscard, D3D11.MapFlags.None); try { int cbMaxLength; int cbCurrentLenght; IntPtr mediaBufferPointer = mediaBufferNative.Lock(out cbMaxLength, out cbCurrentLenght); try { unsafe { int *frameBufferPointerNative = (int *)mediaBufferPointer.ToPointer(); int *textureBufferPointerNative = (int *)dataBox.DataPointer.ToPointer(); // Performance optimization using MemCopy // see http://www.rolandk.de/wp/2015/05/wie-schnell-man-speicher-falsch-kopieren-kann/ for (int loopY = 0; loopY < m_currentHeight; loopY++) { IntPtr rowStartTexture = new IntPtr(textureBufferPointerNative + (dataBox.RowPitch / 4) * loopY); IntPtr rowStartSource = new IntPtr(frameBufferPointerNative + (m_currentWidth) * loopY); CommonTools.CopyMemory(rowStartSource, rowStartTexture, (ulong)dataBox.RowPitch); } } } finally { mediaBufferNative.Unlock(); } } finally { deviceContext.UnmapSubresource(m_texture, 0); } } }
/// <summary> /// Gets the decoded PCM samples. See remarks. /// </summary> /// <param name="startingPositionInSeconds">The starting position in seconds.</param> /// <returns>An enumerator of pointer to PCM decoded data with the same format as returned by <see cref="WaveFormat"/>.</returns> /// <remarks> /// This method is only working as a single enumerator at a time. /// The <see cref="SetSourceStream(System.IO.Stream)"/> must be set before calling <see cref="GetSamples()"/> /// </remarks> public IEnumerable <DataPointer> GetSamples(TimeSpan startingPositionInSeconds) { // A new reader is setup, so initialize it. lock (sourceReaderLock) { // If the reader was changed if (nextSourceReader != null) { if (sourceReader != null) { sourceReader.Dispose(); } sourceReader = nextSourceReader; nextSourceReader = null; } } // Make sure that any prior call CleanupAndDispose(); CheckIfDisposed(); // Set the position sourceReader.SetCurrentPosition((long)(startingPositionInSeconds.Ticks)); while (true) { int streamIndex; SourceReaderFlags flags; long time; CheckIfDisposed(); using (currentSample = sourceReader.ReadSample(SourceReaderIndex.FirstAudioStream, SourceReaderControlFlags.None, out streamIndex, out flags, out time)) { if ((flags & SourceReaderFlags.Endofstream) != 0) { break; } CheckIfDisposed(); using (currentBuffer = currentSample.ConvertToContiguousBuffer()) { int bufferMaxLength; int bufferCurrentLength; CheckIfDisposed(); var ptr = currentBuffer.Lock(out bufferMaxLength, out bufferCurrentLength); yield return(new DataPointer(ptr, bufferCurrentLength)); // Warning, because the yield could never return here, currentBuffer and currentSample should be disposed when disposing this object or when // calling it again on the GetSamples method. // In case a Dispose occurred while decoding if (currentBuffer == null) { break; } currentBuffer.Unlock(); } } } // They have been disposed, so we can just clear them currentBuffer = null; currentSample = null; }
/// <summary> /// Draws the given frame to the video. /// </summary> /// <param name="device">The device on which the given framebuffer is created.</param> /// <param name="uploadedTexture">The texture which should be added to the video.</param> protected override void DrawFrameInternal(EngineDevice device, MemoryMappedTexture32bpp uploadedTexture) { // Cancel here if the given texture has an invalid size if (m_videoPixelSize != new Size2(uploadedTexture.Width, uploadedTexture.Height)) { return; } m_frameIndex++; MF.MediaBuffer mediaBuffer = MF.MediaFactory.CreateMemoryBuffer((int)uploadedTexture.SizeInBytes); try { // Write all contents to the MediaBuffer for media foundation int cbMaxLength = 0; int cbCurrentLength = 0; IntPtr mediaBufferPointer = mediaBuffer.Lock(out cbMaxLength, out cbCurrentLength); try { if (this.FlipY) { unsafe { int stride = m_videoPixelSize.Width; int *mediaBufferPointerNative = (int *)mediaBufferPointer.ToPointer(); int *targetBufferPointerNative = (int *)uploadedTexture.Pointer.ToPointer(); for (int loopY = 0; loopY < m_videoPixelSize.Height; loopY++) { for (int loopX = 0; loopX < m_videoPixelSize.Width; loopX++) { int actIndexTarget = loopX + (loopY * m_videoPixelSize.Width); int actIndexSource = loopX + ((m_videoPixelSize.Height - (1 + loopY)) * m_videoPixelSize.Width); mediaBufferPointerNative[actIndexTarget] = targetBufferPointerNative[actIndexSource]; } } } } else { unsafe { int stride = m_videoPixelSize.Width; int *mediaBufferPointerNative = (int *)mediaBufferPointer.ToPointer(); int *targetBufferPointerNative = (int *)uploadedTexture.Pointer.ToPointer(); for (int loopY = 0; loopY < m_videoPixelSize.Height; loopY++) { for (int loopX = 0; loopX < m_videoPixelSize.Width; loopX++) { int actIndex = loopX + (loopY * m_videoPixelSize.Width); mediaBufferPointerNative[actIndex] = targetBufferPointerNative[actIndex]; } } } } } finally { mediaBuffer.Unlock(); } mediaBuffer.CurrentLength = (int)uploadedTexture.SizeInBytes; // Create the sample (includes image and timing information) MF.Sample sample = MF.MediaFactory.CreateSample(); try { sample.AddBuffer(mediaBuffer); long frameDuration = 10 * 1000 * 1000 / m_framerate; sample.SampleTime = frameDuration * m_frameIndex; sample.SampleDuration = frameDuration; m_sinkWriter.WriteSample(m_streamIndex, sample); } finally { GraphicsHelper.SafeDispose(ref sample); } } finally { GraphicsHelper.SafeDispose(ref mediaBuffer); } }