/// <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> /// Unloads the movie and releases all resources like file handlers associated with it. /// It's a good idea to stop the playback before unloading the movie. /// </summary> public static void Unload(Movie movie) { if (movie != null) { if (movie.sourceStream != null) { movie.sourceStream.Dispose (); movie.sourceStream = null; } if (movie.videoDecoder != null) { movie.videoDecoder.Shutdown (); movie.videoDecoder = null; } if (movie.audioDecoder != null) { movie.audioDecoder.Shutdown (); movie.audioDecoder = null; } if (movie.demux != null) { movie.demux.Shutdown (); movie.demux = null; } } }
/// <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"); } }