コード例 #1
0
        void ProduceResultsInternal(IConsumer <T> consumer, IProducerContext producerContext)
        {
            IProducerListener producerListener = producerContext.Listener;

            producerListener.OnProducerFinishWithSuccess(producerContext.Id, PRODUCER_NAME, null);
            _inputProducer.ProduceResults(new ThrottlerConsumer(this, consumer), producerContext);
        }
コード例 #2
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <CloseableReference <CloseableImage> > consumer,
            IProducerContext context)
        {
            IProducerListener     listener                  = context.Listener;
            IPostprocessor        postprocessor             = context.ImageRequest.Postprocessor;
            PostprocessorConsumer basePostprocessorConsumer =
                new PostprocessorConsumer(this, consumer, listener, context.Id, postprocessor, context);

            IConsumer <CloseableReference <CloseableImage> > postprocessorConsumer;

            if (postprocessor.GetType() == typeof(IRepeatedPostprocessor))
            {
                postprocessorConsumer = new RepeatedPostprocessorConsumer(
                    basePostprocessorConsumer,
                    (IRepeatedPostprocessor)postprocessor,
                    context);
            }
            else
            {
                postprocessorConsumer = new SingleUsePostprocessorConsumer(basePostprocessorConsumer);
            }

            _inputProducer.ProduceResults(postprocessorConsumer, context);
        }
コード例 #3
0
ファイル: BufferQueueCore.cs プロジェクト: thubn/Ryujinx
        public BufferQueueCore(Switch device, KProcess process)
        {
            Slots                    = new BufferSlotArray();
            IsAbandoned              = false;
            OverrideMaxBufferCount   = 0;
            DequeueEvent             = new AutoResetEvent(false);
            DequeueBufferCannotBlock = false;
            UseAsyncBuffer           = false;
            DefaultWidth             = 1;
            DefaultHeight            = 1;
            DefaultMaxBufferCount    = 2;
            MaxAcquiredBufferCount   = 1;
            FrameCounter             = 0;
            TransformHint            = 0;
            DefaultBufferFormat      = PixelFormat.Rgba8888;
            IsAllocating             = false;
            IsAllocatingEvent        = new AutoResetEvent(false);
            ProducerListener         = null;
            ConsumerListener         = null;
            ConsumerUsageBits        = 0;

            Queue = new List <BufferItem>();

            // TODO: CreateGraphicBufferAlloc?

            _waitBufferFreeEvent  = new KEvent(device.System);
            _frameAvailaibleEvent = new KEvent(device.System);

            Owner = process;
        }
コード例 #4
0
        public void Initialize()
        {
            // Initializes the mock data
            _producerListener = new ProducerListenerImpl(
                (_, __) => { },
                (_, __, ___) => { },
                (_, __, ___) => { },
                (_, __, ___, ____) => { },
                (_, __, ___) => { },
                (_) =>
            {
                return(false);
            });
            _consumer = new BaseConsumerImpl <object>(
                (result, isLast) =>
            {
                ++_consumerOnNewResultCount;
                _consumerInternalResult = result;
                _consumerInternalIsLast = isLast;
            },
                (_) => { },
                () => { },
                (_) => { });
            _producerContext = new SettableProducerContext(
                IMAGE_REQUEST,
                REQUEST_ID,
                _producerListener,
                new object(),
                RequestLevel.FULL_FETCH,
                false,
                true,
                Priority.MEDIUM);

            _nullProducer = new NullProducer <object>();
        }
コード例 #5
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(IConsumer <T> consumer, IProducerContext producerContext)
        {
            IProducerListener producerListener = producerContext.Listener;

            producerListener.OnProducerStart(producerContext.Id, PRODUCER_NAME);

            bool delayRequest;

            lock (_gate)
            {
                if (_numCurrentRequests >= _maxSimultaneousRequests)
                {
                    _pendingRequests.Enqueue(
                        new Tuple <IConsumer <T>, IProducerContext>(consumer, producerContext));

                    delayRequest = true;
                }
                else
                {
                    _numCurrentRequests++;
                    delayRequest = false;
                }
            }

            if (!delayRequest)
            {
                ProduceResultsInternal(consumer, producerContext);
            }
        }
コード例 #6
0
 /// <summary>
 /// Instantiates the <see cref="StatefulProducerRunnableImpl{T}"/>.
 /// </summary>
 public StatefulProducerRunnableImpl(
     IConsumer <T> consumer,
     IProducerListener producerListener,
     string producerName,
     string requestId,
     Action <T> onSuccessFunc,
     Action <Exception> onFailureFunc,
     Action onCancellation,
     Func <T, IDictionary <string, string> > getExtraMapOnSuccessFunc,
     Func <Exception, IDictionary <string, string> > getExtraMapOnFailureFunc,
     Func <IDictionary <string, string> > getExtraMapOnCancellationFunc,
     Action <T> disposeResultFunc,
     Func <Task <T> > getResultFunc) : base(
         consumer,
         producerListener,
         producerName,
         requestId)
 {
     _onSuccessFunc                 = onSuccessFunc;
     _onFailureFunc                 = onFailureFunc;
     _onCancellation                = onCancellation;
     _getExtraMapOnSuccessFunc      = getExtraMapOnSuccessFunc;
     _getExtraMapOnFailureFunc      = getExtraMapOnFailureFunc;
     _getExtraMapOnCancellationFunc = getExtraMapOnCancellationFunc;
     _disposeResultFunc             = disposeResultFunc;
     _getResultFunc                 = getResultFunc;
 }
コード例 #7
0
ファイル: BufferQueueCore.cs プロジェクト: valx76/Ryujinx
        public BufferQueueCore(Switch device, KProcess process)
        {
            Slots                    = new BufferSlotArray();
            IsAbandoned              = false;
            OverrideMaxBufferCount   = 0;
            DequeueBufferCannotBlock = false;
            UseAsyncBuffer           = true;
            DefaultWidth             = 1;
            DefaultHeight            = 1;
            DefaultMaxBufferCount    = 2;
            MaxAcquiredBufferCount   = 1;
            FrameCounter             = 0;
            TransformHint            = 0;
            DefaultBufferFormat      = PixelFormat.Rgba8888;
            IsAllocating             = false;
            ProducerListener         = null;
            ConsumerListener         = null;
            ConsumerUsageBits        = 0;

            Queue = new List <BufferItem>();

            // TODO: CreateGraphicBufferAlloc?

            _waitBufferFreeEvent = new KEvent(device.System.KernelContext);
            _frameAvailableEvent = new KEvent(device.System.KernelContext);

            Owner = process;

            BufferHistory        = new BufferInfo[BufferHistoryArraySize];
            EnableExternalEvent  = true;
            MaxBufferCountCached = 0;
        }
コード例 #8
0
ファイル: BufferQueueConsumer.cs プロジェクト: valx76/Ryujinx
        public Status ReleaseBuffer(int slot, ulong frameNumber, ref AndroidFence fence)
        {
            if (slot < 0 || slot >= Core.Slots.Length)
            {
                return(Status.BadValue);
            }

            IProducerListener listener = null;

            lock (Core.Lock)
            {
                if (Core.Slots[slot].FrameNumber != frameNumber)
                {
                    return(Status.StaleBufferSlot);
                }

                foreach (BufferItem item in Core.Queue)
                {
                    if (item.Slot == slot)
                    {
                        return(Status.BadValue);
                    }
                }

                if (Core.Slots[slot].BufferState == BufferState.Acquired)
                {
                    Core.Slots[slot].BufferState = BufferState.Free;
                    Core.Slots[slot].Fence       = fence;

                    listener = Core.ProducerListener;
                }
                else if (Core.Slots[slot].NeedsCleanupOnRelease)
                {
                    Core.Slots[slot].NeedsCleanupOnRelease = false;

                    return(Status.StaleBufferSlot);
                }
                else
                {
                    return(Status.BadValue);
                }

                Core.Slots[slot].GraphicBuffer.Object.DecrementNvMapHandleRefCount(Core.Owner);

                Core.CheckSystemEventsLocked(Core.GetMaxBufferCountLocked(true));
                Core.SignalDequeueEvent();
            }

            listener?.OnBufferReleased();

            return(Status.Success);
        }
コード例 #9
0
        /// <summary>
        /// Instantiates the <see cref="StatefulProducerRunnable{T}"/>.
        /// </summary>
        public StatefulProducerRunnable(
            IConsumer <T> consumer,
            IProducerListener producerListener,
            string producerName,
            string requestId)
        {
            _consumer         = consumer;
            _producerListener = producerListener;
            _producerName     = producerName;
            _requestId        = requestId;

            _producerListener.OnProducerStart(_requestId, _producerName);
        }
コード例 #10
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <EncodedImage> consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener     = producerContext.Listener;
            string            requestId    = producerContext.Id;
            ImageRequest      imageRequest = producerContext.ImageRequest;
            StatefulProducerRunnable <EncodedImage> cancellableProducerRunnable =
                new StatefulProducerRunnableImpl <EncodedImage>(
                    consumer,
                    listener,
                    ProducerName,
                    requestId,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    (result) =>
            {
                EncodedImage.CloseSafely(result);
            },
                    async() =>
            {
                EncodedImage encodedImage = await GetEncodedImage(imageRequest)
                                            .ConfigureAwait(false);

                if (encodedImage == null)
                {
                    return(null);
                }

                await encodedImage.ParseMetaDataAsync().ConfigureAwait(false);
                return(encodedImage);
            });

            producerContext.AddCallbacks(
                new BaseProducerContextCallbacks(
                    () =>
            {
                cancellableProducerRunnable.Cancel();
            },
                    () => { },
                    () => { },
                    () => { }));

            _executor.Execute(cancellableProducerRunnable.Runnable);
        }
コード例 #11
0
            /// <summary>
            /// Instantiates the <see cref="ProgressiveDecoder"/>.
            /// </summary>
            public ProgressiveDecoder(
                DecodeProducer parent,
                IConsumer <CloseableReference <CloseableImage> > consumer,
                IProducerContext producerContext) :
                base(consumer)
            {
                _parent             = parent;
                _producerContext    = producerContext;
                _producerListener   = producerContext.Listener;
                _imageDecodeOptions = producerContext.ImageRequest.ImageDecodeOptions;
                _isFinished         = false;
                Func <EncodedImage, bool, Task> job = (encodedImage, isLast) =>
                {
                    if (encodedImage != null)
                    {
                        if (_parent._downsampleEnabled)
                        {
                            ImageRequest request = producerContext.ImageRequest;
                            if (_parent._downsampleEnabledForNetwork ||
                                !UriUtil.IsNetworkUri(request.SourceUri))
                            {
                                encodedImage.SampleSize = DownsampleUtil.DetermineSampleSize(
                                    request, encodedImage);
                            }
                        }

                        return(DoDecode(encodedImage, isLast));
                    }

                    return(Task.CompletedTask);
                };

                _jobScheduler = new JobScheduler(
                    _parent._executor, job, _imageDecodeOptions.MinDecodeIntervalMs);

                _producerContext.AddCallbacks(
                    new BaseProducerContextCallbacks(
                        () => { },
                        () => { },
                        () =>
                {
                    if (_producerContext.IsIntermediateResultExpected)
                    {
                        _jobScheduler.ScheduleJob();
                    }
                },
                        () => { }));
            }
コード例 #12
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>

        public void ProduceResults(IConsumer <T> consumer, IProducerContext context)
        {
            IProducerListener            producerListener = context.Listener;
            string                       requestId        = context.Id;
            StatefulProducerRunnable <T> statefulRunnable = new StatefulProducerRunnableImpl <T>(
                consumer,
                producerListener,
                PRODUCER_NAME,
                requestId,
                (T ignored) =>
            {
                producerListener.OnProducerFinishWithSuccess(requestId, PRODUCER_NAME, null);
                _inputProducer.ProduceResults(consumer, context);
            },
                null,
                null,
                (_) =>
            {
                return(default(IDictionary <string, string>));
            },
                (_) =>
            {
                return(default(IDictionary <string, string>));
            },
                () =>
            {
                return(default(IDictionary <string, string>));
            },
                null,
                () =>
            {
                return(Task.FromResult(default(T)));
            });

            context.AddCallbacks(
                new BaseProducerContextCallbacks(
                    () =>
            {
                statefulRunnable.Cancel();
                _threadHandoffProducerQueue.Remove(statefulRunnable.Runnable);
            },
                    () => { },
                    () => { },
                    () => { }));

            _threadHandoffProducerQueue.AddToQueueOrExecute(statefulRunnable.Runnable);
        }
コード例 #13
0
        internal static IDictionary <string, string> GetExtraMap(
            IProducerListener listener,
            string requestId,
            bool valueFound)
        {
            if (!listener.RequiresExtraMap(requestId))
            {
                return(null);
            }

            var extraMap = new Dictionary <string, string>()
            {
                { VALUE_FOUND, valueFound.ToString() }
            };

            return(new ReadOnlyDictionary <string, string>(extraMap));
        }
コード例 #14
0
            private IDictionary <string, string> GetExtraMap(
                IProducerListener listener,
                string requestId,
                IPostprocessor postprocessor)
            {
                if (!listener.RequiresExtraMap(requestId))
                {
                    return(null);
                }

                var extraMap = new Dictionary <string, string>()
                {
                    { POSTPROCESSOR, postprocessor.Name }
                };

                return(new ReadOnlyDictionary <string, string>(extraMap));
            }
コード例 #15
0
        public override Status Disconnect(NativeWindowApi api)
        {
            IProducerListener producerListener = null;

            Status status = Status.BadValue;

            lock (Core.Lock)
            {
                Core.WaitWhileAllocatingLocked();

                if (Core.IsAbandoned)
                {
                    return(Status.Success);
                }

                switch (api)
                {
                case NativeWindowApi.NVN:
                case NativeWindowApi.CPU:
                case NativeWindowApi.Media:
                case NativeWindowApi.Camera:
                    if (Core.ConnectedApi == api)
                    {
                        Core.Queue.Clear();
                        Core.FreeAllBuffersLocked();
                        Core.SignalDequeueEvent();

                        producerListener = Core.ProducerListener;

                        Core.ProducerListener = null;
                        Core.ConnectedApi     = NativeWindowApi.NoApi;

                        Core.SignalWaitBufferFreeEvent();
                        Core.SignalFrameAvailableEvent();

                        status = Status.Success;
                    }
                    break;
                }
            }

            producerListener?.OnBufferReleased();

            return(status);
        }
コード例 #16
0
        public override Status Connect(IProducerListener listener, NativeWindowApi api, bool producerControlledByApp, out QueueBufferOutput output)
        {
            output = new QueueBufferOutput();

            lock (Core.Lock)
            {
                if (Core.IsAbandoned || Core.ConsumerListener == null)
                {
                    return(Status.NoInit);
                }

                if (Core.ConnectedApi != NativeWindowApi.NoApi)
                {
                    return(Status.BadValue);
                }

                Core.BufferHasBeenQueued      = false;
                Core.DequeueBufferCannotBlock = Core.ConsumerControlledByApp && producerControlledByApp;

                switch (api)
                {
                case NativeWindowApi.NVN:
                case NativeWindowApi.CPU:
                case NativeWindowApi.Media:
                case NativeWindowApi.Camera:
                    Core.ProducerListener = listener;
                    Core.ConnectedApi     = api;

                    output.Width             = (uint)Core.DefaultWidth;
                    output.Height            = (uint)Core.DefaultHeight;
                    output.TransformHint     = Core.TransformHint;
                    output.NumPendingBuffers = (uint)Core.Queue.Count;

                    if (NxSettings.Settings.TryGetValue("nv!nvn_no_vsync_capability", out object noVSyncCapability) && (bool)noVSyncCapability)
                    {
                        output.TransformHint |= NativeWindowTransform.NoVSyncCapability;
                    }

                    return(Status.Success);

                default:
                    return(Status.BadValue);
                }
            }
        }
コード例 #17
0
 public void Initialize()
 {
     // Initializes the mock data
     _producerListener = new ProducerListenerImpl(
         (_, __) => { },
         (_, __, ___) => { },
         (_, __, ___) => { },
         (_, __, ___, ____) => { },
         (_, __, ___) => { },
         (_) =>
     {
         return(false);
     });
     _consumer = new BaseConsumerImpl <EncodedImage>(
         (_, __) => { },
         (_) => { },
         () => { },
         (_) => { });
 }
コード例 #18
0
 /// <summary>
 /// Instantiates the <see cref="SettableProducerContext"/>.
 /// </summary>
 public SettableProducerContext(
     ImageRequest imageRequest,
     string id,
     IProducerListener producerListener,
     object callerContext,
     int lowestPermittedRequestLevel,
     bool isPrefetch,
     bool isIntermediateResultExpected,
     int priority) : base(
         imageRequest,
         id,
         producerListener,
         callerContext,
         lowestPermittedRequestLevel,
         isPrefetch,
         isIntermediateResultExpected,
         priority)
 {
 }
コード例 #19
0
 internal PostprocessorConsumer(
     PostprocessorProducer parent,
     IConsumer <CloseableReference <CloseableImage> > consumer,
     IProducerListener listener,
     string requestId,
     IPostprocessor postprocessor,
     IProducerContext producerContext) :
     base(consumer)
 {
     _parent        = parent;
     _listener      = listener;
     _requestId     = requestId;
     _postprocessor = postprocessor;
     producerContext.AddCallbacks(
         new BaseProducerContextCallbacks(
             () =>
     {
         MaybeNotifyOnCancellation();
     },
             () => { },
             () => { },
             () => { }));
 }
コード例 #20
0
        /// <summary>
        /// Instantiates the <see cref="BaseProducerContext"/>
        /// </summary>
        public BaseProducerContext(
            ImageRequest imageRequest,
            string id,
            IProducerListener producerListener,
            object callerContext,
            int lowestPermittedRequestLevel,
            bool isPrefetch,
            bool isIntermediateResultExpected,
            int priority)
        {
            _imageRequest                = imageRequest;
            _id                          = id;
            _producerListener            = producerListener;
            _callerContext               = callerContext;
            _lowestPermittedRequestLevel = lowestPermittedRequestLevel;

            _isPrefetch = isPrefetch;
            _priority   = priority;
            _isIntermediateResultExpected = isIntermediateResultExpected;

            _isCancelled = false;
            _callbacks   = new List <IProducerContextCallbacks>();
        }
コード例 #21
0
        public void OnTransact(uint code, uint flags, Parcel inputParcel, Parcel outputParcel)
        {
            Status            status = Status.Success;
            int               slot;
            AndroidFence      fence;
            QueueBufferInput  queueInput;
            QueueBufferOutput queueOutput;
            NativeWindowApi   api;

            AndroidStrongPointer <GraphicBuffer> graphicBuffer;
            AndroidStrongPointer <AndroidFence>  strongFence;

            switch ((TransactionCode)code)
            {
            case TransactionCode.RequestBuffer:
                slot = inputParcel.ReadInt32();

                status = RequestBuffer(slot, out graphicBuffer);

                outputParcel.WriteStrongPointer(ref graphicBuffer);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.SetBufferCount:
                int bufferCount = inputParcel.ReadInt32();

                status = SetBufferCount(bufferCount);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.DequeueBuffer:
                bool        async  = inputParcel.ReadBoolean();
                uint        width  = inputParcel.ReadUInt32();
                uint        height = inputParcel.ReadUInt32();
                PixelFormat format = inputParcel.ReadUnmanagedType <PixelFormat>();
                uint        usage  = inputParcel.ReadUInt32();

                status      = DequeueBuffer(out int dequeueSlot, out fence, async, width, height, format, usage);
                strongFence = new AndroidStrongPointer <AndroidFence>(fence);

                outputParcel.WriteInt32(dequeueSlot);
                outputParcel.WriteStrongPointer(ref strongFence);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.DetachBuffer:
                slot = inputParcel.ReadInt32();

                status = DetachBuffer(slot);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.DetachNextBuffer:
                status      = DetachNextBuffer(out graphicBuffer, out fence);
                strongFence = new AndroidStrongPointer <AndroidFence>(fence);

                outputParcel.WriteStrongPointer(ref graphicBuffer);
                outputParcel.WriteStrongPointer(ref strongFence);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.AttachBuffer:
                graphicBuffer = inputParcel.ReadStrongPointer <GraphicBuffer>();

                status = AttachBuffer(out slot, graphicBuffer);

                outputParcel.WriteInt32(slot);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.QueueBuffer:
                slot       = inputParcel.ReadInt32();
                queueInput = inputParcel.ReadFlattenable <QueueBufferInput>();

                status = QueueBuffer(slot, ref queueInput, out queueOutput);

                outputParcel.WriteUnmanagedType(ref queueOutput);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.CancelBuffer:
                slot  = inputParcel.ReadInt32();
                fence = inputParcel.ReadFlattenable <AndroidFence>();

                CancelBuffer(slot, ref fence);

                outputParcel.WriteStatus(Status.Success);

                break;

            case TransactionCode.Query:
                NativeWindowAttribute what = inputParcel.ReadUnmanagedType <NativeWindowAttribute>();

                status = Query(what, out int outValue);

                outputParcel.WriteInt32(outValue);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.Connect:
                bool hasListener = inputParcel.ReadBoolean();

                IProducerListener listener = null;

                if (hasListener)
                {
                    throw new NotImplementedException("Connect with a strong binder listener isn't implemented");
                }

                api = inputParcel.ReadUnmanagedType <NativeWindowApi>();

                bool producerControlledByApp = inputParcel.ReadBoolean();

                status = Connect(listener, api, producerControlledByApp, out queueOutput);

                outputParcel.WriteUnmanagedType(ref queueOutput);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.Disconnect:
                api = inputParcel.ReadUnmanagedType <NativeWindowApi>();

                status = Disconnect(api);

                outputParcel.WriteStatus(status);

                break;

            case TransactionCode.SetPreallocatedBuffer:
                slot = inputParcel.ReadInt32();

                graphicBuffer = inputParcel.ReadStrongPointer <GraphicBuffer>();

                status = SetPreallocatedBuffer(slot, graphicBuffer);

                outputParcel.WriteStatus(status);

                break;

            default:
                throw new NotImplementedException($"Transaction {(TransactionCode)code} not implemented");
            }

            if (status != Status.Success)
            {
                Logger.PrintError(LogClass.SurfaceFlinger, $"Error returned by transaction {(TransactionCode)code}: {status}");
            }
        }
コード例 #22
0
 public abstract Status Connect(IProducerListener listener, NativeWindowApi api, bool producerControlledByApp, out QueueBufferOutput output);
コード例 #23
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <EncodedImage> consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener     = producerContext.Listener;
            string            requestId    = producerContext.Id;
            ImageRequest      imageRequest = producerContext.ImageRequest;

            StatefulProducerRunnable <EncodedImage> cancellableProducerRunnable =
                new StatefulProducerRunnableImpl <EncodedImage>(
                    consumer,
                    listener,
                    PRODUCER_NAME,
                    requestId,
                    null,
                    null,
                    null,
                    (result) =>
            {
                IDictionary <string, string> extraMap = new Dictionary <string, string>()
                {
                    { CREATED_THUMBNAIL, (result != null).ToString() }
                };

                return(new ReadOnlyDictionary <string, string>(extraMap));
            },
                    null,
                    null,
                    (result) =>
            {
                EncodedImage.CloseSafely(result);
            },
                    async() =>
            {
                Uri sourceUri    = imageRequest.SourceUri;
                StorageFile file = await StorageFile
                                   .GetFileFromApplicationUriAsync(sourceUri)
                                   .AsTask()
                                   .ConfigureAwait(false);

                using (var fileStream = await file.OpenReadAsync().AsTask().ConfigureAwait(false))
                {
                    byte[] bytes = await BitmapUtil
                                   .GetThumbnailAsync(fileStream)
                                   .ConfigureAwait(false);

                    if (bytes != null)
                    {
                        IPooledByteBuffer pooledByteBuffer =
                            _pooledByteBufferFactory.NewByteBuffer(bytes);

                        return(await BuildEncodedImage(pooledByteBuffer, fileStream)
                               .ConfigureAwait(false));
                    }
                    else
                    {
                        return(null);
                    }
                }
            });

            producerContext.AddCallbacks(
                new BaseProducerContextCallbacks(
                    () =>
            {
                cancellableProducerRunnable.Cancel();
            },
                    () => { },
                    () => { },
                    () => { }));

            _executor.Execute(cancellableProducerRunnable.Runnable);
        }
コード例 #24
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <CloseableReference <CloseableImage> > consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener  = producerContext.Listener;
            string            requestId = producerContext.Id;

            listener.OnProducerStart(requestId, ProducerName);
            ImageRequest imageRequest             = producerContext.ImageRequest;
            object       callerContext            = producerContext.CallerContext;
            ICacheKey    cacheKey                 = _cacheKeyFactory.GetBitmapCacheKey(imageRequest, callerContext);
            IDictionary <string, string> extraMap = default(IDictionary <string, string>);

            CloseableReference <CloseableImage> cachedReference = _memoryCache.Get(cacheKey);

            if (cachedReference != null)
            {
                bool isFinal = cachedReference.Get().QualityInfo.IsOfFullQuality;
                if (isFinal)
                {
                    extraMap = new Dictionary <string, string>()
                    {
                        { VALUE_FOUND, "true" }
                    };

                    listener.OnProducerFinishWithSuccess(
                        requestId,
                        ProducerName,
                        listener.RequiresExtraMap(requestId) ?
                        new ReadOnlyDictionary <string, string>(extraMap) :
                        null);

                    consumer.OnProgressUpdate(1f);
                }

                consumer.OnNewResult(cachedReference, isFinal);
                cachedReference.Dispose();
                if (isFinal)
                {
                    return;
                }
            }

            if (producerContext.LowestPermittedRequestLevel >= RequestLevel.BITMAP_MEMORY_CACHE)
            {
                extraMap = new Dictionary <string, string>()
                {
                    { VALUE_FOUND, "false" }
                };

                listener.OnProducerFinishWithSuccess(
                    requestId,
                    ProducerName,
                    listener.RequiresExtraMap(requestId) ?
                    new ReadOnlyDictionary <string, string>(extraMap) :
                    null);

                consumer.OnNewResult(null, true);
                return;
            }

            extraMap = new Dictionary <string, string>()
            {
                { VALUE_FOUND, "false" }
            };

            IConsumer <CloseableReference <CloseableImage> > wrappedConsumer =
                WrapConsumer(consumer, cacheKey);

            listener.OnProducerFinishWithSuccess(
                requestId,
                ProducerName,
                listener.RequiresExtraMap(requestId) ?
                new ReadOnlyDictionary <string, string>(extraMap) :
                null);

            _inputProducer.ProduceResults(wrappedConsumer, producerContext);
        }
コード例 #25
0
        private void OnFinishDiskReads(
            Task <EncodedImage> task,
            IConsumer <EncodedImage> consumer,
            BufferedDiskCache preferredCache,
            ICacheKey preferredCacheKey,
            IProducerContext producerContext)
        {
            string            requestId = producerContext.Id;
            IProducerListener listener  = producerContext.Listener;

            if (IsTaskCancelled(task))
            {
                listener.OnProducerFinishWithCancellation(requestId, PRODUCER_NAME, null);
                consumer.OnCancellation();
            }
            else if (task.IsFaulted)
            {
                listener.OnProducerFinishWithFailure(requestId, PRODUCER_NAME, task.Exception, null);
                MaybeStartInputProducer(
                    consumer,
                    new DiskCacheConsumer(
                        _defaultBufferedDiskCache,
                        _smallImageBufferedDiskCache,
                        _chooseCacheByImageSize,
                        _forceSmallCacheThresholdBytes,
                        consumer,
                        preferredCache,
                        preferredCacheKey),
                    producerContext);
            }
            else
            {
                EncodedImage cachedReference = task.Result;
                if (cachedReference != null)
                {
                    listener.OnProducerFinishWithSuccess(
                        requestId,
                        PRODUCER_NAME,
                        GetExtraMap(listener, requestId, true));

                    consumer.OnProgressUpdate(1);
                    consumer.OnNewResult(cachedReference, true);
                    cachedReference.Dispose();
                }
                else
                {
                    listener.OnProducerFinishWithSuccess(
                        requestId,
                        PRODUCER_NAME,
                        GetExtraMap(listener, requestId, false));

                    MaybeStartInputProducer(
                        consumer,
                        new DiskCacheConsumer(
                            _defaultBufferedDiskCache,
                            _smallImageBufferedDiskCache,
                            _chooseCacheByImageSize,
                            _forceSmallCacheThresholdBytes,
                            consumer,
                            preferredCache,
                            preferredCacheKey),
                        producerContext);
                }
            }
        }
コード例 #26
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <EncodedImage> consumer,
            IProducerContext producerContext)
        {
            string            requestId = producerContext.Id;
            IProducerListener listener  = producerContext.Listener;

            listener.OnProducerStart(requestId, PRODUCER_NAME);
            ImageRequest imageRequest = producerContext.ImageRequest;
            ICacheKey    cacheKey     = _cacheKeyFactory.GetEncodedCacheKey(
                imageRequest, producerContext.CallerContext);

            CloseableReference <IPooledByteBuffer> cachedReference = _memoryCache.Get(cacheKey);
            IDictionary <string, string>           extraMap        = default(IDictionary <string, string>);

            try
            {
                if (cachedReference != null)
                {
                    EncodedImage cachedEncodedImage = new EncodedImage(cachedReference);

                    try
                    {
                        extraMap = new Dictionary <string, string>()
                        {
                            { VALUE_FOUND, "true" }
                        };

                        listener.OnProducerFinishWithSuccess(
                            requestId,
                            PRODUCER_NAME,
                            listener.RequiresExtraMap(requestId) ?
                            new ReadOnlyDictionary <string, string>(extraMap) :
                            null);
                        consumer.OnProgressUpdate(1f);
                        consumer.OnNewResult(cachedEncodedImage, true);
                        return;
                    }
                    finally
                    {
                        EncodedImage.CloseSafely(cachedEncodedImage);
                    }
                }

                if (producerContext.LowestPermittedRequestLevel >= RequestLevel.ENCODED_MEMORY_CACHE)
                {
                    extraMap = new Dictionary <string, string>()
                    {
                        { VALUE_FOUND, "false" }
                    };

                    listener.OnProducerFinishWithSuccess(
                        requestId,
                        PRODUCER_NAME,
                        listener.RequiresExtraMap(requestId) ?
                        new ReadOnlyDictionary <string, string>(extraMap) :
                        null);

                    consumer.OnNewResult(null, true);
                    return;
                }

                IConsumer <EncodedImage> consumerOfInputProducer =
                    new EncodedMemoryCacheConsumer(_memoryCache, consumer, cacheKey);

                extraMap = new Dictionary <string, string>()
                {
                    { VALUE_FOUND, "false" }
                };

                listener.OnProducerFinishWithSuccess(
                    requestId,
                    PRODUCER_NAME,
                    listener.RequiresExtraMap(requestId) ?
                    new ReadOnlyDictionary <string, string>(extraMap) :
                    null);

                _inputProducer.ProduceResults(consumerOfInputProducer, producerContext);
            }
            finally
            {
                CloseableReference <IPooledByteBuffer> .CloseSafely(cachedReference);
            }
        }
コード例 #27
0
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <CloseableReference <CloseableImage> > consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener      = producerContext.Listener;
            string            requestId     = producerContext.Id;
            ImageRequest      imageRequest  = producerContext.ImageRequest;
            object            callerContext = producerContext.CallerContext;

            // If there's no postprocessor or the postprocessor doesn't
            // require caching, forward results.
            IPostprocessor postprocessor = imageRequest.Postprocessor;

            if (postprocessor == null || postprocessor.PostprocessorCacheKey == null)
            {
                _inputProducer.ProduceResults(consumer, producerContext);
                return;
            }

            listener.OnProducerStart(requestId, ProducerName);
            ICacheKey cacheKey = _cacheKeyFactory.GetPostprocessedBitmapCacheKey(
                imageRequest, callerContext);

            CloseableReference <CloseableImage> cachedReference = _memoryCache.Get(cacheKey);
            var extraMap = default(Dictionary <string, string>);

            if (cachedReference != null)
            {
                extraMap = new Dictionary <string, string>()
                {
                    { VALUE_FOUND, "true" }
                };

                listener.OnProducerFinishWithSuccess(
                    requestId,
                    ProducerName,
                    listener.RequiresExtraMap(requestId) ?
                    new ReadOnlyDictionary <string, string>(extraMap) :
                    null);

                consumer.OnProgressUpdate(1.0f);
                consumer.OnNewResult(cachedReference, true);
                cachedReference.Dispose();
            }
            else
            {
                bool isRepeatedProcessor = postprocessor.GetType() == typeof(IRepeatedPostprocessor);
                IConsumer <CloseableReference <CloseableImage> > cachedConsumer =
                    new CachedPostprocessorConsumer(
                        consumer,
                        cacheKey,
                        isRepeatedProcessor,
                        _memoryCache);

                extraMap = new Dictionary <string, string>()
                {
                    { VALUE_FOUND, "false" }
                };

                listener.OnProducerFinishWithSuccess(
                    requestId,
                    ProducerName,
                    listener.RequiresExtraMap(requestId) ?
                    new ReadOnlyDictionary <string, string>(extraMap) :
                    null);

                _inputProducer.ProduceResults(cachedConsumer, producerContext);
            }
        }
コード例 #28
0
        public void Initialize()
        {
            // Initializes mock data
            _consumer = new BaseConsumerImpl <IDisposable>(
                (result, isLast) =>
            {
                ++_consumerOnNewResultCount;
                _consumerInternalResult = result;
                _consumerInternalIsLast = isLast;
            },
                (error) =>
            {
                ++_consumerOnFailureCount;
                _consumerInternalException = error;
            },
                () =>
            {
                ++_consumerOnCancellationCount;
            },
                (_) => { });

            _producerListener = new ProducerListenerImpl(
                (requestId, producerName) =>
            {
                ++_onProducerStartCount;
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
            },
                (_, __, ___) => { },
                (requestId, producerName, extraMap) =>
            {
                ++_onProducerFinishWithSuccessCount;
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
                _internalExtraMap     = extraMap;
            },
                (requestId, producerName, error, extraMap) =>
            {
                ++_onProducerFinishWithFailureCount;
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
                _internalException    = error;
                _internalExtraMap     = extraMap;
            },
                (requestId, producerName, extraMap) =>
            {
                ++_onProducerFinishWithCancellationCount;
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
                _internalExtraMap     = extraMap;
            },
                (_) =>
            {
                return(_requiresExtraMap);
            });

            _resultSupplier = new SupplierImpl <IDisposable>(() =>
            {
                if (_throwExceptionInResultSupplierGet)
                {
                    throw EXCEPTION;
                }

                return(RESULT);
            });

            _successMap = new Dictionary <string, string>();
            _successMap.Add("state", "success");
            _failureMap = new Dictionary <string, string>();
            _failureMap.Add("state", "failure");
            _cancellationMap = new Dictionary <string, string>();
            _cancellationMap.Add("state", "cancelled");

            _statefulProducerRunnable = new StatefulProducerRunnableImpl <IDisposable>(
                _consumer,
                _producerListener,
                PRODUCER_NAME,
                REQUEST_ID,
                null,
                null,
                null,
                (_) =>
            {
                return(_successMap);
            },
                (_) =>
            {
                return(_failureMap);
            },
                () =>
            {
                return(_cancellationMap);
            },
                (IDisposable result) =>
            {
                try
                {
                    result.Dispose();
                }
                catch (Exception e)
                {
                    throw new Exception("Unexpected IOException", e);
                }
            },
                () =>
            {
                return(Task.FromResult(_resultSupplier.Get()));
            });

            _throwExceptionInResultSupplierGet = false;
            _requiresExtraMap = false;
        }
コード例 #29
0
        public void Initialize()
        {
            // Initializes mock data
            _inputProducer = new ProducerImpl <object>((consumer, producerContext) =>
            {
                _internalConsumer        = consumer;
                _internalProducerContext = (SettableProducerContext)producerContext;
                _completion.Set();
            });

            _consumer = new BaseConsumerImpl <object>(
                (_, __) => { },
                (_) => { },
                () =>
            {
                ++_consumerOnCancellationCount;
                _completion.Set();
            },
                (_) => { });

            _producerListener = new ProducerListenerImpl(
                (requestId, producerName) =>
            {
                ++_onProducerStartCount;
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
            },
                (_, __, ___) =>
            {
                ++_onProducerEventCount;
            },
                (requestId, producerName, extraMap) =>
            {
                ++_onProducerFinishWithSuccessCount;
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
                _internalExtraMap     = extraMap;
            },
                (_, __, ___, ____) =>
            {
                ++_onProducerFinishWithFailureCount;
                _completion.Set();
            },
                (requestId, producerName, extraMap) =>
            {
                ++_onProducerFinishWithCancellationCount;
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
                _internalExtraMap     = extraMap;
            },
                (_) =>
            {
                ++_requiresExtraMapCount;
                return(false);
            });

            _producerContext = new SettableProducerContext(
                IMAGE_REQUEST,
                REQUEST_ID,
                _producerListener,
                new object(),
                RequestLevel.FULL_FETCH,
                false,
                true,
                Priority.MEDIUM);

            _testExecutorService   = new MockSerialExecutorService();
            _threadHandoffProducer = new ThreadHandoffProducer <object>(
                _inputProducer,
                new ThreadHandoffProducerQueue(_testExecutorService));

            _completion = new ManualResetEvent(false);
        }
コード例 #30
0
        public void Initialize()
        {
            _testExecutor            = Executors.NewFixedThreadPool(MAX_DEGREE_OF_PARALLELISM);
            _poolFactory             = new PoolFactory(PoolConfig.NewBuilder().Build());
            _pooledByteBufferFactory = _poolFactory.PooledByteBufferFactory;
            _byteArrayPool           = _poolFactory.SmallByteArrayPool;
            _producerListener        = new ProducerListenerImpl(
                (_, __) => { },
                (requestId, producerName, eventName) =>
            {
                if (eventName.Equals(NetworkFetchProducer.INTERMEDIATE_RESULT_PRODUCER_EVENT))
                {
                    ++_intermediateResultProducerEventCalls;
                }
            },
                (_, __, ___) =>
            {
                ++_onProducerFinishWithSuccessFuncCalls;
            },
                (requestId, producerName, error, extraMap) =>
            {
                _internalRequestId    = requestId;
                _internalProducerName = producerName;
                _internalError        = error;
                _internalExtraMap     = extraMap;
                ++_onProducerFinishWithFailureFuncCalls;
            },
                (_, __, ___) =>
            {
                ++_onProducerFinishWithCancellationFuncCalls;
            },
                (_) =>
            {
                return(false);
            });

            _consumer = new BaseConsumerImpl <EncodedImage>(
                (_, isLast) =>
            {
                ++_onNewResultImplCalls;

                if (isLast)
                {
                    _completion.Set();
                }
            },
                (_) =>
            {
                _completion.Set();
            },
                () =>
            {
                _completion.Set();
            },
                (_) => { });

            _networkFetchProducer = new NetworkFetchProducer(
                _pooledByteBufferFactory,
                _byteArrayPool,
                _networkFetcher);

            _completion = new ManualResetEvent(false);
        }