Author: jcsston
Date: 2004-10-02 00:35:50 +0400 (Sat, 02 Oct 2004)
New Revision: 849
Added:
trunk/JEBML/JEBML.sln
trunk/JEBML/src/org/ebml/FileDataSource.java
Modified:
trunk/JEBML/
trunk/JEBML/JEBML.jpx
trunk/JEBML/JEBML.vjsproj
trunk/JEBML/src/ebml/EbmlSampleAppFrame.java
trunk/JEBML/src/org/ebml/DataSource.java
trunk/JEBML/src/org/ebml/DateElement.java
trunk/JEBML/src/org/ebml/InputStreamDataSource.java
trunk/JEBML/src/org/ebml/StringElement.java
trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java
trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java
trunk/JEBML/src/org/ebml/matroska/jmf/JMFPullSourceStreamDataSource.java
trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexer.java
trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexerTrack.java
Log:
Property changes on: trunk/JEBML
___________________________________________________________________
Name: svn:ignore
+ classes
obj
bak
bin
Modified: trunk/JEBML/JEBML.jpx
===================================================================
--- trunk/JEBML/JEBML.jpx 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/JEBML.jpx 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,73 +1,107 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--JBuilder XML Project-->
-<project>
- <property category="debug.0" name="SmartStepRedefineClasses" value="0"/>
- <property category="debug.0" name="SmartStepSkipStaticInitializers" value="0"/>
- <property category="debug.0" name="SmartStepSkipSynthetics" value="0"/>
- <property category="javaFormatting" name="catchOnNewLine" value="0"/>
- <property category="javaFormatting" name="classBraceNextLine" value="1"/>
- <property category="javaFormatting" name="elseOnNewLine" value="0"/>
- <property category="javaFormatting" name="spaceAfterTypecast" value="0"/>
- <property category="javaFormatting" name="spaceBeforeLparen" value="0"/>
- <property category="javaFormatting" name="whileOnNewLine" value="0"/>
- <property category="javadoc" name="custom.tags.1" value="todo;a;To Do:"/>
- <property category="runtime" name="DefaultConfiguration" value="-1"/>
- <property category="runtime.0" name="ConfigurationName" value="EbmlSampleApp"/>
- <property category="runtime.0" name="RunnableType" value="com.borland.jbuilder.runtime.ApplicationRunner"/>
- <property category="runtime.0" name="application.class" value="ebml.EbmlSampleApp"/>
- <property category="serverservices" name="single.server.name" value="Tomcat 4.0"/>
- <property category="sys" name="AuthorLabel" value="@author"/>
- <property category="sys" name="BackupPath" value="bak"/>
- <property category="sys" name="CheckStable" value="1"/>
- <property category="sys" name="Company" value=""/>
- <property category="sys" name="CompanyLabel" value="Company:"/>
- <property category="sys" name="Copyright" value="Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]>"/>
- <property category="sys" name="CopyrightLabel" value="Copyright:"/>
- <property category="sys" name="DefaultPath" value="src"/>
- <property category="sys" name="Description" value="Java Classes to Read EBML Elements"/>
- <property category="sys" name="DescriptionLabel" value="Description:"/>
- <property category="sys" name="DocPath" value="doc"/>
- <property category="sys" name="Encoding" value="UTF8"/>
- <property category="sys" name="ExcludeClassEnabled" value="0"/>
- <property category="sys" name="IncludeTestPath" value="1"/>
- <property category="sys" name="InstanceVisibility" value="2"/>
- <property category="sys" name="JDK" value="java version 1.4.1_02-b06"/>
- <property category="sys" name="JvmVersion" value="1.2"/>
- <property category="sys" name="LastTag" value="0"/>
- <property category="sys" name="Libraries" value="JUnit"/>
- <property category="sys" name="MakeStable" value="0"/>
- <property category="sys" name="OutPath" value="classes"/>
- <property category="sys" name="SourcePath" value="src;test"/>
- <property category="sys" name="TestPath" value="test"/>
- <property category="sys" name="Title" value="JEBML"/>
- <property category="sys" name="TitleLabel" value="Title:"/>
- <property category="sys" name="Version" value="1.0"/>
- <property category="sys" name="VersionLabel" value="@version"/>
- <property category="sys" name="WorkingDirectory" value="."/>
- <node name="Application" type="Archive">
- <property category="archiving" name="archiverClass" value="com.borland.jbuilder.wizard.archive.ApplicationArchiver"/>
- <property category="archiving" name="buildWithProject" value="0"/>
- <property category="archiving" name="contentRules.1" value="I:**/*.*"/>
- <property category="archiving" name="contentRules.2" value="F:JEBML-src.jar;JEBML-src.jar"/>
- <property category="archiving" name="targetCompressed" value="1"/>
- <property category="archiving" name="targetPath" value="JEBMLSample.jar"/>
- <property category="archiving" name="usingRules" value="1"/>
- </node>
- <node name="Source" type="Archive">
- <property category="archiving" name="archiverClass" value="com.borland.jbuilder.wizard.archive.SourceArchiver"/>
- <property category="archiving" name="buildWithProject" value="0"/>
- <property category="archiving" name="targetCompressed" value="1"/>
- <property category="archiving" name="targetPath" value="JEBML.jar"/>
- </node>
- <file path="src/org/ebml/BinaryElement.java"/>
- <file path="src/ebml/CommandLineSample.java"/>
- <file path="src/org/ebml/DataSource.java"/>
- <file path="src/org/ebml/EBMLReader.java"/>
- <file path="src/ebml/EbmlSampleApp.java"/>
- <file path="src/ebml/EbmlSampleAppFrame.java"/>
- <file path="src/org/ebml/Element.java"/>
- <file path="src/org/ebml/InputStreamDataSource.java"/>
- <file path="src/org/ebml/SignedInteger.java"/>
- <file path="src/org/ebml/StringElement.java"/>
- <file path="src/org/ebml/UnsignedInteger.java"/>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--JBuilder XML Project-->
+<project>
+ <property category="debug.0" name="SmartStepRedefineClasses" value="0"/>
+ <property category="debug.0" name="SmartStepSkipStaticInitializers" value="0"/>
+ <property category="debug.0" name="SmartStepSkipSynthetics" value="0"/>
+ <property category="idl" name="ProcessIDL" value="false"/>
+ <property category="javaFormatting" name="catchOnNewLine" value="0"/>
+ <property category="javaFormatting" name="classBraceNextLine" value="1"/>
+ <property category="javaFormatting" name="elseOnNewLine" value="0"/>
+ <property category="javaFormatting" name="spaceAfterTypecast" value="0"/>
+ <property category="javaFormatting" name="spaceBeforeLparen" value="0"/>
+ <property category="javaFormatting" name="whileOnNewLine" value="0"/>
+ <property category="javadoc" name="custom.tags.1" value="todo;a;To Do:"/>
+ <property category="optimize.0" name="OptimizableType" value="com.borland.jbuilder.optimize.IntroOptimizeitProfiler"/>
+ <property category="optimize.1" name="OptimizableType" value="intuitive.ide.borland.jb10.ProfilerBootstrap"/>
+ <property category="optimize.1" name="oicc.FilterFile" value="C:\Documents and Settings\Jory.JCSSTON\My Documents\Visual Studio Projects\matroska\JEBML\JEBML.oif"/>
+ <property category="optimize.1" name="oipr.FilterFile" value="C:\Documents and Settings\Jory.JCSSTON\My Documents\Visual Studio Projects\matroska\JEBML\JEBML.oif"/>
+ <property category="personality" name="personality" value=""/>
+ <property category="runtime" name="ConfigurationCount" value="1"/>
+ <property category="runtime.0" name="BuildTargetOnRun" value="com.borland.jbuilder.build.ProjectBuilder$ProjectBuildAction;make"/>
+ <property category="runtime.0" name="ConfigurationName" value="EbmlSampleApp"/>
+ <property category="runtime.0" name="RunnableType" value="com.borland.jbuilder.runtime.ApplicationRunner"/>
+ <property category="runtime.0" name="application.class" value="ebml.EbmlSampleApp"/>
+ <property category="runtime.1" name="BuildTargetOnRun" value="com.borland.jbuilder.build.ProjectBuilder$ProjectBuildAction;make"/>
+ <property category="runtime.1" name="ConfigurationName" value="JMStudio - JMF"/>
+ <property category="runtime.1" name="RunnableType" value="com.borland.jbuilder.runtime.ApplicationRunner"/>
+ <property category="runtime.1" name="application.class" value="JMStudio"/>
+ <property category="runtime.1" name="application.parameters" value=""I:\videos\111-Videos_111\Linkin Park - Crawling-remux-no-lacing.mkv""/>
+ <property category="runtime.1" name="custom.init_required" value="0"/>
+ <property category="runtime.1" name="custom.required.1" value="JMF"/>
+ <property category="serverservices" name="disabled.services" value="jdatastore;sqlj"/>
+ <property category="serverservices" name="single.server.name" value="Tomcat 4.0"/>
+ <property category="sys" name="AuthorLabel" value="@author"/>
+ <property category="sys" name="BackupPath" value="bak"/>
+ <property category="sys" name="CheckStable" value="1"/>
+ <property category="sys" name="Company" value=""/>
+ <property category="sys" name="CompanyLabel" value="Company:"/>
+ <property category="sys" name="Copyright" value="Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]>"/>
+ <property category="sys" name="CopyrightLabel" value="Copyright:"/>
+ <property category="sys" name="DefaultPath" value="src"/>
+ <property category="sys" name="Description" value="Java Classes to Read EBML Elements"/>
+ <property category="sys" name="DescriptionLabel" value="Description:"/>
+ <property category="sys" name="DocPath" value="doc"/>
+ <property category="sys" name="Encoding" value="UTF8"/>
+ <property category="sys" name="ExcludeClassEnabled" value="0"/>
+ <property category="sys" name="IncludeTestPath" value="1"/>
+ <property category="sys" name="InstanceVisibility" value="2"/>
+ <property category="sys" name="JDK" value="java version 1.4.2_01-b06"/>
+ <property category="sys" name="JvmVersion" value="1.2"/>
+ <property category="sys" name="LastTag" value="0"/>
+ <property category="sys" name="Libraries" value="JMF"/>
+ <property category="sys" name="MakeStable" value="0"/>
+ <property category="sys" name="OutPath" value="classes"/>
+ <property category="sys" name="SourcePath" value="src;test"/>
+ <property category="sys" name="TestPath" value="test"/>
+ <property category="sys" name="Title" value="JEBML"/>
+ <property category="sys" name="TitleLabel" value="Title:"/>
+ <property category="sys" name="Version" value="1.0"/>
+ <property category="sys" name="VersionLabel" value="@version"/>
+ <property category="sys" name="WorkingDirectory" value="."/>
+ <node name="Application" type="Archive">
+ <property category="archiving" name="archiverClass" value="com.borland.jbuilder.wizard.archive.ApplicationArchiver"/>
+ <property category="archiving" name="buildWithProject" value="0"/>
+ <property category="archiving" name="contentRules.1" value="I:**/*.*"/>
+ <property category="archiving" name="contentRules.2" value="F:JEBML-src.jar;JEBML-src.jar"/>
+ <property category="archiving" name="targetCompressed" value="1"/>
+ <property category="archiving" name="targetPath" value="JEBML.jar"/>
+ <property category="archiving" name="usingRules" value="1"/>
+ </node>
+ <node name="Native Executable" type="Archive">
+ <property category="archiving" name="archiverClass" value="com.borland.jbuilder.wizard.archive.ExecutableArchiver"/>
+ <property category="archiving" name="buildWithProject" value="0"/>
+ <property category="archiving" name="contentRules.1" value="I:**/*.*"/>
+ <property category="archiving" name="executableEnabled.1" value="1"/>
+ <property category="archiving" name="executableEnabled.2" value="0"/>
+ <property category="archiving" name="executableEnabled.3" value="1"/>
+ <property category="archiving" name="executableEnabled.4" value="0"/>
+ <property category="archiving" name="executableEnabled.5" value="0"/>
+ <property category="archiving" name="executableFiles.1" value=""/>
+ <property category="archiving" name="executableFiles.2" value="JEBML2.exe"/>
+ <property category="archiving" name="executableFiles.3" value=""/>
+ <property category="archiving" name="executableFiles.4" value="JEBML2-solaris"/>
+ <property category="archiving" name="executableFiles.5" value="JEBML2-mac"/>
+ <property category="archiving" name="manifestMainClass" value="ebml.EbmlSampleApp"/>
+ <property category="archiving" name="targetCompressed" value="1"/>
+ <property category="archiving" name="targetPath" value="JEBML-Native.jar"/>
+ <property category="archiving" name="usingRules" value="1"/>
+ </node>
+ <node name="Source" type="Archive">
+ <property category="archiving" name="archiverClass" value="com.borland.jbuilder.wizard.archive.SourceArchiver"/>
+ <property category="archiving" name="buildWithProject" value="0"/>
+ <property category="archiving" name="targetCompressed" value="1"/>
+ <property category="archiving" name="targetPath" value="JEBML-src.jar"/>
+ </node>
+ <file path="src/org/ebml/BinaryElement.java"/>
+ <file path="src/ebml/CommandLineSample.java"/>
+ <file path="src/org/ebml/DataSource.java"/>
+ <file path="src/org/ebml/EBMLReader.java"/>
+ <file path="src/ebml/EbmlSampleApp.java"/>
+ <file path="src/ebml/EbmlSampleAppFrame.java"/>
+ <file path="src/org/ebml/Element.java"/>
+ <file path="src/org/ebml/InputStreamDataSource.java"/>
+ <file path="src/org/ebml/SignedInteger.java"/>
+ <file path="src/org/ebml/StringElement.java"/>
+ <file path="src/org/ebml/UnsignedInteger.java"/>
+</project>
Added: trunk/JEBML/JEBML.sln
===================================================================
--- trunk/JEBML/JEBML.sln 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/JEBML.sln 2004-10-01 20:35:50 UTC (rev 849)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{E6FDF86B-F3D1-11D4-8576-0002A516ECE8}") = "JEBML", "JEBML.vjsproj", "{2FE45AE7-D916-497F-9035-B6EDA1C9E34C}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {2FE45AE7-D916-497F-9035-B6EDA1C9E34C}.Debug.ActiveCfg = Debug|.NET
+ {2FE45AE7-D916-497F-9035-B6EDA1C9E34C}.Debug.Build.0 = Debug|.NET
+ {2FE45AE7-D916-497F-9035-B6EDA1C9E34C}.Release.ActiveCfg = Release|.NET
+ {2FE45AE7-D916-497F-9035-B6EDA1C9E34C}.Release.Build.0 = Release|.NET
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
Modified: trunk/JEBML/JEBML.vjsproj
===================================================================
--- trunk/JEBML/JEBML.vjsproj 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/JEBML.vjsproj 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,166 +1,171 @@
-<VisualStudioProject>
- <VISUALJSHARP
- ProjectType = "Local"
- ProductVersion = "7.10.3077"
- SchemaVersion = "2.0"
- ProjectGuid = "{2FE45AE7-D916-497F-9035-B6EDA1C9E34C}"
- >
- <Build>
- <Settings
- AssemblyKeyContainerName = ""
- AssemblyName = "JEBML"
- AssemblyOriginatorKeyFile = ""
- DefaultClientScript = "JScript"
- DefaultHTMLPageLayout = "Grid"
- DefaultTargetSchema = "IE50"
- OutputType = "Library"
- PreBuildEvent = ""
- PostBuildEvent = ""
- RootNamespace = "JEBML"
- RunPostBuildEvent = "OnBuildSuccess"
- StartupObject = ""
- >
- <Config
- Name = "Debug"
- BaseAddress = "285212672"
- ConfigurationOverrideFile = ""
- DefineConstants = "DEBUG;TRACE"
- DebugSymbols = "true"
- NoWarn = ""
- Optimize = "false"
- OutputPath = "bin\Debug\"
- RegisterForComInterop = "false"
- TreatWarningsAsErrors = "false"
- WarningLevel = "4"
- AdditionalOptions = ""
- />
- <Config
- Name = "Release"
- BaseAddress = "285212672"
- ConfigurationOverrideFile = ""
- DefineConstants = "TRACE"
- DebugSymbols = "false"
- NoWarn = ""
- Optimize = "true"
- OutputPath = "bin\Release\"
- RegisterForComInterop = "false"
- TreatWarningsAsErrors = "false"
- WarningLevel = "4"
- AdditionalOptions = ""
- />
- </Settings>
- <References>
- <Reference
- Name = "vjslib"
- AssemblyName = "vjslib"
- HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\vjslib.dll"
- />
- <Reference
- Name = "System"
- AssemblyName = "System"
- HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\System.dll"
- />
- <Reference
- Name = "System.Data"
- AssemblyName = "System.Data"
- HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
- />
- <Reference
- Name = "System.XML"
- AssemblyName = "System.XML"
- HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
- />
- </References>
- </Build>
- <Files>
- <Include>
- <File
- RelPath = "src\org\ebml\BinaryElement.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\DataSource.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\DateElement.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\DocType.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\EBMLReader.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\Element.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\ElementType.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\FloatElement.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\InputStreamDataSource.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\MasterElement.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\SignedInteger.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\StringElement.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\UnknownElementType.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\UnsignedInteger.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\matroska\MatroskaBlock.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\matroska\MatroskaDocType.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
- RelPath = "src\org\ebml\matroska\MatroskaFile.java"
- SubType = "Code"
- BuildAction = "Compile"
- />
- </Include>
- </Files>
- </VISUALJSHARP>
-</VisualStudioProject>
-
+<VisualStudioProject>
+ <VISUALJSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{2FE45AE7-D916-497F-9035-B6EDA1C9E34C}"
+ >
+ <Build>
+ <Settings
+ AssemblyKeyContainerName = ""
+ AssemblyName = "JEBML"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = ""
+ RootNamespace = "JEBML"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ BaseAddress = "285212672"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DebugSymbols = "true"
+ NoWarn = ""
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ AdditionalOptions = ""
+ />
+ <Config
+ Name = "Release"
+ BaseAddress = "285212672"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DebugSymbols = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ AdditionalOptions = ""
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "vjslib"
+ AssemblyName = "vjslib"
+ HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\vjslib.dll"
+ />
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\WINXP\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "src\org\ebml\BinaryElement.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\DataSource.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\DateElement.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\DocType.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\EBMLReader.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\Element.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\ElementType.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\FileDataSource.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\FloatElement.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\InputStreamDataSource.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\MasterElement.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\SignedInteger.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\StringElement.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\UnknownElementType.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\UnsignedInteger.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\matroska\MatroskaBlock.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\matroska\MatroskaDocType.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\org\ebml\matroska\MatroskaFile.java"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </VISUALJSHARP>
+</VisualStudioProject>
+
Modified: trunk/JEBML/src/ebml/EbmlSampleAppFrame.java
===================================================================
--- trunk/JEBML/src/ebml/EbmlSampleAppFrame.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/ebml/EbmlSampleAppFrame.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,151 +1,151 @@
-package ebml;
-
-import java.io.*;
-import java.lang.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-
-import org.ebml.*;
-import org.ebml.matroska.MatroskaFile;
-
-/**
- * <p>Title: EBMLReader</p>
- * <p>Description: Java Classes to Read EBML Elements</p>
- * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
- * <p>Company: </p>
- * @author jcsston
- * @version 1.0
- */
-
-public class EbmlSampleAppFrame
- extends JFrame {
- JPanel contentPane;
- JMenuBar jMenuBar1 = new JMenuBar();
- JMenu jMenuFile = new JMenu();
- JMenuItem jMenuFileExit = new JMenuItem();
- BorderLayout borderLayout1 = new BorderLayout();
- JMenuItem jMenuItemOpen = new JMenuItem();
- JFileChooser jFileChooser1 = new JFileChooser();
- JTextArea jTextArea1 = new JTextArea();
-
- //Construct the frame
- public EbmlSampleAppFrame() {
- enableEvents(AWTEvent.WINDOW_EVENT_MASK);
- try {
- jbInit();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- //Component initialization
- private void jbInit() throws Exception {
- contentPane = (JPanel)this.getContentPane();
- contentPane.setLayout(borderLayout1);
- this.setSize(new Dimension(400, 300));
- this.setTitle("Ebml Sample App");
- jMenuFile.setText("File");
- jMenuFileExit.setText("Exit");
- jMenuFileExit.addActionListener(new
- EbmlSampleAppFrame_jMenuFileExit_ActionAdapter(this));
- jMenuItemOpen.setText("Open");
- jMenuItemOpen.addActionListener(new
- EbmlSampleAppFrame_jMenuItemOpen_actionAdapter(this));
- jFileChooser1.setAcceptAllFileFilterUsed(true);
- jFileChooser1.setDialogTitle("Select a Matroska File");
- jFileChooser1.setFileFilter(null);
- jTextArea1.setTabSize(8);
- jMenuFile.add(jMenuItemOpen);
- jMenuFile.add(jMenuFileExit);
- jMenuBar1.add(jMenuFile);
- contentPane.add(jTextArea1, BorderLayout.CENTER);
- this.setJMenuBar(jMenuBar1);
- }
-
- //File | Exit action performed
- public void jMenuFileExit_actionPerformed(ActionEvent e) {
- System.exit(0);
- }
-
- //Overridden so we can exit when window is closed
- protected void processWindowEvent(WindowEvent e) {
- super.processWindowEvent(e);
- if (e.getID() == WindowEvent.WINDOW_CLOSING) {
- jMenuFileExit_actionPerformed(null);
- }
- }
-
- void jMenuItemOpen_actionPerformed(ActionEvent e) {
- try {
- jFileChooser1.setFileFilter(new org.ebml.matroska.MatroskaFileFilter());
-
- int ret = jFileChooser1.showOpenDialog(this);
- if (ret == JFileChooser.APPROVE_OPTION) {
- /*
- FileInputStream inFS1 = new FileInputStream("I:\\videos\\111-Videos_111\\Linkin Park - Crawling-remux.mkvmerge.mp3");
- FileOutputStream outFS1 = new FileOutputStream("I:\\videos\\111-Videos_111\\Linkin Park - Crawling-remux.mkvmerge.java.mp3");
- byte [] buffer = new byte[64];
- int len = 64;
- while (len > 0) {
- len = inFS1.read(buffer);
- outFS1.write(buffer, 0, len);
- }
- */
- FileOutputStream outFS = new FileOutputStream(jFileChooser1.getSelectedFile() + ".mp3");
- FileInputStream ioF = new FileInputStream(jFileChooser1.getSelectedFile());
- jTextArea1.append("Scanning file: " + jFileChooser1.getSelectedFile().toString() + "\n");
-
- MatroskaFile mF = new MatroskaFile(ioF);
- mF.readFile();
- jTextArea1.append(mF.getReport());
-
- MatroskaFile.MatroskaFrame frame = mF.getNextFrame(2);
- while (frame != null) {
- frame = mF.getNextFrame(2);
- if (frame != null)
- outFS.write(frame.Data);
- }
-
- jTextArea1.append("Scan complete.\n");
- }
- } catch (java.io.FileNotFoundException ex) {
- jTextArea1.append("File Not Found!\n");
- ex.printStackTrace();
- } catch (java.io.IOException ex) {
- jTextArea1.append("File IO Error!\n");
- ex.printStackTrace();
- } catch (java.lang.RuntimeException ex) {
- jTextArea1.append("Error: " + ex.toString() + ex.getMessage() + "\"\n");
- ex.printStackTrace();
- }
- }
-}
-
-class EbmlSampleAppFrame_jMenuFileExit_ActionAdapter
- implements ActionListener {
- EbmlSampleAppFrame adaptee;
-
- EbmlSampleAppFrame_jMenuFileExit_ActionAdapter(EbmlSampleAppFrame adaptee) {
- this.adaptee = adaptee;
- }
-
- public void actionPerformed(ActionEvent e) {
- adaptee.jMenuFileExit_actionPerformed(e);
- }
-}
-
-class EbmlSampleAppFrame_jMenuItemOpen_actionAdapter
- implements java.awt.event.ActionListener {
- EbmlSampleAppFrame adaptee;
-
- EbmlSampleAppFrame_jMenuItemOpen_actionAdapter(EbmlSampleAppFrame adaptee) {
- this.adaptee = adaptee;
- }
-
- public void actionPerformed(ActionEvent e) {
- adaptee.jMenuItemOpen_actionPerformed(e);
- }
+package ebml;
+
+import java.io.*;
+import java.lang.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import org.ebml.*;
+import org.ebml.matroska.MatroskaFile;
+
+/**
+ * <p>Title: EBMLReader</p>
+ * <p>Description: Java Classes to Read EBML Elements</p>
+ * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
+ * <p>Company: </p>
+ * @author jcsston
+ * @version 1.0
+ */
+
+public class EbmlSampleAppFrame
+ extends JFrame {
+ JPanel contentPane;
+ JMenuBar jMenuBar1 = new JMenuBar();
+ JMenu jMenuFile = new JMenu();
+ JMenuItem jMenuFileExit = new JMenuItem();
+ BorderLayout borderLayout1 = new BorderLayout();
+ JMenuItem jMenuItemOpen = new JMenuItem();
+ JFileChooser jFileChooser1 = new JFileChooser();
+ JTextArea jTextArea1 = new JTextArea();
+
+ //Construct the frame
+ public EbmlSampleAppFrame() {
+ enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+ try {
+ jbInit();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //Component initialization
+ private void jbInit() throws Exception {
+ contentPane = (JPanel)this.getContentPane();
+ contentPane.setLayout(borderLayout1);
+ this.setSize(new Dimension(400, 300));
+ this.setTitle("Ebml Sample App");
+ jMenuFile.setText("File");
+ jMenuFileExit.setText("Exit");
+ jMenuFileExit.addActionListener(new
+ EbmlSampleAppFrame_jMenuFileExit_ActionAdapter(this));
+ jMenuItemOpen.setText("Open");
+ jMenuItemOpen.addActionListener(new
+ EbmlSampleAppFrame_jMenuItemOpen_actionAdapter(this));
+ jFileChooser1.setAcceptAllFileFilterUsed(true);
+ jFileChooser1.setDialogTitle("Select a Matroska File");
+ jFileChooser1.setFileFilter(null);
+ jTextArea1.setTabSize(8);
+ jMenuFile.add(jMenuItemOpen);
+ jMenuFile.add(jMenuFileExit);
+ jMenuBar1.add(jMenuFile);
+ contentPane.add(jTextArea1, BorderLayout.CENTER);
+ this.setJMenuBar(jMenuBar1);
+ }
+
+ //File | Exit action performed
+ public void jMenuFileExit_actionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
+
+ //Overridden so we can exit when window is closed
+ protected void processWindowEvent(WindowEvent e) {
+ super.processWindowEvent(e);
+ if (e.getID() == WindowEvent.WINDOW_CLOSING) {
+ jMenuFileExit_actionPerformed(null);
+ }
+ }
+
+ void jMenuItemOpen_actionPerformed(ActionEvent e) {
+ try {
+ jFileChooser1.setFileFilter(new org.ebml.matroska.MatroskaFileFilter());
+
+ int ret = jFileChooser1.showOpenDialog(this);
+ if (ret == JFileChooser.APPROVE_OPTION) {
+ /*
+ FileInputStream inFS1 = new FileInputStream("I:\\videos\\111-Videos_111\\Linkin Park - Crawling-remux.mkvmerge.mp3");
+ FileOutputStream outFS1 = new FileOutputStream("I:\\videos\\111-Videos_111\\Linkin Park - Crawling-remux.mkvmerge.java.mp3");
+ byte [] buffer = new byte[64];
+ int len = 64;
+ while (len > 0) {
+ len = inFS1.read(buffer);
+ outFS1.write(buffer, 0, len);
+ }
+ */
+ FileOutputStream outFS = new FileOutputStream(jFileChooser1.getSelectedFile() + ".mp3");
+ FileInputStream ioF = new FileInputStream(jFileChooser1.getSelectedFile());
+ jTextArea1.append("Scanning file: " + jFileChooser1.getSelectedFile().toString() + "\n");
+
+ MatroskaFile mF = new MatroskaFile(ioF);
+ mF.readFile();
+ jTextArea1.append(mF.getReport());
+
+ /*MatroskaFile.MatroskaFrame frame = mF.getNextFrame(2);
+ while (frame != null) {
+ frame = mF.getNextFrame(2);
+ if (frame != null)
+ outFS.write(frame.Data);
+ }*/
+
+ jTextArea1.append("Scan complete.\n");
+ }
+ } catch (java.io.FileNotFoundException ex) {
+ jTextArea1.append("File Not Found!\n");
+ ex.printStackTrace();
+ } catch (java.io.IOException ex) {
+ jTextArea1.append("File IO Error!\n");
+ ex.printStackTrace();
+ } catch (java.lang.RuntimeException ex) {
+ jTextArea1.append("Error: " + ex.toString() + ex.getMessage() + "\"\n");
+ ex.printStackTrace();
+ }
+ }
+}
+
+class EbmlSampleAppFrame_jMenuFileExit_ActionAdapter
+ implements ActionListener {
+ EbmlSampleAppFrame adaptee;
+
+ EbmlSampleAppFrame_jMenuFileExit_ActionAdapter(EbmlSampleAppFrame adaptee) {
+ this.adaptee = adaptee;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ adaptee.jMenuFileExit_actionPerformed(e);
+ }
+}
+
+class EbmlSampleAppFrame_jMenuItemOpen_actionAdapter
+ implements java.awt.event.ActionListener {
+ EbmlSampleAppFrame adaptee;
+
+ EbmlSampleAppFrame_jMenuItemOpen_actionAdapter(EbmlSampleAppFrame adaptee) {
+ this.adaptee = adaptee;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ adaptee.jMenuItemOpen_actionPerformed(e);
+ }
}
\ No newline at end of file
Modified: trunk/JEBML/src/org/ebml/DataSource.java
===================================================================
--- trunk/JEBML/src/org/ebml/DataSource.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/DataSource.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,29 +1,60 @@
-package org.ebml;
-
-/*
- * DataSource.java
- *
- * Created on November 18, 2002, 4:08 PM
- */
-
-/**
- * Defines the interface used for custom <code>DataSource</code>'s. A
- * <code>DataSource</code> provides methods of reading bytes individually or
- * in arrays. These basic functions must be defined in any <code>DataSource</code>
- * objects to be used with the <code>EBMLReader</code>.
- *
- * @author John Cannon
- */
-
-public interface DataSource {
-
- public byte readByte();
-
- public int read(byte[] buff);
-
- public int read(byte[] buff, int offset, int length);
-
- public int skip(long offset);
-
- public int getBytePosition();
-}
+package org.ebml;
+
+/*
+ * DataSource.java
+ *
+ * Created on November 18, 2002, 4:08 PM
+ */
+
+/**
+ * Defines the interface used for custom <code>DataSource</code>'s. A
+ * <code>DataSource</code> provides methods of reading bytes individually or
+ * in arrays. These basic functions must be defined in any <code>DataSource</code>
+ * objects to be used with the <code>EBMLReader</code>.
+ *
+ * @author John Cannon
+ * @author Jory Stone
+ */
+
+public interface DataSource {
+
+ public byte readByte();
+
+ public int read(byte[] buff);
+
+ public int read(byte[] buff, int offset, int length);
+
+ /**
+ * Skip a number of bytes in the <code>DatSource</code>
+ *
+ * @param offset The number of bytes to skip
+ * @return The number of bytes skipped
+ */
+ public long skip(long offset);
+
+ /**
+ * Returns the length
+ *
+ * @return <code>-1</code> if the length is unknown
+ * @return <code> >0</code> length of the <code>DataSource</code>
+ */
+ public long length();
+
+ public long getFilePointer();
+
+ /**
+ * Check if the <code>DataSource</code> object is seekable
+ *
+ * @return <code>true</code> if seeking is supported.
+ * @return <code>false</code> if seeking is not supported.
+ */
+ public boolean isSeekable();
+
+ /**
+ * Seeks in the <code>DataSource</code>
+ *
+ * @param pos Absolute position to seek to
+ * @return The new file position
+ */
+ public long seek(long pos);
+}
Modified: trunk/JEBML/src/org/ebml/DateElement.java
===================================================================
--- trunk/JEBML/src/org/ebml/DateElement.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/DateElement.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,35 +1,65 @@
-package org.ebml;
-
-import java.util.Date;
-/**
- * <p>Title: JEBML</p>
- * <p>Description: Java Classes to Read EBML Elements</p>
- * <p>Copyright: Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]></p>
- * <p>Company: </p>
- * @author jcsston
- * @version 1.0
- */
-
-public class DateElement extends UnsignedInteger {
-
- public DateElement(byte[] type) {
- super(type);
- }
-
- /**
- * Set the Date of this element
- * @param value Date to set
- */
- public void setDate(Date value) {
- this.setValue(value.getTime());
- }
-
- /**
- * Get the Date value of this element
- * @return Date of this element
- */
- public Date getDate() {
- return new Date(this.getValue());
- }
-
+package org.ebml;
+
+import java.io.*;
+import java.util.*;
+/**
+ * <p>Title: JEBML</p>
+ * <p>Description: Java Classes to Read EBML Elements</p>
+ * <p>Copyright: Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]></p>
+ * <p>Company: </p>
+ * @author jcsston
+ * @version 1.0
+ */
+
+public class DateElement extends BinaryElement {
+ //const uint64 EbmlDate::UnixEpochDelay = 978307200; // 2001/01/01 00:00:00 UTC
+ public static long UnixEpochDelay = 978307200; // 2001/01/01 00:00:00 UTC
+
+ public DateElement(byte[] type) {
+ super(type);
+ }
+
+ /**
+ * Set the Date of this element
+ * @param value Date to set
+ */
+ public void setDate(Date value) {
+ long val = (value.getTime() - UnixEpochDelay) * 100000;
+ try {
+ ByteArrayOutputStream bOS = new ByteArrayOutputStream(8);
+ DataOutputStream dOS = new DataOutputStream(bOS);
+ dOS.writeLong(val);
+ dOS.flush();
+ data = bOS.toByteArray();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Get the Date value of this element
+ * @return Date of this element
+ */
+ public Date getDate() {
+ /*
+ Date begin = new Date(0);
+ Date start = new Date(1970, 1, 1, 0, 0, 0);
+ Date end = new Date(2001, 1, 1, 0, 0, 0);
+ long diff0 = begin.getTime();
+ long diff1 = start.getTime();
+ long diff2 = end.getTime();
+ long diff3 = Date.UTC(2001, 1, 1, 0, 0, 0) - Date.UTC(1970, 1, 1, 0, 0, 0);
+ */
+ long val = 0;
+ try {
+ ByteArrayInputStream bIS = new ByteArrayInputStream(data);
+ DataInputStream dIS = new DataInputStream(bIS);
+ val = dIS.readLong();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ val = val/1000000000 + UnixEpochDelay;
+ return new Date(val);
+ }
+
}
\ No newline at end of file
Added: trunk/JEBML/src/org/ebml/FileDataSource.java
===================================================================
--- trunk/JEBML/src/org/ebml/FileDataSource.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/FileDataSource.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -0,0 +1,76 @@
+package org.ebml;
+
+import java.io.*;
+
+/**
+ * <p>Title: JEBML</p>
+ * <p>Description: Java Classes to Read EBML Elements</p>
+ * <p>Copyright: Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]></p>
+ * <p>Company: </p>
+ * @author jcsston
+ * @version 1.0
+ */
+
+public class FileDataSource implements DataSource {
+ RandomAccessFile file = null;
+
+ public FileDataSource(String filename) throws FileNotFoundException, IOException {
+ file = new RandomAccessFile(filename, "r");
+ }
+ public FileDataSource(String filename, String mode) throws FileNotFoundException, IOException {
+ file = new RandomAccessFile(filename, mode);
+ }
+ public byte readByte() {
+ try {
+ return file.readByte();
+ } catch (IOException ex) {
+ return 0;
+ }
+ }
+ public int read(byte[] buff) {
+ try {
+ return file.read(buff);
+ } catch (IOException ex) {
+ return 0;
+ }
+ }
+ public int read(byte[] buff, int offset, int length) {
+ try {
+ return file.read(buff, offset, length);
+ } catch (IOException ex) {
+ return 0;
+ }
+ }
+ public long skip(long offset) {
+ try {
+ return file.skipBytes((int)offset);
+ } catch (IOException ex) {
+ return 0;
+ }
+ }
+ public long length() {
+ try {
+ return file.length();
+ } catch (IOException ex) {
+ return -1;
+ }
+ }
+ public long getFilePointer() {
+ try {
+ return file.getFilePointer();
+ } catch (IOException ex) {
+ return -1;
+ }
+ }
+ public boolean isSeekable() {
+ return true;
+ }
+ public long seek(long pos) {
+ try {
+ file.seek(pos);
+ return file.getFilePointer();
+ } catch (IOException ex) {
+ return -1;
+ }
+ }
+}
\ No newline at end of file
Modified: trunk/JEBML/src/org/ebml/InputStreamDataSource.java
===================================================================
--- trunk/JEBML/src/org/ebml/InputStreamDataSource.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/InputStreamDataSource.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,75 +1,100 @@
-/*
- * InputStreamDataSource.java
- *
- * Created on November 19, 2002, 9:35 PM
- */
-
-package org.ebml;
-
-/**
- *
- * @author John Cannon
- */
-
-import java.io.*;
-
-public class InputStreamDataSource
- implements DataSource {
- protected InputStream in;
- protected int pos;
-
- public InputStream getInputStream() {
- return in;
- }
- /** Creates a new instance of InputStreamDataSource */
- public InputStreamDataSource(InputStream in) {
- this.in = in;
- }
-
- public int read(byte[] buff) {
- try {
- return pos += in.read(buff);
- }
- catch (IOException e) {
- e.printStackTrace();
- return -1;
- }
- }
-
- public int read(byte[] buff, int offset, int length) {
- try {
- return pos += in.read(buff, offset, length);
- }
- catch (IOException e) {
- e.printStackTrace();
- return -1;
- }
- }
-
- public int skip(long offset) {
- try {
- pos += in.skip(offset);
- return 0;
- }
- catch (IOException e) {
- e.printStackTrace();
- return -1;
- }
- }
-
- public byte readByte() {
- try {
- byte[] b = new byte[1];
- pos += in.read(b);
- return b[0];
- }
- catch (IOException e) {
- e.printStackTrace();
- return -1;
- }
- }
-
- public int getBytePosition() {
- return pos;
- }
-}
+/*
+ * InputStreamDataSource.java
+ *
+ * Created on November 19, 2002, 9:35 PM
+ */
+
+package org.ebml;
+
+/**
+ *
+ * @author John Cannon
+ */
+
+import java.io.*;
+
+public class InputStreamDataSource
+ implements DataSource {
+ protected InputStream in = null;
+ protected long pos = 0;
+ protected byte[] buffer = new byte[1];
+
+ public InputStream getInputStream() {
+ return in;
+ }
+ /** Creates a new instance of InputStreamDataSource */
+ public InputStreamDataSource(InputStream in) {
+ this.in = in;
+ }
+
+ public byte readByte() {
+ try {
+ int l = in.read(buffer);
+ pos += l;
+ return buffer[0];
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ public int read(byte[] buff) {
+ try {
+ int l = in.read(buff);
+ pos += l;
+ return l;
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ public int read(byte[] buff, int offset, int length) {
+ try {
+ int l = in.read(buff, offset, length);
+ pos += l;
+ return l;
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ public long skip(long offset) {
+ try {
+ long l = in.skip(offset);
+ pos += l;
+ return l;
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ public long length() {
+ try {
+ return pos + in.available();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ public long getFilePointer() {
+ return pos;
+ }
+
+ public boolean isSeekable() {
+ return false;
+ }
+
+ public long seek(long pos) {
+ return pos;
+ }
+
+}
Modified: trunk/JEBML/src/org/ebml/StringElement.java
===================================================================
--- trunk/JEBML/src/org/ebml/StringElement.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/StringElement.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,50 +1,64 @@
-package org.ebml;
-
-/**
- * Baisc class for handling an EBML string data type. This class encapsulates
- * both UTF and ASCII string types and can use any string type supported by
- * the Java platform.
- *
- * @author John Cannon
- */
-public class StringElement
- extends org.ebml.BinaryElement {
-
- private String charset = "UTF-8";
-
- /** Creates a new instance of StringElement */
- public StringElement(byte[] typeID) {
- super(typeID);
- }
-
- public StringElement(byte[] typeID, String encoding) {
- super(typeID);
- charset = encoding;
- }
-
- public String getValue() {
- try {
- if (data == null)
- throw new java.lang.IllegalStateException("Call readData() before trying to extract the string value.");
-
- return new String(data, charset);
- }
- catch (java.io.UnsupportedEncodingException ex) {
- ex.printStackTrace();
- return "";
- }
- }
-
- public void setValue(String value) {
- try {
- setData(value.getBytes(charset));
- }
- catch (java.io.UnsupportedEncodingException ex) {
- ex.printStackTrace();
- }
- }
-
- public String getEncoding() {
- return charset;
- }
-}
+package org.ebml;
+
+/**
+ * Baisc class for handling an EBML string data type. This class encapsulates
+ * both UTF and ASCII string types and can use any string type supported by
+ * the Java platform.
+ *
+ * @author John Cannon
+ */
+public class StringElement
+ extends org.ebml.BinaryElement {
+
+ private String charset = "UTF-8";
+
+ /** Creates a new instance of StringElement */
+ public StringElement(byte[] typeID) {
+ super(typeID);
+ }
+
+ public StringElement(byte[] typeID, String encoding) {
+ super(typeID);
+ charset = encoding;
+ }
+
+ public String getValue() {
+ try {
+ if (data == null)
+ throw new java.lang.IllegalStateException("Call readData() before trying to extract the string value.");
+
+ return new String(data, charset);
+ }
+ catch (java.io.UnsupportedEncodingException ex) {
+ // Check if we are trying to read UTF-8, if so lets try UTF8.
+ // Microsofts Java supports "UTF8" but not "UTF-8"
+ if (charset.compareTo("UTF-8") == 0)
+ {
+ charset = "UTF8";
+ // Let's try again
+ return getValue();
+ } else if (charset.compareTo("US-ASCII") == 0) {
+ // This is the same story as UTF-8,
+ // If Microsoft is going to hijack Java they should at least support the orignal :>
+ charset = "ASCII";
+ // Let's try again
+ return getValue();
+ }
+ ex.printStackTrace();
+ return "";
+ }
+ }
+
+ public void setValue(String value) {
+ try {
+ setData(value.getBytes(charset));
+ }
+ catch (java.io.UnsupportedEncodingException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public String getEncoding() {
+ return charset;
+ }
+}
Modified: trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,153 +1,153 @@
-package org.ebml.matroska;
-
-import org.ebml.*;
-
-/**
- * <p>Title: JEBML</p>
- * <p>Description: Java Classes to Read EBML Elements</p>
- * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
- *
- * @author jcsston
- * @version 1.0
- */
-
-public class MatroskaBlock extends BinaryElement {
- protected int [] Sizes = null;
- protected int HeaderSize = 0;
- protected int BlockTimecode = 0;
- protected int TrackNo = 0;
-
- public MatroskaBlock(byte[] type) {
- super(type);
- }
-
- public void readData(DataSource source) {
- parseBlock(source);
- }
-
- public void parseBlock(DataSource source) {
-
- TrackNo = (int)EBMLReader.readEBMLCode(source);
- HeaderSize += Element.EBMLCodedSizeLength(TrackNo);
-
- short BlockTimecode1 = (short)(source.readByte() & 0xFF);
- short BlockTimecode2 = (short)(source.readByte() & 0xFF);
- if (BlockTimecode1 != 0 || BlockTimecode2 != 0) {
- BlockTimecode = (BlockTimecode1 << 8) | BlockTimecode2;
- }
-
- int LaceFlag = source.readByte() & 0x06;
- // Increase the HeaderSize by the number of bytes we have read
- HeaderSize += 3;
- if (LaceFlag != 0x00) {
- // We have lacing
- byte LaceCount = source.readByte();
- HeaderSize += 1;
- if (LaceFlag == 0x02) { // Xiph Lacing
- Sizes = readXiphLaceSizes(source, LaceCount);
-
- } else if (LaceFlag == 0x06) { // EBML Lacing
- Sizes = readEBMLLaceSizes(source, LaceCount);
-
- } else if (LaceFlag == 0x04) { // Fixed Size Lacing
- Sizes = new int[LaceCount+1];
- Sizes[0] = (int)(this.getSize() - HeaderSize) / (LaceCount+1);
- for (int s = 0; s < LaceCount; s++)
- Sizes[s+1] = Sizes[0];
- } else {
- throw new java.lang.RuntimeException("Unsupported lacing type flag.");
- }
- }
- data = new byte[(int)(this.getSize() - HeaderSize)];
- source.read(data, 0, data.length);
- this.dataRead = true;
- }
-
- public int[] readEBMLLaceSizes(DataSource source, short LaceCount) {
- int [] LaceSizes = new int[LaceCount+1];
- LaceSizes[LaceCount] = (int)this.getSize();
-
- // This uses the DataSource.getBytePosition() for finding the header size
- // because of the trouble of finding the byte size of sized ebml coded integers
- int ByteStartPos = source.getBytePosition();
-
- LaceSizes[0] = (int)EBMLReader.readEBMLCode(source);
- long FirstEBMLSize = LaceSizes[0];
- long LastEBMLSize = 0;
- for (int l = 0; l < LaceCount-1; l++) {
- LastEBMLSize = EBMLReader.readSignedEBMLCode(source);
-
- FirstEBMLSize += LastEBMLSize;
- LaceSizes[l+1] = (int)FirstEBMLSize;
-
- // Update the size of the last block
- LaceSizes[LaceCount] -= LaceSizes[l+1];
- }
- int ByteEndPos = source.getBytePosition();
-
- HeaderSize = HeaderSize + (ByteEndPos - ByteStartPos);
- LaceSizes[LaceCount] -= HeaderSize;
-
- return LaceSizes;
- }
-
- public int[] readXiphLaceSizes(DataSource source, short LaceCount) {
- int [] LaceSizes = new int[LaceCount+1];
- LaceSizes[LaceCount] = (int)this.getSize();
-
- int ByteStartPos = source.getBytePosition();
-
- for (int l = 0; l < LaceCount; l++) {
- short LaceSizeByte = 255;
- while (LaceSizeByte == 255) {
- LaceSizeByte = (short)(source.readByte() & 0xFF);
- HeaderSize += 1;
- LaceSizes[l] += LaceSizeByte;
- }
- // Update the size of the last block
- LaceSizes[LaceCount] -= LaceSizes[l];
- }
- int ByteEndPos = source.getBytePosition();
-
- LaceSizes[LaceCount] -= HeaderSize;
-
- return LaceSizes;
- }
-
- public int getFrameCount() {
- if (Sizes == null) {
- return 1;
- }
- return Sizes.length;
- }
-
- public byte [] getFrame(int frame) {
- if (Sizes == null) {
- if (frame != 0) {
- throw new java.lang.IllegalArgumentException("Tried to read laced frame on non-laced Block. MatroskaBlock.getFrame(frame > 0)");
- }
- return data;
- }
- byte [] FrameData = new byte[Sizes[frame]];
-
- // Calc the frame data offset
- int StartOffset = 0;
- for (int s = 0; s < frame; s++) {
- StartOffset += Sizes[s];
- }
-
- // Copy the frame data
- System.arraycopy(data, StartOffset, FrameData, 0, FrameData.length);
-
- return FrameData;
- }
- public long getAdjustedBlockTimecode(long ClusterTimecode, long TimecodeScale) {
- return ClusterTimecode + (BlockTimecode * TimecodeScale);
- }
- public int getTrackNo() {
- return TrackNo;
- }
- public int getBlockTimecode() {
- return BlockTimecode;
- }
-}
+package org.ebml.matroska;
+
+import org.ebml.*;
+
+/**
+ * <p>Title: JEBML</p>
+ * <p>Description: Java Classes to Read EBML Elements</p>
+ * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
+ *
+ * @author jcsston
+ * @version 1.0
+ */
+
+public class MatroskaBlock extends BinaryElement {
+ protected int [] Sizes = null;
+ protected int HeaderSize = 0;
+ protected int BlockTimecode = 0;
+ protected int TrackNo = 0;
+
+ public MatroskaBlock(byte[] type) {
+ super(type);
+ }
+
+ public void readData(DataSource source) {
+ parseBlock(source);
+ }
+
+ public void parseBlock(DataSource source) {
+
+ TrackNo = (int)EBMLReader.readEBMLCode(source);
+ HeaderSize += Element.EBMLCodedSizeLength(TrackNo);
+
+ short BlockTimecode1 = (short)(source.readByte() & 0xFF);
+ short BlockTimecode2 = (short)(source.readByte() & 0xFF);
+ if (BlockTimecode1 != 0 || BlockTimecode2 != 0) {
+ BlockTimecode = (BlockTimecode1 << 8) | BlockTimecode2;
+ }
+
+ int LaceFlag = source.readByte() & 0x06;
+ // Increase the HeaderSize by the number of bytes we have read
+ HeaderSize += 3;
+ if (LaceFlag != 0x00) {
+ // We have lacing
+ byte LaceCount = source.readByte();
+ HeaderSize += 1;
+ if (LaceFlag == 0x02) { // Xiph Lacing
+ Sizes = readXiphLaceSizes(source, LaceCount);
+
+ } else if (LaceFlag == 0x06) { // EBML Lacing
+ Sizes = readEBMLLaceSizes(source, LaceCount);
+
+ } else if (LaceFlag == 0x04) { // Fixed Size Lacing
+ Sizes = new int[LaceCount+1];
+ Sizes[0] = (int)(this.getSize() - HeaderSize) / (LaceCount+1);
+ for (int s = 0; s < LaceCount; s++)
+ Sizes[s+1] = Sizes[0];
+ } else {
+ throw new java.lang.RuntimeException("Unsupported lacing type flag.");
+ }
+ }
+ data = new byte[(int)(this.getSize() - HeaderSize)];
+ source.read(data, 0, data.length);
+ this.dataRead = true;
+ }
+
+ public int[] readEBMLLaceSizes(DataSource source, short LaceCount) {
+ int [] LaceSizes = new int[LaceCount+1];
+ LaceSizes[LaceCount] = (int)this.getSize();
+
+ // This uses the DataSource.getBytePosition() for finding the header size
+ // because of the trouble of finding the byte size of sized ebml coded integers
+ long ByteStartPos = source.getFilePointer();
+
+ LaceSizes[0] = (int)EBMLReader.readEBMLCode(source);
+ long FirstEBMLSize = LaceSizes[0];
+ long LastEBMLSize = 0;
+ for (int l = 0; l < LaceCount-1; l++) {
+ LastEBMLSize = EBMLReader.readSignedEBMLCode(source);
+
+ FirstEBMLSize += LastEBMLSize;
+ LaceSizes[l+1] = (int)FirstEBMLSize;
+
+ // Update the size of the last block
+ LaceSizes[LaceCount] -= LaceSizes[l+1];
+ }
+ long ByteEndPos = source.getFilePointer();
+
+ HeaderSize = HeaderSize + (int)(ByteEndPos - ByteStartPos);
+ LaceSizes[LaceCount] -= HeaderSize;
+
+ return LaceSizes;
+ }
+
+ public int[] readXiphLaceSizes(DataSource source, short LaceCount) {
+ int [] LaceSizes = new int[LaceCount+1];
+ LaceSizes[LaceCount] = (int)this.getSize();
+
+ long ByteStartPos = source.getFilePointer();
+
+ for (int l = 0; l < LaceCount; l++) {
+ short LaceSizeByte = 255;
+ while (LaceSizeByte == 255) {
+ LaceSizeByte = (short)(source.readByte() & 0xFF);
+ HeaderSize += 1;
+ LaceSizes[l] += LaceSizeByte;
+ }
+ // Update the size of the last block
+ LaceSizes[LaceCount] -= LaceSizes[l];
+ }
+ long ByteEndPos = source.getFilePointer();
+
+ LaceSizes[LaceCount] -= HeaderSize;
+
+ return LaceSizes;
+ }
+
+ public int getFrameCount() {
+ if (Sizes == null) {
+ return 1;
+ }
+ return Sizes.length;
+ }
+
+ public byte [] getFrame(int frame) {
+ if (Sizes == null) {
+ if (frame != 0) {
+ throw new java.lang.IllegalArgumentException("Tried to read laced frame on non-laced Block. MatroskaBlock.getFrame(frame > 0)");
+ }
+ return data;
+ }
+ byte [] FrameData = new byte[Sizes[frame]];
+
+ // Calc the frame data offset
+ int StartOffset = 0;
+ for (int s = 0; s < frame; s++) {
+ StartOffset += Sizes[s];
+ }
+
+ // Copy the frame data
+ System.arraycopy(data, StartOffset, FrameData, 0, FrameData.length);
+
+ return FrameData;
+ }
+ public long getAdjustedBlockTimecode(long ClusterTimecode, long TimecodeScale) {
+ return ClusterTimecode + (BlockTimecode * TimecodeScale);
+ }
+ public int getTrackNo() {
+ return TrackNo;
+ }
+ public int getBlockTimecode() {
+ return BlockTimecode;
+ }
+}
Modified: trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,683 +1,781 @@
-package org.ebml.matroska;
-
-import org.ebml.*;
-import java.util.*;
-import org.ebml.matroska.MatroskaFile.*;
-
-/**
- * <p>Title: JEBML</p>
- * <p>Description: Java Classes to Read EBML Elements</p>
- * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
- * @author jcsston
- * @version 1.0
- */
-
-public class MatroskaFile {
- /**
- * Matroska Frame, holds a Matroska frame timecode, duration, and Data
- */
- public class MatroskaFrame {
- public int TrackNo;
- public long Timecode;
- public long Duration;
- public long Reference;
- public byte [] Data;
-
- /**
- * MatroskaFrame Default constructor
- */
- public MatroskaFrame() {
- //System.out.println("new " + this);
- }
-
- /**
- * MatroskaFrame Copy constructor
- * @param copy MatroskaFrame to copy
- */
- public MatroskaFrame(MatroskaFrame copy) {
- //System.out.println("MatroskaFrame copy " + this);
- this.TrackNo = copy.TrackNo;
- this.Timecode = copy.Timecode;
- this.Duration = copy.Duration;
- if (copy.Data != null) {
- this.Data = new byte[copy.Data.length];
- System.arraycopy(copy.Data, 0, this.Data, 0, copy.Data.length);
- }
- }
- }
- /**
- * Matroska Frame Puller interface
- */
- public interface MatroskaFramePuller {
- public void PushNewMatroskaFrame(MatroskaFrame frame);
- }
-
- /**
- * Matroska Track Class
- */
- public class MatroskaFileTrack {
- public short TrackNo;
- public long TrackUID;
- public byte TrackType;
- public long DefaultDuration;
- public String Name;
- public String Language;
- public String CodecID;
- public byte [] CodecPrivate;
-
- public short Video_PixelWidth;
- public short Video_PixelHeight;
- public short Video_DisplayWidth;
- public short Video_DisplayHeight;
- public float Audio_SamplingFrequency;
- public float Audio_OutputSamplingFrequency;
- public short Audio_Channels;
- public byte Audio_BitDepth;
-
- /**
- * Converts the Track to String form
- * @return String form of MatroskaFileTrack data
- */
- public String toString() {
- String s = new String();
-
- s += "\t\t" + "TrackNo: " + TrackNo + "\n";
- s += "\t\t" + "TrackUID: " + TrackUID + "\n";
- s += "\t\t" + "TrackType: " + MatroskaDocType.TrackTypeToString(TrackType) + "\n";
- s += "\t\t" + "DefaultDuration: " + DefaultDuration + "\n";
- s += "\t\t" + "Name: " + Name + "\n";
- s += "\t\t" + "Language: " + Language + "\n";
- s += "\t\t" + "CodecID: " + CodecID + "\n";
- if (CodecPrivate != null)
- s += "\t\t" + "CodecPrivate: " + CodecPrivate.length + " byte(s)" + "\n";
-
- if (TrackType == MatroskaDocType.track_video) {
- s += "\t\t" + "PixelWidth: " + Video_PixelWidth + "\n";
- s += "\t\t" + "PixelHeight: " + Video_PixelHeight + "\n";
- s += "\t\t" + "DisplayWidth: " + Video_DisplayWidth + "\n";
- s += "\t\t" + "DisplayHeight: " + Video_DisplayHeight + "\n";
- }
-
- if (TrackType == MatroskaDocType.track_audio) {
- s += "\t\t" + "SamplingFrequency: " + Audio_SamplingFrequency + "\n";
- if (Audio_OutputSamplingFrequency != 0)
- s += "\t\t" + "OutputSamplingFrequency: " + Audio_OutputSamplingFrequency + "\n";
- s += "\t\t" + "Channels: " + Audio_Channels + "\n";
- if (Audio_BitDepth != 0)
- s += "\t\t" + "BitDepth: " + Audio_BitDepth + "\n";
- }
-
- return s;
- }
- }
- public class MatroskaFileSimpleTag {
- public String Name;
- public String Value;
- public ArrayList Children = new ArrayList();
-
- public String toString(int depth) {
- String s = new String();
- String depthIndent = new String();
- for (int d = 0; d < depth; d++)
- depthIndent += "\t";
-
- s += depthIndent + "SimpleTag\n";
- s += depthIndent + "\tName: " + Name + "\n";
- s += depthIndent + "\tValue: " + Value + "\n";
-
- depth++;
- for (int t = 0; t < Children.size(); t++) {
- s += ((MatroskaFileSimpleTag)Children.get(t)).toString(depth);
- }
-
- return s;
- }
- }
- public class MatroskaFileTagEntry {
- public ArrayList TrackUID = new ArrayList();
- public ArrayList ChapterUID = new ArrayList();
- public ArrayList AttachmentUID = new ArrayList();
- public ArrayList SimpleTags = new ArrayList();
-
- public String toString() {
- String s = new String();
-
- if (TrackUID.size() > 0) {
- s += "\t\t" + "TrackUID: " + TrackUID.toArray().toString() + "\n";
- }
- if (ChapterUID.size() > 0) {
- s += "\t\t" + "ChapterUID: " + ChapterUID.toArray().toString() + "\n";
- }
- if (AttachmentUID.size() > 0) {
- s += "\t\t" + "AttachmentUID: " + AttachmentUID.toArray().toString() + "\n";
- }
-
- for (int t = 0; t < SimpleTags.size(); t++) {
- s += ((MatroskaFileSimpleTag)SimpleTags.get(t)).toString(2);
- }
-
- return s;
- }
- }
-
- /**
- * Number of Clusters to search before assuming that a track has ended
- */
- public static int CLUSTER_TRACK_SEARCH_COUNT = 4;
-
- protected DataSource ioDS;
- protected EBMLReader reader;
- protected Element level0 = null;
- protected String SegmentTitle;
- protected String MuxingApp;
- protected String WritingApp;
- protected long TimecodeScale = 1000000;
- protected double Duration;
- protected ArrayList TrackList = new ArrayList();
- protected ArrayList TagList = new ArrayList();
- protected LinkedList FrameQueue = new LinkedList();
-
- /**
- * Primary Constructor for Matroska File class.
- *
- * @param inputStream InputStream to read the Matroska file from
- */
- public MatroskaFile(java.io.InputStream inputStream) {
- ioDS = new InputStreamDataSource(inputStream);
- reader = new EBMLReader(ioDS, MatroskaDocType.obj);
- }
- public MatroskaFile(DataSource inputDataSource) {
- ioDS = inputDataSource;
- reader = new EBMLReader(ioDS, MatroskaDocType.obj);
- }
-
- /**
- * Read / Parse the Matroska file.
- * @throws RuntimeException On various errors
- */
- public void readFile() {
- Element level1 = null;
- Element level2 = null;
- Element level3 = null;
- Element level4 = null;
-
- level0 = reader.readNextElement();
- if (level0 == null) {
- throw new java.lang.RuntimeException("Error: Unable to scan for EBML elements");
- }
-
- if (level0.equals(MatroskaDocType.EBMLHeader_Id)) {
- level1 = ((MasterElement)level0).readNextChild(reader);
-
- while (level1 != null) {
- level1.readData(ioDS);
- if (level1.equals(MatroskaDocType.DocType_Id)) {
- String DocType = ((StringElement)level1).getValue();
- if (DocType.compareTo("matroska") != 0) {
- throw new java.lang.RuntimeException("Error: DocType is not matroska, " + ((StringElement)level1).getValue());
- }
- }
- level1 = ((MasterElement)level0).readNextChild(reader);
- }
- } else {
- throw new java.lang.RuntimeException("Error: EBML Header not the first element in the file");
- }
-
- level0 = reader.readNextElement();
- if (level0.equals(MatroskaDocType.Segment_Id)) {
- level1 = ((MasterElement)level0).readNextChild(reader);
-
- while (level1 != null) {
- if (level1.equals(MatroskaDocType.SegmentInfo_Id)) {
- _parseSegmentInfo(level1, level2);
-
- } else if (level1.equals(MatroskaDocType.Tracks_Id)) {
- _parseTracks(level1, level2);
-
- } else if (level1.equals(MatroskaDocType.Cluster_Id)) {
- _parseNextCluster(level1);
- // Break out of this loop, we should only parse the first cluster
- break;
-
- } else if (level1.equals(MatroskaDocType.Tags_Id)) {
- _parseTags(level1, level2);
-
- }
-
- level1.skipData(ioDS);
- level1 = ((MasterElement)level0).readNextChild(reader);
- }
- } else {
- throw new java.lang.RuntimeException("Error: Segment not the second element in the file");
- }
- }
- /**
- * Get the Next MatroskaFrame
- *
- * @return The next MatroskaFrame in the queue, or null if the file has ended
- */
- public MatroskaFrame getNextFrame() {
- if (FrameQueue.isEmpty()) {
- _fillFrameQueue();
- }
-
- // If FrameQueue is still empty, must be the end of the file
- if (FrameQueue.isEmpty()) {
- return null;
- }
- return (MatroskaFrame)FrameQueue.removeFirst();
- }
- /**
- * Get the Next MatroskaFrame, limited by TrackNo
- *
- * @param TrackNo The track number to only get MatroskaFrames from
- * @return The next MatroskaFrame in the queue, or null if there are no more frames for the TrackNo track
- */
- public MatroskaFrame getNextFrame(int TrackNo) {
- if (FrameQueue.isEmpty()) {
- _fillFrameQueue();
- }
-
- // If FrameQueue is still empty, must be the end of the file
- if (FrameQueue.isEmpty()) {
- return null;
- }
- int tryCount = 0;
- MatroskaFrame frame = null;
- ListIterator iter = FrameQueue.listIterator();
- while (frame == null) {
- if (iter.hasNext()) {
- frame = (MatroskaFrame)iter.next();
- if (frame.TrackNo == TrackNo) {
- iter.remove();
- return frame;
- }
- frame = null;
- } else {
- _fillFrameQueue();
- // Update Iterator
- int index = iter.nextIndex();
- iter = FrameQueue.listIterator(index);
- if (++tryCount > CLUSTER_TRACK_SEARCH_COUNT) {
- // If we have not found any frames belonging to a track in 4 clusters
- // there is a good chance that the track is over
- return null;
- }
- }
- }
- return frame;
- }
-
- private void _fillFrameQueue() {
- if (level0 == null)
- throw new java.lang.IllegalStateException("Call readFile() before reading frames");
-
- Element level1 = ((MasterElement)level0).readNextChild(reader);
- if (level1 != null) {
- if (level1.equals(MatroskaDocType.Cluster_Id)) {
- _parseNextCluster(level1);
- }
- level1.skipData(ioDS);
- }
- }
-
- private void _parseNextCluster(Element level1) {
- Element level2 = null;
- Element level3 = null;
- long ClusterTimecode = 0;
- level2 = ((MasterElement)level1).readNextChild(reader);
-
- while (level2 != null) {
- if (level2.equals(MatroskaDocType.ClusterTimecode_Id)) {
- level2.readData(ioDS);
- ClusterTimecode = ((UnsignedInteger)level2).getValue();
-
- } else if (level2.equals(MatroskaDocType.ClusterBlockGroup_Id)) {
- MatroskaBlock block = null;
- long BlockDuration = 0;
- long BlockReference = 0;
- level3 = ((MasterElement)level2).readNextChild(reader);
-
- while (level3 != null) {
- if (level3.equals(MatroskaDocType.ClusterBlock_Id)) {
- block = (MatroskaBlock)level3;
- block.parseBlock(ioDS);
-
- } else if (level3.equals(MatroskaDocType.ClusterBlockDuration_Id)) {
- level3.readData(ioDS);
- BlockDuration = ((UnsignedInteger)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.ClusterReferenceBlock_Id)) {
- level3.readData(ioDS);
- BlockReference = ((SignedInteger)level3).getValue();
- }
-
- level3.skipData(ioDS);
- level3 = ((MasterElement)level2).readNextChild(reader);
- }
-
- if (block == null)
- throw new java.lang.NullPointerException("BlockGroup element with no child Block!");
-
- MatroskaFrame frame = new MatroskaFrame();
- frame.TrackNo = block.getTrackNo();
- frame.Timecode = block.getAdjustedBlockTimecode(ClusterTimecode, this.TimecodeScale) / TimecodeScale;
- frame.Duration = BlockDuration;
- frame.Reference = BlockReference;
- frame.Data = block.getFrame(0);
- FrameQueue.addLast(new MatroskaFrame(frame));
-
- if (block.getFrameCount() > 1) {
- for (int f = 1; f < block.getFrameCount(); f++) {
- frame.Data = block.getFrame(f);
- if (badMP3Headers()) {
- throw new RuntimeException("Bad Data!");
- }
- FrameQueue.addLast(new MatroskaFrame(frame));
- if (badMP3Headers()) {
- throw new RuntimeException("Bad Data!");
- }
- }
- }
- }
-
- level2.skipData(ioDS);
- level2 = ((MasterElement)level1).readNextChild(reader);
- }
- }
-
- protected boolean badMP3Headers() {
- ListIterator iter = FrameQueue.listIterator();
- while (iter.hasNext()) {
- MatroskaFrame frame = (MatroskaFrame)iter.next();
- if (frame.TrackNo == 2
- && frame.Data[3] != 0x54)
- {
- throw new RuntimeException("Bad MP3 Header! Index: " + iter.nextIndex());
- }
- }
- return false;
- }
- private void _parseSegmentInfo(Element level1, Element level2) {
- level2 = ((MasterElement)level1).readNextChild(reader);
-
- while (level2 != null) {
- if (level2.equals(MatroskaDocType.Title_Id)) {
- level2.readData(ioDS);
- SegmentTitle = ((StringElement)level2).getValue();
-
- } else if (level2.equals(MatroskaDocType.MuxingApp_Id)) {
- level2.readData(ioDS);
- MuxingApp = ((StringElement)level2).getValue();
-
- } else if (level2.equals(MatroskaDocType.WritingApp_Id)) {
- level2.readData(ioDS);
- WritingApp = ((StringElement)level2).getValue();
-
- } else if (level2.equals(MatroskaDocType.Duration_Id)) {
- level2.readData(ioDS);
- Duration = ((FloatElement)level2).getValue();
-
- } else if (level2.equals(MatroskaDocType.TimecodeScale_Id)) {
- level2.readData(ioDS);
- TimecodeScale = ((UnsignedInteger)level2).getValue();
- }
-
- level2.skipData(ioDS);
- level2 = ((MasterElement)level1).readNextChild(reader);
- }
- }
-
- private void _parseTracks(Element level1, Element level2) {
- Element level3 = null;
- Element level4 = null;
- level2 = ((MasterElement)level1).readNextChild(reader);
-
- while (level2 != null) {
- if (level2.equals(MatroskaDocType.TrackEntry_Id)) {
- MatroskaFileTrack track = new MatroskaFileTrack();
- level3 = ((MasterElement)level2).readNextChild(reader);
-
- while (level3 != null) {
- if (level3.equals(MatroskaDocType.TrackNumber_Id)) {
- level3.readData(ioDS);
- track.TrackNo = (short)((UnsignedInteger)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.TrackUID_Id)) {
- level3.readData(ioDS);
- track.TrackUID = ((UnsignedInteger)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.TrackType_Id)) {
- level3.readData(ioDS);
- track.TrackType = (byte)((UnsignedInteger)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.TrackDefaultDuration_Id)) {
- level3.readData(ioDS);
- track.DefaultDuration = ((UnsignedInteger)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.TrackName_Id)) {
- level3.readData(ioDS);
- track.Name = ((StringElement)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.TrackLanguage_Id)) {
- level3.readData(ioDS);
- track.Language = ((StringElement)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.TrackCodecID_Id)) {
- level3.readData(ioDS);
- track.CodecID = ((StringElement)level3).getValue();
-
- } else if (level3.equals(MatroskaDocType.TrackCodecPrivate_Id)) {
- level3.readData(ioDS);
- track.CodecPrivate = ((BinaryElement)level3).getData();
-
- } else if (level3.equals(MatroskaDocType.TrackVideo_Id)) {
- level4 = ((MasterElement)level3).readNextChild(reader);
-
- while (level4 != null) {
- if (level4.equals(MatroskaDocType.PixelWidth_Id)) {
- level4.readData(ioDS);
- track.Video_PixelWidth = (short)((UnsignedInteger)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.PixelHeight_Id)) {
- level4.readData(ioDS);
- track.Video_PixelHeight = (short)((UnsignedInteger)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.DisplayWidth_Id)) {
- level4.readData(ioDS);
- track.Video_DisplayWidth = (short)((UnsignedInteger)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.DisplayHeight_Id)) {
- level4.readData(ioDS);
- track.Video_DisplayHeight = (short)((UnsignedInteger)level4).getValue();
- }
-
- level4.skipData(ioDS);
- level4 = ((MasterElement)level3).readNextChild(reader);
- }
-
- } else if (level3.equals(MatroskaDocType.TrackAudio_Id)) {
- level4 = ((MasterElement)level3).readNextChild(reader);
-
- while (level4 != null) {
- if (level4.equals(MatroskaDocType.SamplingFrequency_Id)) {
- level4.readData(ioDS);
- track.Audio_SamplingFrequency = (float)((FloatElement)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.OutputSamplingFrequency_Id)) {
- level4.readData(ioDS);
- track.Audio_OutputSamplingFrequency = (float)((FloatElement)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.Channels_Id)) {
- level4.readData(ioDS);
- track.Audio_Channels = (short)((UnsignedInteger)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.BitDepth_Id)) {
- level4.readData(ioDS);
- track.Audio_BitDepth = (byte)((UnsignedInteger)level4).getValue();
- }
-
- level4.skipData(ioDS);
- level4 = ((MasterElement)level3).readNextChild(reader);
- }
-
- }
- level3.skipData(ioDS);
- level3 = ((MasterElement)level2).readNextChild(reader);
- }
- TrackList.add(track);
- }
-
- level2.skipData(ioDS);
- level2 = ((MasterElement)level1).readNextChild(reader);
- }
- }
- private void _parseTags(Element level1, Element level2) {
- Element level3 = null;
- Element level4 = null;
- level2 = ((MasterElement)level1).readNextChild(reader);
-
- while (level2 != null) {
- if (level2.equals(MatroskaDocType.Tag_Id)) {
- MatroskaFileTagEntry tag = new MatroskaFileTagEntry();
- level3 = ((MasterElement)level2).readNextChild(reader);
-
- while (level3 != null) {
- if (level3.equals(MatroskaDocType.TagTargets_Id)) {
- level4 = ((MasterElement)level3).readNextChild(reader);
-
- while (level4 != null) {
- if (level4.equals(MatroskaDocType.TagTargetTrackUID_Id)) {
- level4.readData(ioDS);
- tag.TrackUID.add(new Long(((UnsignedInteger)level4).getValue()));
-
- } else if (level4.equals(MatroskaDocType.TagTargetChapterUID_Id)) {
- level4.readData(ioDS);
- tag.ChapterUID.add(new Long(((UnsignedInteger)level4).getValue()));
-
- } else if (level4.equals(MatroskaDocType.TagTargetAttachmentUID_Id)) {
- level4.readData(ioDS);
- tag.AttachmentUID.add(new Long(((UnsignedInteger)level4).getValue()));
- }
-
- level4.skipData(ioDS);
- level4 = ((MasterElement)level3).readNextChild(reader);
- }
-
- } else if (level3.equals(MatroskaDocType.TagSimpleTag_Id)) {
- tag.SimpleTags.add(_parseTagsSimpleTag(level3, level4));
- }
- level3.skipData(ioDS);
- level3 = ((MasterElement)level2).readNextChild(reader);
- }
- TagList.add(tag);
- }
-
- level2.skipData(ioDS);
- level2 = ((MasterElement)level1).readNextChild(reader);
- }
- }
-
- private MatroskaFileSimpleTag _parseTagsSimpleTag(Element level3, Element level4) {
- MatroskaFileSimpleTag SimpleTag = new MatroskaFileSimpleTag();
- level4 = ((MasterElement)level3).readNextChild(reader);
-
- while (level4 != null) {
- if (level4.equals(MatroskaDocType.TagSimpleTagName_Id)) {
- level4.readData(ioDS);
- SimpleTag.Name = ((StringElement)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.TagSimpleTagString_Id)) {
- level4.readData(ioDS);
- SimpleTag.Value = ((StringElement)level4).getValue();
-
- } else if (level4.equals(MatroskaDocType.TagSimpleTag_Id)) {
- SimpleTag.Children.add(_parseTagsSimpleTag(level3, level4));
- }
-
- level4.skipData(ioDS);
- level4 = ((MasterElement)level3).readNextChild(reader);
- }
-
- return SimpleTag;
- }
-
- /**
- * Get a String report for the Matroska file.
- * Call readFile() before this method, else the report will be empty.
- *
- * @return String Report
- */
- public String getReport() {
- java.io.StringWriter s = new java.io.StringWriter();
- int t;
-
- s.write("MatroskaFile report\n");
-
- s.write("Infomation Segment \n");
- s.write("\tSegment Title: " + SegmentTitle + "\n");
- s.write("\tMuxingApp : " + MuxingApp + "\n");
- s.write("\tWritingApp : " + WritingApp + "\n");
- s.write("\tDuration : " + Duration/1000 + "sec \n");
- s.write("\tTimecodeScale : " + TimecodeScale + "\n");
-
- s.write("Track Count: " + TrackList.size() + "\n");
- for (t = 0; t < TrackList.size(); t++) {
- s.write("\tTrack " + t + "\n");
- s.write(TrackList.get(t).toString());
- }
-
- s.write("Tag Count: " + TagList.size() + "\n");
- for (t = 0; t < TagList.size(); t++) {
- s.write("\tTag Entry \n");
- s.write(TagList.get(t).toString());
- }
-
- s.write("End report\n");
-
- return s.getBuffer().toString();
- }
- public String getWritingApp() {
- return WritingApp;
- }
- /**
- * Returns an array of the tracks
- */
- public MatroskaFileTrack [] getTrackList() {
- if (TrackList.size() > 0) {
- MatroskaFileTrack [] tracks = new MatroskaFileTrack[TrackList.size()];
- for (int t = 0; t < TrackList.size(); t++) {
- tracks[t] = (MatroskaFileTrack)TrackList.get(t);
- }
- return tracks;
- } else {
- return new MatroskaFileTrack[0];
- }
- }
- /**
- * This differs from the getTrackList method in that this method scans
- * each track and returns the one that has the same track number as TrackNo
- *
- * TrackNo != track index
- */
- public MatroskaFileTrack getTrack(int TrackNo) {
- for (int t = 0; t < TrackList.size(); t++) {
- MatroskaFileTrack track = (MatroskaFileTrack)TrackList.get(t);
- if (track.TrackNo == TrackNo)
- return track;
- }
- return null;
- }
- public long getTimecodeScale() {
- return TimecodeScale;
- }
- public String getSegmentTitle() {
- return SegmentTitle;
- }
- public String getMuxingApp() {
- return MuxingApp;
- }
- public double getDuration() {
- return Duration;
- }
-}
\ No newline at end of file
+package org.ebml.matroska;
+
+import org.ebml.*;
+import java.util.*;
+import org.ebml.matroska.MatroskaFile.*;
+
+/**
+ * <p>Title: JEBML</p>
+ * <p>Description: Java Classes to Read EBML Elements</p>
+ * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
+ * @author jcsston
+ * @version 1.0
+ */
+
+public class MatroskaFile {
+ /**
+ * Matroska Frame, holds a Matroska frame timecode, duration, and Data
+ */
+ public class MatroskaFrame {
+ public int TrackNo;
+ public long Timecode;
+ public long Duration;
+ public long Reference;
+ public byte [] Data;
+
+ /**
+ * MatroskaFrame Default constructor
+ */
+ public MatroskaFrame() {
+ //System.out.println("new " + this);
+ }
+
+ /**
+ * MatroskaFrame Copy constructor
+ * @param copy MatroskaFrame to copy
+ */
+ public MatroskaFrame(MatroskaFrame copy) {
+ //System.out.println("MatroskaFrame copy " + this);
+ this.TrackNo = copy.TrackNo;
+ this.Timecode = copy.Timecode;
+ this.Duration = copy.Duration;
+ if (copy.Data != null) {
+ this.Data = new byte[copy.Data.length];
+ System.arraycopy(copy.Data, 0, this.Data, 0, copy.Data.length);
+ }
+ }
+ }
+ /**
+ * Matroska Frame Puller interface
+ */
+ public interface MatroskaFramePuller {
+ public void PushNewMatroskaFrame(MatroskaFrame frame);
+ }
+
+ /**
+ * Matroska Track Class
+ */
+ public class MatroskaFileTrack {
+ public short TrackNo;
+ public long TrackUID;
+ public byte TrackType;
+ public long DefaultDuration;
+ public String Name;
+ public String Language;
+ public String CodecID;
+ public byte [] CodecPrivate;
+
+ public short Video_PixelWidth;
+ public short Video_PixelHeight;
+ public short Video_DisplayWidth;
+ public short Video_DisplayHeight;
+ public float Audio_SamplingFrequency;
+ public float Audio_OutputSamplingFrequency;
+ public short Audio_Channels;
+ public byte Audio_BitDepth;
+
+ /**
+ * Converts the Track to String form
+ * @return String form of MatroskaFileTrack data
+ */
+ public String toString() {
+ String s = new String();
+
+ s += "\t\t" + "TrackNo: " + TrackNo + "\n";
+ s += "\t\t" + "TrackUID: " + TrackUID + "\n";
+ s += "\t\t" + "TrackType: " + MatroskaDocType.TrackTypeToString(TrackType) + "\n";
+ s += "\t\t" + "DefaultDuration: " + DefaultDuration + "\n";
+ s += "\t\t" + "Name: " + Name + "\n";
+ s += "\t\t" + "Language: " + Language + "\n";
+ s += "\t\t" + "CodecID: " + CodecID + "\n";
+ if (CodecPrivate != null)
+ s += "\t\t" + "CodecPrivate: " + CodecPrivate.length + " byte(s)" + "\n";
+
+ if (TrackType == MatroskaDocType.track_video) {
+ s += "\t\t" + "PixelWidth: " + Video_PixelWidth + "\n";
+ s += "\t\t" + "PixelHeight: " + Video_PixelHeight + "\n";
+ s += "\t\t" + "DisplayWidth: " + Video_DisplayWidth + "\n";
+ s += "\t\t" + "DisplayHeight: " + Video_DisplayHeight + "\n";
+ }
+
+ if (TrackType == MatroskaDocType.track_audio) {
+ s += "\t\t" + "SamplingFrequency: " + Audio_SamplingFrequency + "\n";
+ if (Audio_OutputSamplingFrequency != 0)
+ s += "\t\t" + "OutputSamplingFrequency: " + Audio_OutputSamplingFrequency + "\n";
+ s += "\t\t" + "Channels: " + Audio_Channels + "\n";
+ if (Audio_BitDepth != 0)
+ s += "\t\t" + "BitDepth: " + Audio_BitDepth + "\n";
+ }
+
+ return s;
+ }
+ }
+ public class MatroskaFileSimpleTag {
+ public String Name;
+ public String Value;
+ public ArrayList Children = new ArrayList();
+
+ public String toString(int depth) {
+ String s = new String();
+ String depthIndent = new String();
+ for (int d = 0; d < depth; d++)
+ depthIndent += "\t";
+
+ s += depthIndent + "SimpleTag\n";
+ s += depthIndent + "\tName: " + Name + "\n";
+ s += depthIndent + "\tValue: " + Value + "\n";
+
+ depth++;
+ for (int t = 0; t < Children.size(); t++) {
+ s += ((MatroskaFileSimpleTag)Children.get(t)).toString(depth);
+ }
+
+ return s;
+ }
+ }
+ public class MatroskaFileTagEntry {
+ public ArrayList TrackUID = new ArrayList();
+ public ArrayList ChapterUID = new ArrayList();
+ public ArrayList AttachmentUID = new ArrayList();
+ public ArrayList SimpleTags = new ArrayList();
+
+ public String toString() {
+ String s = new String();
+
+ if (TrackUID.size() > 0) {
+ s += "\t\t" + "TrackUID: " + TrackUID.toArray().toString() + "\n";
+ }
+ if (ChapterUID.size() > 0) {
+ s += "\t\t" + "ChapterUID: " + ChapterUID.toArray().toString() + "\n";
+ }
+ if (AttachmentUID.size() > 0) {
+ s += "\t\t" + "AttachmentUID: " + AttachmentUID.toArray().toString() + "\n";
+ }
+
+ for (int t = 0; t < SimpleTags.size(); t++) {
+ s += ((MatroskaFileSimpleTag)SimpleTags.get(t)).toString(2);
+ }
+
+ return s;
+ }
+ }
+
+ /**
+ * Number of Clusters to search before assuming that a track has ended
+ */
+ public static int CLUSTER_TRACK_SEARCH_COUNT = 4;
+
+ protected DataSource ioDS;
+ protected EBMLReader reader;
+ protected Element level0 = null;
+ protected String SegmentTitle;
+ protected Date SegmentDate;
+ protected String MuxingApp;
+ protected String WritingApp;
+ protected long TimecodeScale = 1000000;
+ protected double Duration;
+ protected ArrayList TrackList = new ArrayList();
+ protected ArrayList TagList = new ArrayList();
+ protected LinkedList FrameQueue = new LinkedList();
+ protected boolean ScanFirstCluster = true;
+
+ /**
+ * Primary Constructor for Matroska File class.
+ *
+ * @param inputDataSource DataSource to read the Matroska file from
+ */
+ public MatroskaFile(DataSource inputDataSource) {
+ ioDS = inputDataSource;
+ reader = new EBMLReader(ioDS, MatroskaDocType.obj);
+ }
+
+ /**
+ * Read / Parse the Matroska file.
+ * Call this before any other method.
+ * @throws RuntimeException On various errors
+ */
+ public void readFile() {
+ Element level1 = null;
+ Element level2 = null;
+ Element level3 = null;
+ Element level4 = null;
+
+ level0 = reader.readNextElement();
+ if (level0 == null) {
+ throw new java.lang.RuntimeException("Error: Unable to scan for EBML elements");
+ }
+
+ if (level0.equals(MatroskaDocType.EBMLHeader_Id)) {
+ level1 = ((MasterElement)level0).readNextChild(reader);
+
+ while (level1 != null) {
+ level1.readData(ioDS);
+ if (level1.equals(MatroskaDocType.DocType_Id)) {
+ String DocType = ((StringElement)level1).getValue();
+ if (DocType.compareTo("matroska") != 0) {
+ throw new java.lang.RuntimeException("Error: DocType is not matroska, \"" + ((StringElement)level1).getValue() + "\"");
+ }
+ }
+ level1 = ((MasterElement)level0).readNextChild(reader);
+ }
+ } else {
+ throw new java.lang.RuntimeException("Error: EBML Header not the first element in the file");
+ }
+
+ level0 = reader.readNextElement();
+ if (level0.equals(MatroskaDocType.Segment_Id)) {
+ level1 = ((MasterElement)level0).readNextChild(reader);
+
+ while (level1 != null) {
+ if (level1.equals(MatroskaDocType.SegmentInfo_Id)) {
+ _parseSegmentInfo(level1, level2);
+
+ } else if (level1.equals(MatroskaDocType.Tracks_Id)) {
+ _parseTracks(level1, level2);
+
+ } else if (level1.equals(MatroskaDocType.Cluster_Id)) {
+ if (ScanFirstCluster)
+ {
+ _parseNextCluster(level1);
+ }
+ // Break out of this loop, we should only parse the first cluster
+ break;
+
+ } else if (level1.equals(MatroskaDocType.Tags_Id)) {
+ _parseTags(level1, level2);
+
+ }
+
+ level1.skipData(ioDS);
+ level1 = ((MasterElement)level0).readNextChild(reader);
+ }
+ } else {
+ throw new java.lang.RuntimeException("Error: Segment not the second element in the file");
+ }
+ }
+ /**
+ * Get the Next MatroskaFrame
+ *
+ * @return The next MatroskaFrame in the queue, or null if the file has ended
+ */
+ public MatroskaFrame getNextFrame() {
+ if (FrameQueue.isEmpty()) {
+ _fillFrameQueue();
+ }
+
+ // If FrameQueue is still empty, must be the end of the file
+ if (FrameQueue.isEmpty()) {
+ return null;
+ }
+ return (MatroskaFrame)FrameQueue.removeFirst();
+ }
+ /**
+ * Get the Next MatroskaFrame, limited by TrackNo
+ *
+ * @param TrackNo The track number to only get MatroskaFrames from
+ * @return The next MatroskaFrame in the queue, or null if there are no more frames for the TrackNo track
+ */
+ public MatroskaFrame getNextFrame(int TrackNo) {
+ if (FrameQueue.isEmpty()) {
+ _fillFrameQueue();
+ }
+
+ // If FrameQueue is still empty, must be the end of the file
+ if (FrameQueue.isEmpty()) {
+ return null;
+ }
+ int tryCount = 0;
+ MatroskaFrame frame = null;
+ try {
+ ListIterator iter = FrameQueue.listIterator();
+ while (frame == null) {
+ if (iter.hasNext()) {
+ frame = (MatroskaFrame)iter.next();
+ if (frame.TrackNo == TrackNo) {
+ synchronized (FrameQueue) {
+ iter.remove();
+ }
+ return frame;
+ }
+ frame = null;
+ } else {
+ _fillFrameQueue();
+ // Update Iterator
+ int index = iter.nextIndex();
+ iter = FrameQueue.listIterator(index);
+ if (++tryCount > CLUSTER_TRACK_SEARCH_COUNT) {
+ // If we have not found any frames belonging to a track in 4 clusters
+ // there is a good chance that the track is over
+ return null;
+ }
+ }
+ }
+ } catch (ConcurrentModificationException ex) {
+ return getNextFrame(TrackNo);
+ }
+
+ return frame;
+ }
+
+ public boolean isSeekable() {
+ return this.ioDS.isSeekable();
+ }
+
+ /**
+ * Seek to the requested timecode, rescaning clusters and/or discarding frames
+ * until we reach the nearest possible timecode, rounded down.
+ *
+ * <p>
+ * For example<br>
+ * Say we have a file with 10 frames
+ * <table><tr><th>Frame No</th><th>Timecode</th></tr>
+ * <tr><td>Frame 1</td> <td>0ms</td></tr>
+ * <tr><td>Frame 2</td> <td>50ms</td></tr>
+ * <tr><td>Frame 3</td> <td>100ms</td></tr>
+ * <tr><td>Frame 4</td> <td>150ms</td></tr>
+ * <tr><td>Frame 5</td> <td>200ms</td></tr>
+ * <tr><td>Frame 6</td> <td>250ms</td></tr>
+ * <tr><td>Frame 7</td> <td>300ms</td></tr>
+ * <tr><td>Frame 8</td> <td>350ms</td></tr>
+ * <tr><td>Frame 9</td> <td>400ms</td></tr>
+ * <tr><td>Frame 10</td> <td>450ms</td></tr>
+ * </table>
+ * We are requested to seek to 333ms, so we discard frames until we hit an
+ * timecode larger than the requested. We would seek to Frame 7 at 300ms.
+ * </p>
+ *
+ * @param timecode Timecode to seek to in millseconds
+ * @return Actual timecode we seeked to
+ */
+ public long seek(long timecode) {
+ return 0;
+ }
+
+ private void _fillFrameQueue() {
+ if (level0 == null)
+ throw new java.lang.IllegalStateException("Call readFile() before reading frames");
+
+ synchronized (level0) {
+ Element level1 = ((MasterElement)level0).readNextChild(reader);
+ while (level1 != null) {
+ if (level1.equals(MatroskaDocType.Cluster_Id)) {
+ _parseNextCluster(level1);
+ }
+
+ level1.skipData(ioDS);
+ level1 = ((MasterElement)level0).readNextChild(reader);
+ }
+ }
+ }
+
+ private void _parseNextCluster(Element level1) {
+ Element level2 = null;
+ Element level3 = null;
+ long ClusterTimecode = 0;
+ level2 = ((MasterElement)level1).readNextChild(reader);
+
+ while (level2 != null) {
+ if (level2.equals(MatroskaDocType.ClusterTimecode_Id)) {
+ level2.readData(ioDS);
+ ClusterTimecode = ((UnsignedInteger)level2).getValue();
+
+ } else if (level2.equals(MatroskaDocType.ClusterBlockGroup_Id)) {
+ MatroskaBlock block = null;
+ long BlockDuration = 0;
+ long BlockReference = 0;
+ level3 = ((MasterElement)level2).readNextChild(reader);
+
+ while (level3 != null) {
+ if (level3.equals(MatroskaDocType.ClusterBlock_Id)) {
+ block = (MatroskaBlock)level3;
+ block.parseBlock(ioDS);
+
+ } else if (level3.equals(MatroskaDocType.ClusterBlockDuration_Id)) {
+ level3.readData(ioDS);
+ BlockDuration = ((UnsignedInteger)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.ClusterReferenceBlock_Id)) {
+ level3.readData(ioDS);
+ BlockReference = ((SignedInteger)level3).getValue();
+ }
+
+ level3.skipData(ioDS);
+ level3 = ((MasterElement)level2).readNextChild(reader);
+ }
+
+ if (block == null)
+ throw new java.lang.NullPointerException("BlockGroup element with no child Block!");
+
+ MatroskaFrame frame = new MatroskaFrame();
+ frame.TrackNo = block.getTrackNo();
+ frame.Timecode = block.getAdjustedBlockTimecode(ClusterTimecode, this.TimecodeScale) / 1000000;
+ frame.Duration = BlockDuration;
+ frame.Reference = BlockReference;
+ frame.Data = block.getFrame(0);
+ synchronized (FrameQueue) {
+ FrameQueue.addLast(new MatroskaFrame(frame));
+ }
+
+ if (block.getFrameCount() > 1) {
+ for (int f = 1; f < block.getFrameCount(); f++) {
+ frame.Data = block.getFrame(f);
+ /*if (badMP3Headers()) {
+ throw new RuntimeException("Bad Data!");
+ }*/
+ synchronized (FrameQueue) {
+ FrameQueue.addLast(new MatroskaFrame(frame));
+ }
+ /*if (badMP3Headers()) {
+ throw new RuntimeException("Bad Data!");
+ }*/
+ }
+ }
+ }
+
+ level2.skipData(ioDS);
+ level2 = ((MasterElement)level1).readNextChild(reader);
+ }
+ }
+
+ protected boolean badMP3Headers() {
+ ListIterator iter = FrameQueue.listIterator();
+ while (iter.hasNext()) {
+ MatroskaFrame frame = (MatroskaFrame)iter.next();
+ if (frame.TrackNo == 2
+ && frame.Data[3] != 0x54)
+ {
+ throw new RuntimeException("Bad MP3 Header! Index: " + iter.nextIndex());
+ }
+ }
+ return false;
+ }
+ private void _parseSegmentInfo(Element level1, Element level2) {
+ level2 = ((MasterElement)level1).readNextChild(reader);
+
+ while (level2 != null) {
+ if (level2.equals(MatroskaDocType.Title_Id)) {
+ level2.readData(ioDS);
+ SegmentTitle = ((StringElement)level2).getValue();
+
+ } else if (level2.equals(MatroskaDocType.DateUTC_Id)) {
+ level2.readData(ioDS);
+ SegmentDate = ((DateElement)level2).getDate();
+
+ } else if (level2.equals(MatroskaDocType.MuxingApp_Id)) {
+ level2.readData(ioDS);
+ MuxingApp = ((StringElement)level2).getValue();
+
+ } else if (level2.equals(MatroskaDocType.WritingApp_Id)) {
+ level2.readData(ioDS);
+ WritingApp = ((StringElement)level2).getValue();
+
+ } else if (level2.equals(MatroskaDocType.Duration_Id)) {
+ level2.readData(ioDS);
+ Duration = ((FloatElement)level2).getValue();
+
+ } else if (level2.equals(MatroskaDocType.TimecodeScale_Id)) {
+ level2.readData(ioDS);
+ TimecodeScale = ((UnsignedInteger)level2).getValue();
+ }
+
+ level2.skipData(ioDS);
+ level2 = ((MasterElement)level1).readNextChild(reader);
+ }
+ }
+
+ private void _parseTracks(Element level1, Element level2) {
+ Element level3 = null;
+ Element level4 = null;
+ level2 = ((MasterElement)level1).readNextChild(reader);
+
+ while (level2 != null) {
+ if (level2.equals(MatroskaDocType.TrackEntry_Id)) {
+ MatroskaFileTrack track = new MatroskaFileTrack();
+ level3 = ((MasterElement)level2).readNextChild(reader);
+
+ while (level3 != null) {
+ if (level3.equals(MatroskaDocType.TrackNumber_Id)) {
+ level3.readData(ioDS);
+ track.TrackNo = (short)((UnsignedInteger)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.TrackUID_Id)) {
+ level3.readData(ioDS);
+ track.TrackUID = ((UnsignedInteger)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.TrackType_Id)) {
+ level3.readData(ioDS);
+ track.TrackType = (byte)((UnsignedInteger)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.TrackDefaultDuration_Id)) {
+ level3.readData(ioDS);
+ track.DefaultDuration = ((UnsignedInteger)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.TrackName_Id)) {
+ level3.readData(ioDS);
+ track.Name = ((StringElement)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.TrackLanguage_Id)) {
+ level3.readData(ioDS);
+ track.Language = ((StringElement)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.TrackCodecID_Id)) {
+ level3.readData(ioDS);
+ track.CodecID = ((StringElement)level3).getValue();
+
+ } else if (level3.equals(MatroskaDocType.TrackCodecPrivate_Id)) {
+ level3.readData(ioDS);
+ track.CodecPrivate = ((BinaryElement)level3).getData();
+
+ } else if (level3.equals(MatroskaDocType.TrackVideo_Id)) {
+ level4 = ((MasterElement)level3).readNextChild(reader);
+
+ while (level4 != null) {
+ if (level4.equals(MatroskaDocType.PixelWidth_Id)) {
+ level4.readData(ioDS);
+ track.Video_PixelWidth = (short)((UnsignedInteger)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.PixelHeight_Id)) {
+ level4.readData(ioDS);
+ track.Video_PixelHeight = (short)((UnsignedInteger)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.DisplayWidth_Id)) {
+ level4.readData(ioDS);
+ track.Video_DisplayWidth = (short)((UnsignedInteger)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.DisplayHeight_Id)) {
+ level4.readData(ioDS);
+ track.Video_DisplayHeight = (short)((UnsignedInteger)level4).getValue();
+ }
+
+ level4.skipData(ioDS);
+ level4 = ((MasterElement)level3).readNextChild(reader);
+ }
+
+ } else if (level3.equals(MatroskaDocType.TrackAudio_Id)) {
+ level4 = ((MasterElement)level3).readNextChild(reader);
+
+ while (level4 != null) {
+ if (level4.equals(MatroskaDocType.SamplingFrequency_Id)) {
+ level4.readData(ioDS);
+ track.Audio_SamplingFrequency = (float)((FloatElement)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.OutputSamplingFrequency_Id)) {
+ level4.readData(ioDS);
+ track.Audio_OutputSamplingFrequency = (float)((FloatElement)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.Channels_Id)) {
+ level4.readData(ioDS);
+ track.Audio_Channels = (short)((UnsignedInteger)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.BitDepth_Id)) {
+ level4.readData(ioDS);
+ track.Audio_BitDepth = (byte)((UnsignedInteger)level4).getValue();
+ }
+
+ level4.skipData(ioDS);
+ level4 = ((MasterElement)level3).readNextChild(reader);
+ }
+
+ }
+ level3.skipData(ioDS);
+ level3 = ((MasterElement)level2).readNextChild(reader);
+ }
+ TrackList.add(track);
+ }
+
+ level2.skipData(ioDS);
+ level2 = ((MasterElement)level1).readNextChild(reader);
+ }
+ }
+ private void _parseTags(Element level1, Element level2) {
+ Element level3 = null;
+ Element level4 = null;
+ level2 = ((MasterElement)level1).readNextChild(reader);
+
+ while (level2 != null) {
+ if (level2.equals(MatroskaDocType.Tag_Id)) {
+ MatroskaFileTagEntry tag = new MatroskaFileTagEntry();
+ level3 = ((MasterElement)level2).readNextChild(reader);
+
+ while (level3 != null) {
+ if (level3.equals(MatroskaDocType.TagTargets_Id)) {
+ level4 = ((MasterElement)level3).readNextChild(reader);
+
+ while (level4 != null) {
+ if (level4.equals(MatroskaDocType.TagTargetTrackUID_Id)) {
+ level4.readData(ioDS);
+ tag.TrackUID.add(new Long(((UnsignedInteger)level4).getValue()));
+
+ } else if (level4.equals(MatroskaDocType.TagTargetChapterUID_Id)) {
+ level4.readData(ioDS);
+ tag.ChapterUID.add(new Long(((UnsignedInteger)level4).getValue()));
+
+ } else if (level4.equals(MatroskaDocType.TagTargetAttachmentUID_Id)) {
+ level4.readData(ioDS);
+ tag.AttachmentUID.add(new Long(((UnsignedInteger)level4).getValue()));
+ }
+
+ level4.skipData(ioDS);
+ level4 = ((MasterElement)level3).readNextChild(reader);
+ }
+
+ } else if (level3.equals(MatroskaDocType.TagSimpleTag_Id)) {
+ tag.SimpleTags.add(_parseTagsSimpleTag(level3, level4));
+ }
+ level3.skipData(ioDS);
+ level3 = ((MasterElement)level2).readNextChild(reader);
+ }
+ TagList.add(tag);
+ }
+
+ level2.skipData(ioDS);
+ level2 = ((MasterElement)level1).readNextChild(reader);
+ }
+ }
+
+ private MatroskaFileSimpleTag _parseTagsSimpleTag(Element level3, Element level4) {
+ MatroskaFileSimpleTag SimpleTag = new MatroskaFileSimpleTag();
+ level4 = ((MasterElement)level3).readNextChild(reader);
+
+ while (level4 != null) {
+ if (level4.equals(MatroskaDocType.TagSimpleTagName_Id)) {
+ level4.readData(ioDS);
+ SimpleTag.Name = ((StringElement)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.TagSimpleTagString_Id)) {
+ level4.readData(ioDS);
+ SimpleTag.Value = ((StringElement)level4).getValue();
+
+ } else if (level4.equals(MatroskaDocType.TagSimpleTag_Id)) {
+ SimpleTag.Children.add(_parseTagsSimpleTag(level3, level4));
+ }
+
+ level4.skipData(ioDS);
+ level4 = ((MasterElement)level3).readNextChild(reader);
+ }
+
+ return SimpleTag;
+ }
+
+ /**
+ * Get a String report for the Matroska file.
+ * Call readFile() before this method, else the report will be empty.
+ *
+ * @return String Report
+ */
+ public String getReport() {
+ java.io.StringWriter s = new java.io.StringWriter();
+ int t;
+
+ s.write("MatroskaFile report\n");
+
+ s.write("Infomation Segment \n");
+ s.write("\tSegment Title: " + SegmentTitle + "\n");
+ s.write("\tSegment Date: " + SegmentDate + "\n");
+ s.write("\tMuxing App : " + MuxingApp + "\n");
+ s.write("\tWriting App : " + WritingApp + "\n");
+ s.write("\tDuration : " + Duration/1000 + "sec \n");
+ s.write("\tTimecodeScale : " + TimecodeScale + "\n");
+
+ s.write("Track Count: " + TrackList.size() + "\n");
+ for (t = 0; t < TrackList.size(); t++) {
+ s.write("\tTrack " + t + "\n");
+ s.write(TrackList.get(t).toString());
+ }
+
+ s.write("Tag Count: " + TagList.size() + "\n");
+ for (t = 0; t < TagList.size(); t++) {
+ s.write("\tTag Entry \n");
+ s.write(TagList.get(t).toString());
+ }
+
+ s.write("End report\n");
+
+ return s.getBuffer().toString();
+ }
+ public String getWritingApp() {
+ return WritingApp;
+ }
+ /**
+ * Returns an array of the tracks.
+ * If there are no MatroskaFileTracks to return the returned array
+ * will have a size of 0.
+ *
+ * @return Array of MatroskaFileTrack's
+ */
+ public MatroskaFileTrack [] getTrackList() {
+ if (TrackList.size() > 0) {
+ MatroskaFileTrack [] tracks = new MatroskaFileTrack[TrackList.size()];
+ for (int t = 0; t < TrackList.size(); t++) {
+ tracks[t] = (MatroskaFileTrack)TrackList.get(t);
+ }
+ return tracks;
+ } else {
+ return new MatroskaFileTrack[0];
+ }
+ }
+ /**
+ * <p>
+ * This differs from the getTrackList method in that this method scans
+ * each track and returns the one that has the same track number as TrackNo.
+ * </p>
+ *
+ * <p>Note: TrackNo != track index</p>
+ *
+ * @param TrackNo The actual track number of the MatroskaFileTrack you would like to get
+ * @return null if no MatroskaFileTrack is found with the requested TrackNo
+ */
+ public MatroskaFileTrack getTrack(int TrackNo) {
+ for (int t = 0; t < TrackList.size(); t++) {
+ MatroskaFileTrack track = (MatroskaFileTrack)TrackList.get(t);
+ if (track.TrackNo == TrackNo)
+ return track;
+ }
+ return null;
+ }
+ /**
+ * Get the timecode scale for this MatroskaFile.
+ * In Matroska the timecodes are stored scaled by this value.
+ * However any MatroskaFileFrame you get through the methods of this class
+ * will already have the timecodes correctly scaled to millseconds.
+ *
+ * @return TimecodeScale
+ */
+ public long getTimecodeScale() {
+ return TimecodeScale;
+ }
+ public String getSegmentTitle() {
+ return SegmentTitle;
+ }
+ public String getMuxingApp() {
+ return MuxingApp;
+ }
+ /**
+ * Get the duration for this MatroskaFile.
+ * This is the duration value stored in the segment info.
+ * Which may or may not be the exact length of all, some, or one of the tracks.
+ *
+ * @return Duration in seconds
+ */
+ public double getDuration() {
+ return Duration;
+ }
+
+ /**
+ * Sets if the readFile() method should scan the first cluster for infomation.
+ * Set to false for faster parsing.
+ */
+ public void setScanFirstCluster(boolean scanFirstCluster)
+ {
+ ScanFirstCluster = scanFirstCluster;
+ }
+
+ /**
+ * Gets if the readFile() method should scan the first cluster for infomation.
+ * When set to false parsing is slightly faster.
+ */
+ public boolean getScanFirstCluster()
+ {
+ return ScanFirstCluster;
+ }
+}
Modified: trunk/JEBML/src/org/ebml/matroska/jmf/JMFPullSourceStreamDataSource.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/jmf/JMFPullSourceStreamDataSource.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/matroska/jmf/JMFPullSourceStreamDataSource.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,63 +1,97 @@
-package org.ebml.matroska.jmf;
-
-import org.ebml.DataSource;
-
-/**
- * <p>Title: JEBML</p>
- * <p>Description: Java Classes to Read EBML Elements</p>
- * <p>Copyright: Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]></p>
- * <p>Company: </p>
- * @author jcsston
- * @version 1.0
- */
-
-public class JMFPullSourceStreamDataSource implements DataSource {
- protected javax.media.protocol.PullSourceStream source = null;
- protected byte [] buffer = new byte[1];
- protected int pos = 0;
-
- public JMFPullSourceStreamDataSource(javax.media.protocol.PullSourceStream source) {
- this.source = source;
- }
- public byte readByte() {
- try {
- pos += source.read(buffer, 0, 1);
- return buffer[0];
- } catch (java.io.IOException e) {
- // Internal error?
- return 0;
- }
- }
- public int read(byte[] buff) {
- try {
- return pos += source.read(buff, 0, buff.length);
- } catch (java.io.IOException e) {
- // Internal error?
- return 0;
- }
- }
- public int read(byte[] buff, int offset, int length) {
- try {
- return pos += source.read(buff, offset, length);
- } catch (java.io.IOException e) {
- // Internal error?
- return 0;
- }
- }
- public int skip(long offset) {
- try {
- int origPos = pos;
- while ((offset--) > 0) {
- pos += source.read(buffer, 0, 1);
- }
- return pos-origPos;
- } catch (java.io.IOException e) {
- // Internal error?
-
- }
- return 0;
- }
- public int getBytePosition() {
- return pos;
- }
+package org.ebml.matroska.jmf;
+
+import org.ebml.DataSource;
+
+/**
+ * <p>Title: JEBML</p>
+ * <p>Description: Java Classes to Read EBML Elements</p>
+ * <p>Copyright: Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]></p>
+ * <p>Company: </p>
+ * @author jcsston
+ * @version 1.0
+ */
+
+public class JMFPullSourceStreamDataSource implements DataSource {
+ protected javax.media.protocol.PullSourceStream source = null;
+ protected javax.media.protocol.Seekable seeking = null;
+ protected byte [] buffer = new byte[1];
+ protected long pos = 0;
+
+ public JMFPullSourceStreamDataSource(javax.media.protocol.PullSourceStream source) {
+ this.source = source;
+ if (source instanceof javax.media.protocol.Seekable) {
+ seeking = (javax.media.protocol.Seekable)source;
+ if (!seeking.isRandomAccess()) {
+ seeking = null;
+ }
+ }
+ }
+ public byte readByte() {
+ try {
+ int l = source.read(buffer, 0, 1);
+ pos += l;
+ return buffer[0];
+ } catch (java.io.IOException e) {
+ // Internal error?
+ return 0;
+ }
+ }
+ public int read(byte[] buff) {
+ try {
+ int l = source.read(buff, 0, buff.length);
+ pos += l;
+ return l;
+ } catch (java.io.IOException e) {
+ // Internal error?
+ return 0;
+ }
+ }
+ public int read(byte[] buff, int offset, int length) {
+ try {
+ int l = source.read(buff, offset, length);
+ pos += l;
+ return l;
+ } catch (java.io.IOException e) {
+ // Internal error?
+ return 0;
+ }
+ }
+ public long skip(long offset) {
+ try {
+ long origPos = pos;
+ while ((offset--) > 0) {
+ pos += source.read(buffer, 0, 1);
+ }
+ return pos-origPos;
+ } catch (java.io.IOException e) {
+ // Internal error?
+
+ }
+ return 0;
+ }
+
+ public long length() {
+ long length = source.getContentLength();
+ if (length == source.LENGTH_UNKNOWN)
+ return -1;
+
+ return length;
+ }
+
+ public long getFilePointer() {
+ return pos;
+ }
+
+ public boolean isSeekable() {
+ if (seeking != null)
+ return true;
+ return false;
+ }
+
+ public long seek(long pos) {
+ if (seeking != null) {
+ return seeking.seek(pos);
+ }
+ return -1;
+ }
}
\ No newline at end of file
Modified: trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexer.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexer.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexer.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,216 +1,304 @@
-package org.ebml.matroska.jmf;
-
-import org.ebml.matroska.MatroskaFile;
-import java.io.*;
-import java.util.*;
-import javax.media.*;
-import javax.media.protocol.*;
-
-/**
- * <p>Title: JMF Matroska Demultiplexer</p>
- * <p>Description: A Matroska Demultiplexer for JMF (Java Media Framework)</p>
- * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
- * @author jcsston
- * @version 0.0.1
- */
-
-// org.ebml.matroska.jmf.MatroskaDemultiplexer
-public class MatroskaDemultiplexer
- implements Demultiplexer
-{
- protected boolean seekable = false;
- protected long lastTimecode = 0;
-
- protected MatroskaFile file = null;
- protected PullSourceStream stream = null;
- protected DataSource source = null;
- protected SourceStream[] streams = null;
- protected static ContentDescriptor[] supportedFormat =
- new ContentDescriptor[] {
- new ContentDescriptor("video.x_matroska"),
- new ContentDescriptor("audio.x_matroska")};
-
- public ContentDescriptor[] getSupportedInputContentDescriptors() {
- System.out.println("MatroskaDemultiplexer.getSupportedInputContentDescriptors()");
- return supportedFormat;
- }
-
- public Track[] getTracks() throws java.io.IOException,
- javax.media.BadHeaderException {
- System.out.println("MatroskaDemultiplexer.getTracks()");
- if (file == null) {
- file = new MatroskaFile(new JMFPullSourceStreamDataSource(stream));
- try {
- file.readFile();
- } catch (java.lang.RuntimeException ex) {
- ex.printStackTrace();
- throw new javax.media.BadHeaderException("MatroskaDemultiplexer: " +
- ex.toString() + ex.getMessage());
- }
- }
- ArrayList demuxTracks = new ArrayList();
- MatroskaFile.MatroskaFileTrack [] fileTracks = file.getTrackList();
- for (int t = 0; t < fileTracks.length; t++) {
- MatroskaDemultiplexerTrack track = new MatroskaDemultiplexerTrack(file, fileTracks[t].TrackNo);
- if (track.isEnabled())
- demuxTracks.add(track);
- }
-
- if (demuxTracks.size() == 0) {
- throw new javax.media.BadHeaderException("MatroskaDemultiplexer: No playable tracks found.");
- }
-
- Track [] tracks = new Track[demuxTracks.size()];
- for (int t = 0; t < demuxTracks.size(); t++) {
- tracks[t] = (Track)demuxTracks.get(t);
- }
-
- return tracks;
-
- //return (Track[])demuxTracks.toArray();
- }
-
- public boolean isPositionable() {
- return seekable;
- }
-
- public boolean isRandomAccess() {
- return seekable;
- }
-
- public Time setPosition(Time parm1, int parm2) {
- if (!seekable) {
- return getMediaTime();
- } else {
- throw new java.lang.UnsupportedOperationException(
- "Method setPosition() not yet implemented.");
- }
- }
-
- public Time getMediaTime() {
- return new Time(lastTimecode);
- }
-
- public Time getDuration() {
- return this.DURATION_UNKNOWN;
- }
-
- public String getName() {
- return "MatroskaDemultiplexer v0.0.1";
- }
-
- /**
- * Opens the plug-in software or hardware component and acquires
- * necessary resources. If all the needed resources could not be
- * acquired, it throws a ResourceUnavailableException. Data should not
- * be passed into the plug-in without first calling this method.
- */
- public void open() throws javax.media.ResourceUnavailableException {
- // Not needed
- }
-
- /**
- * Closes the plug-in component and releases resources. No more data
- * will be accepted by the plug-in after a call to this method. The
- * plug-in can be reinstated after being closed by calling
- * <code>open</code>.
- */
- public void close() {
- if (source != null) {
- try {
- source.stop();
- source.disconnect();
- } catch (IOException e) {
- // Internal error?
- }
- source = null;
- }
- }
-
- /**
- * This get called when the player/processor is started.
- */
- public void start() throws IOException {
- if (source != null) {
- source.start();
- }
- }
-
- /**
- * This get called when the player/processor is stopped.
- */
- public void stop() {
- if (source != null) {
- try {
- source.stop();
- } catch (IOException e) {
- // Internal errors?
- }
- }
- }
-
- /**
- * Resets the state of the plug-in. Typically at end of media or when media
- * is repositioned.
- */
- public void reset() {
- // Not needed
- }
-
- public void setSource(DataSource source) throws java.io.IOException,
- javax.media.IncompatibleSourceException {
- System.out.println("MatroskaDemultiplexer.setSource(source = " + source + ")");
- if (!(source instanceof PullDataSource)) {
- throw new IncompatibleSourceException("DataSource not supported: " +
- source);
- } else {
- streams = ((PullDataSource)source).getStreams();
- }
-
- if (streams == null) {
- throw new IOException("Got a null stream from the DataSource");
- }
-
- if (streams.length == 0) {
- throw new IOException("Got a empty stream array from the DataSource");
- }
-
- this.source = source;
- this.streams = streams;
-
- //positionable = (streams[0] instanceof Seekable);
- //seekable = positionable && ((Seekable) streams[0]).isRandomAccess();
-
- if (!supports(streams)) {
- throw new IncompatibleSourceException("DataSource not supported: " +
- source);
- }
- stream = (PullSourceStream)streams[0];
- }
-
- /**
- * A Demultiplexer may support pull only or push only or both
- * pull and push streams.
- * Some Demultiplexer may have other requirements.
- * For e.g a quicktime Demultiplexer imposes an additional
- * requirement that
- * isSeekable() and isRandomAccess() be true
- */
- protected boolean supports(SourceStream[] streams) {
- return ((streams[0] != null) &&
- (streams[0] instanceof PullSourceStream));
-
- }
-
- /**
- * Not sure what these Control methods do...
- */
- public Object[] getControls() {
- return new Object[0];
- }
-
- public Object getControl(String controlType) {
- return null;
- }
-
+package org.ebml.matroska.jmf;
+
+import org.ebml.matroska.MatroskaFile;
+import java.io.*;
+import java.util.*;
+import javax.media.*;
+import javax.media.protocol.*;
+import com.sun.media.MimeManager;
+
+/**
+ * <p>Title: JMF Matroska Demultiplexer</p>
+ * <p>Description: A Matroska Demultiplexer for JMF (Java Media Framework)</p>
+ * <p>Copyright: Copyright (c) 2004 Jory Stone <[email protected]></p>
+ * @author jcsston
+ * @version 0.0.1
+ */
+
+// org.ebml.matroska.jmf.MatroskaDemultiplexer
+public class MatroskaDemultiplexer
+ implements Demultiplexer
+{
+ // Reg function
+ public static void main(String [] args) {
+ try {//MatroskaDemultiplexer
+ String pluginName = "org.ebml.matroska.jmf.MatroskaDemultiplexer";
+ int pluginType = PlugInManager.DEMULTIPLEXER;
+
+ boolean install = true;
+ if (args.length > 0) {
+ if (args[0].trim().compareToIgnoreCase("/u") == 0) {
+ // Uninstall instead
+ install = false;
+ } else {
+ // Display usage
+ System.out.println("Usage:");
+ System.out.println("\t \t Install");
+ System.out.println("\t /u \t Uninstall");
+ return;
+ }
+ }
+
+ boolean ret = true;
+ if (install == true) {
+ System.out.println(
+ "Adding " + pluginName + " to the plug-in registry...");
+ // Add the this plug-in to the plug-in registry
+ ret = PlugInManager.addPlugIn(
+ pluginName,
+ new ContentDescriptor[] {new ContentDescriptor("video/x_matroska"),
+ new ContentDescriptor("audio/x_matroska")}
+ ,
+ null,
+ pluginType);
+ if (ret == false) {
+ System.out.println(
+ "Failed, PlugInManager.addPlugIn() returned false.");
+ }
+ ret = MimeManager.addMimeType("mkv", "video/x_matroska");
+ if (ret == false) {
+ System.out.println(
+ "Failed, MimeManager.addMimeType() returned false.");
+ }
+ ret = MimeManager.addMimeType("mka", "audio/x_matroska");
+ if (ret == false) {
+ System.out.println(
+ "Failed, MimeManager.addMimeType() returned false.");
+ }
+
+ } else {
+ // Uninstall
+ System.out.println(
+ "Removing " + pluginName + " from the plug-in registry...");
+ // Remove the this plug-in from the plug-in registry
+ ret = PlugInManager.removePlugIn(pluginName, pluginType);
+ if (ret == false) {
+ System.out.println(
+ "Failed, PlugInManager.removePlugIn() returned false.");
+ }
+ ret = MimeManager.removeMimeType("mkv");
+ if (ret == false) {
+ System.out.println(
+ "Failed, MimeManager.removeMimeType() returned false.");
+ }
+ ret = MimeManager.removeMimeType("mka");
+ if (ret == false) {
+ System.out.println(
+ "Failed, MimeManager.removeMimeType() returned false.");
+ }
+
+ }
+
+ // Save the changes to the plug-in registry
+ PlugInManager.commit();
+
+ // Save the changes to the mime type registry
+ MimeManager.commit();
+
+ System.out.println("Complete");
+
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ protected boolean seekable = false;
+ protected long lastTimecode = 0;
+
+ protected MatroskaFile file = null;
+ protected PullSourceStream stream = null;
+ protected DataSource source = null;
+ protected SourceStream[] streams = null;
+ protected static ContentDescriptor[] supportedFormat =
+ new ContentDescriptor[] {
+ new ContentDescriptor("video.x_matroska"),
+ new ContentDescriptor("audio.x_matroska")};
+
+ public ContentDescriptor[] getSupportedInputContentDescriptors() {
+ System.out.println("MatroskaDemultiplexer.getSupportedInputContentDescriptors()");
+ return supportedFormat;
+ }
+
+ public Track[] getTracks() throws java.io.IOException,
+ javax.media.BadHeaderException {
+ System.out.println("MatroskaDemultiplexer.getTracks()");
+ if (file == null) {
+ file = new MatroskaFile(new JMFPullSourceStreamDataSource(stream));
+ try {
+ file.readFile();
+ } catch (java.lang.RuntimeException ex) {
+ ex.printStackTrace();
+ throw new javax.media.BadHeaderException("MatroskaDemultiplexer: " +
+ ex.toString() + ex.getMessage());
+ }
+ seekable = file.isSeekable();
+ }
+ ArrayList demuxTracks = new ArrayList();
+ MatroskaFile.MatroskaFileTrack [] fileTracks = file.getTrackList();
+ for (int t = 0; t < fileTracks.length; t++) {
+ MatroskaDemultiplexerTrack track = new MatroskaDemultiplexerTrack(file, fileTracks[t].TrackNo);
+ if (track.isEnabled())
+ demuxTracks.add(track);
+ }
+
+ if (demuxTracks.size() == 0) {
+ throw new javax.media.BadHeaderException("MatroskaDemultiplexer: No playable tracks found.");
+ }
+
+ Track [] tracks = new Track[demuxTracks.size()];
+ for (int t = 0; t < demuxTracks.size(); t++) {
+ tracks[t] = (Track)demuxTracks.get(t);
+ }
+
+ return tracks;
+ }
+
+ public boolean isPositionable() {
+ return seekable;
+ }
+
+ public boolean isRandomAccess() {
+ return seekable;
+ }
+
+ public Time setPosition(Time parm1, int parm2) {
+ System.out.println("MatroskaDemultiplexer.setPosition(parm1 = " + parm1 + ", parm2 = " + parm2 +")");
+ if (!seekable) {
+ return getMediaTime();
+ } else {
+ throw new java.lang.UnsupportedOperationException(
+ "Method setPosition() not yet implemented.");
+ }
+ }
+
+ public Time getMediaTime() {
+ return new Time(lastTimecode);
+ }
+
+ public Time getDuration() {
+ return new Time(file.getDuration());
+ }
+
+ public String getName() {
+ return "Matroska Demuxer v0.0.1";
+ }
+
+ /**
+ * Opens the plug-in software or hardware component and acquires
+ * necessary resources. If all the needed resources could not be
+ * acquired, it throws a ResourceUnavailableException. Data should not
+ * be passed into the plug-in without first calling this method.
+ */
+ public void open() throws javax.media.ResourceUnavailableException {
+ System.out.println("MatroskaDemultiplexer.open()");
+ // Not needed
+ }
+
+ /**
+ * Closes the plug-in component and releases resources. No more data
+ * will be accepted by the plug-in after a call to this method. The
+ * plug-in can be reinstated after being closed by calling
+ * <code>open</code>.
+ */
+ public void close() {
+ System.out.println("MatroskaDemultiplexer.close()");
+ if (source != null) {
+ try {
+ source.stop();
+ source.disconnect();
+ } catch (IOException e) {
+ // Internal error?
+ }
+ source = null;
+ }
+ }
+
+ /**
+ * This get called when the player/processor is started.
+ */
+ public void start() throws IOException {
+ System.out.println("MatroskaDemultiplexer.start()");
+ if (source != null) {
+ source.start();
+ }
+ }
+
+ /**
+ * This get called when the player/processor is stopped.
+ */
+ public void stop() {
+ System.out.println("MatroskaDemultiplexer.stop()");
+ if (source != null) {
+ try {
+ source.stop();
+ } catch (IOException e) {
+ // Internal errors?
+ }
+ }
+ }
+
+ /**
+ * Resets the state of the plug-in. Typically at end of media or when media
+ * is repositioned.
+ */
+ public void reset() {
+ // Not needed
+ }
+
+ public void setSource(DataSource source) throws java.io.IOException,
+ javax.media.IncompatibleSourceException {
+ System.out.println("MatroskaDemultiplexer.setSource(source = " + source + ")");
+ if (!(source instanceof PullDataSource)) {
+ throw new IncompatibleSourceException("DataSource not supported: " +
+ source);
+ } else {
+ streams = ((PullDataSource)source).getStreams();
+ }
+
+ if (streams == null) {
+ throw new IOException("Got a null stream from the DataSource");
+ }
+
+ if (streams.length == 0) {
+ throw new IOException("Got a empty stream array from the DataSource");
+ }
+
+ this.source = source;
+ this.streams = streams;
+
+ //positionable = (streams[0] instanceof Seekable);
+ //seekable = positionable && ((Seekable) streams[0]).isRandomAccess();
+
+ if (!supports(streams)) {
+ throw new IncompatibleSourceException("DataSource not supported: " +
+ source);
+ }
+ stream = (PullSourceStream)streams[0];
+ }
+
+ /**
+ * A Demultiplexer may support pull only or push only or both
+ * pull and push streams.
+ * Some Demultiplexer may have other requirements.
+ * For e.g a quicktime Demultiplexer imposes an additional
+ * requirement that
+ * isSeekable() and isRandomAccess() be true
+ */
+ protected boolean supports(SourceStream[] streams) {
+ return ((streams[0] != null) &&
+ (streams[0] instanceof PullSourceStream));
+
+ }
+
+ /**
+ * Not sure what these Control methods do...
+ */
+ public Object[] getControls() {
+ return new Object[0];
+ }
+
+ public Object getControl(String controlType) {
+ return null;
+ }
+
}
\ No newline at end of file
Modified: trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexerTrack.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexerTrack.java 2004-09-27 15:46:45 UTC (rev 848)
+++ trunk/JEBML/src/org/ebml/matroska/jmf/MatroskaDemultiplexerTrack.java 2004-10-01 20:35:50 UTC (rev 849)
@@ -1,96 +1,99 @@
-package org.ebml.matroska.jmf;
-
-import org.ebml.matroska.MatroskaFile;
-import javax.media.Track;
-import javax.media.Format;
-import javax.media.Time;
-import javax.media.Buffer;
-import javax.media.TrackListener;
-import javax.media.format.*;
-
-/**
- * <p>Title: JEBML</p>
- * <p>Description: Java Classes to Read EBML Elements</p>
- * <p>Copyright: Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]></p>
- * <p>Company: </p>
- * @author jcsston
- * @version 1.0
- */
-
-public class MatroskaDemultiplexerTrack implements Track {
- protected MatroskaFile file = null;
- protected int TrackNo = -1;
- protected boolean Valid = false;
- protected Format format = null;
- protected boolean Enabled = false;
-
- public MatroskaDemultiplexerTrack(MatroskaFile file, int TrackNo) {
- this.file = file;
- this.TrackNo = TrackNo;
- init();
- }
-
- public void init() {
- MatroskaFile.MatroskaFileTrack track = file.getTrack(TrackNo);
- if (track.CodecID.compareTo("V_MS/VFW/FOURCC") == 0) {
-
- } else if (track.CodecID.compareTo("A_MPEG/L3") == 0) {
- if (track.Audio_BitDepth == 0)
- track.Audio_BitDepth = 16;
- format = new AudioFormat(AudioFormat.MPEGLAYER3, track.Audio_SamplingFrequency, track.Audio_BitDepth, track.Audio_Channels);
-
- setEnabled(true);
- } else if (track.CodecID.compareTo("A_MPEG/L2") == 0) {
- if (track.Audio_BitDepth == 0)
- track.Audio_BitDepth = 16;
- format = new AudioFormat("mpegaudio", track.Audio_SamplingFrequency, track.Audio_BitDepth, track.Audio_Channels);
-
- setEnabled(true);
- }
- }
-
- public Format getFormat() {
- return format;
- }
- public void setEnabled(boolean Enabled) {
- this.Enabled = Enabled;
- }
- public boolean isEnabled() {
- return Enabled;
- }
- public Time getStartTime() {
- /**@todo Implement this javax.media.Track method*/
- throw new java.lang.UnsupportedOperationException("Method getStartTime() not yet implemented.");
- }
- public void readFrame(Buffer buffer) {
- //System.out.println("MatroskaDemultiplexerTrack.readFrame(buffer = " + buffer + ")");
- MatroskaFile.MatroskaFrame frame = file.getNextFrame(TrackNo);
- if (frame == null) {
- buffer.setDiscard(true);
- buffer.setEOM(true);
- return;
- }
- buffer.setTimeStamp(frame.Timecode * 1000000);
- if (frame.Duration != 0) {
- buffer.setDuration(frame.Duration * 1000000);
- } else {
- buffer.setDuration(buffer.TIME_UNKNOWN);
- }
- Object data = buffer.getData();
- buffer.setData(frame.Data);
- buffer.setLength(frame.Data.length);
- }
- public int mapTimeToFrame(Time time) {
- return this.FRAME_UNKNOWN;
- }
- public Time mapFrameToTime(int frame) {
- return this.TIME_UNKNOWN;
- }
- public void setTrackListener(TrackListener listen) {
- /**@todo Implement this javax.media.Track method*/
- //throw new java.lang.UnsupportedOperationException("Method setTrackListener() not yet implemented.");
- }
- public Time getDuration() {
- return this.DURATION_UNKNOWN;
- }
+package org.ebml.matroska.jmf;
+
+import org.ebml.matroska.MatroskaFile;
+import javax.media.Track;
+import javax.media.Format;
+import javax.media.Time;
+import javax.media.Buffer;
+import javax.media.TrackListener;
+import javax.media.format.*;
+
+/**
+ * <p>Title: JEBML</p>
+ * <p>Description: Java Classes to Read EBML Elements</p>
+ * <p>Copyright: Copyright (c) 2002-2004 John Cannon <[email protected]>, Jory Stone <[email protected]></p>
+ * <p>Company: </p>
+ * @author jcsston
+ * @version 1.0
+ */
+
+public class MatroskaDemultiplexerTrack implements Track {
+ protected MatroskaFile file = null;
+ protected int TrackNo = -1;
+ protected boolean Valid = false;
+ protected Format format = null;
+ protected boolean Enabled = false;
+ protected long StartTimecode = -1;
+
+ public MatroskaDemultiplexerTrack(MatroskaFile file, int TrackNo) {
+ this.file = file;
+ this.TrackNo = TrackNo;
+ init();
+ }
+
+ public void init() {
+ MatroskaFile.MatroskaFileTrack track = file.getTrack(TrackNo);
+ if (track.CodecID.compareTo("V_MS/VFW/FOURCC") == 0) {
+
+ } else if (track.CodecID.compareTo("A_MPEG/L3") == 0) {
+ if (track.Audio_BitDepth == 0)
+ track.Audio_BitDepth = 16;
+ format = new AudioFormat(AudioFormat.MPEGLAYER3, track.Audio_SamplingFrequency, track.Audio_BitDepth, track.Audio_Channels);
+
+ setEnabled(true);
+ } else if (track.CodecID.compareTo("A_MPEG/L2") == 0) {
+ if (track.Audio_BitDepth == 0)
+ track.Audio_BitDepth = 16;
+ format = new AudioFormat("mpegaudio", track.Audio_SamplingFrequency, track.Audio_BitDepth, track.Audio_Channels);
+
+ setEnabled(true);
+ }
+ }
+
+ public Format getFormat() {
+ return format;
+ }
+ public void setEnabled(boolean Enabled) {
+ this.Enabled = Enabled;
+ }
+ public boolean isEnabled() {
+ return Enabled;
+ }
+ public Time getStartTime() {
+ return new Time(StartTimecode);
+ }
+ public void readFrame(Buffer buffer) {
+ //System.out.println("MatroskaDemultiplexerTrack.readFrame(buffer = " + buffer + ")");
+ MatroskaFile.MatroskaFrame frame = file.getNextFrame(TrackNo);
+ if (frame == null) {
+ buffer.setDiscard(true);
+ buffer.setEOM(true);
+ return;
+ }
+ if (StartTimecode == -1) {
+ StartTimecode = frame.Timecode;
+ }
+ buffer.setTimeStamp(frame.Timecode * 1000000);
+ if (frame.Duration != 0) {
+ buffer.setDuration(frame.Duration * 1000000);
+ } else {
+ buffer.setDuration(buffer.TIME_UNKNOWN);
+ }
+ Object data = buffer.getData();
+ buffer.setData(frame.Data);
+ buffer.setLength(frame.Data.length);
+ }
+ public int mapTimeToFrame(Time time) {
+ return this.FRAME_UNKNOWN;
+ }
+ public Time mapFrameToTime(int frame) {
+ return this.TIME_UNKNOWN;
+ }
+ public void setTrackListener(TrackListener listen) {
+ /**@todo Implement this javax.media.Track method*/
+ //throw new java.lang.UnsupportedOperationException("Method setTrackListener() not yet implemented.");
+ }
+ public Time getDuration() {
+ return new Time(file.getDuration());
+ }
}
\ No newline at end of file
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.