Beispiel #1
0
 public static VTCompressionSession Create(int width, int height, CMVideoCodecType codecType,
                                           VTCompressionOutputCallback compressionOutputCallback,
                                           VTVideoEncoderSpecification encoderSpecification = null, // hardware acceleration is default behavior on iOS. no opt-in required.
                                           NSDictionary sourceImageBufferAttributes         = null)
 {
     return(Create(width, height, codecType, compressionOutputCallback, encoderSpecification, sourceImageBufferAttributes, static_newCompressionOutputCallback));
 }
 public static VTCompressionSession Create(int width, int height, CMVideoCodecType codecType,
                                           VTVideoEncoderSpecification encoderSpecification = null,
                                           NSDictionary sourceImageBufferAttributes         = null)
 {
     return(Create(width, height, codecType, null,
                   encoderSpecification, sourceImageBufferAttributes));
 }
Beispiel #3
0
        static VTCompressionSession Create(int width, int height, CMVideoCodecType codecType,
                                           VTCompressionOutputCallback compressionOutputCallback,
                                           VTVideoEncoderSpecification encoderSpecification,                                // hardware acceleration is default behavior on iOS. no opt-in required.
                                           NSDictionary sourceImageBufferAttributes, CompressionOutputCallback staticCback) // Undocumented options, probably always null
        {
            var callbackHandle = default(GCHandle);

            if (compressionOutputCallback != null)
            {
                callbackHandle = GCHandle.Alloc(compressionOutputCallback);
            }

            IntPtr ret;

            var result = VTCompressionSessionCreate(IntPtr.Zero, width, height, codecType,
                                                    encoderSpecification != null ? encoderSpecification.Dictionary.Handle : IntPtr.Zero,
                                                    sourceImageBufferAttributes != null ? sourceImageBufferAttributes.Handle : IntPtr.Zero,
                                                    IntPtr.Zero,
                                                    callbackHandle.IsAllocated ? (staticCback) : null,
                                                    GCHandle.ToIntPtr(callbackHandle),
                                                    out ret);

            if (result == VTStatus.Ok && ret != IntPtr.Zero)
            {
                return new VTCompressionSession(ret, true)
                       {
                           callbackHandle = callbackHandle
                       }
            }
            ;

            if (callbackHandle.IsAllocated)
            {
                callbackHandle.Free();
            }

            return(null);
        }
Beispiel #4
0
		public static VTCompressionSession Create (int width, int height, CMVideoCodecType codecType,
			VTCompressionOutputCallback compressionOutputCallback,
			VTVideoEncoderSpecification encoderSpecification = null, // hardware acceleration is default behavior on iOS. no opt-in required.
			NSDictionary sourceImageBufferAttributes = null)
		{
			return Create (width, height, codecType, compressionOutputCallback, encoderSpecification, sourceImageBufferAttributes, static_newCompressionOutputCallback);
		}
Beispiel #5
0
		static VTCompressionSession Create (int width, int height, CMVideoCodecType codecType,
			VTCompressionOutputCallback compressionOutputCallback,
			VTVideoEncoderSpecification encoderSpecification, // hardware acceleration is default behavior on iOS. no opt-in required.
		        NSDictionary sourceImageBufferAttributes, CompressionOutputCallback staticCback) // Undocumented options, probably always null
		{
			var callbackHandle = default (GCHandle);
			if (compressionOutputCallback != null)
				callbackHandle = GCHandle.Alloc (compressionOutputCallback);

			IntPtr ret;

			var result = VTCompressionSessionCreate (IntPtr.Zero, width, height, codecType,
				encoderSpecification != null ? encoderSpecification.Dictionary.Handle : IntPtr.Zero,
				sourceImageBufferAttributes != null ? sourceImageBufferAttributes.Handle : IntPtr.Zero,
				IntPtr.Zero,
				callbackHandle.IsAllocated ? (staticCback) : null,
				GCHandle.ToIntPtr (callbackHandle),
	            out ret);

			if (result == VTStatus.Ok && ret != IntPtr.Zero)
				return new VTCompressionSession (ret, true) {
					callbackHandle = callbackHandle
				};

			if (callbackHandle.IsAllocated)
				callbackHandle.Free ();

			return null;
		}
Beispiel #6
0
		public static VTCompressionSession Create (int width, int height, CMVideoCodecType codecType,
			VTVideoEncoderSpecification encoderSpecification = null,
			NSDictionary sourceImageBufferAttributes = null)
		{
			return Create (width, height, codecType, null,
				encoderSpecification, sourceImageBufferAttributes);
		}
        public void TestCallbackBackground(bool stronglyTyped)
        {
            var      width  = 640;
            var      height = 480;
            var      encoder_specification = new VTVideoEncoderSpecification();
            var      source_attributes     = new CVPixelBufferAttributes(CVPixelFormatType.CV420YpCbCr8BiPlanarFullRange, width, height);
            var      duration = new CMTime(40, 1);
            VTStatus status;

            using var frameProperties = new NSDictionary();

            int callbackCounter = 0;
            var failures        = new List <string> ();
            var callback        = new VTCompressionSession.VTCompressionOutputCallback((IntPtr sourceFrame, VTStatus status, VTEncodeInfoFlags flags, CMSampleBuffer buffer) =>
            {
                Interlocked.Increment(ref callbackCounter);
                if (status != VTStatus.Ok)
                {
                    failures.Add($"Callback #{callbackCounter} failed. Expected status = Ok, got status = {status}");
                }
#if !NET
                // Work around a crash that occur if the buffer isn't retained
                if (stronglyTyped)
                {
                    CFRetain(buffer.Handle);
                }
#endif
            });

            using var session = stronglyTyped
                                ? VTCompressionSession.Create(
                      width, height,
                      CMVideoCodecType.H264,
                      callback,
                      encoder_specification,
                      source_attributes
                      )
                                : VTCompressionSession.Create(
                      width, height,
                      CMVideoCodecType.H264,
                      callback,
                      encoder_specification,
                      source_attributes.Dictionary
                      );

            var frameCount = 20;

            for (var i = 0; i < frameCount; i++)
            {
                using var imageBuffer = new CVPixelBuffer(width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarFullRange);
                var pts = new CMTime(40 * i, 1);
                status = session.EncodeFrame(imageBuffer, pts, duration, null, imageBuffer, out var infoFlags);
                Assert.AreEqual(status, VTStatus.Ok, $"status #{i}");
                // This looks weird, but it seems the video encoder can become overwhelmed otherwise, and it
                // will start failing (and taking a long time to do so, eventually timing out the test).
                Thread.Sleep(10);
            }
            ;
            status = session.CompleteFrames(new CMTime(40 * frameCount, 1));
            Assert.AreEqual(status, VTStatus.Ok, "status finished");
            Assert.AreEqual(callbackCounter, frameCount, "frame count");
            Assert.That(failures, Is.Empty, "no callback failures");
        }