diff --git a/FFMSsharp.Tests/FFMSsharp.Tests.csproj b/FFMSsharp.Tests/FFMSsharp.Tests.csproj
index f4ae3b7..1493cd9 100644
--- a/FFMSsharp.Tests/FFMSsharp.Tests.csproj
+++ b/FFMSsharp.Tests/FFMSsharp.Tests.csproj
@@ -72,9 +72,6 @@
PreserveNewest
-
- PreserveNewest
-
PreserveNewest
diff --git a/FFMSsharp.Tests/UnitTest1.cs b/FFMSsharp.Tests/UnitTest1.cs
index 78da0c2..da10b83 100644
--- a/FFMSsharp.Tests/UnitTest1.cs
+++ b/FFMSsharp.Tests/UnitTest1.cs
@@ -151,6 +151,17 @@ public void IndexAudioIndex()
Assert.AreEqual(2, index.GetFirstIndexedTrackOfType(TrackType.Audio));
}
+ [TestMethod]
+ public void IndexAudioDump()
+ {
+ Indexer indexer = new Indexer("h264_720p_hp_5.1_3mbps_vorbis_styled_and_unstyled_subs_suzumiya.mkv");
+
+ List AudioDumpList = new List();
+ AudioDumpList.Add(1);
+
+ indexer.Index(audioDump: AudioDumpList, audioDumpFileName: @"%sourcefile%_track%trackzn%.w64");
+ }
+
[TestMethod]
public void ReadIndex()
{
diff --git a/FFMSsharp.Tests/samples.dat, how to verify.jpg b/FFMSsharp.Tests/samples.dat, how to verify.jpg
deleted file mode 100644
index 178a8f8..0000000
Binary files a/FFMSsharp.Tests/samples.dat, how to verify.jpg and /dev/null differ
diff --git a/FFMSsharp/FFMSsharp.xml b/FFMSsharp/FFMSsharp.xml
index 362c9df..22548f3 100644
--- a/FFMSsharp/FFMSsharp.xml
+++ b/FFMSsharp/FFMSsharp.xml
@@ -473,11 +473,13 @@
In FFMS2, the equivalent is FFMS_Frame.
See VideoSource.GetFrame on how to create a Frame object.
+ The frame is only valid until after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the parent has been destroyed.
+ Attempting to access any data from the frame after it has been rendered invalid will result in an ObjectDisposedException.
- An array of pointers to the pixel data
+ A list of pointers to the pixel data
In FFMS2, the equivalent is FFMS_Frame->Data.
@@ -485,11 +487,11 @@
Packed formats (such as the various RGB32 flavors) use only the first plane.
If you want to determine if plane i contains data or not, check for [i] != 0.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
- An array of integers representing the length of each scan line in each of the four picture planes, in bytes
+ A list of integers representing the length of each scan line in each of the four picture planes, in bytes
In FFMS2, the equivalent is FFMS_Frame->Linesize.
@@ -498,7 +500,7 @@
This may be negative; if so the image is stored inverted in memory and Data actually points of the last row of the data.
You usually do not need to worry about this, as it mostly works correctly by default if you're processing the image correctly.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -509,7 +511,7 @@
As encoded in the compressed file, before any scaling was applied.
Note that this must not necessarily be the same for all frames in a stream.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -519,7 +521,7 @@
In FFMS2, the equivalent is FFMS_Frame->EncodedPixelFormat.
As encoded in the compressed file.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -529,7 +531,7 @@
In FFMS2, the equivalent is FFMS_Frame->ScaledWidth and ScaledHeight.
The resolution of what is actually stored in the field.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -539,7 +541,7 @@
In FFMS2, the equivalent is FFMS_Frame->ConvertedPixelFormat.
The pixel format of what is actually stored in the field.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -548,7 +550,7 @@
In FFMS2, the equivalent is FFMS_Frame->KeyFrame.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -559,7 +561,7 @@
The frame shall be displayed for 1+ time units, where the time units are expressed in the special RFF timebase available in and .
Note that if you actually end up using this, you need to ignore the usual timestamps (calculated via the / and the ) since they are fundamentally incompatible with RFF flags.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -568,7 +570,7 @@
In FFMS2, the equivalent is FFMS_Frame->InterlacedFrame.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -578,7 +580,7 @@
In FFMS2, the equivalent is FFMS_Frame->TopFieldFirst.
Only relevant if is nonzero.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -587,7 +589,7 @@
In FFMS2, the equivalent is FFMS_Frame.PictType.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -596,7 +598,7 @@
In FFMS2, the equivalent is FFMS_Frame->ColorSpace.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -606,7 +608,7 @@
In FFMS2, the equivalent is FFMS_Frame->ColorRange.
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -616,7 +618,7 @@
This only works if you've set the PixelFormat to "bgra".
- Calling this function after you have called VideoSource.GetFrame(int)/(double), SetInputFormat(FFMSSharp.ColorSpace, FFMSSharp.ColorRange)/(int, FFMSSharp.ColorSpace, FFMSSharp.ColorRange), ResetInputFormat, SetOutputFormat, ResetOutputFormat, or after the has been destroyed.
+ Trying to access data from an invalidated Frame, see .
@@ -942,7 +944,7 @@
In FFMS2, the equivalent is FFMS_GetErrorHandling.
-
+
@@ -1060,7 +1062,7 @@
Track type
Trying to access a Track that doesn't exist.
- Calling this function after you have already called .
+ Calling this function after you have already called .
@@ -1072,9 +1074,9 @@
Track number
The human-readable name ("long name" in FFmpeg terms) of the codec
Trying to access a Track that doesn't exist.
- Calling this function after you have already called .
+ Calling this function after you have already called .
-
+
Index the media file
@@ -1083,6 +1085,17 @@
By default, you will index all Audio tracks.
A list of specific Audio tracks to index
+ A list of Audio tracks to dump while indexing
+ The filename format for audio tracks getting dumped
+ The following variables can be used:
+ %sourcefile% - same as the source file name, i.e. the file the audio is decoded from
+ %trackn% - the track number
+ %trackzn% - the track number zero padded to 2 digits
+ %samplerate% - the audio sample rate
+ %channels% - number of audio channels
+ %bps% - bits per sample
+ %delay% - delay, or more exactly the first timestamp encountered in the audio stream
+ Example string: %sourcefile%_track%trackzn%.w64
Control behavior when a decoding error is encountered
The generated Index object
Called to give you an update on indexing progress
@@ -1090,7 +1103,7 @@
Attempting to index a codec not supported by the indexer
Failure to index a file that should be supported
Canceling the indexing process
- Calling this function after you have already called .
+ Calling this function after you have already called .
diff --git a/FFMSsharp/Index.cs b/FFMSsharp/Index.cs
index ab11114..54e9a0a 100644
--- a/FFMSsharp/Index.cs
+++ b/FFMSsharp/Index.cs
@@ -233,7 +233,7 @@ public Source Source
///
/// In FFMS2, the equivalent is FFMS_GetErrorHandling.
///
- ///
+ ///
public IndexErrorHandling IndexErrorHandling
{
get
diff --git a/FFMSsharp/Indexer.cs b/FFMSsharp/Indexer.cs
index b4f0e00..e05b1d7 100644
--- a/FFMSsharp/Indexer.cs
+++ b/FFMSsharp/Indexer.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
+using System.Text;
namespace FFMSSharp
{
@@ -30,12 +31,12 @@ static partial class NativeMethods
public static extern IntPtr FFMS_GetFormatNameI(SafeIndexerHandle Indexer);
[DllImport("ffms2.dll", SetLastError = false)]
- public static extern int FFMS_DefaultAudioFilename(string SourceFile, int Track, ref FFMS_AudioProperties AP, IntPtr FileName, int FNSize, IntPtr Private);
+ public static extern int FFMS_DefaultAudioFilename(string SourceFile, int Track, ref FFMS_AudioProperties AP, StringBuilder FileName, int FNSize, IntPtr Private);
- [DllImport("ffms2.dll", SetLastError = false)]
- public static extern SafeIndexHandle FFMS_DoIndexing(SafeIndexerHandle Indexer, int IndexMask, int DumpMask, TAudioNameCallback ANC, IntPtr ANCPrivate, int ErrorHandling, TIndexCallback IC, IntPtr ICPrivate, ref FFMS_ErrorInfo ErrorInfo);
+ [DllImport("ffms2.dll", SetLastError = false, BestFitMapping = false, ThrowOnUnmappableChar = true)]
+ 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);
- public delegate int TAudioNameCallback(string SourceFile, int Track, ref FFMS_AudioProperties AP, IntPtr FileName, int FNSize, IntPtr Private);
+ public delegate int TAudioNameCallback(string SourceFile, int Track, ref FFMS_AudioProperties AP, StringBuilder FileName, int FNSize, IntPtr Private);
public delegate int TIndexCallback(long Current, long Total, IntPtr ICPrivate);
}
@@ -265,7 +266,7 @@ protected virtual void Dispose(bool disposing)
/// Track type
///
/// Trying to access a Track that doesn't exist.
- /// Calling this function after you have already called .
+ /// Calling this function after you have already called .
public TrackType GetTrackType(int track)
{
if (track < 0 || track > NativeMethods.FFMS_GetNumTracksI(handle))
@@ -285,7 +286,7 @@ public TrackType GetTrackType(int track)
/// Track number
/// The human-readable name ("long name" in FFmpeg terms) of the codec
/// Trying to access a Track that doesn't exist.
- /// Calling this function after you have already called .
+ /// Calling this function after you have already called .
public string GetCodecName(int track)
{
if (track < 0 || track > NativeMethods.FFMS_GetNumTracksI(handle))
@@ -300,43 +301,6 @@ public string GetCodecName(int track)
#region Object creation
- private Index Index(int AudioIndexMask, int AudioDumpMask, IndexErrorHandling IndexErrorHandling)
- {
- if (handle.IsInvalid)
- throw new ObjectDisposedException("Indexer");
-
- SafeIndexHandle index;
- FFMS_ErrorInfo err = new FFMS_ErrorInfo();
- err.BufferSize = 1024;
- err.Buffer = new String((char)0, 1024);
- isIndexing = true;
- cancelIndexing = false;
-
- lock(this)
- {
- index = NativeMethods.FFMS_DoIndexing(handle, AudioIndexMask, AudioDumpMask, AudioNameCallback, IntPtr.Zero, (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)
- {
- 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_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));
- }
-
- return new FFMSSharp.Index(index);
- }
-
///
/// Index the media file
///
@@ -345,6 +309,17 @@ private Index Index(int AudioIndexMask, int AudioDumpMask, IndexErrorHandling In
/// By default, you will index all Audio tracks.
///
/// A list of specific Audio tracks to index
+ /// A list of Audio tracks to dump while indexing
+ /// The filename format for audio tracks getting dumped
+ /// The following variables can be used:
+ /// %sourcefile% - same as the source file name, i.e. the file the audio is decoded from
+ /// %trackn% - the track number
+ /// %trackzn% - the track number zero padded to 2 digits
+ /// %samplerate% - the audio sample rate
+ /// %channels% - number of audio channels
+ /// %bps% - bits per sample
+ /// %delay% - delay, or more exactly the first timestamp encountered in the audio stream
+ /// Example string: %sourcefile%_track%trackzn%.w64
/// Control behavior when a decoding error is encountered
/// The generated Index object
/// Called to give you an update on indexing progress
@@ -352,11 +327,13 @@ private Index Index(int AudioIndexMask, int AudioDumpMask, IndexErrorHandling In
/// Attempting to index a codec not supported by the indexer
/// Failure to index a file that should be supported
/// Canceling the indexing process
- /// Calling this function after you have already called .
- public Index Index(IEnumerable audioIndex = null, IndexErrorHandling indexErrorHandling = IndexErrorHandling.Abort)
+ /// Calling this function after you have already called .
+ public Index Index(IEnumerable audioIndex = null, IEnumerable audioDump = null, string audioDumpFileName = null, IndexErrorHandling indexErrorHandling = IndexErrorHandling.Abort)
{
- int indexMask = -1;
+ if (handle.IsInvalid)
+ throw new ObjectDisposedException("Indexer");
+ int indexMask = -1;
if (audioIndex != null)
{
indexMask = 0;
@@ -366,38 +343,55 @@ public Index Index(IEnumerable audioIndex = null, IndexErrorHandling indexE
}
}
- return Index(indexMask, 0, indexErrorHandling);
- }
-
- /*
- * Audio dumping is broken, so this constructor is hidden.
- *
- public Index Index(List AudioIndex, List AudioDump, IndexErrorHandling IndexErrorHandling = IndexErrorHandling.Abort)
- {
- int IndexMask = 0;
- if (AudioIndex != null)
+ int dumpMask = 0;
+ if (audioDump != null)
{
- foreach (int Track in AudioIndex)
+ if (audioDumpFileName == null)
+ throw new ArgumentNullException("audioDumpFileName", "You must specify a filename format if you want to dump audio files.");
+
+ foreach (int Track in audioDump)
{
- IndexMask = IndexMask | (1 << Track);
+ dumpMask = dumpMask | (1 << Track);
}
}
- int DumpMask = 0;
- foreach (int Track in AudioDump)
+ SafeIndexHandle index;
+ FFMS_ErrorInfo err = new FFMS_ErrorInfo();
+ err.BufferSize = 1024;
+ err.Buffer = new String((char)0, 1024);
+ 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)
{
- DumpMask = DumpMask | (1 << Track);
+ 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_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));
}
- return Index(IndexMask, DumpMask, IndexErrorHandling);
+ return new FFMSSharp.Index(index);
}
- */
#endregion
#region Callback stuff
- int AudioNameCallback(string SourceFile, int Track, ref FFMS_AudioProperties AP, IntPtr FileName, int FNSize, IntPtr Private)
+ int AudioNameCallback(string SourceFile, int Track, ref FFMS_AudioProperties AP, StringBuilder FileName, int FNSize, IntPtr Private)
{
return NativeMethods.FFMS_DefaultAudioFilename(SourceFile, Track, ref AP, FileName, FNSize, Private);
}