コード例 #1
0
        /// <summary>
        /// Reads one frame from srcStream, performs duplicate check, writes to dstStream.
        /// Call it repeatedly until all frames are processed (until false is returned).
        /// </summary>
        bool ProcessNextFrame()
        {
            if (!dupFinder.Progress())
            {
                return(false);
            }

            var dups = dupFinder.duplicates;

            int lastProcessedFrameIndex = dupFinder.framesProcessed - 1;
            int lookbackFrameIndex      = dups [lastProcessedFrameIndex];

            if (!string.IsNullOrEmpty(logDuplicatesPath))
            {
                using (var file = File.AppendText(logDuplicatesPath)) {
                    file.WriteLine(lastProcessedFrameIndex + " " + lookbackFrameIndex);
                }
            }

            byte[] buf;
            if (lookbackFrameIndex < 0 || !remux.WriteLookbackVideoFrame(lookbackFrameIndex))
            {
                movie.demux.VideoPosition = lastProcessedFrameIndex;
                int bytesRead = movie.demux.ReadVideoFrame(out buf);
                remux.WriteNextVideoFrame(buf, bytesRead);
            }

            if (!discardAudio && movie.demux.hasAudio)
            {
                int wantCnt = Mathf.RoundToInt(movie.demux.audioStreamInfo.sampleRate / movie.demux.videoStreamInfo.framerate);
                movie.demux.AudioPosition = lastProcessedFrameIndex * wantCnt;
                int samplesRead = movie.demux.ReadAudioSamples(out buf, wantCnt);
                remux.WriteNextAudioSamples(buf, samplesRead * movie.demux.audioStreamInfo.sampleSize);
            }
            return(true);
        }
コード例 #2
0
    void DropHalfTheFramesRemux()
    {
        // In this example we're going one level deeper in the API and work directly
        // with Demux class. We could use MoviePlayerUtil.Load too, but for remuxing
        // we don't need Decoders to be instantiated, because we're just copying encoded
        // frame bytes around.
        //
        // Since we're not using decoders, we're not referencing anything from Unity API.
        // Therefore it's possible to run it in separate thread.
        RunInBackgroundOrNot(delegate() {
            // Instantiate a demux for an input stream based on stream type.
            Stream instream = File.OpenRead(infile);
            Demux demux     = Demux.forSource(instream);
            demux.Init(instream);

            // Instantiate a remux for an output stream. Here we have to explicity
            // instantiate the remux we want, in this case, AviRemux, and set its
            // properties. Since we're not doing much here, we can use the same
            // videoStreamInfo and audioStreamInfo for remux as demux. For the video
            // however we clone the stream info, because we want to change it. Since
            // we're going to drop every other frame, we also need to lower the
            // video framerate.
            Stream outstream                = File.OpenWrite(outfile);
            Remux remux                     = new AviRemux();
            var remuxVideoStreamInfo        = new VideoStreamInfo(demux.videoStreamInfo);
            remuxVideoStreamInfo.framerate /= 2;
            remux.Init(outstream, remuxVideoStreamInfo, demux.audioStreamInfo);

            // Just sum buffers and variables needed later
            byte[] videoBuffer, audioBuffer;
            int videoBytesRead, audioBytesRead;

            // Loop until we've processed all the video frames. If we wanted to run this code
            // in main Unity thread without blocking, then we could wrap it all in a coroutine
            // and do "yield return 1" inside the loop.
            do
            {
                // Here we're using sequential access to video (and audio) stream. The same could
                // be achieved with random access, but then only demuxes that can seek in a file
                // can be used (no streaming from network or webcam).
                videoBytesRead = demux.ReadVideoFrame(out videoBuffer);
                if (videoBytesRead > 0)
                {
                    // Read the exact number of audio samples that are to be played during this frame
                    int samplesPerVideoFrame = (int)(demux.audioStreamInfo.sampleRate / demux.videoStreamInfo.framerate);
                    audioBytesRead           = demux.ReadAudioSamples(out audioBuffer, samplesPerVideoFrame);

                    // Only write every second video frame, but all the audio samples. The total stream
                    // lengths will still be the same, because we've set the framerate for remuxed stream
                    // to half of the original.
                    if (demux.VideoPosition % 2 == 1)
                    {
                        remux.WriteNextVideoFrame(videoBuffer, videoBytesRead);
                    }
                    remux.WriteNextAudioSamples(audioBuffer, audioBytesRead);
                }
            } while(videoBytesRead > 0);

            // Close the remux and demux. While it's possible to leave demux just hanging there unclosed and
            // possibly introducing a memory leak, we have to Close the remux for the output to be playable.
            // The reason is that AviDemux needs to write all unwritten index chunks and update the avi header
            // after all frames have been written.
            remux.Shutdown();
            demux.Shutdown();
        });
    }