Initial commit
This commit is contained in:
commit
262601edb8
2025 files changed
+218754
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a8e6a8de22731125a98a64d230c668f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,606 @@
|
||||
//
|
||||
// Box.cs: Provides a generic implementation of a ISO/IEC 14496-12 box.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This abstract class provides a generic implementation of a
|
||||
/// ISO/IEC 14496-12 box.
|
||||
/// </summary>
|
||||
public class Box
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box header.
|
||||
/// </summary>
|
||||
BoxHeader header;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the position of the box data.
|
||||
/// </summary>
|
||||
readonly long data_position;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Box" /> with a specified header and handler.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object describing the new
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance, or <see
|
||||
/// langword="null" /> if no handler applies.
|
||||
/// </param>
|
||||
protected Box (BoxHeader header, IsoHandlerBox handler)
|
||||
{
|
||||
this.header = header;
|
||||
data_position = header.Position + header.HeaderSize;
|
||||
Handler = handler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Box" /> with a specified header.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object describing the new
|
||||
/// instance.
|
||||
/// </param>
|
||||
protected Box (BoxHeader header)
|
||||
: this (header, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Box" /> with a specified box type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// type to use for the new instance.
|
||||
/// </param>
|
||||
protected Box (ByteVector type)
|
||||
: this (new BoxHeader (type))
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MPEG-4 box type of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the four
|
||||
/// byte box type of the current instance.
|
||||
/// </value>
|
||||
public virtual ByteVector BoxType {
|
||||
get { return header.BoxType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total size of the current instance as it last
|
||||
/// appeared on disk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the total size of
|
||||
/// the current instance as it last appeared on disk.
|
||||
/// </value>
|
||||
public virtual int Size {
|
||||
get { return (int)header.TotalBoxSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public virtual ByteVector Data {
|
||||
get { return null; }
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public virtual IEnumerable<Box> Children {
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handler box that applies to the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the current instance, or <see
|
||||
/// langword="null" /> if no handler applies.
|
||||
/// </value>
|
||||
public IsoHandlerBox Handler { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance, including its children, to
|
||||
/// a new <see cref="ByteVector" /> object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
return Render (new ByteVector ());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a child box from the current instance by finding
|
||||
/// a matching box type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// type to match.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Box" /> object containing the matched box,
|
||||
/// or <see langword="null" /> if no matching box was found.
|
||||
/// </returns>
|
||||
public Box GetChild (ByteVector type)
|
||||
{
|
||||
if (Children == null)
|
||||
return null;
|
||||
|
||||
foreach (Box box in Children)
|
||||
if (box.BoxType == type)
|
||||
return box;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all child boxes from the current instance by finding
|
||||
/// a matching box type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// type to match.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A List of <see cref="Box" /> objects containing the matched box,
|
||||
/// or <see langword="null" /> if no matching boxes was found.
|
||||
/// </returns>
|
||||
public List<Box> GetChildren (ByteVector type)
|
||||
{
|
||||
if (Children == null)
|
||||
return null;
|
||||
|
||||
List<Box> boxes = new List<Box> ();
|
||||
foreach (Box box in Children)
|
||||
if (box.BoxType == type)
|
||||
boxes.Add (box);
|
||||
|
||||
if (boxes.Count > 0)
|
||||
return boxes;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Gets a child box from the current instance by finding
|
||||
/// a matching object type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.Type" /> object containing the object
|
||||
/// type to match.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Box" /> object containing the matched box,
|
||||
/// or <see langword="null" /> if no matching box was found.
|
||||
/// </returns>
|
||||
public Box GetChild (System.Type type)
|
||||
{
|
||||
if (Children == null)
|
||||
return null;
|
||||
|
||||
foreach (Box box in Children)
|
||||
if (box.GetType () == type)
|
||||
return box;
|
||||
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets a child box from the current instance by finding
|
||||
/// a matching box type, searching recursively.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// type to match.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Box" /> object containing the matched box,
|
||||
/// or <see langword="null" /> if no matching box was found.
|
||||
/// </returns>
|
||||
public Box GetChildRecursively (ByteVector type)
|
||||
{
|
||||
if (Children == null)
|
||||
return null;
|
||||
|
||||
foreach (Box box in Children)
|
||||
if (box.BoxType == type)
|
||||
return box;
|
||||
|
||||
foreach (Box box in Children) {
|
||||
Box child_box = box.GetChildRecursively (type);
|
||||
if (child_box != null)
|
||||
return child_box;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Gets a child box from the current instance by finding
|
||||
/// a matching object type, searching recursively.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.Type" /> object containing the object
|
||||
/// type to match.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Box" /> object containing the matched box,
|
||||
/// or <see langword="null" /> if no matching box was found.
|
||||
/// </returns>
|
||||
public Box GetChildRecursively (System.Type type)
|
||||
{
|
||||
if (Children == null)
|
||||
return null;
|
||||
|
||||
foreach (Box box in Children)
|
||||
if (box.GetType () == type)
|
||||
return box;
|
||||
|
||||
foreach (Box box in Children) {
|
||||
Box child_box = box.GetChildRecursively (type);
|
||||
if (child_box != null)
|
||||
return child_box;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Removes all children with a specified box type from the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// type to remove.
|
||||
/// </param>
|
||||
public void RemoveChild (ByteVector type)
|
||||
{
|
||||
if (!(Children is ICollection<Box> children))
|
||||
return;
|
||||
|
||||
foreach (Box b in new List<Box> (children))
|
||||
if (b.BoxType == type)
|
||||
children.Remove (b);
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Removes all children with a specified box type from the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// type to remove.
|
||||
/// </param>
|
||||
public void RemoveChild (System.Type type)
|
||||
{
|
||||
ICollection<Box> children = Children as ICollection<Box>;
|
||||
|
||||
if (children == null)
|
||||
return;
|
||||
|
||||
foreach (Box b in new List<Box> (children))
|
||||
if (b.GetType () == type)
|
||||
children.Remove (b);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Removes a specified box from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="box">
|
||||
/// A <see cref="Box" /> object to remove from the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
public void RemoveChild (Box box)
|
||||
{
|
||||
if (Children is ICollection<Box> children)
|
||||
children.Remove (box);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a specified box to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="box">
|
||||
/// A <see cref="Box" /> object to add to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
public void AddChild (Box box)
|
||||
{
|
||||
if (Children is ICollection<Box> children)
|
||||
children.Add (box);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all children from the current instance.
|
||||
/// </summary>
|
||||
public void ClearChildren ()
|
||||
{
|
||||
if (Children is ICollection<Box> children)
|
||||
children.Clear ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current instance has children.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// current instance has any children.
|
||||
/// </value>
|
||||
public bool HasChildren {
|
||||
get {
|
||||
return Children is ICollection<Box> children && children.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the data contained in the current
|
||||
/// instance, minux the size of any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the size of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected int DataSize {
|
||||
get {
|
||||
return (int)(header.DataSize + data_position -
|
||||
DataPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of the data contained in the current
|
||||
/// instance, after any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected virtual long DataPosition {
|
||||
get { return data_position; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the header of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// of the current instance.
|
||||
/// </value>
|
||||
protected BoxHeader Header {
|
||||
get { return header; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Loads the children of the current instance from a
|
||||
/// specified file using the internal data position and size.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// The <see cref="TagLib.File" /> from which the current
|
||||
/// instance was read and from which to read the children.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// boxes read from the file.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
protected IEnumerable<Box> LoadChildren (TagLib.File file)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
var children = new List<Box> ();
|
||||
|
||||
long position = DataPosition;
|
||||
long end = position + DataSize;
|
||||
|
||||
header.Box = this;
|
||||
while (position < end) {
|
||||
Box child = BoxFactory.CreateBox (file, position, header, Handler, children.Count);
|
||||
if (child.Size == 0)
|
||||
break;
|
||||
|
||||
children.Add (child);
|
||||
position += child.Size;
|
||||
}
|
||||
header.Box = null;
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data of the current instance from a specified
|
||||
/// file using the internal data position and size.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// The <see cref="TagLib.File" /> from which the current
|
||||
/// instance was read and from which to read the data.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// read from the file.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
protected ByteVector LoadData (TagLib.File file)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
file.Seek (DataPosition);
|
||||
return file.ReadBlock (DataSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance, including its children, to
|
||||
/// a new <see cref="ByteVector" /> object, preceeding the
|
||||
/// contents with a specified block of data.
|
||||
/// </summary>
|
||||
/// <param name="topData">
|
||||
/// A <see cref="ByteVector" /> object containing box
|
||||
/// specific header data to preceed the content.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
protected virtual ByteVector Render (ByteVector topData)
|
||||
{
|
||||
bool free_found = false;
|
||||
var output = new ByteVector ();
|
||||
|
||||
if (Children != null)
|
||||
foreach (Box box in Children)
|
||||
if (box.GetType () == typeof (
|
||||
IsoFreeSpaceBox))
|
||||
free_found = true;
|
||||
else
|
||||
output.Add (box.Render ());
|
||||
else if (Data != null)
|
||||
output.Add (Data);
|
||||
|
||||
// If there was a free, don't take it away, and let meta
|
||||
// be a special case.
|
||||
if (free_found || BoxType == Mpeg4.BoxType.Meta) {
|
||||
long size_difference = DataSize - output.Count;
|
||||
|
||||
// If we have room for free space, add it so we
|
||||
// don't have to resize the file.
|
||||
if (header.DataSize != 0 && size_difference >= 8)
|
||||
output.Add ((new IsoFreeSpaceBox (size_difference)).Render ());
|
||||
|
||||
// If we're getting bigger, get a lot bigger so
|
||||
// we might not have to again.
|
||||
else
|
||||
output.Add ((new IsoFreeSpaceBox (2048)).Render ());
|
||||
}
|
||||
|
||||
// Adjust the header's data size to match the content.
|
||||
header.DataSize = topData.Count + output.Count;
|
||||
|
||||
// Render the full box.
|
||||
output.Insert (0, topData);
|
||||
output.Insert (0, header.Render ());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/*
|
||||
#region Internal Methods
|
||||
|
||||
/// <summary>
|
||||
/// Dumps the child tree of the current instance to the
|
||||
/// console.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="string" /> object to preface each line with.
|
||||
/// </param>
|
||||
internal void DumpTree (string start)
|
||||
{
|
||||
if (BoxType == BoxType.Data)
|
||||
Console.WriteLine ("{0}{1} {2}", start,
|
||||
BoxType.ToString (),
|
||||
(this as AppleDataBox).Text);
|
||||
else
|
||||
Console.WriteLine ("{0}{1}", start,
|
||||
BoxType.ToString ());
|
||||
|
||||
if (Children != null)
|
||||
foreach (Box child in Children)
|
||||
child.DumpTree (start + " ");
|
||||
}
|
||||
|
||||
#endregion
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94cea67188e625da6aff7fd2abdce53e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,251 @@
|
||||
//
|
||||
// BoxFactory.cs: Provides support for reading boxes from a file.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This static class provides support for reading boxes from a file.
|
||||
/// </summary>
|
||||
public static class BoxFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a box by reading it from a file given its header,
|
||||
/// parent header, handler, and index in its parent.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object containing the file
|
||||
/// to read from.
|
||||
/// </param>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// of the box to create.
|
||||
/// </param>
|
||||
/// <param name="parent">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// of the parent box.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new box.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// A <see cref="int" /> value containing the index of the
|
||||
/// new box in its parent.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A newly created <see cref="Box" /> object.
|
||||
/// </returns>
|
||||
static Box CreateBox (TagLib.File file,
|
||||
BoxHeader header,
|
||||
BoxHeader parent,
|
||||
IsoHandlerBox handler,
|
||||
int index)
|
||||
{
|
||||
// The first few children of an "stsd" are sample
|
||||
// entries.
|
||||
if (parent.BoxType == BoxType.Stsd &&
|
||||
parent.Box is IsoSampleDescriptionBox &&
|
||||
index < (parent.Box as IsoSampleDescriptionBox).EntryCount) {
|
||||
if (handler != null && handler.HandlerType == BoxType.Soun)
|
||||
return new IsoAudioSampleEntry (header, file, handler);
|
||||
|
||||
if (handler != null && handler.HandlerType == BoxType.Vide)
|
||||
return new IsoVisualSampleEntry (header, file, handler);
|
||||
|
||||
if (handler != null && handler.HandlerType == BoxType.Alis) {
|
||||
if (header.BoxType == BoxType.Text)
|
||||
return new TextBox (header, file, handler);
|
||||
|
||||
if (header.BoxType == BoxType.Url)
|
||||
return new UrlBox (header, file, handler);
|
||||
// This could be anything, so just parse it
|
||||
return new UnknownBox (header, file, handler);
|
||||
}
|
||||
|
||||
return new IsoSampleEntry (header, file, handler);
|
||||
}
|
||||
|
||||
// Standard items...
|
||||
ByteVector type = header.BoxType;
|
||||
|
||||
if (type == BoxType.Mvhd)
|
||||
return new IsoMovieHeaderBox (header, file, handler);
|
||||
else if (type == BoxType.Stbl)
|
||||
return new IsoSampleTableBox (header, file, handler);
|
||||
else if (type == BoxType.Stsd)
|
||||
return new IsoSampleDescriptionBox (header, file, handler);
|
||||
else if (type == BoxType.Stco)
|
||||
return new IsoChunkOffsetBox (header, file, handler);
|
||||
else if (type == BoxType.Co64)
|
||||
return new IsoChunkLargeOffsetBox (header, file, handler);
|
||||
else if (type == BoxType.Hdlr)
|
||||
return new IsoHandlerBox (header, file, handler);
|
||||
else if (type == BoxType.Udta)
|
||||
return new IsoUserDataBox (header, file, handler);
|
||||
else if (type == BoxType.Meta)
|
||||
return new IsoMetaBox (header, file, handler);
|
||||
else if (type == BoxType.Ilst)
|
||||
return new AppleItemListBox (header, file, handler);
|
||||
else if (type == BoxType.Data)
|
||||
return new AppleDataBox (header, file, handler);
|
||||
else if (type == BoxType.Esds)
|
||||
return new AppleElementaryStreamDescriptor (header, file, handler);
|
||||
else if (type == BoxType.Free || type == BoxType.Skip)
|
||||
return new IsoFreeSpaceBox (header, file, handler);
|
||||
else if (type == BoxType.Mean || type == BoxType.Name)
|
||||
return new AppleAdditionalInfoBox (header, file, handler);
|
||||
|
||||
// If we still don't have a tag, and we're inside an
|
||||
// ItemListBox, load the box as an AnnotationBox
|
||||
// (Apple tag item).
|
||||
if (parent.BoxType == BoxType.Ilst)
|
||||
return new AppleAnnotationBox (header, file, handler);
|
||||
|
||||
// Nothing good. Go generic.
|
||||
return new UnknownBox (header, file, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a box by reading it from a file given its
|
||||
/// position in the file, parent header, handler, and index
|
||||
/// in its parent.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object containing the file
|
||||
/// to read from.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifying at what seek
|
||||
/// position in <paramref name="file" /> to start reading.
|
||||
/// </param>
|
||||
/// <param name="parent">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// of the parent box.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new box.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// A <see cref="int" /> value containing the index of the
|
||||
/// new box in its parent.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A newly created <see cref="Box" /> object.
|
||||
/// </returns>
|
||||
internal static Box CreateBox (TagLib.File file, long position, BoxHeader parent, IsoHandlerBox handler, int index)
|
||||
{
|
||||
BoxHeader header = new BoxHeader (file, position);
|
||||
return CreateBox (file, header, parent, handler, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a box by reading it from a file given its
|
||||
/// position in the file and handler.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object containing the file
|
||||
/// to read from.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifying at what seek
|
||||
/// position in <paramref name="file" /> to start reading.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new box.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A newly created <see cref="Box" /> object.
|
||||
/// </returns>
|
||||
public static Box CreateBox (TagLib.File file, long position, IsoHandlerBox handler)
|
||||
{
|
||||
return CreateBox (file, position, BoxHeader.Empty, handler, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a box by reading it from a file given its
|
||||
/// position in the file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object containing the file
|
||||
/// to read from.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifying at what seek
|
||||
/// position in <paramref name="file" /> to start reading.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A newly created <see cref="Box" /> object.
|
||||
/// </returns>
|
||||
public static Box CreateBox (TagLib.File file, long position)
|
||||
{
|
||||
return CreateBox (file, position, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a box by reading it from a file given its header
|
||||
/// and handler.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object containing the file
|
||||
/// to read from.
|
||||
/// </param>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// of the box to create.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new box.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A newly created <see cref="Box" /> object.
|
||||
/// </returns>
|
||||
public static Box CreateBox (TagLib.File file, BoxHeader header, IsoHandlerBox handler)
|
||||
{
|
||||
return CreateBox (file, header, BoxHeader.Empty,
|
||||
handler, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a box by reading it from a file given its header
|
||||
/// and handler.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object containing the file
|
||||
/// to read from.
|
||||
/// </param>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// of the box to create.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A newly created <see cref="Box" /> object.
|
||||
/// </returns>
|
||||
public static Box CreateBox (TagLib.File file, BoxHeader header)
|
||||
{
|
||||
return CreateBox (file, header, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7591bce13aac7742e9d3c970f3557929
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,402 @@
|
||||
//
|
||||
// BoxHeader.cs: Provides support for reading and writing headers for ISO/IEC
|
||||
// 14496-12 boxes.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This structure provides support for reading and writing headers
|
||||
/// for ISO/IEC 14496-12 boxes.
|
||||
/// </summary>
|
||||
public struct BoxHeader
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box size.
|
||||
/// </summary>
|
||||
ulong box_size;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the header size.
|
||||
/// </summary>
|
||||
uint header_size;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the position of the header.
|
||||
/// </summary>
|
||||
readonly long position;
|
||||
|
||||
/// <summary>
|
||||
/// Indicated that the header was read from a file.
|
||||
/// </summary>
|
||||
readonly bool from_disk;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// An empty box header.
|
||||
/// </summary>
|
||||
public static readonly BoxHeader Empty = new BoxHeader ("xxxx");
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="BoxHeader" /> by reading it from a specified seek
|
||||
/// position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the new
|
||||
/// instance from.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifiying the seek position
|
||||
/// in <paramref name="file" /> at which to start reading.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// There isn't enough data in the file to read the complete
|
||||
/// header.
|
||||
/// </exception>
|
||||
public BoxHeader (TagLib.File file, long position)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
Box = null;
|
||||
from_disk = true;
|
||||
this.position = position;
|
||||
file.Seek (position);
|
||||
|
||||
ByteVector data = file.ReadBlock (32);
|
||||
int offset = 0;
|
||||
|
||||
if (data.Count < 8 + offset)
|
||||
throw new CorruptFileException ("Not enough data in box header.");
|
||||
|
||||
header_size = 8;
|
||||
box_size = data.Mid (offset, 4).ToUInt ();
|
||||
BoxType = data.Mid (offset + 4, 4);
|
||||
|
||||
// If the size is 1, that just tells us we have a
|
||||
// massive ULONG size waiting for us in the next 8
|
||||
// bytes.
|
||||
if (box_size == 1) {
|
||||
if (data.Count < 8 + offset)
|
||||
throw new CorruptFileException ("Not enough data in box header.");
|
||||
|
||||
header_size += 8;
|
||||
offset += 8;
|
||||
box_size = data.Mid (offset, 8).ToULong ();
|
||||
}
|
||||
|
||||
// UUID has a special header with 16 extra bytes.
|
||||
if (BoxType == Mpeg4.BoxType.Uuid) {
|
||||
if (data.Count < 16 + offset)
|
||||
throw new CorruptFileException ("Not enough data in box header.");
|
||||
|
||||
header_size += 16;
|
||||
ExtendedType = data.Mid (offset, 16);
|
||||
} else
|
||||
ExtendedType = null;
|
||||
|
||||
if (box_size > (ulong)(file.Length - position)) {
|
||||
throw new CorruptFileException (
|
||||
$"Box header specified a size of {box_size} bytes but only {file.Length - position} bytes left in the file");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="BoxHeader" /> with a specified box type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the four
|
||||
/// byte box type.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// <see cref="BoxHeader(ByteVector,ByteVector)" /> must be
|
||||
/// used to create a header of type "<c>uuid</c>".
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="type" /> is <see langword="null" /> or is
|
||||
/// equal to "<c>uuid</c>".
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="type" /> isn't exactly 4 bytes long.
|
||||
/// </exception>
|
||||
public BoxHeader (ByteVector type) : this (type, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="BoxHeader" /> with a specified box type and
|
||||
/// optionally extended type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the four
|
||||
/// byte box type.
|
||||
/// </param>
|
||||
/// <param name="extendedType">
|
||||
/// A <see cref="ByteVector" /> object containing the four
|
||||
/// byte box type.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="type" /> is <see langword="null" /> - or -
|
||||
/// <paramref name="type" /> is equal to "<c>uuid</c>" and
|
||||
/// <paramref name="extendedType" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="type" /> isn't exactly 4 bytes long - or
|
||||
/// - <paramref name="type" /> isn't "<c>uuid</c>" but
|
||||
/// <paramref name="extendedType" /> isn't <see
|
||||
/// langword="null" /> - or - paramref name="type" /> is
|
||||
/// "<c>uuid</c>" but <paramref name="extendedType" /> isn't
|
||||
/// exactly 16 bytes long.
|
||||
/// </exception>
|
||||
public BoxHeader (ByteVector type, ByteVector extendedType)
|
||||
{
|
||||
position = -1;
|
||||
Box = null;
|
||||
from_disk = false;
|
||||
BoxType = type;
|
||||
|
||||
if (type == null)
|
||||
throw new ArgumentNullException (nameof (type));
|
||||
|
||||
if (type.Count != 4)
|
||||
throw new ArgumentException ("Box type must be 4 bytes in length.", nameof (type));
|
||||
|
||||
box_size = header_size = 8;
|
||||
|
||||
if (type != "uuid") {
|
||||
if (extendedType != null)
|
||||
throw new ArgumentException ("Extended type only permitted for 'uuid'.", nameof (extendedType));
|
||||
|
||||
ExtendedType = extendedType;
|
||||
return;
|
||||
}
|
||||
|
||||
if (extendedType == null)
|
||||
throw new ArgumentNullException (nameof (extendedType));
|
||||
|
||||
if (extendedType.Count != 16)
|
||||
throw new ArgumentException (
|
||||
"Extended type must be 16 bytes in length.",
|
||||
nameof (extendedType));
|
||||
|
||||
box_size = header_size = 24;
|
||||
ExtendedType = extendedType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of box represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the 4 byte
|
||||
/// box type.
|
||||
/// </value>
|
||||
public ByteVector BoxType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the extended type of the box represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the 16 byte
|
||||
/// extended type, or <see langword="null" /> if <see
|
||||
/// cref="BoxType" /> is not "<c>uuid</c>".
|
||||
/// </value>
|
||||
public ByteVector ExtendedType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the header represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the size of the
|
||||
/// header represented by the current instance.
|
||||
/// </value>
|
||||
public long HeaderSize {
|
||||
get { return header_size; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the size of the data in the box described
|
||||
/// by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the size of the
|
||||
/// data in the box described by the current instance.
|
||||
/// </value>
|
||||
public long DataSize {
|
||||
get { return (long)(box_size - header_size); }
|
||||
set { box_size = (ulong)value + header_size; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the offset of the box data from the position of the
|
||||
/// header.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the offset of the
|
||||
/// box data from the position of the header.
|
||||
/// </value>
|
||||
[Obsolete ("Use HeaderSize")]
|
||||
public long DataOffset {
|
||||
get { return header_size; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total size of the box described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the total size of
|
||||
/// the box described by the current instance.
|
||||
/// </value>
|
||||
public long TotalBoxSize {
|
||||
get { return (long)box_size; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position box represented by the current instance
|
||||
/// in the file it comes from.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position box
|
||||
/// represented by the current instance in the file it comes
|
||||
/// from.
|
||||
/// </value>
|
||||
public long Position {
|
||||
get { return from_disk ? position : -1; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Overwrites the header on disk, updating it to include a
|
||||
/// change in the size of the box.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object containing the file
|
||||
/// from which the box originates.
|
||||
/// </param>
|
||||
/// <param name="sizeChange">
|
||||
/// A <see cref="long" /> value indicating the change in the
|
||||
/// size of the box described by the current instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The size change encountered by the box that parents the
|
||||
/// box described the the current instance, equal to the
|
||||
/// size change of the box plus any size change that should
|
||||
/// happen in the header.
|
||||
/// </returns>
|
||||
public long Overwrite (TagLib.File file, long sizeChange)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
if (!from_disk)
|
||||
throw new InvalidOperationException ("Cannot overwrite headers not on disk.");
|
||||
|
||||
long old_header_size = HeaderSize;
|
||||
DataSize += sizeChange;
|
||||
file.Insert (Render (), position, old_header_size);
|
||||
return sizeChange + HeaderSize - old_header_size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the header represented by the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
// Enlarge for size if necessary.
|
||||
if ((header_size == 8 || header_size == 24) && box_size > uint.MaxValue) {
|
||||
header_size += 8;
|
||||
box_size += 8;
|
||||
}
|
||||
|
||||
// Add the box size and type to the output.
|
||||
ByteVector output = ByteVector.FromUInt (
|
||||
(header_size == 8 || header_size == 24) ?
|
||||
(uint)box_size : 1);
|
||||
output.Add (BoxType);
|
||||
|
||||
// If the box size is 16 or 32, we must have more a
|
||||
// large header to append.
|
||||
if (header_size == 16 || header_size == 32)
|
||||
output.Add (ByteVector.FromULong (box_size));
|
||||
|
||||
// The only reason for such a big size is an extended
|
||||
// type. Extend!!!
|
||||
if (header_size >= 24)
|
||||
output.Add (ExtendedType);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the box represented by the current instance
|
||||
/// as a means of temporary storage for internal uses.
|
||||
/// </summary>
|
||||
internal Box Box { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b97e0d4d07d086e4ea9bef8a36f38e08
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// BoxTypes.cs: Contains common box names.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="BoxType" /> provides references to different box types
|
||||
/// used by the library.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>This class is used to severely reduce the number of times
|
||||
/// these types are created in <see cref="AppleTag" />, greatly
|
||||
/// improving the speed at which warm files are read.</para>
|
||||
/// <para>The reason it is marked as internal is because I'm not sure
|
||||
/// I like the way the fields are named, and it is really
|
||||
/// unneccessary for external uses. While the library may use
|
||||
/// <c>DataBoxes (BoxType.Gen, BoxType.Gnre);</c>, an external user
|
||||
/// could use <c>tag.DataBoxes ("gen", "gnre");</c> with the same
|
||||
/// result.</para>
|
||||
/// <see url="https://picard.musicbrainz.org/docs/mappings/"/>
|
||||
/// </remarks>
|
||||
static class BoxType
|
||||
{
|
||||
public static readonly ReadOnlyByteVector Aart = "aART";
|
||||
public static readonly ReadOnlyByteVector Alb = AppleTag.FixId ("alb");
|
||||
public static readonly ReadOnlyByteVector Art = AppleTag.FixId ("ART");
|
||||
public static readonly ReadOnlyByteVector Cmt = AppleTag.FixId ("cmt");
|
||||
public static readonly ReadOnlyByteVector Cond = "cond";
|
||||
public static readonly ReadOnlyByteVector Covr = "covr";
|
||||
public static readonly ReadOnlyByteVector Co64 = "co64";
|
||||
public static readonly ReadOnlyByteVector Cpil = "cpil";
|
||||
public static readonly ReadOnlyByteVector Cprt = "cprt";
|
||||
public static readonly ReadOnlyByteVector Data = "data";
|
||||
public static readonly ReadOnlyByteVector Day = AppleTag.FixId ("day");
|
||||
public static readonly ReadOnlyByteVector Desc = "desc";
|
||||
public static readonly ReadOnlyByteVector Disk = "disk";
|
||||
public static readonly ReadOnlyByteVector Dtag = "dtag";
|
||||
public static readonly ReadOnlyByteVector Esds = "esds";
|
||||
public static readonly ReadOnlyByteVector Ilst = "ilst";
|
||||
public static readonly ReadOnlyByteVector Free = "free";
|
||||
public static readonly ReadOnlyByteVector Gen = AppleTag.FixId ("gen");
|
||||
public static readonly ReadOnlyByteVector Gnre = "gnre";
|
||||
public static readonly ReadOnlyByteVector Grp = AppleTag.FixId ("grp");
|
||||
public static readonly ReadOnlyByteVector Hdlr = "hdlr";
|
||||
public static readonly ReadOnlyByteVector Lyr = AppleTag.FixId ("lyr");
|
||||
public static readonly ReadOnlyByteVector Mdat = "mdat";
|
||||
public static readonly ReadOnlyByteVector Mdia = "mdia";
|
||||
public static readonly ReadOnlyByteVector Meta = "meta";
|
||||
public static readonly ReadOnlyByteVector Mean = "mean";
|
||||
public static readonly ReadOnlyByteVector Minf = "minf";
|
||||
public static readonly ReadOnlyByteVector Moov = "moov";
|
||||
public static readonly ReadOnlyByteVector Mvhd = "mvhd";
|
||||
public static readonly ReadOnlyByteVector Nam = AppleTag.FixId ("nam");
|
||||
public static readonly ReadOnlyByteVector Name = "name";
|
||||
public static readonly ReadOnlyByteVector Role = "role";
|
||||
public static readonly ReadOnlyByteVector Skip = "skip";
|
||||
public static readonly ReadOnlyByteVector Soaa = "soaa"; // Album Artist Sort
|
||||
public static readonly ReadOnlyByteVector Soar = "soar"; // Performer Sort
|
||||
public static readonly ReadOnlyByteVector Soco = "soco"; // Composer Sort
|
||||
public static readonly ReadOnlyByteVector Sonm = "sonm"; // Track Title Sort
|
||||
public static readonly ReadOnlyByteVector Soal = "soal"; // Album Title Sort
|
||||
public static readonly ReadOnlyByteVector Stbl = "stbl";
|
||||
public static readonly ReadOnlyByteVector Stco = "stco";
|
||||
public static readonly ReadOnlyByteVector Stsd = "stsd";
|
||||
public static readonly ReadOnlyByteVector Subt = "Subt";
|
||||
public static readonly ReadOnlyByteVector Text = "text";
|
||||
public static readonly ReadOnlyByteVector Tmpo = "tmpo";
|
||||
public static readonly ReadOnlyByteVector Trak = "trak";
|
||||
public static readonly ReadOnlyByteVector Trkn = "trkn";
|
||||
public static readonly ReadOnlyByteVector Udta = "udta";
|
||||
public static readonly ReadOnlyByteVector Url = AppleTag.FixId ("url");
|
||||
public static readonly ReadOnlyByteVector Uuid = "uuid";
|
||||
public static readonly ReadOnlyByteVector Wrt = AppleTag.FixId ("wrt");
|
||||
public static readonly ReadOnlyByteVector DASH = "----";
|
||||
|
||||
// Handler types.
|
||||
public static readonly ReadOnlyByteVector Soun = "soun";
|
||||
public static readonly ReadOnlyByteVector Vide = "vide";
|
||||
|
||||
// Another handler type, found in wild in audio file ripped using iTunes
|
||||
public static readonly ReadOnlyByteVector Alis = "alis";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: adcf753dd486a5dd18b8630838fa4e14
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3d7613a8f16e0d90b1b09f05ae96ba1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// AppleAdditionalInfoBox.cs: Provides an implementation of an Apple
|
||||
// AdditionalInfoBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of an Apple AdditionalInfoBox.
|
||||
/// </summary>
|
||||
public class AppleAdditionalInfoBox : FullBox
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box data.
|
||||
/// </summary>
|
||||
ByteVector data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleAdditionalInfoBox" /> with a provided header
|
||||
/// and handler by reading the contents from a specified
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public AppleAdditionalInfoBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
// We do not care what is in this custom data section
|
||||
// see: https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html
|
||||
Data = file.ReadBlock (DataSize > 0 ? DataSize : 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleAdditionalInfoBox" /> using specified header, version and flags
|
||||
/// </summary>
|
||||
/// <param name="header">defines the header data</param>
|
||||
/// <param name="version"></param>
|
||||
/// <param name="flags"></param>
|
||||
public AppleAdditionalInfoBox (ByteVector header, byte version, uint flags) : base (header, version, flags)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get { return data; }
|
||||
set { data = value ?? new ByteVector (); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the text contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the text
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public string Text {
|
||||
get { return Data.ToString (StringType.Latin1).TrimStart ('\0'); }
|
||||
set { Data = ByteVector.FromString (value, StringType.Latin1); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25ff95a004e56b4e79c632e60c49ec0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// AppleAnnotationBox.cs: Provides an implementation of an Apple AnnotationBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide an
|
||||
/// implementation of an Apple AnnotationBox.
|
||||
/// </summary>
|
||||
public class AppleAnnotationBox : Box
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleAnnotationBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public AppleAnnotationBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
Children = LoadChildren (file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleAnnotationBox" /> of specified type with no
|
||||
/// children.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing a 4-byte
|
||||
/// box type.
|
||||
/// </param>
|
||||
public AppleAnnotationBox (ByteVector type)
|
||||
: base (type)
|
||||
{
|
||||
Children = new List<Box> ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override IEnumerable<Box> Children { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e048a50f4a5ab35bb7cc862e7f30529
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,212 @@
|
||||
//
|
||||
// AppleDataBox.cs: Provides an implementation of an Apple DataBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of an Apple DataBox.
|
||||
/// </summary>
|
||||
public class AppleDataBox : FullBox
|
||||
{
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the type of data contained in a box.
|
||||
/// </summary>
|
||||
public enum FlagType
|
||||
{
|
||||
/// <summary>
|
||||
/// The box contains UTF-8 text.
|
||||
/// </summary>
|
||||
ContainsText = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// The box contains binary data.
|
||||
/// </summary>
|
||||
ContainsData = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// The box contains data for a tempo box.
|
||||
/// </summary>
|
||||
ForTempo = 0x15,
|
||||
|
||||
/// <summary>
|
||||
/// The box contains a raw JPEG image.
|
||||
/// </summary>
|
||||
ContainsJpegData = 0x0D,
|
||||
|
||||
/// <summary>
|
||||
/// The box contains a raw PNG image.
|
||||
/// </summary>
|
||||
ContainsPngData = 0x0E,
|
||||
|
||||
/// <summary>
|
||||
/// The box contains a raw BMP image.
|
||||
/// </summary>
|
||||
ContainsBmpData = 0x1B
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box data.
|
||||
/// </summary>
|
||||
ByteVector data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleDataBox" /> with a provided header and handler
|
||||
/// by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public AppleDataBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
Data = LoadData (file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleDataBox" /> with specified data and flags.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the data to
|
||||
/// store in the new instance.
|
||||
/// </param>
|
||||
/// <param name="flags">
|
||||
/// A <see cref="uint" /> value containing flags to use for
|
||||
/// the new instance.
|
||||
/// </param>
|
||||
public AppleDataBox (ByteVector data, uint flags)
|
||||
: base ("data", 0, flags)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of the data contained in the current
|
||||
/// instance, after any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected override long DataPosition {
|
||||
get { return base.DataPosition + 4; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get { return data; }
|
||||
set { data = value ?? new ByteVector (); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the text contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the text
|
||||
/// contained in the current instance, or <see
|
||||
/// langword="null" /> if the box is not flagged as
|
||||
/// containing text.
|
||||
/// </value>
|
||||
public string Text {
|
||||
get {
|
||||
return ((Flags & (int)FlagType.ContainsText) != 0) ? Data.ToString (StringType.UTF8) : null;
|
||||
}
|
||||
set {
|
||||
Flags = (int)FlagType.ContainsText;
|
||||
Data = ByteVector.FromString (value, StringType.UTF8);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance, including its children, to
|
||||
/// a new <see cref="ByteVector" /> object, preceeding the
|
||||
/// contents with a specified block of data.
|
||||
/// </summary>
|
||||
/// <param name="topData">
|
||||
/// A <see cref="ByteVector" /> object containing box
|
||||
/// specific header data to preceed the content.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
protected override ByteVector Render (ByteVector topData)
|
||||
{
|
||||
var output = new ByteVector (4) {
|
||||
topData
|
||||
};
|
||||
return base.Render (output);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b2e8b5da62b154548412a411227a170
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,435 @@
|
||||
//
|
||||
// AppleElementaryStreamDescriptor.cs: Provides an implementation of an Apple
|
||||
// ItemListBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
// RBoy1
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of an Apple ElementaryStreamDescriptor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This box may appear as a child of a <see
|
||||
/// cref="IsoAudioSampleEntry" /> and provided further information
|
||||
/// about an audio stream.
|
||||
/// </remarks>
|
||||
public class AppleElementaryStreamDescriptor : FullBox
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Descriptor Tags
|
||||
/// </summary>
|
||||
enum DescriptorTag
|
||||
{
|
||||
Forbidden_00 = 0,
|
||||
ObjectDescrTag = 1,
|
||||
InitialObjectDescrTag = 2,
|
||||
ES_DescrTag = 3,
|
||||
DecoderConfigDescrTag = 4,
|
||||
DecSpecificInfoTag = 5,
|
||||
SLConfigDescrTag = 6,
|
||||
ContentIdentDescrTag = 7,
|
||||
SupplContentIdentDescrTag = 8,
|
||||
IPI_DescrPointerTag = 9,
|
||||
IPMP_DescrPointerTag = 10,
|
||||
IPMP_DescrTag = 11,
|
||||
QoS_DescrTag = 12,
|
||||
RegistrationDescrTag = 13,
|
||||
ES_ID_IncTag = 14,
|
||||
ES_ID_RefTag = 15,
|
||||
MP4_IOD_Tag = 16,
|
||||
MP4_OD_Tag = 17,
|
||||
IPL_DescrPointerRefTag = 18,
|
||||
ExtensionProfileLevelDescrTag = 19,
|
||||
profileLevelIndicationIndexDescrTag = 20,
|
||||
ReservedForFutureISOUse_15_TO_3F = 21,
|
||||
ContentClassificationDescrTag = 64,
|
||||
KeyWordDescrTag = 65,
|
||||
RatingDescrTag = 66,
|
||||
LanguageDescrTag = 67,
|
||||
ShortTextualDescrTag = 68,
|
||||
ExpandedTextualDescrTag = 69,
|
||||
ContentCreatorNameDescrTag = 70,
|
||||
ContentCreationDateDescrTag = 71,
|
||||
OCICreatorNameDescrTag = 72,
|
||||
OCICreationDateDescrTag = 73,
|
||||
SmpteCameraPositionDescrTag = 74,
|
||||
SegmentDescrTag = 75,
|
||||
MediaTimeDescrTag = 76,
|
||||
ReservedForFutureISOUseOCI = 77,
|
||||
IPMP_ToolsListDescrTag = 96,
|
||||
IPMP_ToolTag = 97,
|
||||
M4MuxTimingDescrTag = 98,
|
||||
M4MuxCodeTableDescrTag = 99,
|
||||
ExtSLConfigDescrTag = 100,
|
||||
M4MuxBufferSizeDescrTag = 101,
|
||||
M4MuxIdentDescrTag = 102,
|
||||
DependencyPointerTag = 103,
|
||||
DependencyMarkerTag = 104,
|
||||
M4MuxChannelDescrTag = 105,
|
||||
ReservedForFutureISO_6A_TO_BF = 106,
|
||||
UserPrivate = 192,
|
||||
Forbidden_FF = 255,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the ES_ID of another elementary stream on which this elementary stream depends
|
||||
/// </summary>
|
||||
ushort dependsOn_ES_ID;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a dependsOn_ES_ID will follow
|
||||
/// </summary>
|
||||
readonly bool stream_dependence_flag;
|
||||
|
||||
/// <summary>
|
||||
/// OCR Stream Flag
|
||||
/// </summary>
|
||||
readonly bool ocr_stream_flag;
|
||||
|
||||
/// <summary>
|
||||
/// OCR ES_ID
|
||||
/// </summary>
|
||||
ushort OCR_ES_Id;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a URLstring will follow
|
||||
/// </summary>
|
||||
readonly bool URL_flag;
|
||||
|
||||
/// <summary>
|
||||
/// Length of URL String
|
||||
/// </summary>
|
||||
readonly byte URLlength;
|
||||
|
||||
/// <summary>
|
||||
/// URL String of URLlength, contains a URL that shall point to the location of an SL-packetized stream by name
|
||||
/// </summary>
|
||||
string URLstring;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that this stream is used for upstream information
|
||||
/// </summary>
|
||||
bool upStream;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the maximum bitrate.
|
||||
/// </summary>
|
||||
readonly uint max_bitrate;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the average bitrate.
|
||||
/// </summary>
|
||||
readonly uint average_bitrate;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleElementaryStreamDescriptor" /> with a provided
|
||||
/// header and handler by reading the contents from a
|
||||
/// specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// Valid data could not be read.
|
||||
/// </exception>
|
||||
public AppleElementaryStreamDescriptor (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
/* ES_Descriptor Specifications
|
||||
* Section 7.2.6.5 http://ecee.colorado.edu/~ecen5653/ecen5653/papers/ISO%2014496-1%202004.PDF
|
||||
*/
|
||||
|
||||
ByteVector box_data = file.ReadBlock (DataSize);
|
||||
DecoderConfig = new ByteVector ();
|
||||
int offset = 0;
|
||||
|
||||
// Elementary Stream Descriptor Tag
|
||||
if ((DescriptorTag)box_data[offset++] != DescriptorTag.ES_DescrTag)
|
||||
throw new CorruptFileException ("Invalid Elementary Stream Descriptor, missing tag.");
|
||||
|
||||
// We have a descriptor tag. Check that the remainder of the tag is at least [Base (3 bytes) + DecoderConfigDescriptor (15 bytes) + SLConfigDescriptor (3 bytes) + OtherDescriptors] bytes long
|
||||
uint es_length = ReadLength (box_data, ref offset);
|
||||
uint min_es_length = 3 + 15 + 3; // Base minimum length
|
||||
if (es_length < min_es_length)
|
||||
throw new CorruptFileException ("Insufficient data present.");
|
||||
|
||||
StreamId = box_data.Mid (offset, 2).ToUShort ();
|
||||
offset += 2; // Done with ES_ID
|
||||
|
||||
stream_dependence_flag = ((byte)((box_data[offset] >> 7) & 0x1) == 0x1 ? true : false); // 1st bit
|
||||
URL_flag = ((byte)((box_data[offset] >> 6) & 0x1) == 0x1 ? true : false); // 2nd bit
|
||||
ocr_stream_flag = ((byte)((box_data[offset] >> 5) & 0x1) == 0x1 ? true : false); // 3rd bit
|
||||
StreamPriority = (byte)(box_data[offset++] & 0x1F); // Last 5 bits and we're done with this byte
|
||||
|
||||
if (stream_dependence_flag) {
|
||||
min_es_length += 2; // We need 2 more bytes
|
||||
if (es_length < min_es_length)
|
||||
throw new CorruptFileException ("Insufficient data present.");
|
||||
|
||||
dependsOn_ES_ID = box_data.Mid (offset, 2).ToUShort ();
|
||||
offset += 2; // Done with stream dependence
|
||||
}
|
||||
|
||||
if (URL_flag) {
|
||||
min_es_length += 2; // We need 1 more byte
|
||||
if (es_length < min_es_length)
|
||||
throw new CorruptFileException ("Insufficient data present.");
|
||||
|
||||
URLlength = box_data[offset++]; // URL Length
|
||||
min_es_length += URLlength; // We need URLength more bytes
|
||||
if (es_length < min_es_length)
|
||||
throw new CorruptFileException ("Insufficient data present.");
|
||||
|
||||
URLstring = box_data.Mid (offset, URLlength).ToString (); // URL name
|
||||
offset += URLlength; // Done with URL name
|
||||
}
|
||||
|
||||
if (ocr_stream_flag) {
|
||||
min_es_length += 2; // We need 2 more bytes
|
||||
if (es_length < min_es_length)
|
||||
throw new CorruptFileException ("Insufficient data present.");
|
||||
|
||||
OCR_ES_Id = box_data.Mid (offset, 2).ToUShort ();
|
||||
offset += 2; // Done with OCR
|
||||
}
|
||||
|
||||
while (offset < DataSize) // Loop through all trailing Descriptors Tags
|
||||
{
|
||||
DescriptorTag tag = (DescriptorTag)box_data[offset++];
|
||||
switch (tag) {
|
||||
case DescriptorTag.DecoderConfigDescrTag: // DecoderConfigDescriptor
|
||||
{
|
||||
// Check that the remainder of the tag is at least 13 bytes long (13 + DecoderSpecificInfo[] + profileLevelIndicationIndexDescriptor[])
|
||||
if (ReadLength (box_data, ref offset) < 13)
|
||||
throw new CorruptFileException ("Could not read data. Too small.");
|
||||
|
||||
// Read a lot of good info.
|
||||
ObjectTypeId = box_data[offset++];
|
||||
|
||||
StreamType = (byte)(box_data[offset] >> 2); // First 6 bits
|
||||
upStream = ((byte)((box_data[offset++] >> 1) & 0x1) == 0x1 ? true : false); // 7th bit and we're done with the stream bits
|
||||
|
||||
BufferSizeDB = box_data.Mid (offset, 3).ToUInt ();
|
||||
offset += 3; // Done with bufferSizeDB
|
||||
|
||||
max_bitrate = box_data.Mid (offset, 4).ToUInt ();
|
||||
offset += 4; // Done with maxBitrate
|
||||
|
||||
average_bitrate = box_data.Mid (offset, 4).ToUInt ();
|
||||
offset += 4; // Done with avgBitrate
|
||||
|
||||
// If there's a DecoderSpecificInfo[] array at the end it'll pick it up in the while loop
|
||||
}
|
||||
break;
|
||||
|
||||
case DescriptorTag.DecSpecificInfoTag: // DecoderSpecificInfo
|
||||
{
|
||||
// The rest of the info is decoder specific.
|
||||
uint length = ReadLength (box_data, ref offset);
|
||||
|
||||
DecoderConfig = box_data.Mid (offset, (int)length);
|
||||
offset += (int)length; // We're done with the config
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DescriptorTag.SLConfigDescrTag: // SLConfigDescriptor
|
||||
{
|
||||
// The rest of the info is SL specific.
|
||||
uint length = ReadLength (box_data, ref offset);
|
||||
|
||||
offset += (int)length; // Skip the rest of the descriptor as reported in the length so we can move onto the next one
|
||||
}
|
||||
break;
|
||||
|
||||
case DescriptorTag.Forbidden_00:
|
||||
case DescriptorTag.Forbidden_FF:
|
||||
throw new CorruptFileException ("Invalid Descriptor tag.");
|
||||
|
||||
default: {
|
||||
/* TODO: Should we handle other optional descriptor tags?
|
||||
* ExtensionDescriptor extDescr[0 .. 255];
|
||||
LanguageDescriptor langDescr[0 .. 1];
|
||||
IPI_DescPointer ipiPtr[0 .. 1];
|
||||
IP_IdentificationDataSet ipIDS[0 .. 1];
|
||||
QoS_Descriptor qosDescr[0 .. 1];
|
||||
*/
|
||||
uint length = ReadLength (box_data, ref offset); // Every descriptor starts with a length
|
||||
|
||||
offset += (int)length; // Skip the rest of the descriptor as reported in the length so we can move onto the next one
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the stream described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort" /> value containing the ID of the
|
||||
/// stream described by the current instance.
|
||||
/// </value>
|
||||
public ushort StreamId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority of the stream described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="byte" /> value containing the priority of
|
||||
/// the stream described by the current instance.
|
||||
/// </value>
|
||||
public byte StreamPriority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object type ID of the stream described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="byte" /> value containing the object type ID
|
||||
/// of the stream described by the current instance.
|
||||
/// </value>
|
||||
public byte ObjectTypeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type the stream described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="byte" /> value containing the type the
|
||||
/// stream described by the current instance.
|
||||
/// </value>
|
||||
public byte StreamType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the buffer size DB value the stream described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the buffer size DB
|
||||
/// value the stream described by the current instance.
|
||||
/// </value>
|
||||
public uint BufferSizeDB { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum bitrate the stream described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the maximum
|
||||
/// bitrate the stream described by the current instance.
|
||||
/// </value>
|
||||
public uint MaximumBitrate { get { return max_bitrate / 1000; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum average the stream described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the average
|
||||
/// bitrate the stream described by the current instance.
|
||||
/// </value>
|
||||
public uint AverageBitrate { get { return average_bitrate / 1000; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the decoder config data of stream described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the decoder
|
||||
/// config data of the stream described by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public ByteVector DecoderConfig { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads a section length and updates the offset to the end
|
||||
/// of of the length block.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object to read from.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="int" /> value reference specifying the
|
||||
/// offset at which to read. This value gets updated to the
|
||||
/// position following the size data.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="uint" /> value containing the length that
|
||||
/// was read.
|
||||
/// </returns>
|
||||
static uint ReadLength (ByteVector data, ref int offset)
|
||||
{
|
||||
byte b;
|
||||
int end = offset + 4;
|
||||
uint length = 0;
|
||||
|
||||
do {
|
||||
b = data[offset++];
|
||||
length = (uint)(length << 7) | (uint)(b & 0x7f);
|
||||
} while ((b & 0x80) != 0 && offset <= end); // The Length could be between 1 and 4 bytes for each descriptor
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01db5a51c2f9ebccb80b8b8c7c857ec1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// AppleItemListBox.cs: Provides an implementation of an Apple ItemListBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide an
|
||||
/// implementation of an Apple ItemListBox.
|
||||
/// </summary>
|
||||
public class AppleItemListBox : Box
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleItemListBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public AppleItemListBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
Children = LoadChildren (file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AppleItemListBox" /> with no children.
|
||||
/// </summary>
|
||||
public AppleItemListBox () : base ("ilst")
|
||||
{
|
||||
Children = new List<Box> ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override IEnumerable<Box> Children { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67b229427379dec19804cd115530bd73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// FullBox.cs: Provides an implementation of a ISO/IEC 14496-12 FullBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 FullBox.
|
||||
/// </summary>
|
||||
public abstract class FullBox : Box
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box version.
|
||||
/// </summary>
|
||||
byte version;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="FullBox" /> with a provided header and handler by
|
||||
/// reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
protected FullBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
file.Seek (base.DataPosition);
|
||||
ByteVector header_data = file.ReadBlock (4);
|
||||
version = header_data[0];
|
||||
Flags = header_data.Mid (1, 3).ToUInt ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="FullBox" /> with a provided header, version, and
|
||||
/// flags.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="version">
|
||||
/// A <see cref="byte" /> value containing the version of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="flags">
|
||||
/// A <see cref="byte" /> value containing the flags for the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
protected FullBox (BoxHeader header, byte version, uint flags)
|
||||
: base (header)
|
||||
{
|
||||
this.version = version;
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="FullBox" /> with a provided header, version, and
|
||||
/// flags.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="ByteVector" /> object containing the four
|
||||
/// byte box type.
|
||||
/// </param>
|
||||
/// <param name="version">
|
||||
/// A <see cref="byte" /> value containing the version of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="flags">
|
||||
/// A <see cref="byte" /> value containing the flags for the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="type" /> is <see langword="null" /> of
|
||||
/// equal to "<c>uuid</c>".
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="type" /> isn't exactly 4 bytes long.
|
||||
/// </exception>
|
||||
protected FullBox (ByteVector type, byte version, uint flags)
|
||||
: this (new BoxHeader (type), version, flags)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of the data contained in the current
|
||||
/// instance, after any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected override long DataPosition {
|
||||
get { return base.DataPosition + 4; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the version number of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="byte" /> value containing the version
|
||||
/// number of the current instance.
|
||||
/// </value>
|
||||
public uint Version {
|
||||
get { return version; }
|
||||
set { version = (byte)value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the flags that apply to the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the flags that
|
||||
/// apply to the current instance.
|
||||
/// </value>
|
||||
public uint Flags { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance, including its children, to
|
||||
/// a new <see cref="ByteVector" /> object, preceeding the
|
||||
/// contents with a specified block of data.
|
||||
/// </summary>
|
||||
/// <param name="topData">
|
||||
/// A <see cref="ByteVector" /> object containing box
|
||||
/// specific header data to preceed the content.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
protected override ByteVector Render (ByteVector topData)
|
||||
{
|
||||
var output = new ByteVector (version) {
|
||||
ByteVector.FromUInt (Flags).Mid (1, 3),
|
||||
topData
|
||||
};
|
||||
|
||||
return base.Render (output);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34757a28f0c3382fe90faa1055a948ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,231 @@
|
||||
//
|
||||
// IsoAudioSampleEntry.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// AudioSampleEntry and support for reading MPEG-4 video properties.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Globalization;
|
||||
|
||||
namespace TagLib.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="IsoSampleEntry" /> and implements
|
||||
/// <see cref="IAudioCodec" /> to provide an implementation of a
|
||||
/// ISO/IEC 14496-12 AudioSampleEntry and support for reading MPEG-4
|
||||
/// video properties.
|
||||
/// </summary>
|
||||
public class IsoAudioSampleEntry : IsoSampleEntry, IAudioCodec
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the channel count.
|
||||
/// </summary>
|
||||
readonly ushort channel_count;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the sample size.
|
||||
/// </summary>
|
||||
readonly ushort sample_size;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the sample rate.
|
||||
/// </summary>
|
||||
readonly uint sample_rate;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the children of the box.
|
||||
/// </summary>
|
||||
readonly IEnumerable<Box> children;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoVisualSampleEntry" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoAudioSampleEntry (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
file.Seek (base.DataPosition + 8);
|
||||
channel_count = file.ReadBlock (2).ToUShort ();
|
||||
sample_size = file.ReadBlock (2).ToUShort ();
|
||||
file.Seek (base.DataPosition + 16);
|
||||
sample_rate = file.ReadBlock (4).ToUInt ();
|
||||
children = LoadChildren (file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of the data contained in the current
|
||||
/// instance, after any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected override long DataPosition {
|
||||
get { return base.DataPosition + 20; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override IEnumerable<Box> Children {
|
||||
get { return children; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region IAudioCodec Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="TimeSpan.Zero" />.
|
||||
/// </value>
|
||||
public TimeSpan Duration {
|
||||
get { return TimeSpan.Zero; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Video" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes {
|
||||
get { return MediaTypes.Audio; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get {
|
||||
return string.Format (CultureInfo.InvariantCulture, "MPEG-4 Audio ({0})", BoxType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bitrate of the audio represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing a bitrate of the
|
||||
/// audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioBitrate {
|
||||
get {
|
||||
// If we don't have an stream descriptor, we
|
||||
// don't know what's what.
|
||||
if (!(GetChildRecursively ("esds") is AppleElementaryStreamDescriptor esds))
|
||||
return 0;
|
||||
|
||||
// Return from the elementary stream descriptor.
|
||||
return (int)esds.AverageBitrate;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleRate {
|
||||
get { return (int)(sample_rate >> 16); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels in the audio represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of
|
||||
/// channels in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int AudioChannels {
|
||||
get { return channel_count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample size of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample size of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleSize {
|
||||
get { return sample_size; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 985d1265608f9adbda1c1dbe038bd412
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// IsoChunkLargeOffsetBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// ChunkLargeOffsetBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 ChunkLargeOffsetBox.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="IsoChunkOffsetBox" /> and <see
|
||||
/// cref="IsoChunkLargeOffsetBox" /> contain offsets of media data
|
||||
/// within the file. As such, if the file changes by even one byte,
|
||||
/// these values are devalidatated and the box will have to be
|
||||
/// overwritten to maintain playability.
|
||||
/// </remarks>
|
||||
public class IsoChunkLargeOffsetBox : FullBox
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoChunkLargeOffsetBox" /> with a provided header
|
||||
/// and handler by reading the contents from a specified
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
public IsoChunkLargeOffsetBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
ByteVector box_data = file.ReadBlock (DataSize);
|
||||
|
||||
Offsets = new ulong[(int)
|
||||
box_data.Mid (0, 4).ToUInt ()];
|
||||
|
||||
for (int i = 0; i < Offsets.Length; i++)
|
||||
Offsets[i] = box_data.Mid (4 + i * 8, 8).ToULong ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get {
|
||||
ByteVector output = ByteVector.FromUInt ((uint)Offsets.Length);
|
||||
for (int i = 0; i < Offsets.Length; i++)
|
||||
output.Add (ByteVector.FromULong (Offsets[i]));
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the offset table contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:ulong[]" /> containing the offset table
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public ulong[] Offsets { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Overwrites the existing box in the file after updating
|
||||
/// the table for a size change.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="File" /> object containing the file to which
|
||||
/// the current instance belongs and wo which modifications
|
||||
/// must be applied.
|
||||
/// </param>
|
||||
/// <param name="sizeDifference">
|
||||
/// A <see cref="long" /> value containing the size
|
||||
/// change that occurred in the file.
|
||||
/// </param>
|
||||
/// <param name="after">
|
||||
/// A <see cref="long" /> value containing the position in
|
||||
/// the file after which offsets will be invalidated. If an
|
||||
/// offset is before this point, it won't be updated.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <see param="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public void Overwrite (File file, long sizeDifference, long after)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
file.Insert (Render (sizeDifference, after), Header.Position, Size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance after updating the table for
|
||||
/// a size change.
|
||||
/// </summary>
|
||||
/// <param name="sizeDifference">
|
||||
/// A <see cref="long" /> value containing the size
|
||||
/// change that occurred in the file.
|
||||
/// </param>
|
||||
/// <param name="after">
|
||||
/// A <see cref="long" /> value containing the position in
|
||||
/// the file after which offsets will be invalidated. If an
|
||||
/// offset is before this point, it won't be updated.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the file.
|
||||
/// </returns>
|
||||
public ByteVector Render (long sizeDifference, long after)
|
||||
{
|
||||
for (int i = 0; i < Offsets.Length; i++)
|
||||
if (Offsets[i] >= (ulong)after)
|
||||
Offsets[i] = (ulong)((long)Offsets[i] + sizeDifference);
|
||||
|
||||
return Render ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0ca89970f2030b84926ebeebcbce72a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,168 @@
|
||||
//
|
||||
// IsoChunkOffsetBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// ChunkOffsetBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 ChunkOffsetBox.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="IsoChunkOffsetBox" /> and <see
|
||||
/// cref="IsoChunkLargeOffsetBox" /> contain offsets of media data
|
||||
/// within the file. As such, if the file changes by even one byte,
|
||||
/// these values are devalidatated and the box will have to be
|
||||
/// overwritten to maintain playability.
|
||||
/// </remarks>
|
||||
public class IsoChunkOffsetBox : FullBox
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoChunkOffsetBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
public IsoChunkOffsetBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
ByteVector box_data = file.ReadBlock (DataSize);
|
||||
|
||||
Offsets = new uint[(int)box_data.Mid (0, 4).ToUInt ()];
|
||||
|
||||
for (int i = 0; i < Offsets.Length; i++)
|
||||
Offsets[i] = box_data.Mid (4 + i * 4, 4).ToUInt ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get {
|
||||
ByteVector output = ByteVector.FromUInt ((uint)Offsets.Length);
|
||||
for (int i = 0; i < Offsets.Length; i++)
|
||||
output.Add (ByteVector.FromUInt (Offsets[i]));
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the offset table contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:uint[]" /> containing the offset table
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public uint[] Offsets { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Overwrites the existing box in the file after updating
|
||||
/// the table for a size change.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="File" /> object containing the file to which
|
||||
/// the current instance belongs and wo which modifications
|
||||
/// must be applied.
|
||||
/// </param>
|
||||
/// <param name="sizeDifference">
|
||||
/// A <see cref="long" /> value containing the size
|
||||
/// change that occurred in the file.
|
||||
/// </param>
|
||||
/// <param name="after">
|
||||
/// A <see cref="long" /> value containing the position in
|
||||
/// the file after which offsets will be invalidated. If an
|
||||
/// offset is before this point, it won't be updated.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <see param="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public void Overwrite (File file, long sizeDifference, long after)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
file.Insert (Render (sizeDifference, after), Header.Position, Size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance after updating the table for
|
||||
/// a size change.
|
||||
/// </summary>
|
||||
/// <param name="sizeDifference">
|
||||
/// A <see cref="long" /> value containing the size
|
||||
/// change that occurred in the file.
|
||||
/// </param>
|
||||
/// <param name="after">
|
||||
/// A <see cref="long" /> value containing the position in
|
||||
/// the file after which offsets will be invalidated. If an
|
||||
/// offset is before this point, it won't be updated.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the file.
|
||||
/// </returns>
|
||||
public ByteVector Render (long sizeDifference, long after)
|
||||
{
|
||||
for (int i = 0; i < Offsets.Length; i++)
|
||||
if (Offsets[i] >= (uint)after)
|
||||
Offsets[i] = (uint)
|
||||
(Offsets[i] + sizeDifference);
|
||||
|
||||
return Render ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d43ea3e18f67dbd899b0e0090caaa74c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// IsoFreeSpaceBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// FreeSpaceBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 FreeSpaceBox.
|
||||
/// </summary>
|
||||
public class IsoFreeSpaceBox : Box
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the size of the padding.
|
||||
/// </summary>
|
||||
long padding;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoMetaBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
public IsoFreeSpaceBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
padding = DataSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoFreeSpaceBox" /> to occupy a specified number of
|
||||
/// bytes.
|
||||
/// </summary>
|
||||
/// <param name="padding">
|
||||
/// A <see cref="long" /> value specifying the number of
|
||||
/// bytes the new instance should occupy when rendered.
|
||||
/// </param>
|
||||
public IsoFreeSpaceBox (long padding) : base ("free")
|
||||
{
|
||||
PaddingSize = padding;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get { return new ByteVector ((int)padding); }
|
||||
set { padding = (value != null) ? value.Count : 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the size the current instance will occupy
|
||||
/// when rendered.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the size the
|
||||
/// current instance will occupy when rendered.
|
||||
/// </value>
|
||||
public long PaddingSize {
|
||||
get { return padding + 8; }
|
||||
set { padding = value - 8; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 989139d0574affb60983d4b835fa07a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,155 @@
|
||||
//
|
||||
// IsoHandlerBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// HandlerBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 FullBox.
|
||||
/// </summary>
|
||||
public class IsoHandlerBox : FullBox
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoHandlerBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoHandlerBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
file.Seek (DataPosition + 4);
|
||||
ByteVector box_data = file.ReadBlock (DataSize - 4);
|
||||
HandlerType = box_data.Mid (0, 4);
|
||||
|
||||
int end = box_data.Find ((byte)0, 16);
|
||||
if (end < 16)
|
||||
end = box_data.Count;
|
||||
Name = end > 16 ? box_data.ToString (StringType.UTF8, 16, end - 16) : string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoHandlerBox" /> with a specified type and name.
|
||||
/// </summary>
|
||||
/// <param name="handlerType">
|
||||
/// A <see cref="ByteVector" /> object specifying a 4 byte
|
||||
/// handler type.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object specifying the handler
|
||||
/// name.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="handlerType" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="handlerType" /> is less than 4 bytes
|
||||
/// long.
|
||||
/// </exception>
|
||||
public IsoHandlerBox (ByteVector handlerType, string name)
|
||||
: base ("hdlr", 0, 0)
|
||||
{
|
||||
if (handlerType == null)
|
||||
throw new ArgumentNullException (nameof (handlerType));
|
||||
|
||||
if (handlerType.Count < 4)
|
||||
throw new ArgumentException ("The handler type must be four bytes long.",
|
||||
nameof (handlerType));
|
||||
|
||||
HandlerType = handlerType.Mid (0, 4);
|
||||
Name = name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the data contained in the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get {
|
||||
var output = new ByteVector (4) {
|
||||
HandlerType,
|
||||
new ByteVector (12),
|
||||
ByteVector.FromString (Name,
|
||||
StringType.UTF8),
|
||||
new ByteVector (2)
|
||||
};
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handler type of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// handler type of the current instance.
|
||||
/// </value>
|
||||
public ByteVector HandlerType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// current instance.
|
||||
/// </value>
|
||||
public string Name { get; private set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c2babf0b4360f99d974d9b7a8578846
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// IsoMetaBox.cs: Provides an implementation of a ISO/IEC 14496-12 MetaBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 MetaBox.
|
||||
/// </summary>
|
||||
public class IsoMetaBox : FullBox
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoMetaBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoMetaBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
Children = LoadChildren (file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoMetaBox" /> with a specified handler.
|
||||
/// </summary>
|
||||
/// <param name="handlerType">
|
||||
/// A <see cref="ByteVector" /> object specifying a 4 byte
|
||||
/// handler type.
|
||||
/// </param>
|
||||
/// <param name="handlerName">
|
||||
/// A <see cref="string" /> object specifying the handler
|
||||
/// name.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="handlerType" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="handlerType" /> is less than 4 bytes
|
||||
/// long.
|
||||
/// </exception>
|
||||
public IsoMetaBox (ByteVector handlerType, string handlerName)
|
||||
: base ("meta", 0, 0)
|
||||
{
|
||||
if (handlerType == null)
|
||||
throw new ArgumentNullException (nameof (handlerType));
|
||||
|
||||
if (handlerType.Count < 4)
|
||||
throw new ArgumentException ("The handler type must be four bytes long.", nameof (handlerType));
|
||||
|
||||
Children = new List<Box> ();
|
||||
AddChild (new IsoHandlerBox (handlerType, handlerName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override IEnumerable<Box> Children { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44fce7ebbf90e84a8931eb530441db21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,238 @@
|
||||
//
|
||||
// IsoMovieHeaderBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// MovieHeaderBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 MovieHeaderBox.
|
||||
/// </summary>
|
||||
public class IsoMovieHeaderBox : FullBox
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the creation time of the movie.
|
||||
/// </summary>
|
||||
readonly ulong creation_time;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the modification time of the movie.
|
||||
/// </summary>
|
||||
readonly ulong modification_time;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the timescale.
|
||||
/// </summary>
|
||||
readonly uint timescale;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the duration.
|
||||
/// </summary>
|
||||
readonly ulong duration;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the rate.
|
||||
/// </summary>
|
||||
readonly uint rate;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the volume.
|
||||
/// </summary>
|
||||
readonly ushort volume;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoMovieHeaderBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoMovieHeaderBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
int bytes_remaining = DataSize;
|
||||
ByteVector data;
|
||||
|
||||
if (Version == 1) {
|
||||
// Read version one (large integers).
|
||||
data = file.ReadBlock (Math.Min (28,
|
||||
bytes_remaining));
|
||||
if (data.Count >= 8)
|
||||
creation_time = data.Mid (0,
|
||||
8).ToULong ();
|
||||
if (data.Count >= 16)
|
||||
modification_time = data.Mid (8,
|
||||
8).ToULong ();
|
||||
if (data.Count >= 20)
|
||||
timescale = data.Mid (16, 4).ToUInt ();
|
||||
if (data.Count >= 28)
|
||||
duration = data.Mid (20, 8).ToULong ();
|
||||
bytes_remaining -= 28;
|
||||
} else {
|
||||
// Read version zero (normal integers).
|
||||
data = file.ReadBlock (Math.Min (16,
|
||||
bytes_remaining));
|
||||
if (data.Count >= 4)
|
||||
creation_time = data.Mid (0,
|
||||
4).ToUInt ();
|
||||
if (data.Count >= 8)
|
||||
modification_time = data.Mid (4,
|
||||
4).ToUInt ();
|
||||
if (data.Count >= 12)
|
||||
timescale = data.Mid (8, 4).ToUInt ();
|
||||
if (data.Count >= 16)
|
||||
duration = data.Mid (12, 4).ToUInt ();
|
||||
bytes_remaining -= 16;
|
||||
}
|
||||
|
||||
data = file.ReadBlock (Math.Min (6, bytes_remaining));
|
||||
if (data.Count >= 4)
|
||||
rate = data.Mid (0, 4).ToUInt ();
|
||||
if (data.Count >= 6)
|
||||
volume = data.Mid (4, 2).ToUShort ();
|
||||
file.Seek (file.Tell + 70);
|
||||
bytes_remaining -= 76;
|
||||
|
||||
data = file.ReadBlock (Math.Min (4,
|
||||
bytes_remaining));
|
||||
|
||||
if (data.Count >= 4)
|
||||
NextTrackId = data.Mid (0, 4).ToUInt ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation time of movie represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DateTime" /> value containing the creation
|
||||
/// time of the movie represented by the current instance.
|
||||
/// </value>
|
||||
public DateTime CreationTime {
|
||||
get {
|
||||
return new DateTime (1904, 1, 1, 0, 0,
|
||||
0).AddTicks ((long)(10000000 * creation_time));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the modification time of movie represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DateTime" /> value containing the
|
||||
/// modification time of the movie represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public DateTime ModificationTime {
|
||||
get {
|
||||
return new DateTime (1904, 1, 1, 0, 0,
|
||||
0).AddTicks ((long)(10000000 * modification_time));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the movie represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> value containing the duration
|
||||
/// of the movie represented by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan Duration {
|
||||
get {
|
||||
// The length is the number of ticks divided by
|
||||
// ticks per second.
|
||||
return TimeSpan.FromSeconds (duration / (double)timescale);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playback rate of the movie represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="double" /> value containing the playback
|
||||
/// rate of the movie represented by the current instance.
|
||||
/// </value>
|
||||
public double Rate {
|
||||
get { return rate / ((double)0x10000); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playback volume of the movie represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="double" /> value containing the playback
|
||||
/// volume of the movie represented by the current instance.
|
||||
/// </value>
|
||||
public double Volume {
|
||||
get { return volume / ((double)0x100); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the next track in the movie represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the ID of the next
|
||||
/// track in the movie represented by the current instance.
|
||||
/// </value>
|
||||
public uint NextTrackId { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbdf1fa58c6e4ee8f90050b4ba200e1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// IsoSampleDescriptionBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// SampleDescriptionBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="FullBox" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 SampleDescriptionBox.
|
||||
/// </summary>
|
||||
public class IsoSampleDescriptionBox : FullBox
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoSampleDescriptionBox" /> with a provided header
|
||||
/// and handler by reading the contents from a specified
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoSampleDescriptionBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
EntryCount = file.ReadBlock (4).ToUInt ();
|
||||
Children = LoadChildren (file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of the data contained in the current
|
||||
/// instance, after any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected override long DataPosition {
|
||||
get { return base.DataPosition + 4; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of boxes at the begining of the children
|
||||
/// that will be stored as <see cref="IsoAudioSampleEntry" />
|
||||
/// of <see cref="IsoVisualSampleEntry" /> objects, depending
|
||||
/// on the handler.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the number of
|
||||
/// children that will appear as sample entries.
|
||||
/// </value>
|
||||
public uint EntryCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override IEnumerable<Box> Children { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63519246ddd625dc09d803ea727347f1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// IsoSampleEntry.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// SampleEntry.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 SampleEntry.
|
||||
/// </summary>
|
||||
public class IsoSampleEntry : Box
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoSampleEntry" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoSampleEntry (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
file.Seek (base.DataPosition + 6);
|
||||
DataReferenceIndex = file.ReadBlock (2).ToUShort ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of the data contained in the current
|
||||
/// instance, after any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected override long DataPosition {
|
||||
get { return base.DataPosition + 8; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data reference index of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort" /> value containing the data
|
||||
/// reference index of the current instance.
|
||||
/// </value>
|
||||
public ushort DataReferenceIndex { get; private set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5118d3397eaabd6396f8c7420c3bb9f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// IsoSampleTableBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// SampleTableBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 SampleTableBox.
|
||||
/// </summary>
|
||||
public class IsoSampleTableBox : Box
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoSampleTableBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoSampleTableBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
Children = LoadChildren (file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override IEnumerable<Box> Children { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea0ba1a02fe1b62b2881512be697e629
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// IsoUserDataBox.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// UserDataBox.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide an
|
||||
/// implementation of a ISO/IEC 14496-12 UserDataBox.
|
||||
/// </summary>
|
||||
public class IsoUserDataBox : Box
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoUserDataBox" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoUserDataBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
Children = LoadChildren (file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoUserDataBox" /> with no children.
|
||||
/// </summary>
|
||||
public IsoUserDataBox () : base ("udta")
|
||||
{
|
||||
Children = new List<Box> ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override IEnumerable<Box> Children { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the box headers for the current "<c>udta</c>" box and
|
||||
/// all parent boxes up to the top of the file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:BoxHeader[]" /> containing the headers for
|
||||
/// the current "<c>udta</c>" box and its parent boxes up to
|
||||
/// the top of the file, in the order they appear, or <see
|
||||
/// langword="null" /> if none is present.
|
||||
/// </value>
|
||||
public BoxHeader[] ParentTree { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d443e2d449f2857a5b6e79db0ad53dc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// IsoVisualSampleEntry.cs: Provides an implementation of a ISO/IEC 14496-12
|
||||
// VisualSampleEntry and support for reading MPEG-4 video properties.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Globalization;
|
||||
|
||||
namespace TagLib.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="IsoSampleEntry" /> and implements
|
||||
/// <see cref="IVideoCodec" /> to provide an implementation of a
|
||||
/// ISO/IEC 14496-12 VisualSampleEntry and support for reading MPEG-4
|
||||
/// video properties.
|
||||
/// </summary>
|
||||
public class IsoVisualSampleEntry : IsoSampleEntry, IVideoCodec
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the width of the visual.
|
||||
/// </summary>
|
||||
readonly ushort width;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the height of the visual.
|
||||
/// </summary>
|
||||
readonly ushort height;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Contains the children of the box.
|
||||
/// </summary>
|
||||
private BoxList children;
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="IsoVisualSampleEntry" /> with a provided header and
|
||||
/// handler by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public IsoVisualSampleEntry (BoxHeader header, TagLib.File file,
|
||||
IsoHandlerBox handler)
|
||||
: base (header, file, handler)
|
||||
{
|
||||
file.Seek (base.DataPosition + 16);
|
||||
width = file.ReadBlock (2).ToUShort ();
|
||||
height = file.ReadBlock (2).ToUShort ();
|
||||
|
||||
/*
|
||||
TODO: What are the children anyway?
|
||||
children = LoadChildren (file);
|
||||
*/
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of the data contained in the current
|
||||
/// instance, after any box specific headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the position of
|
||||
/// the data contained in the current instance.
|
||||
/// </value>
|
||||
protected override long DataPosition {
|
||||
get { return base.DataPosition + 62; }
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Gets the children of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="IEnumerable{T}" /> object enumerating the
|
||||
/// children of the current instance.
|
||||
/// </value>
|
||||
public override BoxList Children {
|
||||
get {return children;}
|
||||
}
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region IVideoCodec Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="TimeSpan.Zero" />.
|
||||
/// </value>
|
||||
public TimeSpan Duration {
|
||||
get { return TimeSpan.Zero; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Video" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes {
|
||||
get { return MediaTypes.Video; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get {
|
||||
return string.Format (CultureInfo.InvariantCulture, "MPEG-4 Video ({0})", BoxType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width of the video represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> containing the width of the video
|
||||
/// represented by the current instance.
|
||||
/// </value>
|
||||
public int VideoWidth {
|
||||
get { return width; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of the video represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> containing the height of the video
|
||||
/// represented by the current instance.
|
||||
/// </value>
|
||||
public int VideoHeight {
|
||||
get { return height; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2683606c312126038bc7840ea8af72c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// TextBox.cs
|
||||
//
|
||||
// Author:
|
||||
// Alan McGovern <alan.mcgovern@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2012 Alan McGovern
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 2.1 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// 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 TagLib.Mpeg4;
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Represent an MP4 text box
|
||||
/// </summary>
|
||||
public class TextBox : Box
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box's data.
|
||||
/// </summary>
|
||||
ByteVector data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="UnknownBox" /> with a provided header and handler
|
||||
/// by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public TextBox (BoxHeader header, File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
data = LoadData (file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the box data contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// data contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get { return data; }
|
||||
set { data = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41c315eb322c671bd9ed59b891d2094b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// UnknownBox.cs: Provides a simple implementation of a box of unknown type.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Box" /> to provide a simple
|
||||
/// implementation of a box of unknown type.
|
||||
/// </summary>
|
||||
public class UnknownBox : Box
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box's data.
|
||||
/// </summary>
|
||||
ByteVector data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="UnknownBox" /> with a provided header and handler
|
||||
/// by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public UnknownBox (BoxHeader header, TagLib.File file, IsoHandlerBox handler) : base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
data = file.ReadBlock (DataSize > 0 ? DataSize : 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the box data contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// data contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get { return data; }
|
||||
set { data = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3061613889bb6748db8f631a7e1fbf49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// UrlBox.cs
|
||||
//
|
||||
// Author:
|
||||
// Alan McGovern <alan.mcgovern@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2012 Alan McGovern
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 2.1 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// 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 TagLib.Mpeg4;
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Represent a MP4 URL box
|
||||
/// </summary>
|
||||
public class UrlBox : Box
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box's data.
|
||||
/// </summary>
|
||||
ByteVector data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="UnknownBox" /> with a provided header and handler
|
||||
/// by reading the contents from a specified file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BoxHeader" /> object containing the header
|
||||
/// to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to read the contents
|
||||
/// of the box from.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object containing the
|
||||
/// handler that applies to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public UrlBox (BoxHeader header, File file, IsoHandlerBox handler)
|
||||
: base (header, handler)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
data = LoadData (file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the box data contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the box
|
||||
/// data contained in the current instance.
|
||||
/// </value>
|
||||
public override ByteVector Data {
|
||||
get { return data; }
|
||||
set { data = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57b4e67ab7e85f6988b741084a6db2bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,455 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for MPEG-4 files.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Linq;
|
||||
|
||||
namespace TagLib.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.File" /> to provide tagging
|
||||
/// and properties support for MPEG-4 files.
|
||||
/// </summary>
|
||||
[SupportedMimeType ("taglib/m4a", "m4a")]
|
||||
[SupportedMimeType ("taglib/m4b", "m4b")]
|
||||
[SupportedMimeType ("taglib/m4v", "m4v")]
|
||||
[SupportedMimeType ("taglib/m4p", "m4p")]
|
||||
[SupportedMimeType ("taglib/mp4", "mp4")]
|
||||
[SupportedMimeType ("audio/mp4")]
|
||||
[SupportedMimeType ("audio/x-m4a")]
|
||||
[SupportedMimeType ("video/mp4")]
|
||||
[SupportedMimeType ("video/x-m4v")]
|
||||
public class File : TagLib.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Apple tag.
|
||||
/// </summary>
|
||||
AppleTag apple_tag;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the combined tag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// TODO: Add support for ID3v2 tags.
|
||||
/// </remarks>
|
||||
CombinedTag tag;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the media properties.
|
||||
/// </summary>
|
||||
Properties properties;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path, ReadStyle propertiesStyle)
|
||||
: base (path)
|
||||
{
|
||||
Read (propertiesStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system with an average read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path)
|
||||
: this (path, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (IFileAbstraction abstraction, ReadStyle propertiesStyle)
|
||||
: base (abstraction)
|
||||
{
|
||||
Read (propertiesStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction with an
|
||||
/// average read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (IFileAbstraction abstraction)
|
||||
: this (abstraction, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a abstract representation of all tags stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Tag" /> object representing all tags
|
||||
/// stored in the current instance.
|
||||
/// </value>
|
||||
public override Tag Tag {
|
||||
get { return tag; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media properties of the file represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Properties" /> object containing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public override Properties Properties {
|
||||
get { return properties; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the UDTA Boxes
|
||||
/// </summary>
|
||||
protected List<IsoUserDataBox> UdtaBoxes { get; } = new List<IsoUserDataBox> ();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the changes made in the current instance to the
|
||||
/// file it represents.
|
||||
/// </summary>
|
||||
public override void Save ()
|
||||
{
|
||||
// Boilerplate
|
||||
PreSave ();
|
||||
|
||||
if (UdtaBoxes.Count == 0) {
|
||||
var udtaBox = new IsoUserDataBox ();
|
||||
UdtaBoxes.Add (udtaBox);
|
||||
}
|
||||
|
||||
// Try to get into write mode.
|
||||
Mode = AccessMode.Write;
|
||||
try {
|
||||
var parser = new FileParser (this);
|
||||
parser.ParseBoxHeaders ();
|
||||
|
||||
InvariantStartPosition = parser.MdatStartPosition;
|
||||
InvariantEndPosition = parser.MdatEndPosition;
|
||||
|
||||
long size_change = 0;
|
||||
long write_position = 0;
|
||||
|
||||
// To avoid rewriting udta blocks which might not have been modified,
|
||||
// the code here will work correctly if:
|
||||
// 1. There is a single udta for the entire file
|
||||
// - OR -
|
||||
// 2. There are multiple utdtas, but only 1 of them contains the Apple ILST box.
|
||||
// We should be OK in the vast majority of cases
|
||||
IsoUserDataBox udtaBox = FindAppleTagUdta ();
|
||||
if (null == udtaBox)
|
||||
udtaBox = new IsoUserDataBox ();
|
||||
ByteVector tag_data = udtaBox.Render ();
|
||||
|
||||
// If we don't have a "udta" box to overwrite...
|
||||
if (udtaBox.ParentTree == null ||
|
||||
udtaBox.ParentTree.Length == 0) {
|
||||
|
||||
// Stick the box at the end of the moov box.
|
||||
BoxHeader moov_header = parser.MoovTree[parser.MoovTree.Length - 1];
|
||||
size_change = tag_data.Count;
|
||||
write_position = moov_header.Position + moov_header.TotalBoxSize;
|
||||
Insert (tag_data, write_position, 0);
|
||||
|
||||
// Overwrite the parent box sizes.
|
||||
for (int i = parser.MoovTree.Length - 1; i >= 0; i--)
|
||||
size_change = parser.MoovTree[i].Overwrite (this, size_change);
|
||||
} else {
|
||||
// Overwrite the old box.
|
||||
BoxHeader udta_header = udtaBox.ParentTree[udtaBox.ParentTree.Length - 1];
|
||||
size_change = tag_data.Count - udta_header.TotalBoxSize;
|
||||
write_position = udta_header.Position;
|
||||
Insert (tag_data, write_position, udta_header.TotalBoxSize);
|
||||
|
||||
// Overwrite the parent box sizes.
|
||||
for (int i = udtaBox.ParentTree.Length - 2; i >= 0; i--)
|
||||
size_change = udtaBox.ParentTree[i].Overwrite (this, size_change);
|
||||
}
|
||||
|
||||
// If we've had a size change, we may need to adjust
|
||||
// chunk offsets.
|
||||
if (size_change != 0) {
|
||||
// We may have moved the offset boxes, so we
|
||||
// need to reread.
|
||||
parser.ParseChunkOffsets ();
|
||||
InvariantStartPosition = parser.MdatStartPosition;
|
||||
InvariantEndPosition = parser.MdatEndPosition;
|
||||
|
||||
foreach (Box box in parser.ChunkOffsetBoxes) {
|
||||
if (box is IsoChunkLargeOffsetBox co64) {
|
||||
co64.Overwrite (this, size_change, write_position);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (box is IsoChunkOffsetBox stco) {
|
||||
stco.Overwrite (this, size_change, write_position);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TagTypesOnDisk = TagTypes;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance,
|
||||
/// optionally creating a new tag if possible.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value specifying whether or not to
|
||||
/// try and create the tag if one is not found.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in or added to the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// At the time of this writing, only <see cref="AppleTag" />
|
||||
/// is supported. All other tag types will be ignored.
|
||||
/// </remarks>
|
||||
public override Tag GetTag (TagTypes type, bool create)
|
||||
{
|
||||
if (type == TagTypes.Apple) {
|
||||
if (apple_tag == null && create) {
|
||||
IsoUserDataBox udtaBox = FindAppleTagUdta ();
|
||||
if (null == udtaBox) {
|
||||
udtaBox = new IsoUserDataBox ();
|
||||
}
|
||||
apple_tag = new AppleTag (udtaBox);
|
||||
tag.SetTags (apple_tag);
|
||||
}
|
||||
|
||||
return apple_tag;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a set of tag types from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="types">
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||
/// containing tag types to be removed from the file.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// In order to remove all tags from a file, pass <see
|
||||
/// cref="TagTypes.AllTags" /> as <paramref name="types" />.
|
||||
/// </remarks>
|
||||
public override void RemoveTags (TagTypes types)
|
||||
{
|
||||
if ((types & TagTypes.Apple) != TagTypes.Apple || apple_tag == null)
|
||||
return;
|
||||
|
||||
apple_tag.DetachIlst ();
|
||||
apple_tag = null;
|
||||
tag.SetTags ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads the file with a specified read style.
|
||||
/// </summary>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
void Read (ReadStyle propertiesStyle)
|
||||
{
|
||||
// TODO: Support Id3v2 boxes!!!
|
||||
tag = new CombinedTag ();
|
||||
Mode = AccessMode.Read;
|
||||
try {
|
||||
var parser = new FileParser (this);
|
||||
|
||||
if ((propertiesStyle & ReadStyle.Average) == 0)
|
||||
parser.ParseTag ();
|
||||
else
|
||||
parser.ParseTagAndProperties ();
|
||||
|
||||
InvariantStartPosition = parser.MdatStartPosition;
|
||||
InvariantEndPosition = parser.MdatEndPosition;
|
||||
|
||||
UdtaBoxes.AddRange (parser.UserDataBoxes);
|
||||
|
||||
// Ensure our collection contains at least a single empty box
|
||||
if (UdtaBoxes.Count == 0) {
|
||||
var dummy = new IsoUserDataBox ();
|
||||
UdtaBoxes.Add (dummy);
|
||||
}
|
||||
|
||||
// Check if a udta with ILST actually exists
|
||||
if (IsAppleTagUdtaPresent ())
|
||||
TagTypesOnDisk |= TagTypes.Apple; //There is an udta present with ILST info
|
||||
|
||||
// Find the udta box with the Apple Tag ILST
|
||||
IsoUserDataBox udtaBox = FindAppleTagUdta ();
|
||||
if (null == udtaBox) {
|
||||
udtaBox = new IsoUserDataBox ();
|
||||
}
|
||||
apple_tag = new AppleTag (udtaBox);
|
||||
tag.SetTags (apple_tag);
|
||||
|
||||
// If we're not reading properties, we're done.
|
||||
if ((propertiesStyle & ReadStyle.Average) == 0) {
|
||||
Mode = AccessMode.Closed;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the movie header box.
|
||||
var mvhd_box = parser.MovieHeaderBox;
|
||||
if (mvhd_box == null) {
|
||||
Mode = AccessMode.Closed;
|
||||
throw new CorruptFileException ("mvhd box not found.");
|
||||
}
|
||||
|
||||
var audio_sample_entry = parser.AudioSampleEntry;
|
||||
var visual_sample_entry = parser.VisualSampleEntry;
|
||||
|
||||
// Read the properties.
|
||||
properties = new Properties (mvhd_box.Duration, audio_sample_entry, visual_sample_entry);
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the udta box within our collection that contains the Apple ILST data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If there is a single udta in a file, we return that.
|
||||
/// If there are multiple udtas, we search for the one that contains the ILST box.
|
||||
/// </remarks>
|
||||
IsoUserDataBox FindAppleTagUdta ()
|
||||
{
|
||||
if (UdtaBoxes.Count == 1)
|
||||
return UdtaBoxes[0]; //Single udta - just return it
|
||||
|
||||
// multiple udta : pick out the shallowest node which has an ILst tag
|
||||
var udtaBox = UdtaBoxes
|
||||
.Where (box => box.GetChildRecursively (BoxType.Ilst) != null)
|
||||
.OrderBy (box => box.ParentTree.Length)
|
||||
.FirstOrDefault ();
|
||||
|
||||
return udtaBox;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if there is a udta with ILST present in our collection
|
||||
/// </summary>
|
||||
bool IsAppleTagUdtaPresent ()
|
||||
{
|
||||
foreach (var udtaBox in UdtaBoxes) {
|
||||
if (udtaBox.GetChild (BoxType.Meta) != null && udtaBox.GetChild (BoxType.Meta).GetChild (BoxType.Ilst) != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94a393d23a72f232488c3771e55ef837
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,606 @@
|
||||
//
|
||||
// FileParser.cs: Provides methods for reading important information from an
|
||||
// MPEG-4 file.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Mpeg4
|
||||
{
|
||||
/// <summary>
|
||||
/// This class provides methods for reading important information
|
||||
/// from an MPEG-4 file.
|
||||
/// </summary>
|
||||
public class FileParser
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the file to read from.
|
||||
/// </summary>
|
||||
readonly TagLib.File file;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the first header found in the file.
|
||||
/// </summary>
|
||||
readonly BoxHeader first_header;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the ISO movie header box.
|
||||
/// </summary>
|
||||
IsoMovieHeaderBox mvhd_box;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the ISO user data boxes.
|
||||
/// </summary>
|
||||
readonly List<IsoUserDataBox> udta_boxes = new List<IsoUserDataBox> ();
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box headers from the top of the file to the
|
||||
/// "moov" box.
|
||||
/// </summary>
|
||||
BoxHeader[] moov_tree;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the box headers from the top of the file to the
|
||||
/// "udta" box.
|
||||
/// </summary>
|
||||
BoxHeader[] udta_tree;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the "stco" boxes found in the file.
|
||||
/// </summary>
|
||||
readonly List<Box> stco_boxes = new List<Box> ();
|
||||
|
||||
/// <summary>
|
||||
/// Contains the "stsd" boxes found in the file.
|
||||
/// </summary>
|
||||
readonly List<Box> stsd_boxes = new List<Box> ();
|
||||
|
||||
/// <summary>
|
||||
/// Contains the position at which the "mdat" box starts.
|
||||
/// </summary>
|
||||
long mdat_start = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the position at which the "mdat" box ends.
|
||||
/// </summary>
|
||||
long mdat_end = -1;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="FileParser" /> for a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to perform operations
|
||||
/// on.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="file" /> does not start with a
|
||||
/// "<c>ftyp</c>" box.
|
||||
/// </exception>
|
||||
public FileParser (TagLib.File file)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
this.file = file;
|
||||
first_header = new BoxHeader (file, 0);
|
||||
|
||||
if (first_header.BoxType != "ftyp")
|
||||
throw new CorruptFileException ("File does not start with 'ftyp' box.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the movie header box read by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="IsoMovieHeaderBox" /> object read by the
|
||||
/// current instance, or <see langword="null" /> if not found.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value will only be set by calling <see
|
||||
/// cref="ParseTagAndProperties()" />.
|
||||
/// </remarks>
|
||||
public IsoMovieHeaderBox MovieHeaderBox {
|
||||
get { return mvhd_box; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all user data boxes read by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="IsoUserDataBox" /> array read by the
|
||||
/// current instance.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value will only be set by calling <see
|
||||
/// cref="ParseTag()" /> and <see
|
||||
/// cref="ParseTagAndProperties()" />.
|
||||
/// </remarks>
|
||||
public IsoUserDataBox[] UserDataBoxes {
|
||||
get { return udta_boxes.ToArray (); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the User Data Box
|
||||
/// </summary>
|
||||
public IsoUserDataBox UserDataBox {
|
||||
get { return UserDataBoxes.Length == 0 ? null : UserDataBoxes[0]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the audio sample entry read by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="IsoAudioSampleEntry" /> object read by the
|
||||
/// current instance, or <see langword="null" /> if not found.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value will only be set by calling <see
|
||||
/// cref="ParseTagAndProperties()" />.
|
||||
/// </remarks>
|
||||
public IsoAudioSampleEntry AudioSampleEntry {
|
||||
get {
|
||||
foreach (IsoSampleDescriptionBox box in stsd_boxes)
|
||||
foreach (Box sub in box.Children) {
|
||||
if (sub is IsoAudioSampleEntry entry)
|
||||
return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the visual sample entry read by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="IsoVisualSampleEntry" /> object read by the
|
||||
/// current instance, or <see langword="null" /> if not found.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value will only be set by calling <see
|
||||
/// cref="ParseTagAndProperties()" />.
|
||||
/// </remarks>
|
||||
public IsoVisualSampleEntry VisualSampleEntry {
|
||||
get {
|
||||
foreach (IsoSampleDescriptionBox box in stsd_boxes)
|
||||
foreach (Box sub in box.Children) {
|
||||
if (sub is IsoVisualSampleEntry entry)
|
||||
return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the box headers for the first "<c>moov</c>" box and
|
||||
/// all parent boxes up to the top of the file as read by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:BoxHeader[]" /> containing the headers for
|
||||
/// the first "<c>moov</c>" box and its parent boxes up to
|
||||
/// the top of the file, in the order they appear, or <see
|
||||
/// langword="null" /> if none is present.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value is useful for overwriting box headers, and is
|
||||
/// only be set by calling <see cref="ParseBoxHeaders()" />.
|
||||
/// </remarks>
|
||||
public BoxHeader[] MoovTree {
|
||||
get { return moov_tree; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the box headers for the first "<c>udta</c>" box and
|
||||
/// all parent boxes up to the top of the file as read by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:BoxHeader[]" /> containing the headers for
|
||||
/// the first "<c>udta</c>" box and its parent boxes up to
|
||||
/// the top of the file, in the order they appear, or <see
|
||||
/// langword="null" /> if none is present.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value is useful for overwriting box headers, and is
|
||||
/// only be set by calling <see cref="ParseBoxHeaders()" />.
|
||||
/// </remarks>
|
||||
public BoxHeader[] UdtaTree {
|
||||
get { return udta_tree; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all chunk offset boxes read by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:Box[]" /> containing all chunk offset boxes
|
||||
/// read by the current instance.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// These boxes contain offset information for media data in
|
||||
/// the current instance and can be devalidated by size
|
||||
/// change operations, in which case they need to be
|
||||
/// corrected. This value will only be set by calling <see
|
||||
/// cref="ParseChunkOffsets()" />.
|
||||
/// </remarks>
|
||||
public Box[] ChunkOffsetBoxes {
|
||||
get { return stco_boxes.ToArray (); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position at which the "<c>mdat</c>" box starts.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the "<c>mdat</c>" box starts.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The "<c>mdat</c>" box contains the media data for the
|
||||
/// file and is used for estimating the invariant data
|
||||
/// portion of the file.
|
||||
/// </remarks>
|
||||
public long MdatStartPosition {
|
||||
get { return mdat_start; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position at which the "<c>mdat</c>" box ends.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the "<c>mdat</c>" box ends.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The "<c>mdat</c>" box contains the media data for the
|
||||
/// file and is used for estimating the invariant data
|
||||
/// portion of the file.
|
||||
/// </remarks>
|
||||
public long MdatEndPosition {
|
||||
get { return mdat_end; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Parses the file referenced by the current instance,
|
||||
/// searching for box headers that will be useful in saving
|
||||
/// the file.
|
||||
/// </summary>
|
||||
public void ParseBoxHeaders ()
|
||||
{
|
||||
try {
|
||||
ResetFields ();
|
||||
ParseBoxHeaders (first_header.TotalBoxSize, file.Length, null);
|
||||
} catch (CorruptFileException e) {
|
||||
file.MarkAsCorrupt (e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the file referenced by the current instance,
|
||||
/// searching for tags.
|
||||
/// </summary>
|
||||
public void ParseTag ()
|
||||
{
|
||||
try {
|
||||
ResetFields ();
|
||||
ParseTag (first_header.TotalBoxSize, file.Length, null);
|
||||
} catch (CorruptFileException e) {
|
||||
file.MarkAsCorrupt (e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the file referenced by the current instance,
|
||||
/// searching for tags and properties.
|
||||
/// </summary>
|
||||
public void ParseTagAndProperties ()
|
||||
{
|
||||
try {
|
||||
ResetFields ();
|
||||
ParseTagAndProperties (first_header.TotalBoxSize, file.Length, null, null);
|
||||
} catch (CorruptFileException e) {
|
||||
file.MarkAsCorrupt (e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the file referenced by the current instance,
|
||||
/// searching for chunk offset boxes.
|
||||
/// </summary>
|
||||
public void ParseChunkOffsets ()
|
||||
{
|
||||
try {
|
||||
ResetFields ();
|
||||
ParseChunkOffsets (first_header.TotalBoxSize, file.Length);
|
||||
} catch (CorruptFileException e) {
|
||||
file.MarkAsCorrupt (e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Parses boxes for a specified range, looking for headers.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to start reading.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to stop reading.
|
||||
/// </param>
|
||||
/// <param name="parents">
|
||||
/// A <see cref="T:System.Collections.Generic.List`1" /> object containing all the parent
|
||||
/// handlers that apply to the range.
|
||||
/// </param>
|
||||
void ParseBoxHeaders (long start, long end, List<BoxHeader> parents)
|
||||
{
|
||||
BoxHeader header;
|
||||
|
||||
for (long position = start; position < end; position += header.TotalBoxSize) {
|
||||
header = new BoxHeader (file, position);
|
||||
|
||||
if (moov_tree == null && header.BoxType == BoxType.Moov) {
|
||||
List<BoxHeader> new_parents = AddParent (parents, header);
|
||||
moov_tree = new_parents.ToArray ();
|
||||
ParseBoxHeaders (header.HeaderSize + position, header.TotalBoxSize + position, new_parents);
|
||||
} else if (header.BoxType == BoxType.Mdia ||
|
||||
header.BoxType == BoxType.Minf ||
|
||||
header.BoxType == BoxType.Stbl ||
|
||||
header.BoxType == BoxType.Trak) {
|
||||
ParseBoxHeaders (header.HeaderSize + position, header.TotalBoxSize + position, AddParent (parents, header));
|
||||
} else if (udta_tree == null &&
|
||||
header.BoxType == BoxType.Udta) {
|
||||
// For compatibility, we still store the tree to the first udta
|
||||
// block. The proper way to get this info is from the individual
|
||||
// IsoUserDataBox.ParentTree member.
|
||||
udta_tree = AddParent (parents, header).ToArray ();
|
||||
} else if (header.BoxType == BoxType.Mdat) {
|
||||
mdat_start = position;
|
||||
mdat_end = position + header.TotalBoxSize;
|
||||
}
|
||||
|
||||
if (header.TotalBoxSize == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses boxes for a specified range, looking for tags.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to start reading.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to stop reading.
|
||||
/// </param>
|
||||
/// <param name="parents">
|
||||
/// A <see cref="T:List" /> of <see cref="BoxHeader" /> parents.
|
||||
/// </param>
|
||||
void ParseTag (long start, long end, List<BoxHeader> parents)
|
||||
{
|
||||
BoxHeader header;
|
||||
|
||||
for (long position = start; position < end; position += header.TotalBoxSize) {
|
||||
header = new BoxHeader (file, position);
|
||||
|
||||
if (header.BoxType == BoxType.Moov) {
|
||||
ParseTag (header.HeaderSize + position, header.TotalBoxSize + position, AddParent (parents, header));
|
||||
} else if (header.BoxType == BoxType.Mdia ||
|
||||
header.BoxType == BoxType.Minf ||
|
||||
header.BoxType == BoxType.Stbl ||
|
||||
header.BoxType == BoxType.Trak) {
|
||||
ParseTag (header.HeaderSize + position, header.TotalBoxSize + position, AddParent (parents, header));
|
||||
} else if (header.BoxType == BoxType.Udta) {
|
||||
var udtaBox = BoxFactory.CreateBox (file, header) as IsoUserDataBox;
|
||||
|
||||
// Since we can have multiple udta boxes, save the parent for each one
|
||||
List<BoxHeader> new_parents = AddParent (parents, header);
|
||||
udtaBox.ParentTree = new_parents.ToArray ();
|
||||
|
||||
udta_boxes.Add (udtaBox);
|
||||
} else if (header.BoxType == BoxType.Mdat) {
|
||||
mdat_start = position;
|
||||
mdat_end = position + header.TotalBoxSize;
|
||||
}
|
||||
|
||||
if (header.TotalBoxSize == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses boxes for a specified range, looking for tags and
|
||||
/// properties.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to start reading.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to stop reading.
|
||||
/// </param>
|
||||
/// <param name="handler">
|
||||
/// A <see cref="IsoHandlerBox" /> object that applied to the
|
||||
/// range being searched.
|
||||
/// </param>
|
||||
/// <param name="parents">
|
||||
/// A <see cref="T:List" /> of <see cref="BoxHeader" /> parents.
|
||||
/// </param>
|
||||
void ParseTagAndProperties (long start, long end, IsoHandlerBox handler, List<BoxHeader> parents)
|
||||
{
|
||||
BoxHeader header;
|
||||
|
||||
for (long position = start; position < end; position += header.TotalBoxSize) {
|
||||
header = new BoxHeader (file, position);
|
||||
ByteVector type = header.BoxType;
|
||||
|
||||
if (type == BoxType.Moov) {
|
||||
ParseTagAndProperties (header.HeaderSize + position, header.TotalBoxSize + position, handler, AddParent (parents, header));
|
||||
} else if (type == BoxType.Mdia ||
|
||||
type == BoxType.Minf ||
|
||||
type == BoxType.Stbl ||
|
||||
type == BoxType.Trak) {
|
||||
ParseTagAndProperties (header.HeaderSize + position, header.TotalBoxSize + position, handler, AddParent (parents, header));
|
||||
} else if (type == BoxType.Stsd) {
|
||||
stsd_boxes.Add (BoxFactory.CreateBox (file, header, handler));
|
||||
} else if (type == BoxType.Hdlr) {
|
||||
handler = BoxFactory.CreateBox (file, header, handler) as IsoHandlerBox;
|
||||
} else if (mvhd_box == null &&
|
||||
type == BoxType.Mvhd) {
|
||||
mvhd_box = BoxFactory.CreateBox (file, header, handler) as IsoMovieHeaderBox;
|
||||
} else if (type == BoxType.Udta) {
|
||||
var udtaBox = BoxFactory.CreateBox (file, header, handler) as IsoUserDataBox;
|
||||
|
||||
// Since we can have multiple udta boxes, save the parent for each one
|
||||
List<BoxHeader> new_parents = AddParent (parents, header);
|
||||
udtaBox.ParentTree = new_parents.ToArray ();
|
||||
|
||||
udta_boxes.Add (udtaBox);
|
||||
} else if (type == BoxType.Mdat) {
|
||||
mdat_start = position;
|
||||
mdat_end = position + header.TotalBoxSize;
|
||||
}
|
||||
|
||||
if (header.TotalBoxSize == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses boxes for a specified range, looking for chunk
|
||||
/// offset boxes.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to start reading.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to stop reading.
|
||||
/// </param>
|
||||
void ParseChunkOffsets (long start, long end)
|
||||
{
|
||||
BoxHeader header;
|
||||
|
||||
for (long position = start; position < end; position += header.TotalBoxSize) {
|
||||
header = new BoxHeader (file, position);
|
||||
|
||||
if (header.BoxType == BoxType.Moov) {
|
||||
ParseChunkOffsets (header.HeaderSize + position, header.TotalBoxSize + position);
|
||||
} else if (header.BoxType == BoxType.Moov ||
|
||||
header.BoxType == BoxType.Mdia ||
|
||||
header.BoxType == BoxType.Minf ||
|
||||
header.BoxType == BoxType.Stbl ||
|
||||
header.BoxType == BoxType.Trak) {
|
||||
ParseChunkOffsets (header.HeaderSize + position, header.TotalBoxSize + position);
|
||||
} else if (header.BoxType == BoxType.Stco ||
|
||||
header.BoxType == BoxType.Co64) {
|
||||
stco_boxes.Add (BoxFactory.CreateBox (file, header));
|
||||
} else if (header.BoxType == BoxType.Mdat) {
|
||||
mdat_start = position;
|
||||
mdat_end = position + header.TotalBoxSize;
|
||||
}
|
||||
|
||||
if (header.TotalBoxSize == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets all internal fields.
|
||||
/// </summary>
|
||||
void ResetFields ()
|
||||
{
|
||||
mvhd_box = null;
|
||||
udta_boxes.Clear ();
|
||||
moov_tree = null;
|
||||
udta_tree = null;
|
||||
stco_boxes.Clear ();
|
||||
stsd_boxes.Clear ();
|
||||
mdat_start = -1;
|
||||
mdat_end = -1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parent to the end of an existing list of parents.
|
||||
/// </summary>
|
||||
/// <param name="parents">
|
||||
/// A <see cref="T:System.Collections.Generic.List`1" /> object containing an existing
|
||||
/// list of parents.
|
||||
/// </param>
|
||||
/// <param name="current">
|
||||
/// A <see cref="BoxHeader" /> object to add to the list.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new <see cref="T:System.Collections.Generic.List`1" /> object containing the list
|
||||
/// of parents, including the added header.
|
||||
/// </returns>
|
||||
static List<BoxHeader> AddParent (List<BoxHeader> parents,
|
||||
BoxHeader current)
|
||||
{
|
||||
var boxes = new List<BoxHeader> ();
|
||||
if (parents != null)
|
||||
boxes.AddRange (parents);
|
||||
boxes.Add (current);
|
||||
return boxes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4127087987d48cdcdab867448633fd84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user