Initial commit

This commit is contained in:
Thastertyn committed 2024-06-07 00:47:07 +02:00
commit 262601edb8
2025 files changed
+218754

No files matched your search

+215
View File
@@ -0,0 +1,215 @@
//
// SimpleTag.cs:
//
// Author:
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2017 Starwer
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
using System.IO;
namespace TagLib.Matroska
{
/// <summary>
/// Describes a Matroska Attachment.
/// Attachments may be pictures, but also any other content type.
/// </summary>
public class Attachment : PictureLazy, IUIDElement
{
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Attachment" /> with no data or values.
/// </summary>
public Attachment ()
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Attachment" /> by reading in the contents of a
/// specified file.
/// </summary>
/// <param name="path">
/// A <see cref="string"/> object containing the path of the
/// file to read.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public Attachment (string path)
: base (path)
{
SetTypeFromFilename ();
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Attachment" /> by reading in the contents of a
/// specified file abstraction.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction"/> object containing
/// abstraction of the file to read.
/// </param>
/// <param name="offset">
/// The position in bytes where the picture is located in the
/// <see cref="T:File.IFileAbstraction"/>.
/// </param>
/// <param name="size">
/// The size in bytes of the picture in the
/// <see cref="T:File.IFileAbstraction"/> (default: read all).
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public Attachment (TagLib.File.IFileAbstraction abstraction, long offset = 0, long size = -1)
: base (abstraction, offset, size)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Attachment" /> by using the contents of a <see
/// cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector"/> object containing picture data
/// to use.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
public Attachment (ByteVector data)
: base (data)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Attachment" /> by doing a shallow copy of <see
/// cref="IPicture" />.
/// </summary>
/// <param name="picture">
/// A <see cref="IPicture"/> object containing picture data
/// to convert to an Attachment.
/// </param>
public Attachment (IPicture picture)
: base (picture)
{
}
#endregion
#region Methods
/// <summary>
/// Derive the Picture-type from the the file-name.
/// It change the <see cref="P:Type"/> from the <see cref="P:Filename"/>.
/// </summary>
public void SetTypeFromFilename ()
{
if (MimeType != null && !MimeType.StartsWith ("image/")) {
Type = PictureType.NotAPicture;
return;
}
if (Filename == null) {
Type = PictureType.Other;
return;
}
PictureType type = PictureType.Other;
string fname = Filename.ToLower ();
foreach (var ptype in Enum.GetNames (typeof (PictureType))) {
if (fname.Contains (ptype.ToLower ())) {
type = (PictureType)Enum.Parse (typeof (PictureType), ptype);
break;
}
}
if (type == PictureType.Other && ((fname.Contains ("cover") || fname.Contains ("poster")))) {
type = PictureType.FrontCover;
}
Type = type;
}
/// <summary>
/// Derive thefile-name from the the Piture type.
/// It change the <see cref="P:Filename"/> from the <see cref="P:Type"/> if required,
/// but not if the filename already matches the type.
/// </summary>
/// <returns>true if <see cref="P:Filename"/> changed</returns>
public bool SetFilenameFromType ()
{
PictureType type = Type;
if (!string.IsNullOrEmpty (Filename)) {
SetTypeFromFilename ();
// Filename already matches the type, so do not change it
if (type == Type) return false;
// restore the type
Type = type;
}
// Derive extension from file or MimeType
string ext = null;
if (Filename != null) ext = Path.GetExtension (Filename);
if (ext == null && MimeType != null && MimeType.StartsWith ("image/")) ext = "." + MimeType.Substring (6);
if (ext == null || ext.Length < 2) ext = "";
// Change the filename
Filename = type + ext;
return true;
}
#endregion
#region IUIDElement Boilerplate
/// <summary>
/// Unique ID representing the element, as random as possible (setting zero will generate automatically a new one).
/// </summary>
public ulong UID {
get { return _UID; }
set { _UID = UIDElement.GenUID (value); }
}
ulong _UID = UIDElement.GenUID ();
/// <summary>
/// Get the Tag type the UID should be represented by, or 0 if undefined
/// </summary>
public MatroskaID UIDType { get { return MatroskaID.TagAttachmentUID; } }
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f61f84258e7ab3b6ebcb9b16ff0b9e53
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+146
View File
@@ -0,0 +1,146 @@
//
// AudioTrack.cs:
//
// Author:
// Julien Moutte <julien@fluendo.com>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System.Collections.Generic;
namespace TagLib.Matroska
{
/// <summary>
/// Describes a Matroska Audio track.
/// </summary>
public class AudioTrack : Track, IAudioCodec
{
#region Private fields
#pragma warning disable 414 // Assigned, never used
readonly double rate;
readonly ulong channels;
readonly ulong depth;
#pragma warning restore 414
#endregion
#region Constructors
/// <summary>
/// Construct a <see cref="AudioTrack" /> reading information from
/// provided file data.
/// Parsing will be done reading from _file at position references by
/// parent element's data section.
/// </summary>
/// <param name="_file"><see cref="File" /> instance to read from.</param>
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
public AudioTrack (File _file, EBMLreader element)
: base (_file, element)
{
// Here we handle the unknown elements we know, and store the rest
foreach (EBMLreader elem in base.UnknownElements) {
var matroska_id = elem.ID;
switch (matroska_id) {
case MatroskaID.TrackAudio: {
ulong i = 0;
while (i < elem.DataSize) {
EBMLreader child = new EBMLreader (_file, elem.DataOffset + i);
matroska_id = child.ID;
switch (matroska_id) {
case MatroskaID.AudioChannels:
channels = child.ReadULong ();
break;
case MatroskaID.AudioBitDepth:
depth = child.ReadULong ();
break;
case MatroskaID.AudioSamplingFreq:
rate = child.ReadDouble ();
break;
default:
UnknownElements.Add (child);
break;
}
i += child.Size;
}
break;
}
default:
UnknownElements.Add (elem);
break;
}
}
}
#endregion
#region Public fields
/// <summary>
/// List of unknown elements encountered while parsing.
/// </summary>
public new List<EBMLreader> UnknownElements { get; } = new List<EBMLreader>();
#endregion
#region ICodec
/// <summary>
/// This type of track only has audio media type.
/// </summary>
public override MediaTypes MediaTypes {
get { return MediaTypes.Audio; }
}
#endregion
#region IAudioCodec
/// <summary>
/// Audio track bitrate.
/// </summary>
public int AudioBitrate {
get { return 0; }
}
/// <summary>
/// Audio track sampling rate.
/// </summary>
public int AudioSampleRate {
get { return (int)rate; }
}
/// <summary>
/// Number of audio channels in this track.
/// </summary>
public int AudioChannels {
get { return (int)channels; }
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4acff302cab1d869f8d197a37fc3f624
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+420
View File
@@ -0,0 +1,420 @@
//
// EBMLElement.cs:
//
// Author:
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
using System.Collections.Generic;
namespace TagLib.Matroska
{
/// <summary>
/// Represent a generic EBML Element and its content.
/// </summary>
public class EBMLelement
{
#region Constructors
/// <summary>
/// Constructs an empty <see cref="EBMLelement" />.
/// </summary>
public EBMLelement ()
{
}
/// <summary>
/// Construct a <see cref="EBMLelement" /> to contain children elements.
/// </summary>
/// <param name="ebmlid">EBML ID of the element to be created.</param>
public EBMLelement (MatroskaID ebmlid)
{
ID = ebmlid;
Children = new List<EBMLelement> ();
}
/// <summary>
/// Construct a <see cref="EBMLelement" /> to contain data.
/// </summary>
/// <param name="ebmlid">EBML ID of the element to be created.</param>
/// <param name="data">EBML data of the element to be created.</param>
public EBMLelement (MatroskaID ebmlid, ByteVector data)
{
ID = ebmlid;
Data = data;
}
/// <summary>
/// Construct <see cref="EBMLelement" /> to contain data.
/// </summary>
/// <param name="ebmlid">EBML ID of the element to be created.</param>
/// <param name="value">EBML data as an <see cref="ulong"/> value.</param>
public EBMLelement (MatroskaID ebmlid, ulong value)
{
ID = ebmlid;
SetData (value);
}
#endregion
#region Public Properties
/// <summary>
/// EBML Element Identifier.
/// </summary>
public MatroskaID ID = 0;
/// <summary>
/// Get or set the data represented by the EBML
/// </summary>
public ByteVector Data;
/// <summary>
/// Get or set the element embedded in the EBML
/// </summary>
public List<EBMLelement> Children;
/// <summary>
/// Get or set whether the EBML should have a size of one byte more
/// than the optimal size.
/// </summary>
public bool IncSize;
#endregion
#region Public Methods
/// <summary>
/// EBML Element size in bytes.
/// </summary>
public long Size {
get {
long size_length = DataSize;
return IDSize + EBMLByteSize ((ulong)size_length) + (IncSize ? 1 : 0) + size_length;
}
}
/// <summary>
/// Get the size of the EBML ID, in bytes
/// </summary>
public long IDSize {
get {
uint ebml_id = (uint)ID;
// Figure out the ID size in bytes
long mask = 0xFF000000, id_length = 4;
while (id_length > 0 && (ebml_id & mask) == 0) {
id_length--;
mask >>= 8;
}
if (id_length == 0)
throw new CorruptFileException ("invalid EBML ID (zero)");
return id_length;
}
}
/// <summary>
/// Get the size of the EBML data-size, in bytes
/// </summary>
public long DataSizeSize {
get { return EBMLByteSize ((ulong)DataSize) + (IncSize ? 1 : 0); }
}
/// <summary>
/// EBML Element data/content size in bytes.
/// </summary>
public long DataSize {
get {
long ret = 0;
if (Data != null) {
// Get Data size
ret = Data.Count;
if (Children != null)
throw new UnsupportedFormatException ("EBML element cannot contain both Data and Children");
} else {
// Get the content size
foreach (var child in Children) {
ret += child.Size;
}
}
return ret;
}
}
/// <summary>
/// Try to increase the size of the EBML by 1 byte.
/// </summary>
/// <returns>True if successfully increased size, false if failed.</returns>
public bool IncrementSize ()
{
// Try to extend current DataSizeSize
if (!IncSize && DataSizeSize < 8) {
return IncSize = true;
}
// Try to extend one of the children
if (Children != null) {
foreach (var child in Children) {
if (child.IncrementSize ()) return true;
}
}
// Failed
return false;
}
/// <summary>
/// Get the EBML ID and data-size as a vector of bytes.
/// </summary>
public ByteVector Header {
get {
// Retrieve sizes
var id_length = IDSize;
var size_length = DataSizeSize;
// Create vector
ByteVector vector = new ByteVector ((int)(id_length + size_length));
// Construct the ID field
uint ebml_id = (uint)ID;
uint mask = ebml_id;
for (int i = (int)id_length - 1; i >= 0; i--) {
vector[i] = (byte)(mask & 0xFF);
mask >>= 8;
}
// Construct the data-size field
ulong lmask = (ulong)DataSize;
for (int i = (int)(id_length + size_length - 1); i >= id_length; i--) {
vector[i] = (byte)(lmask & 0xFF);
lmask >>= 8;
}
// Set the marker bit of the Data-size
vector[(int)id_length] |= (byte)(0x100 >> (int)size_length);
return vector;
}
}
#endregion
#region Class functions
/// <summary>
/// Get the byte-size required to encode an EBML value with the leading 1.
/// </summary>
/// <param name="value">Encoded value</param>
/// <returns>size in bytes</returns>
public static long EBMLByteSize (ulong value)
{
// Figure out the required data-size size in bytes
long size_length;
if (value == 0x7F) {
// Special case: Avoid element-size reserved word of 0xFF (all ones)
size_length = 2;
} else {
size_length = 8;
ulong mask = (ulong)0x7F << (7 * 7);
while (size_length > 1 && (value & mask) == 0) {
size_length--;
mask >>= 7;
}
}
return size_length;
}
#endregion
#region Public Methods Data access
/// <summary>
/// Get a string from EBML Element's data section (UTF-8).
/// Handle null-termination.
/// </summary>
/// <returns>a string object containing the parsed value.</returns>
public string GetString ()
{
if (Data == null) return null;
var idx = Data.IndexOf (0x00); // Detected Null termination
if (idx >= 0) return Data.ToString (StringType.UTF8, 0, idx);
return Data.ToString (StringType.UTF8);
}
/// <summary>
/// Get a boolean from EBML Element's data section.
/// </summary>
/// <returns>a bool containing the parsed value.</returns>
public bool GetBool ()
{
if (Data == null) return false;
return (Data.ToUInt () > 0);
}
/// <summary>
/// Get a double from EBML Element's data section.
/// </summary>
/// <returns>a double containing the parsed value.</returns>
public double GetDouble ()
{
if (Data == null) return 0;
double result = 0.0;
if (Data.Count == 4) {
result = Data.ToFloat ();
} else if (Data.Count == 8) {
result = Data.ToDouble ();
} else {
throw new UnsupportedFormatException ("Can not read a Double with sizes differing from 4 or 8");
}
return result;
}
/// <summary>
/// Get an unsigned integer (any size from 1 to 8 bytes) from EBML Element's data section.
/// </summary>
/// <returns>a ulong containing the parsed value.</returns>
public ulong GetULong ()
{
if (Data == null) return 0;
return Data.ToULong ();
}
/// <summary>
/// Get a bytes vector from EBML Element's data section.
/// </summary>
/// <returns>a <see cref="ByteVector" /> containing the parsed value.</returns>
public ByteVector GetBytes ()
{
return Data;
}
/// <summary>
/// Set data content as <see cref="string"/> to the EBML file
/// </summary>
/// <param name="data">data as <see cref="string"/></param>
public void SetData (string data)
{
Data = data;
}
/// <summary>
/// Set data content as <see cref="ulong"/> to the EBML file
/// </summary>
/// <param name="data">unsigned long number to write</param>
public void SetData (ulong data)
{
const ulong mask = 0xffffffff00000000;
bool isLong = (data & mask) != 0;
ByteVector vector = new ByteVector (isLong ? 8 : 4);
for (int i = vector.Count - 1; i >= 0; i--) {
vector[i] = (byte)(data & 0xff);
data >>= 8;
}
Data = vector;
}
#endregion
#region Public Methods Write to file
/// <summary>
/// Write the EMBL (and all its data/content) to a file.
/// </summary>
/// <param name="file">A <see cref="File"/> representing the file to write to.</param>
/// <param name="position">The byte-position in the file to write the EBML to.</param>
/// <param name="reserved">The reserved size in bytes that the EBML may overwrite from the given position. (Default: 0, insert)</param>
public void Write (File file, long position, long reserved = 0)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
if (position > file.Length || position < 0)
throw new ArgumentOutOfRangeException (nameof (position));
if (Data != null && Children != null)
throw new UnsupportedFormatException ("EBML element cannot contain both Data and Children");
// Reserve required size upfront to speed up writing
var size = Size;
if (size > reserved) {
// Extend reserved size
file.Insert (size - reserved, position + reserved);
reserved = size;
}
// Write the Header
var header = Header;
file.Insert (header, position, header.Count);
position += header.Count;
reserved -= header.Count;
// Write the data/content
if (Data != null) {
file.Insert (Data, position, Data.Count);
} else if (Children != null) {
foreach (var child in Children) {
child.Write (file, position, reserved);
var csize = child.Size;
position += csize;
reserved -= csize;
}
}
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c23a6d98ba04c36aa2f7a19dece41aa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+76
View File
@@ -0,0 +1,76 @@
//
// EBMLIDs.cs:
//
// Author:
// Julien Moutte <julien@fluendo.com>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
namespace TagLib.Matroska
{
/// <summary>
/// Public enumeration listing the possible EBML element identifiers.
/// </summary>
public enum EBMLID
{
/// <summary>
/// Indicates an EBML Header element.
/// </summary>
EBMLHeader = 0x1A45DFA3,
/// <summary>
/// Indicates an EBML Version element.
/// </summary>
EBMLVersion = 0x4286,
/// <summary>
/// Indicates an EBML Read Version element.
/// </summary>
EBMLReadVersion = 0x42F7,
/// <summary>
/// Indicates an EBML Max ID Length element.
/// </summary>
EBMLMaxIDLength = 0x42F2,
/// <summary>
/// Indicates an EBML Max Size Length element.
/// </summary>
EBMLMaxSizeLength = 0x42F3,
/// <summary>
/// Indicates an EBML Doc Type element.
/// </summary>
EBMLDocType = 0x4282,
/// <summary>
/// Indicates an EBML Doc Type Version element.
/// </summary>
EBMLDocTypeVersion = 0x4287,
/// <summary>
/// Indicates an EBML Doc Type Read Version element.
/// </summary>
EBMLDocTypeReadVersion = 0x4285,
/// <summary>
/// Indicates an EBML Void element.
/// </summary>
EBMLVoid = 0xEC
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f47242669f076f52f84ea6b8b4204168
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+483
View File
@@ -0,0 +1,483 @@
//
// EBMLElement.cs:
//
// Author:
// Julien Moutte <julien@fluendo.com>
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
namespace TagLib.Matroska
{
/// <summary>
/// Read a Matroska EBML element from a file, but also provides basic modifications to an
/// EBML element directly on the file (write). This can also represent an abstract EBML
/// on the file (placeholder).
/// </summary>
/// <remarks>
/// This was intitialy called <see cref="EBMLelement"/>, but this was in fact a file-reader.
/// The name <see cref="EBMLelement"/> correspond more to the class which has been created to
/// represent an EBML structure (regardless of file-issues) to support the EBML writing to file.
/// </remarks>
public class EBMLreader
{
#region Private Fields
File file;
ulong offset;
uint ebml_id;
#endregion
#region Constructors
/// <summary>
/// Constructs a root <see cref="EBMLreader" /> instance, by reading from
/// the provided file position.
/// </summary>
/// <param name="_file"><see cref="File" /> File instance to read from.</param>
/// <param name="position">Position in the file to start reading from.</param>
public EBMLreader (File _file, ulong position)
{
// Keep a reference to the file
file = _file;
Parent = null;
// Initialize attributes
offset = position;
DataOffset = position;
ebml_id = 0;
DataSize = 0;
// Actually read the EBML on the file
Read (true);
}
/// <summary>
/// Constructs a child <see cref="EBMLreader" /> reading the data from the
/// EBML parent at the provided file position.
/// </summary>
/// <param name="parent">The <see cref="EBMLreader" /> that contains the instance to be created.</param>
/// <param name="position">Position in the file to start reading from.</param>
public EBMLreader (EBMLreader parent, ulong position)
{
if (parent == null)
throw new ArgumentNullException (nameof (parent));
// Keep a reference to the file
file = parent.file;
Parent = parent;
// Initialize attributes
offset = position;
DataOffset = position;
ebml_id = 0;
DataSize = 0;
// Actually read the EBML on the file
Read (true);
}
/// <summary>
/// Create a new abstract <see cref="EBMLreader" /> with arbitrary attributes,
/// without reading its information on the file.
/// </summary>
/// <param name="parent">The <see cref="EBMLreader" /> that contains the instance to be described.</param>
/// <param name="position">Position in the file.</param>
/// <param name="ebmlid">EBML ID of the element</param>
/// <param name="size">Total size of the EBML, in bytes</param>
public EBMLreader (EBMLreader parent, ulong position, MatroskaID ebmlid, ulong size = 0)
{
// Keep a reference to the file
if (parent != null)
file = parent.file;
Parent = parent;
// Initialize attributes
offset = position;
DataOffset = offset;
ebml_id = (uint)ebmlid;
DataSize = size;
}
#endregion
#region Public Properties
/// <summary>
/// EBML Element Identifier.
/// </summary>
public MatroskaID ID {
get { return (MatroskaID)ebml_id; }
}
/// <summary>
/// EBML Parent instance.
/// </summary>
public EBMLreader Parent { get; }
/// <summary>
/// EBML Element size in bytes.
/// </summary>
public ulong Size {
set { DataSize = value - (DataOffset - offset); }
get { return (DataOffset - offset) + DataSize; }
}
/// <summary>
/// EBML Element data size in bytes.
/// </summary>
public ulong DataSize { set; get; }
/// <summary>
/// EBML Element data offset position in file in bytes.
/// </summary>
public ulong DataOffset { get; set; }
/// <summary>
/// EBML Element offset position in file in bytes.
/// </summary>
public ulong Offset {
set {
DataOffset = (ulong)((long)DataOffset + ((long)value - (long)offset));
offset = value;
}
get { return offset; }
}
/// <summary>
/// Defines that the EBML element is not read-out from file,
/// but is an abstract representation of an element on the disk.
/// </summary>
public bool Abstract {
get { return offset == DataOffset; }
}
#endregion
#region Public Methods for Reading
/// <summary>
/// Read EBML header and data-size if it is an abstract one.
/// It then becomes a non abstract EBML.
/// </summary>
/// <param name="throwException">Throw exception on invalid EBML read if true (Default: false).</param>
/// <returns>True if successful.</returns>
public bool Read (bool throwException = false)
{
if (!Abstract) return true;
if (file == null)
throw new ArgumentNullException (nameof(file));
try {
var ex = new InvalidOperationException ("Invalid EBML format Read");
if (offset >= (ulong)(file.Length) - 1) throw ex;
// Prepare for Consitency check
uint ebml_id_check = ebml_id;
ulong ebml_size_check = Size;
file.Seek ((long)offset);
// Get the header byte
ByteVector vector = file.ReadBlock (1);
byte header_byte = vector[0];
// Define a mask
byte mask = 0x80, id_length = 1;
// Figure out the size in bytes
while (id_length <= 4 && (header_byte & mask) == 0) {
id_length++;
mask >>= 1;
}
if (id_length > 4) throw ex;
// Now read the rest of the EBML ID
if (id_length > 1) {
vector.Add (file.ReadBlock (id_length - 1));
}
ebml_id = vector.ToUInt ();
vector.Clear ();
// Get the size length
vector = file.ReadBlock (1);
header_byte = vector[0];
mask = 0x80;
byte size_length = 1;
// Iterate through various possibilities
while (size_length <= 8 && (header_byte & mask) == 0) {
size_length++;
mask >>= 1;
}
if (size_length > 8)
size_length = 1; // Special: Empty element (all zero state)
else
vector[0] &= (byte)(mask - 1); // Clear the marker bit
// Now read the rest of the EBML element size
if (size_length > 1) {
vector.Add (file.ReadBlock (size_length - 1));
}
DataSize = vector.ToULong ();
// Special: Auto-size (0xFF byte)
if (size_length == 1 && DataSize == 0x7F) {
// Resolve auto-size to fill in to its containing element
ulong bound = Parent == null ? (ulong)file.Length : Parent.Offset + Parent.Size;
DataSize = bound - offset - (ulong)(id_length + size_length);
}
DataOffset = offset + id_length + size_length;
// Consistency check: Detect descrepencies between read data and abstract data
if (ebml_id_check != 0 && ebml_id_check != ebml_id) throw ex;
if (ebml_size_check != 0 && ebml_size_check != Size) throw ex;
return true;
} catch (Exception) {
if (throwException)
throw;
return false;
}
}
/// <summary>
/// Reads a vector of bytes (raw data) from EBML Element's data section.
/// </summary>
/// <returns>a <see cref="ByteVector" /> containing the parsed value.</returns>
public ByteVector ReadBytes ()
{
if (file == null) {
return null;
}
file.Seek ((long)DataOffset);
ByteVector vector = file.ReadBlock ((int)DataSize);
return vector;
}
/// <summary>
/// Reads a string from EBML Element's data section (UTF-8).
/// </summary>
/// <returns>a string object containing the parsed value.</returns>
public string ReadString ()
{
if (file == null) return null;
ByteVector vector = ReadBytes ();
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
return ebml.GetString ();
}
/// <summary>
/// Reads a boolean from EBML Element's data section.
/// </summary>
/// <returns>a bool containing the parsed value.</returns>
public bool ReadBool ()
{
if (file == null || DataSize == 0) return false;
ByteVector vector = ReadBytes ();
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
return ebml.GetBool ();
}
/// <summary>
/// Reads a double from EBML Element's data section.
/// </summary>
/// <returns>a double containing the parsed value.</returns>
public double ReadDouble ()
{
if (file == null || DataSize == 0) return 0;
ByteVector vector = ReadBytes ();
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
return ebml.GetDouble ();
}
/// <summary>
/// Reads an unsigned integer (any size from 1 to 8 bytes) from EBML Element's data section.
/// </summary>
/// <returns>a ulong containing the parsed value.</returns>
public ulong ReadULong ()
{
if (file == null || DataSize == 0) return 0;
ByteVector vector = ReadBytes ();
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
return ebml.GetULong ();
}
#endregion
#region Public Methods for Writing
/// <summary>
/// Write the <see cref="DataSize"/> to the EBML file.
/// Resize the data-size length to 8 bytes.
/// This will *not* insert extra bytes, but overwrite next contiguous bytes.
/// It will claim the size added on the value of the data-size.
/// </summary>
/// <returns>Offset created in Writing the new data-size</returns>
public long WriteDataSize ()
{
ulong value = DataSize;
const ulong newsize_length = 8;
// Figure out the ID size in bytes
ulong mask = 0xFF000000, id_length = 4;
while (id_length > 0 && (ebml_id & mask) == 0) {
id_length--;
mask >>= 8;
}
if (id_length == 0)
throw new CorruptFileException ("invalid EBML ID (zero)");
// Figure out the Data size length in bytes
ulong size_length = DataOffset - offset - id_length;
if (size_length > 8)
throw new CorruptFileException ("invalid EBML element size");
// Construct the data-size field
ByteVector vector = new ByteVector ((int)newsize_length);
mask = value;
for (int i = (int)newsize_length - 1; i >= 0; i--) {
vector[i] = (byte)(mask & 0xFF);
mask >>= 8;
}
// Set the marker bit
vector[0] |= 0x100 >> (int)newsize_length;
// Write data-size field to file
file.Insert (vector, (long)(offset + id_length), (long)newsize_length);
// Update fields
ulong woffset = newsize_length - size_length;
DataOffset += woffset;
DataSize = value - woffset;
return (long)woffset;
}
/// <summary>
/// Change an EBML element to a Abstract Void element, but do not write to the file.
/// </summary>
/// <remarks>
/// To do a real conversion to Void EBML element on the file, use <see cref="WriteVoid()"/>.
/// </remarks>
public void SetVoid ()
{
ulong size = Size;
// Update this object
ebml_id = (uint)MatroskaID.Void;
DataOffset = offset; // This will make it abstract
DataSize = size; // Keep the size unchanged
}
/// <summary>
/// Change an EBML element to a Void element directly on the file.
/// </summary>
public void WriteVoid ()
{
if (Size < 2) throw new ArgumentOutOfRangeException (nameof(Size), "WriteVoid Size < 2");
if (file == null)
throw new ArgumentNullException (nameof(file), "WriteVoid file");
if (offset + Size > (ulong)(file.Length))
throw new ArgumentOutOfRangeException (nameof(file), "WriteVoid tries to write out of the file");
ByteVector vector;
int datasize;
if (Size < 100) {
vector = new ByteVector (2);
datasize = (int)Size - 2;
vector[0] = (byte)MatroskaID.Void; // size = 1
vector[1] = (byte)(0x80 | datasize); // Marker + data-size
} else {
vector = new ByteVector (9);
datasize = (int)Size - 9;
vector[0] = (byte)MatroskaID.Void; // size = 1
vector[1] = 0x01; // set marker
// Set data size
int mask = datasize;
for (int i = 8; i > 1; i--) {
vector[i] = (byte)(mask & 0xFF);
mask >>= 8;
}
}
file.Insert (vector, (long)Offset, vector.Count);
// Update this object
ebml_id = (uint)MatroskaID.Void;
DataOffset = Offset + (ulong)vector.Count;
DataSize = (ulong)datasize;
}
/// <summary>
/// Remove the EBML element from the file
/// </summary>
/// <returns>Size difference compare to previous EBML size</returns>
public long Remove ()
{
long ret = -(long)Size;
file.RemoveBlock ((long)Offset, (long)Size);
// Invalidate this object
ebml_id = 0;
DataOffset = offset;
DataSize = 0;
file = null;
return ret;
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9935d41c1f28aa7579c5e3b81a11e1da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 00e44660739fad50fb5cb7c788045b12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+119
View File
@@ -0,0 +1,119 @@
//
// SimpleTag.cs:
//
// Author:
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2017 Starwer
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
namespace TagLib.Matroska
{
/// <summary>
/// Represent a Matroska element that has an Unique Identifier, and can be tagged.
/// </summary>
public interface IUIDElement
{
/// <summary>
/// Unique ID representing the file, as random as possible (setting zero will generate automatically a new one).
/// </summary>
ulong UID { get; set; }
/// <summary>
/// Get the Tag type the UID should be represented by, or 0 if undefined
/// </summary>
MatroskaID UIDType { get; }
}
/// <summary>
/// Represent a basic Matroska UID element
/// </summary>
public class UIDElement : IUIDElement
{
#region Constructors
/// <summary>
/// Create a UIDElement Stub
/// </summary>
/// <param name="type">Tag-type the UID represents</param>
/// <param name="uid">UID of the element</param>
public UIDElement (MatroskaID type, ulong uid)
{
UID = uid;
if (type == MatroskaID.TagTrackUID
|| type == MatroskaID.TagEditionUID
|| type == MatroskaID.TagChapterUID
|| type == MatroskaID.TagAttachmentUID)
UIDType = type;
else
UIDType = 0;
}
#endregion
#region Statics
static readonly Random random = new Random ();
/// <summary>
/// Generate a new random UID
/// </summary>
/// <param name="ret">Value of the UID to be generated. A zero value will randomize it.</param>
/// <returns>Generated UID.</returns>
public static ulong GenUID (ulong ret = 0)
{
while (ret == 0) {
ret = ((ulong)random.Next ()) << 32;
ret |= (uint)random.Next ();
}
return ret;
}
#endregion
#region IUIDElement Boilerplate
/// <summary>
/// Unique ID representing the element, as random as possible (setting zero will generate automatically a new one).
/// </summary>
public ulong UID {
get { return _UID; }
set { _UID = GenUID (value); }
}
ulong _UID = GenUID ();
/// <summary>
/// Get the Tag type the UID should be represented by, or 0 if undefined
/// </summary>
public MatroskaID UIDType { get; private set; } = 0;
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fe1585063c4447dc9d30b572628a8ef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+549
View File
@@ -0,0 +1,549 @@
//
// MatroskaIDs.cs:
//
// Author:
// Julien Moutte <julien@fluendo.com>
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
namespace TagLib.Matroska
{
/// <summary>
/// Public enumeration listing Matroska specific EBML Identifiers.
/// </summary>
public enum MatroskaID : uint
{
/// <summary>
/// Indicates a Matroska Segment EBML element.
/// </summary>
Segment = 0x18538067,
/// <summary>
/// Indicates a Matroska Segment Info EBML element.
/// </summary>
SegmentInfo = 0x1549A966,
/// <summary>
/// Indicates a Matroska Tracks EBML Element.
/// </summary>
Tracks = 0x1654AE6B,
/// <summary>
/// Indicates a Matroska Cues EBML element.
/// </summary>
Cues = 0x1C53BB6B,
/// <summary>
/// Indicates a Matroska Tags EBML element.
/// </summary>
Tags = 0x1254C367,
/// <summary>
/// Indicates a Matroska Seek Head EBML element.
/// </summary>
SeekHead = 0x114D9B74,
/// <summary>
/// Indicates a Matroska Cluster EBML element.
/// </summary>
Cluster = 0x1F43B675,
/// <summary>
/// Indicates a Matroska Attachments EBML element.
/// </summary>
Attachments = 0x1941A469,
/// <summary>
/// Indicates a Matroska Chapters EBML element.
/// </summary>
Chapters = 0x1043A770,
/* IDs in the SegmentInfo master */
/// <summary>
/// Indicate a Matroska Code Scale EBML element.
/// </summary>
TimeCodeScale = 0x2AD7B1,
/// <summary>
/// Indicates a Matroska Duration EBML element.
/// </summary>
Duration = 0x4489,
/// <summary>
/// Indicates a Matroska Writing App EBML element.
/// </summary>
WrittingApp = 0x5741,
/// <summary>
/// Indicates a Matroska Muxing App EBML element.
/// </summary>
MuxingApp = 0x4D80,
/// <summary>
/// Indicate a Matroska Date UTC EBML element.
/// </summary>
DateUTC = 0x4461,
/// <summary>
/// Indicate a Matroska Segment UID EBML element.
/// </summary>
SegmentUID = 0x73A4,
/// <summary>
/// Indicate a Matroska Segment File Name EBML element.
/// </summary>
SegmentFileName = 0x7384,
/// <summary>
/// Indicate a Matroska Prev UID EBML element.
/// </summary>
PrevUID = 0x3CB923,
/// <summary>
/// Indicate a Matroska Prev File Name EBML element.
/// </summary>
PrevFileName = 0x3C83AB,
/// <summary>
/// Indicate a Matroska Nex UID EBML element.
/// </summary>
NexUID = 0x3EB923,
/// <summary>
/// Indicate a Matroska Nex File Name EBML element.
/// </summary>
NexFileName = 0x3E83BB,
/// <summary>
/// Indicate a Matroska Title EBML element.
/// </summary>
Title = 0x7BA9,
/// <summary>
/// Indicate a Matroska Segment Family EBML element.
/// </summary>
SegmentFamily = 0x4444,
/// <summary>
/// Indicate a Matroska Chapter Translate EBML element.
/// </summary>
ChapterTranslate = 0x6924,
/* ID in the Tracks master */
/// <summary>
/// Indicate a Matroska Track Entry EBML element.
/// </summary>
TrackEntry = 0xAE,
/* IDs in the TrackEntry master */
/// <summary>
/// Indicate a Matroska Track Number EBML element.
/// </summary>
TrackNumber = 0xD7,
/// <summary>
/// Indicate a Matroska Track UID EBML element.
/// </summary>
TrackUID = 0x73C5,
/// <summary>
/// Indicate a Matroska Track Type EBML element.
/// </summary>
TrackType = 0x83,
/// <summary>
/// Indicate a Matroska Track Audio EBML element.
/// </summary>
TrackAudio = 0xE1,
/// <summary>
/// Indicate a Matroska Track Video EBML element.
/// </summary>
TrackVideo = 0xE0,
/// <summary>
/// Indicate a Matroska Void EBML element.
/// </summary>
Void = 0xEC,
/// <summary>
/// Indicate a Matroska CRC-32 EBML element.
/// </summary>
/// <remarks>
/// The CRC is computed on all the data of the Master-element it's in.
/// The CRC Element should be the first in it's parent master for easier reading.
/// All level 1 Elements should include a CRC-32. The CRC in use is the IEEE CRC32 Little Endian.
/// </remarks>
CRC32 = 0xBF,
/// <summary>
/// Indicate a Matroska Track Encoding EBML element.
/// </summary>
ContentEncodings = 0x6D80,
/// <summary>
/// Indicate a Matroska Codec ID EBML element.
/// </summary>
CodecID = 0x86,
/// <summary>
/// Indicate a Matroska Codec Private EBML element.
/// </summary>
CodecPrivate = 0x63A2,
/// <summary>
/// Indicate a Matroska Codec Name EBML element.
/// </summary>
CodecName = 0x258688,
/// <summary>
/// Indicate a Matroska Track Name EBML element.
/// </summary>
TrackName = 0x536E,
/// <summary>
/// Indicate a Matroska Track Language EBML element.
/// </summary>
TrackLanguage = 0x22B59C,
/// <summary>
/// Indicate a Matroska Track Enabled EBML element.
/// </summary>
TrackFlagEnabled = 0xB9,
/// <summary>
/// Indicate a Matroska Track Flag Default EBML element.
/// </summary>
TrackFlagDefault = 0x88,
/// <summary>
/// Indicate a Matroska Track Flag Forced EBML element.
/// </summary>
TrackFlagForced = 0x55AA,
/// <summary>
/// Indicate a Matroska Track Flag Lacing EBML element.
/// </summary>
TrackFlagLacing = 0x9C,
/// <summary>
/// Indicate a Matroska Track Min Cache EBML element.
/// </summary>
TrackMinCache = 0x6DE7,
/// <summary>
/// Indicate a Matroska Track Max Cache EBML element.
/// </summary>
TrackMaxCache = 0x6DF8,
/// <summary>
/// Indicate a Matroska Track Default Duration EBML element.
/// </summary>
TrackDefaultDuration = 0x23E383,
/// <summary>
/// Indicate a Matroska Track Time Code Scale EBML element.
/// </summary>
TrackTimeCodeScale = 0x23314F,
/// <summary>
/// Indicate a Matroska Track Max Block Addition EBML element.
/// </summary>
MaxBlockAdditionID = 0x55EE,
/// <summary>
/// Indicate a Matroska Track Attachment Link EBML element.
/// </summary>
TrackAttachmentLink = 0x7446,
/// <summary>
/// Indicate a Matroska Track Overlay EBML element.
/// </summary>
TrackOverlay = 0x6FAB,
/// <summary>
/// Indicate a Matroska Track Translate EBML element.
/// </summary>
TrackTranslate = 0x6624,
/// <summary>
/// Indicate a Matroska Track Offset element.
/// </summary>
TrackOffset = 0x537F,
/// <summary>
/// Indicate a Matroska Codec Settings EBML element.
/// </summary>
CodecSettings = 0x3A9697,
/// <summary>
/// Indicate a Matroska Codec Info URL EBML element.
/// </summary>
CodecInfoUrl = 0x3B4040,
/// <summary>
/// Indicate a Matroska Codec Download URL EBML element.
/// </summary>
CodecDownloadUrl = 0x26B240,
/// <summary>
/// Indicate a Matroska Codec Decode All EBML element.
/// </summary>
CodecDecodeAll = 0xAA,
/* IDs in the TrackVideo master */
/* NOTE: This one is here only for backward compatibility.
* Use _TRACKDEFAULDURATION */
/// <summary>
/// Indicate a Matroska Video Frame Rate EBML element.
/// </summary>
VideoFrameRate = 0x2383E3,
/// <summary>
/// Indicate a Matroska Video Display Width EBML element.
/// </summary>
VideoDisplayWidth = 0x54B0,
/// <summary>
/// Indicate a Matroska Video Display Height EBML element.
/// </summary>
VideoDisplayHeight = 0x54BA,
/// <summary>
/// Indicate a Matroska Video Display Unit EBML element.
/// </summary>
VideoDisplayUnit = 0x54B2,
/// <summary>
/// Indicate a Matroska Video Pixel Width EBML element.
/// </summary>
VideoPixelWidth = 0xB0,
/// <summary>
/// Indicate a Matroska Video Pixel Height EBML element.
/// </summary>
VideoPixelHeight = 0xBA,
/// <summary>
/// Indicate a Matroska Video Pixel Crop Bottom EBML element.
/// </summary>
VideoPixelCropBottom = 0x54AA,
/// <summary>
/// Indicate a Matroska Video Pixel Crop Top EBML element.
/// </summary>
VideoPixelCropTop = 0x54BB,
/// <summary>
/// Indicate a Matroska Video Pixel Crop Left EBML element.
/// </summary>
VideoPixelCropLeft = 0x54CC,
/// <summary>
/// Indicate a Matroska Video Pixel Crop Right EBML element.
/// </summary>
VideoPixelCropRight = 0x54DD,
/// <summary>
/// Indicate a Matroska Video Flag Interlaced EBML element.
/// </summary>
VideoFlagInterlaced = 0x9A,
/// <summary>
/// Indicate a Matroska Video Stereo Mode EBML element.
/// </summary>
VideoStereoMode = 0x53B8,
/// <summary>
/// Indicate a Matroska Video Aspect Ratio Type EBML element.
/// </summary>
VideoAspectRatioType = 0x54B3,
/// <summary>
/// Indicate a Matroska Video Colour Space EBML element.
/// </summary>
VideoColourSpace = 0x2EB524,
/// <summary>
/// Indicate a Matroska Video Gamma Value EBML element.
/// </summary>
VideoGammaValue = 0x2FB523,
/* in the Matroska Seek Head master */
/// <summary>
/// Indicate a Matroska Seek Entry (Master).
/// </summary>
Seek = 0x4DBB,
/// <summary>
/// Indicate a Matroska Seek ID (Binary).
/// </summary>
SeekID = 0x53AB,
/// <summary>
/// Indicate a Matroska Seek Position (uint).
/// </summary>
SeekPosition = 0x53AC,
/* IDs in the TrackAudio master */
/// <summary>
/// Indicate a Matroska Audio Sampling Freq EBML element.
/// </summary>
AudioSamplingFreq = 0xB5,
/// <summary>
/// Indicate a Matroska Audio Bit Depth EBML element.
/// </summary>
AudioBitDepth = 0x6264,
/// <summary>
/// Indicate a Matroska Audio Channels EBML element.
/// </summary>
AudioChannels = 0x9F,
/// <summary>
/// Indicate a Matroska Audio Channels Position EBML element.
/// </summary>
AudioChannelsPositions = 0x7D7B,
/// <summary>
/// Indicate a Matroska Audio Output Sampling Freq EBML element.
/// </summary>
AudioOutputSamplingFreq = 0x78B5,
/* IDs in the Tags master */
/// <summary>
/// Indicate a Matroska Tag EBML element.
/// </summary>
Tag = 0x7373,
/* in the Tag master */
/// <summary>
/// Indicate a Matroska Simple Tag EBML element.
/// </summary>
SimpleTag = 0x67C8,
/// <summary>
/// Indicate a Matroska Targets EBML element.
/// </summary>
Targets = 0x63C0,
/* in the SimpleTag master */
/// <summary>
/// Indicate a Matroska Tag Name EBML element.
/// </summary>
TagName = 0x45A3,
/// <summary>
/// Indicate a Matroska Tag String EBML element.
/// </summary>
TagString = 0x4487,
/// <summary>
/// Indicate a Matroska Tag Language EBML element.
/// </summary>
TagLanguage = 0x447A,
/// <summary>
/// Indicate a Matroska Tag Default EBML element.
/// </summary>
TagDefault = 0x4484,
/// <summary>
/// Indicate a Matroska Tag Binary EBML element.
/// </summary>
TagBinary = 0x4485,
/* in the Targets master */
/// <summary>
/// Indicate a Matroska Target Type Value EBML element (UINT).
/// </summary>
TargetTypeValue = 0x68CA,
/// <summary>
/// Indicate a Matroska Target Type EBML element (string).
/// </summary>
TargetType = 0x63CA,
/// <summary>
/// Indicate a Matroska Target Tag Track UID EBML element (UINT).
/// </summary>
TagTrackUID = 0x63C5,
/// <summary>
/// Indicate a Matroska Target Tag Edition UID EBML element (UINT).
/// </summary>
TagEditionUID = 0x63C9,
/// <summary>
/// Indicate a Matroska Target Tag Chapter UID EBML element (UINT).
/// </summary>
TagChapterUID = 0x63C4,
/// <summary>
/// Indicate a Matroska Target Tag Attachment UID EBML element (UINT).
/// </summary>
TagAttachmentUID = 0x63C6,
/* in the Attachments master */
/// <summary>
/// Indicate a Matroska attached file.
/// </summary>
AttachedFile = 0x61A7,
/// <summary>
/// Indicate a Matroska human-friendly name for the attached file.
/// </summary>
FileDescription = 0x467E,
/// <summary>
/// Indicate a Matroska Filename of the attached file.
/// </summary>
FileName = 0x466E,
/// <summary>
/// Indicate a Matroska MIME type of the file.
/// </summary>
FileMimeType = 0x4660,
/// <summary>
/// Indicate a Matroska data of the file.
/// </summary>
FileData = 0x465C,
/// <summary>
/// Indicate a Matroska Unique ID representing the file, as random as possible.
/// </summary>
FileUID = 0x46AE
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd175d3dd62b5062ca13ba2d98028987
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+125
View File
@@ -0,0 +1,125 @@
//
// SimpleTag.cs:
//
// Author:
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2017 Starwer
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System.Collections.Generic;
using System.Globalization;
namespace TagLib.Matroska
{
/// <summary>
/// Describes a SimpleTag content. The TagName property is not part of the SimpleTag.
/// A <see cref="Tag"/> object may contain several <see cref="SimpleTag"/>.
/// A <see cref="SimpleTag"/> object may contains several <see cref="SimpleTag"/>.
/// </summary>
public class SimpleTag : ByteVector
{
#region Constructors
/// <summary>
/// Constructor
/// </summary>
public SimpleTag ()
{
}
/// <summary>
/// Construct from value
/// </summary>
public SimpleTag (ByteVector value)
{
Value = value;
}
#endregion
#region Properties
/// <summary>
/// Indicate if the content of the SimpleTag is in binary (true) or as a string (false).
/// </summary>
public bool TagBinary = false;
/// <summary>
/// Indication to know if this is the default/original language to use for the given tag.
/// </summary>
public bool TagDefault = true;
/// <summary>
/// Specifies the language of the tag, as a string.
/// </summary>
public string TagLanguage {
get {
var ret = Language.ToString ();
return string.IsNullOrEmpty (ret) ? "und" : ret;
}
set {
if (string.IsNullOrEmpty (value) || value == "und") {
Language = CultureInfo.InvariantCulture;
} else {
try {
Language = new CultureInfo (value);
} catch {
Language = CultureInfo.InvariantCulture;
}
}
}
}
/// <summary>
/// Specifies the language of the tag.
/// </summary>
public CultureInfo Language = CultureInfo.InvariantCulture;
/// <summary>
/// Get/Set the data contained in the SimpleTag
/// </summary>
public ByteVector Value {
get { return this; }
set { Clear (); Add (value); }
}
/// <summary>
/// Children SimpleTag nested inside this SimpleTag
/// </summary>
public Dictionary<string, List<SimpleTag>> SimpleTags = null;
#endregion
#region Implicit Conversions
/// <summary>
/// Convert a SimpleTag to a String in the Default encoding
/// </summary>
/// <param name="v"></param>
public static implicit operator string (SimpleTag v)
{
return v?.ToString (StringType.UTF8);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eddebb00e71a62b07a3df8087973aa93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,86 @@
//
// SubtitleTrack.cs:
//
// Author:
// Julien Moutte <julien@fluendo.com>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System.Collections.Generic;
namespace TagLib.Matroska
{
/// <summary>
/// Describes a Matroska Subtitle Track.
/// </summary>
public class SubtitleTrack : Track
{
#region Constructors
/// <summary>
/// Constructs a <see cref="SubtitleTrack" /> parsing from provided
/// file data.
/// Parsing will be done reading from _file at position references by
/// parent element's data section.
/// </summary>
/// <param name="_file"><see cref="File" /> instance to read from.</param>
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
public SubtitleTrack (File _file, EBMLreader element)
: base (_file, element)
{
// Here we handle the unknown elements we know, and store the rest
foreach (EBMLreader elem in base.UnknownElements) {
MatroskaID matroska_id = elem.ID;
switch (matroska_id) {
default:
UnknownElements.Add (elem);
break;
}
}
}
#endregion
#region Public fields
/// <summary>
/// List of unknown elements encountered while parsing.
/// </summary>
public new List<EBMLreader> UnknownElements { get; } = new List<EBMLreader>();
#endregion
#region Public methods
#endregion
#region ICodec
/// <summary>
/// This type of track only has text media type.
/// </summary>
public override MediaTypes MediaTypes {
get {
return MediaTypes.Text;
}
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 168f0a6ea9893b8d08c795623d1e72e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68b75afa0a1569beea982c60cd9da977
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+292
View File
@@ -0,0 +1,292 @@
//
// Tags.cs:
//
// Author:
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2017 Starwer
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace TagLib.Matroska
{
/// <summary>
/// Describes all the Matroska Tags in a file as a list, ordered from higher TargetTypeValue to lower.
/// A <see cref="Tags"/> object contains several <see cref="Tag"/>
/// </summary>
public class Tags : Collection<Tag>
{
#region Private fields/Properties
// Store the Attachments
Attachment[] attachments = new Attachment[0];
readonly List<Track> _Tracks;
#endregion
#region Constructors
/// <summary>
/// Constructor
/// </summary>
/// <param name="tracks">List of Matroska tracks</param>
public Tags (List<Track> tracks)
{
_Tracks = tracks;
}
#endregion
#region Override Collection, to keep the items ordered
/// <summary>
/// Try to Insert an element to the Tag list at a given index, but can insert it at another index if the
/// index doesn't keep this list sorted by descending TargetTypeValue
/// </summary>
/// <param name="index">index at which the Tag element should be preferably inserted</param>
/// <param name="tag">Tag element to be inserted in the Tag list</param>
protected override void InsertItem (int index, Tag tag)
{
if (tag == null)
throw new ArgumentNullException (nameof(tag), "Can't add a null Matroska.Tag to a Matroska.Tags object");
// Remove duplicate
for (int j = 0; j < Count; j++) {
if (this[j] == tag) {
RemoveAt (j);
break;
}
}
if (index < 0 || index >= Count || this[index].TargetTypeValue < tag.TargetTypeValue || (index + 1 < Count && this[index + 1].TargetTypeValue > tag.TargetTypeValue)) {
for (index = Count - 1; index >= 0; index--) {
if (this[index].TargetTypeValue > tag.TargetTypeValue)
break;
if (this[index].TargetTypeValue == tag.TargetTypeValue && (this[index].Elements == null || tag.Elements != null))
break;
}
index++;
}
base.InsertItem (index, tag);
}
/// <summary>
/// Replace a tag in the list.
/// </summary>
/// <param name="index">Index of the lement to be replaced</param>
/// <param name="tag">tag to replace the older one</param>
protected override void SetItem (int index, Tag tag)
{
RemoveItem (index);
InsertItem (index, tag);
}
/// <summary>
/// Clears the values stored in the current Tags and Children.
/// </summary>
protected override void ClearItems ()
{
Title = null;
var medium = Medium;
foreach (var tag in this) {
tag.Clear ();
}
base.ClearItems ();
// Keep Medium Tag reference unchanged (if any)
if (medium != null) Add (medium);
}
#endregion
#region Methods
/// <summary>
/// Find the first Tag of a given TargetTypeValue
/// </summary>
/// <param name="targetType">TargetTypeValue to find</param>
/// <param name="medium">null: any kind, true: represent the current medium, false: represent a sub-element</param>
/// <returns>the Tag if match found, null otherwise</returns>
public Tag Get (TargetType targetType, bool? medium = true)
{
Tag ret = null;
int i;
// Coerce: Valid values are: 10 20 30 40 50 60 70
ushort targetTypeValue = (ushort)targetType;
targetTypeValue = (ushort)
(targetTypeValue > 70 ? 70
: targetTypeValue < 10 ? 10
: (targetTypeValue / 10) * 10
);
// Find first match of the given targetValue
// List is sorted in descending TargetTypeValue
for (i = Count - 1; i >= 0; i--) {
if (targetTypeValue == this[i].TargetTypeValue) {
ret = this[i];
if (medium != null) {
bool isMedium = (ret.Elements == null);
if (medium == isMedium) break;
} else {
break;
}
}
}
return i >= 0 ? ret : null;
}
/// <summary>
/// Find the first Tag applying to an object (Matroska UID), matching a TargetTypeValue
/// </summary>
/// <param name="UIDelement">Matroska Track, Edition, Chapter or Attachment (element having an UID)</param>
/// <param name="targetTypeValue">TargetTypeValue to match (default: match any)</param>
/// <returns>the first matching Tag representing the UID, or null if not found.</returns>
public Tag Get (IUIDElement UIDelement, ushort targetTypeValue = 0)
{
int i;
ulong UID = UIDelement.UID;
for (i = Count - 1; i >= 0; i--) {
if (targetTypeValue == 0 || targetTypeValue == this[i].TargetTypeValue) {
var ret = this[i];
if (ret.Elements != null) {
foreach (var uid in ret.Elements) {
if (uid.UID == UID) return ret; // found
}
}
}
}
return null;
}
#endregion
#region Properties
/// <summary>
/// Define if this represent a video content (true), or an audio content (false)
/// </summary>
public bool IsVideo = false;
/// <summary>
/// Title of the medium, from the Segment
/// </summary>
public string Title { get; set; }
/// <summary>
/// Get/set the Tag that represents the current medium (file)
/// </summary>
public Tag Medium {
get {
Tag ret = null;
bool vid = IsVideo;
// Try to find a default TargetType
for (int i = Count - 1; i >= 0; i--) {
ret = this[i];
if (ret.TargetType == TargetType.DEFAULT) // Avoid CD/DVD
{
if (ret.Elements == null) return ret;
}
}
// Lower level without UID is the Tag representing the file
// List is sorted in descending TargetTypeValue
for (int i = Count - 1; i >= 0; i--) {
ret = this[i];
if (ret.TargetTypeValue != 40 || !vid) // Avoid CD/DVD
{
if (ret.Elements == null) break;
}
}
return ret;
}
}
/// <summary>
/// Get/set the Tag that represents the Collection the current medium (file) belongs to.
/// For Audio, this should be an Album, type 50 (itself if the mka file represents an album).
/// For Video, this should be a Collection, type 70.
/// </summary>
public Tag Album {
get {
TargetType targetValue = IsVideo ? TargetType.COLLECTION : TargetType.ALBUM;
return Get (targetValue);
}
}
/// <summary>
/// Gets and sets a collection of Attachments associated with
/// the media represented by the current instance.
/// </summary>
/// <value>
/// A <see cref="T:Attachment[]" /> containing a collection of
/// attachments associated with the media represented by the
/// current instance or an empty array if none are present.
/// </value>
public Attachment[] Attachments {
get {
return attachments;
}
set {
if (value == null) {
if (attachments.Length > 0) attachments = new Attachment[0];
} else {
attachments = value;
}
}
}
/// <summary>
/// Get direct access to the Matroska Tracks.
/// </summary>
public ReadOnlyCollection<Track> Tracks {
get { return _Tracks.AsReadOnly (); }
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2e5e763ff71b52aaca2d8b8be98ad491
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+146
View File
@@ -0,0 +1,146 @@
//
// TargetType.cs:
//
// Author:
// Sebastien Mouy <starwer@laposte.net>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
namespace TagLib.Matroska
{
/// <summary>
/// Represents a Matroska TargetType.
/// The TargetType element allows tagging of different parts that are inside or outside a given file.
/// For example in an audio file with one song you could have information about the album it comes
/// from and even the CD set even if it's not found in the file.
/// </summary>
public enum TargetType : ushort
{
/// <summary>
/// Audio/Video: The high hierarchy consisting of many different lower items
/// </summary>
COLLECTION = 70,
/// <summary>
/// Audio/Video: a list of lower levels grouped together
/// </summary>
VOLUME = 60,
/// <summary>
/// Audio: a list of lower levels grouped together
/// </summary>
///
EDITION = 61,
/// <summary>
/// Audio: a list of lower levels grouped together
/// </summary>
ISSUE = 62,
/// <summary>
/// Audio: a list of lower levels grouped together
/// </summary>
OPUS = 63,
/// <summary>
/// Video: a list of lower levels grouped together
/// </summary>
SEASON = 64,
/// <summary>
/// Video: a list of lower levels grouped together
/// </summary>
SEQUEL = 65,
/// <summary>
/// Audio: the most common grouping level of music and video (equals to an episode for TV series)
/// </summary>
ALBUM = 50,
/// <summary>
/// Audio: the most common grouping level of music and video (equals to an episode for TV series)
/// </summary>
OPERA = 51,
/// <summary>
/// Audio/Video: the most common grouping level of music and video (equals to an episode for TV series)
/// </summary>
CONCERT = 52,
/// <summary>
/// Video: the most common grouping level of music and video (equals to an episode for TV series)
/// </summary>
MOVIE = 53,
/// <summary>
/// Video: the most common grouping level of music and video (equals to an episode for TV series)
/// </summary>
EPISODE = 54,
/// <summary>
/// Represent the default TargetType (an empty Targets), i.e. targets everything in the segment.
/// </summary>
DEFAULT = 55,
/// <summary>
/// Audio/Video: when an album or episode has different logical parts
/// </summary>
PART = 40,
/// <summary>
/// Audio/Video: when an album or episode has different logical parts
/// </summary>
SESSION = 41,
/// <summary>
/// Audio: the common parts of an album or a movie
/// </summary>
TRACK = 30,
/// <summary>
/// Audio: the common parts of an album or a movie
/// </summary>
SONG = 31,
/// <summary>
/// Video: the common parts of an album or a movie
/// </summary>
CHAPTER = 32,
/// <summary>
/// Audio: corresponds to parts of a track for audio (like a movement)
/// </summary>
SUBTRACK = 20,
/// <summary>
/// Audio: corresponds to parts of a track for audio (like a movement)
/// </summary>
MOVEMENT = 21,
/// <summary>
/// Video: corresponds to parts of a track for audio (like a movement)
/// </summary>
SCENE = 22,
/// <summary>
/// Video: the lowest hierarchy found in music or movies
/// </summary>
SHOT = 10
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a619c5df2be0e25da875bc2dfc28c85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+170
View File
@@ -0,0 +1,170 @@
//
// Track.cs:
//
// Author:
// Julien Moutte <julien@fluendo.com>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
using System.Collections.Generic;
namespace TagLib.Matroska
{
/// <summary>
/// Describes a Matroska Track.
/// </summary>
public class Track : ICodec, IUIDElement
{
#region Private fields
#pragma warning disable 414 // Assigned, never used
readonly ulong track_number;
readonly string track_codec_id;
readonly string track_codec_name;
readonly string track_name;
readonly string track_language;
readonly bool track_enabled;
readonly bool track_default;
readonly ByteVector codec_data;
#pragma warning restore 414
readonly List<EBMLreader> unknown_elems = new List<EBMLreader> ();
#endregion
#region Constructors
/// <summary>
/// Constructs a <see cref="Track" /> parsing from provided
/// file data.
/// Parsing will be done reading from _file at position references by
/// parent element's data section.
/// </summary>
/// <param name="_file"><see cref="File" /> instance to read from.</param>
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
public Track (File _file, EBMLreader element)
{
ulong i = 0;
while (i < element.DataSize) {
EBMLreader child = new EBMLreader (_file, element.DataOffset + i);
MatroskaID matroska_id = child.ID;
switch (matroska_id) {
case MatroskaID.TrackNumber:
track_number = child.ReadULong ();
break;
case MatroskaID.TrackUID:
_UID = child.ReadULong ();
break;
case MatroskaID.CodecID:
track_codec_id = child.ReadString ();
break;
case MatroskaID.CodecName:
track_codec_name = child.ReadString ();
break;
case MatroskaID.TrackName:
track_name = child.ReadString ();
break;
case MatroskaID.TrackLanguage:
track_language = child.ReadString ();
break;
case MatroskaID.TrackFlagEnabled:
track_enabled = child.ReadBool ();
break;
case MatroskaID.TrackFlagDefault:
track_default = child.ReadBool ();
break;
case MatroskaID.CodecPrivate:
codec_data = child.ReadBytes ();
break;
default:
unknown_elems.Add (child);
break;
}
i += child.Size;
}
}
#endregion
#region Public fields
/// <summary>
/// List of unknown elements encountered while parsing.
/// </summary>
public List<EBMLreader> UnknownElements {
get { return unknown_elems; }
}
#endregion
#region Public methods
#endregion
#region ICodec
/// <summary>
/// Describes track duration.
/// </summary>
public virtual TimeSpan Duration {
get { return TimeSpan.Zero; }
}
/// <summary>
/// Describes track media types.
/// </summary>
public virtual MediaTypes MediaTypes {
get { return MediaTypes.None; }
}
/// <summary>
/// Track description.
/// </summary>
public virtual string Description {
get { return $"{track_codec_name} {track_language}"; }
}
#endregion
#region IUIDElement Boilerplate
/// <summary>
/// Unique ID representing the element, as random as possible (setting zero will generate automatically a new one).
/// </summary>
public ulong UID {
get { return _UID; }
set { _UID = UIDElement.GenUID (value); }
}
ulong _UID = UIDElement.GenUID ();
/// <summary>
/// Get the Tag type the UID should be represented by, or 0 if undefined
/// </summary>
public MatroskaID UIDType { get { return MatroskaID.TagTrackUID; } }
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 25d4925cb4f75c09ead02371134648e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+189
View File
@@ -0,0 +1,189 @@
//
// VideoTrack.cs:
//
// Author:
// Julien Moutte <julien@fluendo.com>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System.Collections.Generic;
namespace TagLib.Matroska
{
/// <summary>
/// Enumeration describing supported Video Aspect Ratio types.
/// </summary>
public enum VideoAspectRatioType
{
/// <summary>
/// Free Aspect Ratio.
/// </summary>
AspectRatioModeFree = 0x0,
/// <summary>
/// Keep Aspect Ratio.
/// </summary>
AspectRatioModeKeep = 0x1,
/// <summary>
/// Fixed Aspect Ratio.
/// </summary>
AspectRatioModeFixed = 0x2
}
/// <summary>
/// Describes a Matroska Video Track.
/// </summary>
public class VideoTrack : Track, IVideoCodec
{
#region Private fields
#pragma warning disable 414 // Assigned, never used
readonly ulong width;
readonly ulong height;
readonly ulong disp_width;
readonly ulong disp_height;
readonly double framerate;
readonly bool interlaced;
readonly VideoAspectRatioType ratio_type;
readonly ByteVector fourcc;
#pragma warning restore 414
readonly List<EBMLreader> unknown_elems = new List<EBMLreader> ();
#endregion
#region Constructors
/// <summary>
/// Constructs a <see cref="VideoTrack" /> parsing from provided
/// file data.
/// Parsing will be done reading from _file at position references by
/// parent element's data section.
/// </summary>
/// <param name="_file"><see cref="File" /> instance to read from.</param>
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
public VideoTrack (File _file, EBMLreader element)
: base (_file, element)
{
// Here we handle the unknown elements we know, and store the rest
foreach (EBMLreader elem in base.UnknownElements) {
var matroska_id = elem.ID;
switch (matroska_id) {
case MatroskaID.TrackVideo: {
ulong i = 0;
while (i < elem.DataSize) {
EBMLreader child = new EBMLreader (_file, elem.DataOffset + i);
matroska_id = child.ID;
switch (matroska_id) {
case MatroskaID.VideoDisplayWidth:
disp_width = child.ReadULong ();
break;
case MatroskaID.VideoDisplayHeight:
disp_height = child.ReadULong ();
break;
case MatroskaID.VideoPixelWidth:
width = child.ReadULong ();
break;
case MatroskaID.VideoPixelHeight:
height = child.ReadULong ();
break;
case MatroskaID.VideoFrameRate:
framerate = child.ReadDouble ();
break;
case MatroskaID.VideoFlagInterlaced:
interlaced = child.ReadBool ();
break;
case MatroskaID.VideoAspectRatioType:
ratio_type = (VideoAspectRatioType)child.ReadULong ();
break;
case MatroskaID.VideoColourSpace:
fourcc = child.ReadBytes ();
break;
default:
unknown_elems.Add (child);
break;
}
i += child.Size;
}
break;
}
case MatroskaID.TrackDefaultDuration:
ulong tmp = elem.ReadULong ();
framerate = 1000000000.0 / tmp;
break;
default:
unknown_elems.Add (elem);
break;
}
}
}
#endregion
#region Public fields
/// <summary>
/// List of unknown elements encountered while parsing.
/// </summary>
public new List<EBMLreader> UnknownElements {
get { return unknown_elems; }
}
#endregion
#region Public methods
#endregion
#region ICodec
/// <summary>
/// This type of track only has video media type.
/// </summary>
public override MediaTypes MediaTypes {
get { return MediaTypes.Video; }
}
#endregion
#region IVideoCodec
/// <summary>
/// Describes video track width in pixels.
/// </summary>
public int VideoWidth {
get { return (int)width; }
}
/// <summary>
/// Describes video track height in pixels.
/// </summary>
public int VideoHeight {
get { return (int)height; }
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e6bf8418b23fcca31a4d61dbe9a8e909
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: