Ejemplo n.º 1
0
        /// <summary>
        /// Return the next frame of a stream.
        /// </summary>
        /// <param name="formatContext">
        /// The format context.
        /// </param>
        /// <returns>
        /// Value indicating wheter a frame was received.
        /// </returns>
        public bool ReadFrame(AVFormatContext formatContext)
        {
            int ret = this.client.ReadFrame(formatContext, this);

            if (ret == 0)
            {
                return(true);
            }
            else if (ret == NativeFFmpeg.AVERROR_EOF)
            {
                return(false);
            }
            else
            {
                this.client.ThrowOnAVError(ret, postiveIndicatesSuccess: false);
                return(false);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Close an opened input AVFormatContext. Free it and all its contents and set *s to NULL.
        /// </summary>
        /// <param name="formatContext">
        /// The format context.
        /// </param>
        public virtual void CloseFormatContext(AVFormatContext formatContext)
        {
            var native = formatContext.NativeObject;

            ffmpeg.avformat_close_input(&native);
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Return the next frame of a stream.
 /// </summary>
 /// <param name="context">
 /// The context.
 /// </param>
 /// <param name="packet">
 /// The packet.
 /// </param>
 /// <returns>
 /// 0 if OK, negative on error or end of file.
 /// </returns>
 public virtual int ReadFrame(AVFormatContext context, AVPacket packet)
 {
     return(ffmpeg.av_read_frame(context.NativeObject, packet.NativeObject));
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Open an input stream and read the header. The codecs are not opened. The stream must be closed with avformat_close_input().
        /// </summary>
        /// <param name="context">
        /// Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
        /// May be a pointer to NULL, in which case an AVFormatContext is allocated by this
        /// function and written into ps. Note that a user-supplied AVFormatContext will
        /// be freed on failure.
        /// </param>
        /// <param name="url">
        /// URL of the stream to open.
        /// </param>
        /// <param name="fmt">
        /// If non-NULL, this parameter forces a specific input format. Otherwise the format is autodetected.
        /// </param>
        /// <param name="options">
        /// A dictionary filled with AVFormatContext and demuxer-private options.On return
        /// this parameter will be destroyed and replaced with a dict containing options
        /// that were not found. May be NULL.
        /// </param>
        /// <returns>
        /// 0 on success, a negative AVERROR on failure.
        /// </returns>
        public int avformat_open_input(AVFormatContext context, string?url, NativeAVInputFormat *fmt, AVDictionary **options)
        {
            var ctx = context.NativeObject;

            return(ffmpeg.avformat_open_input(&ctx, url, fmt, options));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Decodes the current stream and blocks until decoding is done.
        /// </summary>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation.
        /// </param>
        public virtual unsafe void Decode(CancellationToken cancellationToken = default)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException(nameof(H264Decoder));
            }

            var readDelegate = new NativeReadPacket(this.Read);
            var readFunc     = new NativeReadPacketFunc()
            {
                Pointer = Marshal.GetFunctionPointerForDelegate(readDelegate),
            };

            using (var ioContext = new AVIOContext(this.client, ReadBufferSize, readFunc, null))
                using (var formatContext = new AVFormatContext(this.client, ioContext))
                {
                    formatContext.OpenInputStream("h264");
                    var stream = formatContext.GetVideoStream();
                    using (var codec = new AVCodec(this.client, stream))
                        using (var frame = new AVFrame(this.client))
                            using (var packet = new AVPacket(this.client))
                            {
                                int frameNumber = 0;

                                while (packet.ReadFrame(formatContext))
                                {
                                    this.logger.LogDebug($"Got a frame for stream {packet.StreamIndex}");

                                    if (packet.NativeObject->stream_index != stream.Index)
                                    {
                                        continue;
                                    }

                                    this.logger.LogDebug("Sending packet");
                                    codec.SendPacket(packet);

                                    int framesInPacket = 0;

                                    while (codec.ReceiveFrame(frame))
                                    {
                                        this.logger.LogDebug("Receiving frame");

                                        framesInPacket += 1;
                                        if (frame.PictureType != NativeAVPictureType.AV_PICTURE_TYPE_NONE)
                                        {
                                            this.logger.LogDebug($"Got a picture of {frame.Width}x{frame.Height} in color space {frame.Format}");

                                            // decode frame
                                            this.FrameBuffer.DecompresFrame(
                                                frame.Width,
                                                frame.Height,
                                                frame.Width,
                                                frame.Height,
                                                frame.Width * 4,
                                                new Span <byte>(frame.NativeObject->data[0], frame.NativeObject->linesize[0]),
                                                new Span <byte>(frame.NativeObject->data[1], frame.NativeObject->linesize[1]),
                                                new Span <byte>(frame.NativeObject->data[2], frame.NativeObject->linesize[2]),
                                                new int[] { frame.NativeObject->linesize[0], frame.NativeObject->linesize[1], frame.NativeObject->linesize[2] });
                                        }
                                    }

                                    this.logger.LogInformation($"Add {framesInPacket} frames in packet.");
                                    frameNumber++;
                                }
                            }
                }

            GC.KeepAlive(readDelegate);
        }