Exemple #1
0
        /// <summary>
        /// Starts the processing.
        /// </summary>
        void StartProcessing()
        {
            movie = new Movie();
            movie.sourceStream = File.OpenRead(srcPath);

            dstStream = File.OpenWrite(dstPath);
            remux     = new AviRemux();

            // create and initialize demux for the source data
            movie.demux = Demux.forSource(movie.sourceStream);
            movie.demux.Init(movie.sourceStream);

            // create video stream and decoder too. without a decoder we can't access pixels to compare
            if (!movie.demux.hasVideo)
            {
                throw new MpException("Remux needs video stream inside an AVI");
            }
            movie.videoDecoder = VideoDecoder.CreateFor(movie.demux.videoStreamInfo);
            movie.videoDecoder.Init(out framebuffer, movie.demux);

            // create a remux. this will write into dstStream
            bool outputHasAudio = movie.demux.hasAudio && !discardAudio;

            remux.Init(dstStream, movie.demux.videoStreamInfo, outputHasAudio ? movie.demux.audioStreamInfo : null);

            // create a duplicate finder. most of the options control how the frames are actually compared
            options.otherStreamsAvailable = outputHasAudio;
            dupFinder = new DuplicateFrameFinder(movie.videoDecoder, framebuffer, 0, movie.demux.videoStreamInfo.frameCount, options);

            // if we want a to log the duplicate indexes into a file, then clear the file first
            if (!string.IsNullOrEmpty(logDuplicatesPath))
            {
                File.WriteAllText(logDuplicatesPath, "# Duplicate frame index for " + srcPath + "\n");
            }
        }
Exemple #2
0
        /// <summary>
        /// Loads movie with audio. It will be ready for playback
        /// </summary>
        /// <param name="source">Source</param>
        /// <param name="targetFramebuffer">Target framebuffer</param>
        /// <param name="targetAudioBuffer">Target audio buffer</param>
        /// <param name="loadOptions">Load options</param>
        public static Movie Load(MovieSource source, out Texture2D targetFramebuffer, out AudioClip targetAudioBuffer, LoadOptions loadOptions = null)
        {
            if (loadOptions == null)
            {
                loadOptions = LoadOptions.Default;
            }

            if (source.stream == null && source.url == null)
            {
                throw new MpException("Either source.stream or source.url must be provided");
            }

            targetFramebuffer = null;
            targetAudioBuffer = null;

            var movie = new Movie();

            movie.sourceStream = source.stream;             // can be NULL

            // create and initialize demux for the source data
            if (source.url != null)
            {
                movie.demux = loadOptions.demuxOverride != null ? loadOptions.demuxOverride : Streamer.forUrl(source.url);
                ((Streamer)movie.demux).Connect(source.url, loadOptions);
            }
            else
            {
                movie.demux = loadOptions.demuxOverride != null ? loadOptions.demuxOverride : Demux.forSource(source.stream);
                movie.demux.Init(source.stream, loadOptions);
            }

            if (movie.demux.hasVideo && !loadOptions.skipVideo)
            {
                var vsi = movie.demux.videoStreamInfo;
                movie.videoDecoder = VideoDecoder.CreateFor(vsi);
                movie.videoDecoder.Init(out targetFramebuffer, movie.demux, loadOptions);

                if (loadOptions.preloadVideo)
                {
                    movie.frameUV = UnpackFramesToAtlas(movie.videoDecoder, ref targetFramebuffer, vsi.frameCount);
                }
                else
                {
                    movie.frameUV = new Rect[1] {
                        new Rect(0, 0, 1, 1)
                    };
                }
            }
            if (movie.demux.hasAudio && !loadOptions.skipAudio)
            {
                movie.audioDecoder = AudioDecoder.CreateFor(movie.demux.audioStreamInfo);
                movie.audioDecoder.Init(out targetAudioBuffer, movie.demux, loadOptions);
            }
            return(movie);
        }
		/// <summary>
		/// Initializes a duplicate frame finder.
		/// </summary>
		/// <param name="videoDecoder">Video decoder is used to access frame pixel info for comparison</param>
		/// <param name="framebuffer">Provide the same framebuffer here that was returned by video decoder init</param>
		/// <param name="frameOffset">Frame offset. Usually 0</param>
		/// <param name="frameCount">Frame count. Since the decoder doesn't know the frame count, provide it here</param>
		/// <param name="options">Options.</param>
		public DuplicateFrameFinder (VideoDecoder videoDecoder, Texture2D framebuffer, int frameOffset, int frameCount, Options options = null)
		{
			if (options == null)
				options = Options.Default;
			this.options = options;
			this.videoDecoder = videoDecoder;
			this.framebuffer = framebuffer;
			this.frameOffset = frameOffset;
			this.frameCount = frameCount;
			Reset ();
		}
 /// <summary>
 /// Initializes a duplicate frame finder.
 /// </summary>
 /// <param name="videoDecoder">Video decoder is used to access frame pixel info for comparison</param>
 /// <param name="framebuffer">Provide the same framebuffer here that was returned by video decoder init</param>
 /// <param name="frameOffset">Frame offset. Usually 0</param>
 /// <param name="frameCount">Frame count. Since the decoder doesn't know the frame count, provide it here</param>
 /// <param name="options">Options.</param>
 public DuplicateFrameFinder(VideoDecoder videoDecoder, Texture2D framebuffer, int frameOffset, int frameCount, Options options = null)
 {
     if (options == null)
     {
         options = Options.Default;
     }
     this.options      = options;
     this.videoDecoder = videoDecoder;
     this.framebuffer  = framebuffer;
     this.frameOffset  = frameOffset;
     this.frameCount   = frameCount;
     Reset();
 }
        static Rect[] UnpackFramesToAtlas(VideoDecoder videoDecoder, ref Texture2D framebuffer, int frameCount)
        {
            if(frameCount < 1) {
                throw new MpException("Expecting at least 1 video frame");
            }

            #if MP_DEBUG
            var watch = new System.Diagnostics.Stopwatch ();
            watch.Start ();
            #endif

            // TODO don't use PackTexture? Measure performance with alternative implementation

            #if UNITY_STANDALONE || UNITY_WEBPLAYER || UNITY_WEBGL
            int maxWH = MAX_DESKTOP_ATLAS_WH;
            #else
            int maxWH = MAX_MOBILE_ATLAS_WH;
            #endif

            // Seek to the beginning and decode first frame.
            // If it reveals that all the frames won't fit into an atlas, stop.
            videoDecoder.Position = 0;
            videoDecoder.DecodeNext();

            int singleFrameWidth = framebuffer.width;
            int singleFrameHeight = framebuffer.height;

            int maxTilesX = maxWH / singleFrameWidth;
            int maxTilesY = maxWH / singleFrameHeight;
            if(frameCount > maxTilesX * maxTilesY)
            {
                throw new MpException(frameCount + " " + singleFrameWidth + "x" + singleFrameHeight + " video frames can't fit into " +
                                      maxWH + "x" + maxWH + " atlas texture. Consider lowering frame count or resolution, or disable video preloading");
            }

            // Create and fill an array of frame textures that are needed for Unity's PackTextures.
            // Then create an atlas
            var frameTextures = new Texture2D[frameCount];
            frameTextures[0] = CloneTexture(framebuffer);

            for(int i = 1; i < frameCount; i++) {
                videoDecoder.DecodeNext();
                frameTextures[i] = CloneTexture(framebuffer);
            }

            Rect[] uvs = framebuffer.PackTextures(frameTextures, 0, maxWH);

            // Free temporarily allocated textures
            for(int i = 0; i < frameCount; i++) {
                #if UNITY_EDITOR
                Texture2D.DestroyImmediate(frameTextures[i]);
                #else
                Texture2D.Destroy(frameTextures[i]);
                #endif
            }

            #if MP_DEBUG
            watch.Stop ();
            Debug.Log ("Packed " + frameCount + " " + singleFrameWidth + "x" + singleFrameHeight +
                       " video frames into an atlas (" + framebuffer.width + "x" + framebuffer.height + ")" +
                       " in " + (watch.Elapsed.TotalMilliseconds * 0.001f) + " seconds");
            #endif

            return uvs;
        }
Exemple #6
0
        static Rect[] UnpackFramesToAtlas(VideoDecoder videoDecoder, ref Texture2D framebuffer, int frameCount)
        {
            if (frameCount < 1)
            {
                throw new MpException("Expecting at least 1 video frame");
            }

                        #if MP_DEBUG
            var watch = new System.Diagnostics.Stopwatch();
            watch.Start();
                        #endif

            // TODO don't use PackTexture? Measure performance with alternative implementation

                        #if UNITY_STANDALONE || UNITY_WEBPLAYER || UNITY_WEBGL
            int maxWH = MAX_DESKTOP_ATLAS_WH;
                        #else
            int maxWH = MAX_MOBILE_ATLAS_WH;
                        #endif

            // Seek to the beginning and decode first frame.
            // If it reveals that all the frames won't fit into an atlas, stop.
            videoDecoder.Position = 0;
            videoDecoder.DecodeNext();

            int singleFrameWidth  = framebuffer.width;
            int singleFrameHeight = framebuffer.height;

            int maxTilesX = maxWH / singleFrameWidth;
            int maxTilesY = maxWH / singleFrameHeight;
            if (frameCount > maxTilesX * maxTilesY)
            {
                throw new MpException(frameCount + " " + singleFrameWidth + "x" + singleFrameHeight + " video frames can't fit into " +
                                      maxWH + "x" + maxWH + " atlas texture. Consider lowering frame count or resolution, or disable video preloading");
            }

            // Create and fill an array of frame textures that are needed for Unity's PackTextures.
            // Then create an atlas
            var frameTextures = new Texture2D[frameCount];
            frameTextures[0] = CloneTexture(framebuffer);

            for (int i = 1; i < frameCount; i++)
            {
                videoDecoder.DecodeNext();
                frameTextures[i] = CloneTexture(framebuffer);
            }

            Rect[] uvs = framebuffer.PackTextures(frameTextures, 0, maxWH);

            // Free temporarily allocated textures
            for (int i = 0; i < frameCount; i++)
            {
                                #if UNITY_EDITOR
                Texture2D.DestroyImmediate(frameTextures[i]);
                                #else
                Texture2D.Destroy(frameTextures[i]);
                                #endif
            }

                        #if MP_DEBUG
            watch.Stop();
            Debug.Log("Packed " + frameCount + " " + singleFrameWidth + "x" + singleFrameHeight +
                      " video frames into an atlas (" + framebuffer.width + "x" + framebuffer.height + ")" +
                      " in " + (watch.Elapsed.TotalMilliseconds * 0.001f) + " seconds");
                        #endif

            return(uvs);
        }