private void SeekToTimestampInternal(double timestamp, out double newTimestamp)
        {
            var oldTimestamp = currentTimestamp;

            reader.FrameQueue.Clear();
            reader.AudioQueue.Clear();
            previousFrames.Clear();
            reader.SeekToTimestamp(timestamp);
            synchronization = null;
            while (reader.ReadNextPacket() &&
                   (reader.FrameQueue.Count == 0 ||
                    Math.Abs(reader.FrameQueue.Peek().Timestamp - oldTimestamp) < Math.Abs(reader.FrameQueue.Peek().Timestamp - timestamp)))
            {
                reader.FrameQueue.Clear();
                reader.AudioQueue.Clear();
            }

            if (TryEnsureFrameQueueNotEmpty())
            {
                currentFrame = reader.FrameQueue.Dequeue();
                newTimestamp = currentFrame.Timestamp;
            }
            else
            {
                // should never happen
                currentFrame = new MovieFrame
                {
                    RgbaData  = new byte[GraphicsHelper.AlignedSize(reader.Width, reader.Height)],
                    Timestamp = timestamp
                };
                newTimestamp = Movie.Duration;
            }
        }
Exemple #2
0
        public unsafe byte[] GetRawData()
        {
            infra.GlContext.Bindings.Textures.Units[infra.GlContext.Bindings.Textures.EditingIndex].Set(GlTexture);
            var result = new byte[GraphicsHelper.AlignedSize(Size.Width, Size.Height)];

            fixed(byte *pResult = result)
            infra.GlContext.GL.GetTexImage((int)GlTexture.Target, 0, (int)All.Rgba, (int)All.UnsignedByte, (IntPtr)pResult);

            return(result);
        }
 public StandardMoviePlayback(IMovie movie)
     : base(ResourceVolatility.Volatile)
 {
     Movie        = movie;
     reader       = movie.Read();
     videoSpeed   = 1.0;
     frameImage   = new MoviePlaybackImage();
     currentFrame = new MovieFrame
     {
         RgbaData  = new byte[GraphicsHelper.AlignedSize(reader.Width, reader.Height)],
         Timestamp = 0
     };
 }
        public FFmpegMovieReader(IFFmpegMovieReaderIoContextWrapper contextWrapper, string url)
        {
            FrameQueue = new Queue <MovieFrame>();
            AudioQueue = new Queue <MovieAudioFrame>();

            this.contextWrapper = contextWrapper;

            pFormatContext = ffmpeg.avformat_alloc_context();
            contextWrapper.PrepareFormatContext(pFormatContext);
            var pFormatContextLoc = pFormatContext;
            var openInputResult   = ffmpeg.avformat_open_input(&pFormatContextLoc, url, null, null);

            if (openInputResult != 0)
            {
                throw new Exception("Could not open format.");
            }

            if (ffmpeg.avformat_find_stream_info(pFormatContext, null) != 0)
            {
                throw new Exception("Could not find stream info");
            }
            streamVideoIndex = GetVideoStreamIndex();
            //streamAudioIndex = GetAudioStreamIndex();
            pVideoCodecContext = pFormatContext->streams[streamVideoIndex]->codec;
            //pAudioCodecContext = pFormatContext->streams[streamAudioIndex]->codec;

            var width  = Width = pVideoCodecContext->width;
            var height = Height = pVideoCodecContext->height;

            Duration = (double)pFormatContext->duration / ffmpeg.AV_TIME_BASE;
            var sourcePixFmt = pVideoCodecContext->pix_fmt;
            var videoCodecId = pVideoCodecContext->codec_id;

            //var audioCodecId = pAudioCodecContext->codec_id;
            pConvertContext = ffmpeg.sws_getContext(width, height, sourcePixFmt,
                                                    width, height, DestinationPixFmt,
                                                    ffmpeg.SWS_FAST_BILINEAR, null, null, null);
            if (pConvertContext == null)
            {
                throw new Exception("Could not initialize the conversion context.");
            }

            videoDataSize = GraphicsHelper.AlignedSize(width, height);

            pConvertedFrame = ffmpeg.av_frame_alloc();
            var convertedFrameBufferSize =
                ffmpeg.av_image_get_buffer_size(DestinationPixFmt, width, height, ConvertedBufferAlign);

            convertedFrameBuffer = ffmpeg.av_malloc((ulong)convertedFrameBufferSize);
            dstData     = new byte_ptrArray4();
            dstLinesize = new int_array4();

            if (ffmpeg.av_image_fill_arrays(ref dstData, ref dstLinesize, (byte *)convertedFrameBuffer,
                                            DestinationPixFmt, width, height, ConvertedBufferAlign) < 0)
            {
                throw new Exception("Failed to setup destination buffer.");
            }

            var pVideoCodec = ffmpeg.avcodec_find_decoder(videoCodecId);

            if (pVideoCodec == null)
            {
                throw new ApplicationException("Unsupported video codec.");
            }
            //var pAudioCodec = ffmpeg.avcodec_find_decoder(audioCodecId);
            //if (pAudioCodec == null)
            //    throw new ApplicationException("Unsupported audio codec.");

            if ((pVideoCodec->capabilities & ffmpeg.AV_CODEC_CAP_TRUNCATED) == ffmpeg.AV_CODEC_CAP_TRUNCATED)
            {
                pVideoCodecContext->flags |= ffmpeg.AV_CODEC_FLAG_TRUNCATED;
            }

            var openVideoCodecResult = ffmpeg.avcodec_open2(pVideoCodecContext, pVideoCodec, null);

            if (openVideoCodecResult < 0)
            {
                throw new Exception($"Could not open video codec: {openVideoCodecResult}");
            }

            //var openAudioCodecResult = ffmpeg.avcodec_open2(pAudioCodecContext, pAudioCodec, null);
            //if (openAudioCodecResult < 0)
            //    throw new Exception($"Could not open audio codec: {openAudioCodecResult}");

            pDecodedFrame = ffmpeg.av_frame_alloc();
            packet        = new AVPacket();
            var packetLoc = packet;

            ffmpeg.av_init_packet(&packetLoc);
            packet = packetLoc;
        }