Example #1
0
        /// <summary>
        /// Check if the index belongs to a specific file
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_IndexBelongsToFile</c>.</para>
        /// <para>Makes a heuristic (but very reliable) guess about whether the index is of the <paramref name="sourceFile"/> or not.</para>
        /// <para>Useful to determine if the index object you just created by <see cref="Index(string)">loading an index file from disk</see> is actually relevant to your interests, since the only two ways to pair up index files with source files are a) trust the user blindly, or b) comparing the filenames; neither is very reliable.</para>
        /// </remarks>
        /// <param name="sourceFile">File to check against</param>
        /// <returns>True or false depending on the result</returns>
        public bool BelongsToFile(string sourceFile)
        {
            if (sourceFile == null)
            {
                throw new ArgumentNullException(@"sourceFile");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            var sourceFileBytes = Encoding.UTF8.GetBytes(sourceFile);

            if (NativeMethods.FFMS_IndexBelongsToFile(_handle, sourceFileBytes, ref err) == 0)
            {
                return(true);
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_MISMATCH)
            {
                return(false);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #2
0
        /// <summary>
        /// Create an indexer of a media file
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_CreateIndexer</c> or <c>FFMS_CreateIndexerWithDemuxer</c>.</para>
        /// <para>The chosen demuxer gets used for both indexing and decoding later on. Only force one if you know what you're doing.</para>
        /// <para>Picking a demuxer that doesn't work on your file will not cause automatic fallback on lavf or automatic probing; it'll just cause indexer creation to fail.</para>
        /// </remarks>
        /// <param name="sourceFile">The media file</param>
        /// <param name="demuxer">What demuxer to use</param>
        /// <exception cref="System.IO.FileLoadException">Failure to load the media file</exception>
        public Indexer(string sourceFile, Source demuxer = Source.Default)
        {
            if (sourceFile == null)
            {
                throw new ArgumentNullException(@"sourceFile");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            byte[] sourceFileBytes = Encoding.UTF8.GetBytes(sourceFile);
            _handle = NativeMethods.FFMS_CreateIndexerWithDemuxer(sourceFileBytes, (int)demuxer, ref err);

            if (!_handle.IsInvalid)
            {
                return;
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ)
            {
                throw new System.IO.FileLoadException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #3
0
        /// <summary>
        /// Override the source format for video frames
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_SetInputFormatV</c>.</para>
        /// <para>Override the source colorspace passed to SWScale for conversions and resizing for all further calls to <see cref="GetFrame(int)">GetFrame</see>, until the next time you call <see cref="SetInputFormat(int, ColorSpace, ColorRange)">SetInputFormat</see> or <see cref="ResetInputFormat">ResetInputFormat</see>.</para>
        /// <para>This is intended primarily for compatibility with programs which use the wrong YUV colorspace when converting to or from RGB, but can also be useful for files which have incorrect colorspace flags.</para>
        /// <para>Values passed are not checked for sanity; if you wish you may tell FFMS2 to pretend that a RGB files is actually YUV using this function, but doing so is unlikely to have useful results.</para>
        /// <para>This function only has an effect if the output format is also set with <see cref="SetOutputFormat">SetOutputFormat</see>.</para>
        /// </remarks>
        /// <param name="pixelFormat">The desired input pixel format</param>
        /// <param name="colorSpace">The desired input colorspace</param>
        /// <param name="colorRange">The desired input colorrange</param>
        /// <seealso cref="ResetInputFormat"/>
        /// <exception cref="ArgumentException">Trying to set an insane input format.</exception>
        public void SetInputFormat(int pixelFormat, ColorSpace colorSpace = ColorSpace.Unspecified, ColorRange colorRange = ColorRange.Unspecified)
        {
            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            MarkLastFrameAsInvalid();

            if (NativeMethods.FFMS_SetInputFormatV(_nativePtr, (int)colorSpace, (int)colorRange, pixelFormat, ref err) == 0)
            {
                return;
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_SCALING && err.SubType == FFMS_Errors.FFMS_ERROR_INVALID_ARGUMENT)
            {
                throw new ArgumentException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_DECODING && err.SubType == FFMS_Errors.FFMS_ERROR_CODEC)
            {
                throw new ArgumentException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #4
0
        /// <summary>
        /// Retrieves a video frame at a timestamp
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_GetFrameByTime</c>.</para>
        /// <para>The returned frame is owned by the given <see cref="VideoSource">VideoSource object</see>, and remains valid until the video source is destroyed, a different frame is requested from the video source, or the video source's input or output format is changed.</para>
        /// <para>Does the exact same thing as <see cref="GetFrame(int)">GetFrame</see> except instead of giving it a frame number you give it a timestamp in seconds, and it will retrieve the frame that starts closest to that timestamp.</para>
        /// <para>This function exists for the people who are too lazy to build and traverse a mapping between frame numbers and timestamps themselves.</para>
        /// </remarks>
        /// <param name="time">Timestamp</param>
        /// <returns>The generated <see cref="Frame">Frame object</see>.</returns>
        /// <seealso cref="GetFrame(int)"/>
        /// <exception cref="ArgumentOutOfRangeException">Trying to access a Frame that doesn't exist.</exception>
        public Frame GetFrame(double time)
        {
            if (time < 0 || time > LastTime)
            {
                throw new ArgumentOutOfRangeException(@"time", "That frame doesn't exist.");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            MarkLastFrameAsInvalid();

            IntPtr framePtr;

            lock (this)
            {
                framePtr = NativeMethods.FFMS_GetFrameByTime(_nativePtr, time, ref err);
            }

            if (framePtr == IntPtr.Zero)
            {
                throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
            }

            LastFrame = new Frame(framePtr);
            return(LastFrame);
        }
Example #5
0
        /// <summary>
        /// Write the index to disk
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_WriteIndex</c>.</para>
        /// </remarks>
        /// <param name="indexFile">Can be an absolute or relative path; it will be truncated and overwritten if it already exists</param>
        /// <exception cref="System.IO.IOException">Failure to write the index</exception>
        public void WriteIndex(string indexFile)
        {
            if (indexFile == null)
            {
                throw new ArgumentNullException(@"indexFile");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            var indexFileBytes = Encoding.UTF8.GetBytes(indexFile);

            if (NativeMethods.FFMS_WriteIndex(indexFileBytes, _handle, ref err) == 0)
            {
                return;
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ)
            {
                throw new System.IO.IOException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #6
0
        /// <summary>
        /// Writes timecodes for the track to disk
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_WriteTimecodes</c>.</para>
        /// <para>Writes Matroska v2 timecodes for the track to the given file.</para>
        /// <para>Only meaningful for video tracks. </para>
        /// </remarks>
        /// <param name="timecodeFile">Can be a relative or absolute path. The file will be truncated and overwritten if it already exists.</param>
        /// <exception cref="System.IO.IOException">Failure to open or write to the file</exception>
        public void WriteTimecodes(string timecodeFile)
        {
            if (timecodeFile == null)
            {
                throw new ArgumentNullException(@"timecodeFile");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            var timecodeFileBytes = Encoding.UTF8.GetBytes(timecodeFile);

            if (NativeMethods.FFMS_WriteTimecodes(_nativePtr, timecodeFileBytes, ref err) == 0)
            {
                return;
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ) // FFMS2 2.19 throws this type of error
            {
                throw new System.IO.IOException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_TRACK && err.SubType == FFMS_Errors.FFMS_ERROR_NO_FILE)
            {
                throw new System.IO.IOException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_TRACK && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_WRITE)
            {
                throw new System.IO.IOException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #7
0
        /// <summary>
        /// Sets the output format for video frames
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_SetOutputFormatV2</c>.</para>
        /// </remarks>
        /// <param name="targetFormats">The desired output colorspace(s)
        /// <para>The destination that gives the least lossy conversion from the source colorspace will automatically be selected, ON A FRAME BASIS.</para>
        /// <para>To get the integer constant representing a given colorspace, see <see cref="FFMS2.GetPixelFormat">GetPixFmt</see>.</para>
        /// </param>
        /// <param name="width">The desired image width, in pixels
        /// <para>If you do not want to resize just pass the input dimensions.</para>
        /// </param>
        /// <param name="height">The desired image height, in pixels
        /// <para>If you do not want to resize just pass the input dimensions.</para>
        /// </param>
        /// <param name="resizer">The desired image resizing algorithm.
        /// <para>You must choose one even if you're not actually rescaling the image, because the video may change resolution mid-stream and then you will be using a resizer whether you want it or not (you will only know that the resolution changed after you actually decoded a frame with a new resolution), and it may also get used for rescaling subsampled chroma planes.</para>
        /// </param>
        /// <seealso cref="ResetOutputFormat"/>
        /// <exception cref="ArgumentOutOfRangeException">Trying to set the desired image resolution to an invalid size like 0, 0.</exception>
        /// <exception cref="ArgumentNullException">Trying to supply a null list of <paramref name="targetFormats"/>.</exception>
        /// <exception cref="ArgumentException">Trying to set an invalid output format.</exception>
        public void SetOutputFormat(ICollection <int> targetFormats, int width, int height, Resizer resizer)
        {
            if (targetFormats == null)
            {
                throw new ArgumentNullException(@"targetFormats");
            }
            if (width <= 0)
            {
                throw new ArgumentOutOfRangeException(@"width", "Invalid image width.");
            }
            if (height <= 0)
            {
                throw new ArgumentOutOfRangeException(@"height", "Invalid image height.");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            var targetFormatsArray = new int[targetFormats.Count + 1];

            targetFormats.CopyTo(targetFormatsArray, 0);
            targetFormatsArray[targetFormats.Count] = -1;

            MarkLastFrameAsInvalid();

            if (NativeMethods.FFMS_SetOutputFormatV2(_nativePtr, targetFormatsArray, width, height, (int)resizer, ref err) == 0)
            {
                return;
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_SCALING && err.SubType == FFMS_Errors.FFMS_ERROR_INVALID_ARGUMENT)
            {
                throw new ArgumentException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_DECODING && err.SubType == FFMS_Errors.FFMS_ERROR_CODEC)
            {
                throw new ArgumentException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #8
0
        /// <summary>
        /// Create an <see cref="FFMSSharp.AudioSource">AudioSource object</see>
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_CreateAudioSource</c>.</para>
        /// <para>Note that the index object is copied into the <see cref="FFMSSharp.AudioSource">AudioSource object</see> upon its creation, so once you've created the video source you can generally destroy the index object immediately, since all info you can retrieve from it is also retrievable from the <see cref="FFMSSharp.AudioSource">AudioSource object</see>.</para>
        /// </remarks>
        /// <param name="sourceFile">The media file. Can be an absolute or relative path</param>
        /// <param name="track">Track number of the specific audio track</param>
        /// <param name="delayMode">Controls how audio with a non-zero first PTS is handled; in other words what FFMS does about audio delay.</param>
        /// <returns>The generated <see cref="FFMSSharp.AudioSource">AudioSource object</see></returns>
        /// <seealso cref="VideoSource"/>
        /// <seealso cref="GetFirstTrackOfType"/>
        /// <seealso cref="GetFirstIndexedTrackOfType"/>
        /// <exception cref="System.IO.FileLoadException">Failure to open the <paramref name="sourceFile"/></exception>
        /// <exception cref="System.IO.FileNotFoundException">Trying to read a file that does not exist.</exception>
        /// <exception cref="ArgumentException">Trying to make a AudioSource out of an invalid track</exception>
        /// <exception cref="InvalidOperationException">Supplying the wrong <paramref name="sourceFile"/></exception>
        public AudioSource AudioSource(string sourceFile, int track, AudioDelayMode delayMode = AudioDelayMode.FirstVideoTrack)
        {
            if (sourceFile == null)
            {
                throw new ArgumentNullException(@"sourceFile");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            var sourceFileBytes = Encoding.UTF8.GetBytes(sourceFile);
            var audioSource     = NativeMethods.FFMS_CreateAudioSource(sourceFileBytes, track, _handle, (int)delayMode, ref err);

            if (audioSource != IntPtr.Zero)
            {
                return(new AudioSource(audioSource));
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ)
            {
                throw new System.IO.FileLoadException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_NO_FILE)
            {
                throw new System.IO.FileNotFoundException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_INVALID_ARGUMENT)
            {
                throw new ArgumentException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_MISMATCH)
            {
                throw new InvalidOperationException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #9
0
        /// <summary>
        /// Get the track number of the first indexed track of a specific type
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_GetFirstIndexedTrackOfType</c>.</para>
        /// <para>Does the exact same thing as <see cref="GetFirstTrackOfType">GetFirstTrackOfType</see> but ignores tracks that have not been indexed.</para>
        /// </remarks>
        /// <param name="type">Track type</param>
        /// <returns>Track number</returns>
        /// <seealso cref="GetFirstTrackOfType"/>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">Trying to find a type of track that doesn't exist in the media file.</exception>
        public int GetFirstIndexedTrackOfType(TrackType type)
        {
            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            var track = NativeMethods.FFMS_GetFirstIndexedTrackOfType(_handle, (int)type, ref err);

            if (track >= 0)
            {
                return(track);
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_NOT_AVAILABLE)
            {
                throw new System.Collections.Generic.KeyNotFoundException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #10
0
        /// <summary>
        /// Decode a number of audio samples
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_GetAudio</c>.</para>
        /// <para>The output is <paramref name="count"/> samples long, starting from <paramref name="start"/> (inclusive).</para>
        /// </remarks>
        /// <param name="start">The first sample to decode
        /// <para>Sample numbers start from zero and hence the last sample in the stream is number <see cref="NumberOfSamples"/> minus 1.</para>
        /// </param>
        /// <param name="count">The amount of samples to decode
        /// <para>Sample numbers start from zero and hence the last sample in the stream is number <see cref="NumberOfSamples"/> minus 1.</para>
        /// </param>
        /// <returns>The raw audio data</returns>
        /// <threadsafety instance="false"/>
        /// <exception cref="ArgumentOutOfRangeException">Trying to access audio samples that are out of range of the stream.</exception>
        /// <exception cref="NotSupportedException">Trying to start half-way into an unseekable audio stream.</exception>
        public byte[] GetAudio(long start, long count)
        {
            if (start < 0 || start > NumberOfSamples - 1)
            {
                throw new ArgumentOutOfRangeException(@"start", "Invalid start sample.");
            }
            if (count < 0 || start + count > NumberOfSamples - 1)
            {
                throw new ArgumentOutOfRangeException(@"count", "Invalid sample count.");
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };

            var buffer = new byte[(_ap.BitsPerSample / 8) * _ap.Channels * count];

            int success;

            lock (this)
            {
                success = NativeMethods.FFMS_GetAudio(_nativePtr, buffer, start, count, ref err);
            }

            if (success == 0)
            {
                return(buffer);
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_SEEKING && err.SubType == FFMS_Errors.FFMS_ERROR_CODEC)
            {
                throw new NotSupportedException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #11
0
 public static extern SafeIndexHandle FFMS_DoIndexing(SafeIndexerHandle Indexer, int IndexMask, int DumpMask, TAudioNameCallback ANC, [MarshalAs(UnmanagedType.LPStr)] string ANCPrivate, int ErrorHandling, TIndexCallback IC, IntPtr ICPrivate, ref FFMS_ErrorInfo ErrorInfo);
Example #12
0
 public static extern IntPtr FFMS_GetFrame(IntPtr V, int n, ref FFMS_ErrorInfo ErrorInfo);
Example #13
0
        /// <summary>
        /// Create an indexer of a media file
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_CreateIndexer</c> or <c>FFMS_CreateIndexerWithDemuxer</c>.</para>
        /// <para>The chosen demuxer gets used for both indexing and decoding later on. Only force one if you know what you're doing.</para>
        /// <para>Picking a demuxer that doesn't work on your file will not cause automatic fallback on lavf or automatic probing; it'll just cause indexer creation to fail.</para>
        /// </remarks>
        /// <param name="sourceFile">The media file</param>
        /// <param name="demuxer">What demuxer to use</param>
        /// <exception cref="System.IO.FileLoadException">Failure to load the media file</exception>
        public Indexer(string sourceFile, Source demuxer = Source.Default)
        {
            if (sourceFile == null) throw new ArgumentNullException(@"sourceFile");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            byte[] sourceFileBytes = Encoding.UTF8.GetBytes(sourceFile);
            _handle = NativeMethods.FFMS_CreateIndexerWithDemuxer(sourceFileBytes, (int)demuxer, ref err);

            if (!_handle.IsInvalid) return;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ)
                throw new System.IO.FileLoadException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #14
0
 public static extern SafeIndexerHandle FFMS_CreateIndexerWithDemuxer(byte[] SourceFile, int Demuxer, ref FFMS_ErrorInfo ErrorInfo);
Example #15
0
 public static extern IntPtr FFMS_GetFrameByTime(IntPtr V, double Time, ref FFMS_ErrorInfo ErrorInfo);
Example #16
0
 public static extern int FFMS_GetAudio(IntPtr A, byte[] Buf, long Start, long Count, ref FFMS_ErrorInfo ErrorInfo);
Example #17
0
 public static extern IntPtr FFMS_GetFrameByTime(IntPtr V, double Time, ref FFMS_ErrorInfo ErrorInfo);
Example #18
0
 public static extern int FFMS_IndexBelongsToFile(SafeIndexHandle Index, byte[] SourceFile, ref FFMS_ErrorInfo ErrorInfo);
Example #19
0
 public static extern int FFMS_GetFirstTrackOfType(SafeIndexHandle Index, int TrackType, ref FFMS_ErrorInfo ErrorInfo);
Example #20
0
 public static extern IntPtr FFMS_CreateVideoSource(byte[] SourceFile, int Track, SafeIndexHandle Index, int Threads, int SeekMode, ref FFMS_ErrorInfo ErrorInfo);
Example #21
0
 public static extern IntPtr FFMS_CreateAudioSource(byte[] SourceFile, int Track, SafeIndexHandle Index, int DelayMode, ref FFMS_ErrorInfo ErrorInfo);
Example #22
0
        /// <summary>
        /// Write the index to disk
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_WriteIndex</c>.</para>
        /// </remarks>
        /// <param name="indexFile">Can be an absolute or relative path; it will be truncated and overwritten if it already exists</param>
        /// <exception cref="System.IO.IOException">Failure to write the index</exception>
        public void WriteIndex(string indexFile)
        {
            if (indexFile == null) throw new ArgumentNullException(@"indexFile");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            var indexFileBytes = Encoding.UTF8.GetBytes(indexFile);

            if (NativeMethods.FFMS_WriteIndex(indexFileBytes, _handle, ref err) == 0) return;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ)
                throw new System.IO.IOException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #23
0
        /// <summary>
        /// Create a <see cref="FFMSSharp.VideoSource">VideoSource object</see>
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_CreateVideoSource</c>.</para>
        /// <para>Note that the index object is copied into the <see cref="FFMSSharp.VideoSource">VideoSource object</see> upon its creation, so once you've created the video source you can generally destroy the index object immediately, since all info you can retrieve from it is also retrievable from the <see cref="FFMSSharp.VideoSource">VideoSource object</see>.</para>
        /// </remarks>
        /// <param name="sourceFile">The media file. Can be an absolute or relative path</param>
        /// <param name="track">Track number of the specific video track</param>
        /// <param name="threads">Number of threads used for decoding
        /// <para>Anything less than 1 will use threads equal to the number of CPU cores.</para>
        /// <para>Values &gt;1 have no effect if FFmpeg was not compiled with threading support.</para></param>
        /// <param name="seekMode">Controls how seeking (random access) is handled and hence affects frame accuracy
        /// <para>Has no effect on Matroska files, where the equivalent of Normal is always used.</para>
        /// <para>LinearNoRw may come in handy if you want to open images.</para></param>
        /// <returns>The generated <see cref="FFMSSharp.VideoSource">VideoSource object</see></returns>
        /// <seealso cref="AudioSource"/>
        /// <seealso cref="GetFirstTrackOfType"/>
        /// <seealso cref="GetFirstIndexedTrackOfType"/>
        /// <exception cref="System.IO.FileLoadException">Failure to open the <paramref name="sourceFile"/></exception>
        /// <exception cref="System.IO.FileNotFoundException">Trying to read a file that does not exist.</exception>
        /// <exception cref="ArgumentException">Trying to make a VideoSource out of an invalid track</exception>
        /// <exception cref="InvalidOperationException">Supplying the wrong <paramref name="sourceFile"/></exception>
        public VideoSource VideoSource(string sourceFile, int track, int threads = 1, SeekMode seekMode = SeekMode.Normal)
        {
            if (sourceFile == null) throw new ArgumentNullException(@"sourceFile");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            var sourceFileBytes = Encoding.UTF8.GetBytes(sourceFile);
            var videoSource = NativeMethods.FFMS_CreateVideoSource(sourceFileBytes, track, _handle, threads, (int)seekMode, ref err);

            if (videoSource != IntPtr.Zero) return new VideoSource(videoSource);

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ)
                throw new System.IO.FileLoadException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_NO_FILE)
                throw new System.IO.FileNotFoundException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_INVALID_ARGUMENT)
                throw new ArgumentException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_MISMATCH)
                throw new InvalidOperationException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #24
0
 public static extern int FFMS_SetOutputFormatV2(IntPtr V, int[] TargetFormats, int Width, int Height, int Resizer, ref FFMS_ErrorInfo ErrorInfo);
Example #25
0
        /// <summary>
        /// Override the source format for video frames
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_SetInputFormatV</c>.</para>
        /// <para>Override the source colorspace passed to SWScale for conversions and resizing for all further calls to <see cref="GetFrame(int)">GetFrame</see>, until the next time you call <see cref="SetInputFormat(int, ColorSpace, ColorRange)">SetInputFormat</see> or <see cref="ResetInputFormat">ResetInputFormat</see>.</para>
        /// <para>This is intended primarily for compatibility with programs which use the wrong YUV colorspace when converting to or from RGB, but can also be useful for files which have incorrect colorspace flags.</para>
        /// <para>Values passed are not checked for sanity; if you wish you may tell FFMS2 to pretend that a RGB files is actually YUV using this function, but doing so is unlikely to have useful results.</para>
        /// <para>This function only has an effect if the output format is also set with <see cref="SetOutputFormat">SetOutputFormat</see>.</para>
        /// </remarks>
        /// <param name="pixelFormat">The desired input pixel format</param>
        /// <param name="colorSpace">The desired input colorspace</param>
        /// <param name="colorRange">The desired input colorrange</param>
        /// <seealso cref="ResetInputFormat"/>
        /// <exception cref="ArgumentException">Trying to set an insane input format.</exception>
        public void SetInputFormat(int pixelFormat, ColorSpace colorSpace = ColorSpace.Unspecified, ColorRange colorRange = ColorRange.Unspecified)
        {
            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            MarkLastFrameAsInvalid();

            if (NativeMethods.FFMS_SetInputFormatV(_nativePtr, (int) colorSpace, (int) colorRange, pixelFormat, ref err) == 0)
                return;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_SCALING && err.SubType == FFMS_Errors.FFMS_ERROR_INVALID_ARGUMENT)
                throw new ArgumentException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_DECODING && err.SubType == FFMS_Errors.FFMS_ERROR_CODEC)
                throw new ArgumentException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #26
0
 public static extern SafeIndexHandle FFMS_ReadIndex(byte[] IndexFile, ref FFMS_ErrorInfo ErrorInfo);
Example #27
0
        /// <summary>
        /// Decode a number of audio samples
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_GetAudio</c>.</para>
        /// <para>The output is <paramref name="count"/> samples long, starting from <paramref name="start"/> (inclusive).</para>
        /// </remarks>
        /// <param name="start">The first sample to decode
        /// <para>Sample numbers start from zero and hence the last sample in the stream is number <see cref="NumberOfSamples"/> minus 1.</para>
        /// </param>
        /// <param name="count">The amount of samples to decode
        /// <para>Sample numbers start from zero and hence the last sample in the stream is number <see cref="NumberOfSamples"/> minus 1.</para>
        /// </param>
        /// <returns>The raw audio data</returns>
        /// <threadsafety instance="false"/>
        /// <exception cref="ArgumentOutOfRangeException">Trying to access audio samples that are out of range of the stream.</exception>
        /// <exception cref="NotSupportedException">Trying to start half-way into an unseekable audio stream.</exception>
        public byte[] GetAudio(long start, long count)
        {
            if (start < 0 || start > NumberOfSamples - 1)
                throw new ArgumentOutOfRangeException(@"start", "Invalid start sample.");
            if (count < 0 || start + count > NumberOfSamples - 1)
                throw new ArgumentOutOfRangeException(@"count", "Invalid sample count.");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            var buffer = new byte[(_ap.BitsPerSample / 8) * _ap.Channels * count];

            int success;
            lock (this)
            {
                success = NativeMethods.FFMS_GetAudio(_nativePtr, buffer, start, count, ref err);
            }

            if (success == 0) return buffer;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_SEEKING && err.SubType == FFMS_Errors.FFMS_ERROR_CODEC)
                throw new NotSupportedException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #28
0
 public static extern int FFMS_WriteIndex(byte[] IndexFile, SafeIndexHandle TrackIndices, ref FFMS_ErrorInfo ErrorInfo);
Example #29
0
        /// <summary>
        /// Get the track number of the first track of a specific type
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_GetFirstTrackOfType</c>.</para>
        /// </remarks>
        /// <param name="type">Track type</param>
        /// <returns>Track number</returns>
        /// <seealso cref="GetFirstIndexedTrackOfType"/>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">Trying to find a type of track that doesn't exist in the media file.</exception>
        public int GetFirstTrackOfType(TrackType type)
        {
            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            var track = NativeMethods.FFMS_GetFirstTrackOfType(_handle, (int)type, ref err);

            if (track >= 0) return track;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_NOT_AVAILABLE)
                throw new System.Collections.Generic.KeyNotFoundException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #30
0
        /// <summary>
        /// Writes timecodes for the track to disk
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_WriteTimecodes</c>.</para>
        /// <para>Writes Matroska v2 timecodes for the track to the given file.</para>
        /// <para>Only meaningful for video tracks. </para>
        /// </remarks>
        /// <param name="timecodeFile">Can be a relative or absolute path. The file will be truncated and overwritten if it already exists.</param>
        /// <exception cref="System.IO.IOException">Failure to open or write to the file</exception>
        public void WriteTimecodes(string timecodeFile)
        {
            if (timecodeFile == null) throw new ArgumentNullException(@"timecodeFile");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            var timecodeFileBytes = Encoding.UTF8.GetBytes(timecodeFile);

            if (NativeMethods.FFMS_WriteTimecodes(_nativePtr, timecodeFileBytes, ref err) == 0)
                return;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_PARSER && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_READ) // FFMS2 2.19 throws this type of error
                throw new System.IO.IOException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_TRACK && err.SubType == FFMS_Errors.FFMS_ERROR_NO_FILE)
                throw new System.IO.IOException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_TRACK && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_WRITE)
                throw new System.IO.IOException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #31
0
        /// <summary>
        /// Index the media file
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_DoIndexing</c>.</para>
        /// <para>By default, you will index all <see cref="TrackType.Audio">Audio</see> tracks.</para>
        /// </remarks>
        /// <param name="audioIndex">A list of specific <see cref="TrackType.Audio">Audio</see> tracks to index</param>
        /// <param name="audioDump">A list of <see cref="TrackType.Audio">Audio</see> tracks to dump while indexing</param>
        /// <param name="audioDumpFileName">The filename format for audio tracks getting dumped
        /// <para>The following variables can be used:</para>
        /// <para><c>%sourcefile%</c> - same as the source file name, i.e. the file the audio is decoded from</para>
        /// <para><c>%trackn%</c> - the track number</para>
        /// <para><c>%trackzn%</c> - the track number zero padded to 2 digits</para>
        /// <para><c>%samplerate%</c> - the audio sample rate</para>
        /// <para><c>%channels%</c> - number of audio channels</para>
        /// <para><c>%bps%</c> - bits per sample</para>
        /// <para><c>%delay%</c> - delay, or more exactly the first timestamp encountered in the audio stream</para>
        /// <para>Example string: <c>%sourcefile%_track%trackzn%.w64</c></para></param>
        /// <param name="indexErrorHandling">Control behavior when a decoding error is encountered</param>
        /// <returns>The generated <see cref="FFMSSharp.Index">Index</see> object</returns>
        /// <event cref="UpdateIndexProgress">Called to give you an update on indexing progress</event>
        /// <event cref="OnIndexingCompleted">Called when the indexing has finished</event>
        /// <exception cref="NotSupportedException">Attempting to index a codec not supported by the indexer</exception>
        /// <exception cref="System.IO.InvalidDataException">Failure to index a file that should be supported</exception>
        /// <exception cref="OperationCanceledException">Canceling the indexing process</exception>
        /// <exception cref="ObjectDisposedException">Calling this function after you have already called <see cref="Index"/>.</exception>
        public Index Index(IEnumerable<int> audioIndex = null, IEnumerable<int> audioDump = null, string audioDumpFileName = null, IndexErrorHandling indexErrorHandling = IndexErrorHandling.Abort)
        {
            if (_handle.IsInvalid) throw new ObjectDisposedException(@"Indexer");

            var indexMask = -1;
            if (audioIndex != null)
            {
                indexMask = audioIndex.Aggregate(0, (current, track) => current | (1 << track));
            }

            var dumpMask = 0;
            if (audioDump != null)
            {
                if (audioDumpFileName == null)
                    throw new ArgumentNullException(@"audioDumpFileName", "You must specify a filename format if you want to dump audio files.");

                dumpMask = audioDump.Aggregate(dumpMask, (current, track) => current | (1 << track));
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char)0, 1024)
            };
            SafeIndexHandle index;
            IsIndexing = true;
            CancelIndexing = false;

            lock (this)
            {
                index = NativeMethods.FFMS_DoIndexing(_handle, indexMask, dumpMask, AudioNameCallback, audioDumpFileName, (int)indexErrorHandling, IndexingCallback, IntPtr.Zero, ref err);
            }

            _handle.SetHandleAsInvalid(); // "Note that calling this function destroys the FFMS_Indexer object and frees the memory allocated by FFMS_CreateIndexer (even if indexing fails for any reason)."
            IsIndexing = false;

            if (!index.IsInvalid) return new Index(index);

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_CODEC && err.SubType == FFMS_Errors.FFMS_ERROR_UNSUPPORTED)
                throw new NotSupportedException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_UNSUPPORTED && err.SubType == FFMS_Errors.FFMS_ERROR_DECODING)
                throw new NotSupportedException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_CODEC && err.SubType == FFMS_Errors.FFMS_ERROR_DECODING)
                throw new System.IO.InvalidDataException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_CANCELLED && err.SubType == FFMS_Errors.FFMS_ERROR_USER)
                throw new OperationCanceledException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEXING && err.SubType == FFMS_Errors.FFMS_ERROR_PARSER)
                throw new System.IO.InvalidDataException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #32
0
 public static extern int FFMS_WriteTimecodes(IntPtr T, byte[] TimecodeFile, ref FFMS_ErrorInfo ErrorInfo);
Example #33
0
 public static extern SafeIndexHandle FFMS_DoIndexing(SafeIndexerHandle Indexer, int IndexMask, int DumpMask, TAudioNameCallback ANC, [MarshalAs(UnmanagedType.LPStr)] string ANCPrivate, int ErrorHandling, TIndexCallback IC, IntPtr ICPrivate, ref FFMS_ErrorInfo ErrorInfo);
Example #34
0
 public static extern SafeIndexHandle FFMS_ReadIndex(byte[] IndexFile, ref FFMS_ErrorInfo ErrorInfo);
Example #35
0
 public static extern SafeIndexerHandle FFMS_CreateIndexerWithDemuxer(byte[] SourceFile, int Demuxer, ref FFMS_ErrorInfo ErrorInfo);
Example #36
0
 public static extern int FFMS_GetFirstIndexedTrackOfType(SafeIndexHandle Index, int TrackType, ref FFMS_ErrorInfo ErrorInfo);
Example #37
0
        /// <summary>
        /// Index the media file
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_DoIndexing</c>.</para>
        /// <para>By default, you will index all <see cref="TrackType.Audio">Audio</see> tracks.</para>
        /// </remarks>
        /// <param name="audioIndex">A list of specific <see cref="TrackType.Audio">Audio</see> tracks to index</param>
        /// <param name="audioDump">A list of <see cref="TrackType.Audio">Audio</see> tracks to dump while indexing</param>
        /// <param name="audioDumpFileName">The filename format for audio tracks getting dumped
        /// <para>The following variables can be used:</para>
        /// <para><c>%sourcefile%</c> - same as the source file name, i.e. the file the audio is decoded from</para>
        /// <para><c>%trackn%</c> - the track number</para>
        /// <para><c>%trackzn%</c> - the track number zero padded to 2 digits</para>
        /// <para><c>%samplerate%</c> - the audio sample rate</para>
        /// <para><c>%channels%</c> - number of audio channels</para>
        /// <para><c>%bps%</c> - bits per sample</para>
        /// <para><c>%delay%</c> - delay, or more exactly the first timestamp encountered in the audio stream</para>
        /// <para>Example string: <c>%sourcefile%_track%trackzn%.w64</c></para></param>
        /// <param name="indexErrorHandling">Control behavior when a decoding error is encountered</param>
        /// <returns>The generated <see cref="FFMSSharp.Index">Index</see> object</returns>
        /// <event cref="UpdateIndexProgress">Called to give you an update on indexing progress</event>
        /// <event cref="OnIndexingCompleted">Called when the indexing has finished</event>
        /// <exception cref="NotSupportedException">Attempting to index a codec not supported by the indexer</exception>
        /// <exception cref="System.IO.InvalidDataException">Failure to index a file that should be supported</exception>
        /// <exception cref="OperationCanceledException">Canceling the indexing process</exception>
        /// <exception cref="ObjectDisposedException">Calling this function after you have already called <see cref="Index"/>.</exception>
        public Index Index(IEnumerable <int> audioIndex = null, IEnumerable <int> audioDump = null, string audioDumpFileName = null, IndexErrorHandling indexErrorHandling = IndexErrorHandling.Abort)
        {
            if (_handle.IsInvalid)
            {
                throw new ObjectDisposedException(@"Indexer");
            }

            var indexMask = -1;

            if (audioIndex != null)
            {
                indexMask = audioIndex.Aggregate(0, (current, track) => current | (1 << track));
            }

            var dumpMask = 0;

            if (audioDump != null)
            {
                if (audioDumpFileName == null)
                {
                    throw new ArgumentNullException(@"audioDumpFileName", "You must specify a filename format if you want to dump audio files.");
                }

                dumpMask = audioDump.Aggregate(dumpMask, (current, track) => current | (1 << track));
            }

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer     = new String((char)0, 1024)
            };
            SafeIndexHandle index;

            IsIndexing     = true;
            CancelIndexing = false;

            lock (this)
            {
                index = NativeMethods.FFMS_DoIndexing(_handle, indexMask, dumpMask, AudioNameCallback, audioDumpFileName, (int)indexErrorHandling, IndexingCallback, IntPtr.Zero, ref err);
            }

            _handle.SetHandleAsInvalid(); // "Note that calling this function destroys the FFMS_Indexer object and frees the memory allocated by FFMS_CreateIndexer (even if indexing fails for any reason)."
            IsIndexing = false;

            if (!index.IsInvalid)
            {
                return(new Index(index));
            }

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_CODEC && err.SubType == FFMS_Errors.FFMS_ERROR_UNSUPPORTED)
            {
                throw new NotSupportedException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_UNSUPPORTED && err.SubType == FFMS_Errors.FFMS_ERROR_DECODING)
            {
                throw new NotSupportedException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_CODEC && err.SubType == FFMS_Errors.FFMS_ERROR_DECODING)
            {
                throw new System.IO.InvalidDataException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_CANCELLED && err.SubType == FFMS_Errors.FFMS_ERROR_USER)
            {
                throw new OperationCanceledException(err.Buffer);
            }
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEXING && err.SubType == FFMS_Errors.FFMS_ERROR_PARSER)
            {
                throw new System.IO.InvalidDataException(err.Buffer);
            }

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #38
0
 public static extern int FFMS_WriteIndex(byte[] IndexFile, SafeIndexHandle TrackIndices, ref FFMS_ErrorInfo ErrorInfo);
Example #39
0
        /// <summary>
        /// Sets the output format for video frames
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_SetOutputFormatV2</c>.</para>
        /// </remarks>
        /// <param name="targetFormats">The desired output colorspace(s)
        /// <para>The destination that gives the least lossy conversion from the source colorspace will automatically be selected, ON A FRAME BASIS.</para>
        /// <para>To get the integer constant representing a given colorspace, see <see cref="FFMS2.GetPixelFormat">GetPixFmt</see>.</para>
        /// </param>
        /// <param name="width">The desired image width, in pixels
        /// <para>If you do not want to resize just pass the input dimensions.</para>
        /// </param>
        /// <param name="height">The desired image height, in pixels
        /// <para>If you do not want to resize just pass the input dimensions.</para>
        /// </param>
        /// <param name="resizer">The desired image resizing algorithm.
        /// <para>You must choose one even if you're not actually rescaling the image, because the video may change resolution mid-stream and then you will be using a resizer whether you want it or not (you will only know that the resolution changed after you actually decoded a frame with a new resolution), and it may also get used for rescaling subsampled chroma planes.</para>
        /// </param>
        /// <seealso cref="ResetOutputFormat"/>
        /// <exception cref="ArgumentOutOfRangeException">Trying to set the desired image resolution to an invalid size like 0, 0.</exception>
        /// <exception cref="ArgumentNullException">Trying to supply a null list of <paramref name="targetFormats"/>.</exception>
        /// <exception cref="ArgumentException">Trying to set an invalid output format.</exception>
        public void SetOutputFormat(ICollection<int> targetFormats, int width, int height, Resizer resizer)
        {
            if (targetFormats == null)
                throw new ArgumentNullException(@"targetFormats");
            if (width <= 0)
                throw new ArgumentOutOfRangeException(@"width", "Invalid image width.");
            if (height <= 0)
                throw new ArgumentOutOfRangeException(@"height", "Invalid image height.");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            var targetFormatsArray = new int[targetFormats.Count + 1];
            targetFormats.CopyTo(targetFormatsArray, 0);
            targetFormatsArray[targetFormats.Count] = -1;

            MarkLastFrameAsInvalid();

            if (NativeMethods.FFMS_SetOutputFormatV2(_nativePtr, targetFormatsArray, width, height, (int) resizer, ref err) == 0)
                return;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_SCALING && err.SubType == FFMS_Errors.FFMS_ERROR_INVALID_ARGUMENT)
                throw new ArgumentException(err.Buffer);
            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_DECODING && err.SubType == FFMS_Errors.FFMS_ERROR_CODEC)
                throw new ArgumentException(err.Buffer);

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }
Example #40
0
 public static extern int FFMS_IndexBelongsToFile(SafeIndexHandle Index, byte[] SourceFile, ref FFMS_ErrorInfo ErrorInfo);
Example #41
0
 public static extern int FFMS_SetInputFormatV(IntPtr V, int ColorSpace, int ColorRange, int PixelFormat, ref FFMS_ErrorInfo ErrorInfo);
Example #42
0
 public static extern int FFMS_WriteTimecodes(IntPtr T, byte[] TimecodeFile, ref FFMS_ErrorInfo ErrorInfo);
Example #43
0
 public static extern IntPtr FFMS_GetFrame(IntPtr V, int n, ref FFMS_ErrorInfo ErrorInfo);
Example #44
0
 public static extern IntPtr FFMS_CreateVideoSource(byte[] SourceFile, int Track, SafeIndexHandle Index, int Threads, int SeekMode, ref FFMS_ErrorInfo ErrorInfo);
Example #45
0
        /// <summary>
        /// Retrieves a video frame at a timestamp
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_GetFrameByTime</c>.</para>
        /// <para>The returned frame is owned by the given <see cref="VideoSource">VideoSource object</see>, and remains valid until the video source is destroyed, a different frame is requested from the video source, or the video source's input or output format is changed.</para>
        /// <para>Does the exact same thing as <see cref="GetFrame(int)">GetFrame</see> except instead of giving it a frame number you give it a timestamp in seconds, and it will retrieve the frame that starts closest to that timestamp.</para>
        /// <para>This function exists for the people who are too lazy to build and traverse a mapping between frame numbers and timestamps themselves.</para>
        /// </remarks>
        /// <param name="time">Timestamp</param>
        /// <returns>The generated <see cref="Frame">Frame object</see>.</returns>
        /// <seealso cref="GetFrame(int)"/>
        /// <exception cref="ArgumentOutOfRangeException">Trying to access a Frame that doesn't exist.</exception>
        public Frame GetFrame(double time)
        {
            if (time < 0 || time > LastTime)
                throw new ArgumentOutOfRangeException(@"time", "That frame doesn't exist.");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            MarkLastFrameAsInvalid();

            IntPtr framePtr;
            lock (this)
            {
                 framePtr = NativeMethods.FFMS_GetFrameByTime(_nativePtr, time, ref err);
            }

            if (framePtr == IntPtr.Zero)
            {
                throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
            }

            LastFrame = new Frame(framePtr);
            return LastFrame;
        }
Example #46
0
 public static extern int FFMS_SetOutputFormatV2(IntPtr V, int[] TargetFormats, int Width, int Height, int Resizer, ref FFMS_ErrorInfo ErrorInfo);
Example #47
0
 public static extern int FFMS_GetAudio(IntPtr A, byte[] Buf, long Start, long Count, ref FFMS_ErrorInfo ErrorInfo);
Example #48
0
 public static extern IntPtr FFMS_CreateAudioSource(byte[] SourceFile, int Track, SafeIndexHandle Index, int DelayMode, ref FFMS_ErrorInfo ErrorInfo);
Example #49
0
 public static extern int FFMS_SetInputFormatV(IntPtr V, int ColorSpace, int ColorRange, int PixelFormat, ref FFMS_ErrorInfo ErrorInfo);
Example #50
0
        /// <summary>
        /// Check if the index belongs to a specific file
        /// </summary>
        /// <remarks>
        /// <para>In FFMS2, the equivalent is <c>FFMS_IndexBelongsToFile</c>.</para>
        /// <para>Makes a heuristic (but very reliable) guess about whether the index is of the <paramref name="sourceFile"/> or not.</para>
        /// <para>Useful to determine if the index object you just created by <see cref="Index(string)">loading an index file from disk</see> is actually relevant to your interests, since the only two ways to pair up index files with source files are a) trust the user blindly, or b) comparing the filenames; neither is very reliable.</para>
        /// </remarks>
        /// <param name="sourceFile">File to check against</param>
        /// <returns>True or false depending on the result</returns>
        public bool BelongsToFile(string sourceFile)
        {
            if (sourceFile == null) throw new ArgumentNullException(@"sourceFile");

            var err = new FFMS_ErrorInfo
            {
                BufferSize = 1024,
                Buffer = new String((char) 0, 1024)
            };

            var sourceFileBytes = Encoding.UTF8.GetBytes(sourceFile);

            if (NativeMethods.FFMS_IndexBelongsToFile(_handle, sourceFileBytes, ref err) == 0)
                return true;

            if (err.ErrorType == FFMS_Errors.FFMS_ERROR_INDEX && err.SubType == FFMS_Errors.FFMS_ERROR_FILE_MISMATCH)
                return false;

            throw new NotImplementedException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown FFMS2 error encountered: ({0}, {1}, '{2}'). Please report this issue on FFMSSharp's GitHub.", err.ErrorType, err.SubType, err.Buffer));
        }