[matroska] r868 - in trunk/JEBML: . src/org/ebml src/org/ebml/matroska src/org/ebml/sample src/org/ebml/util

[email protected]
Newsgroups gmane.comp.multimedia.matroska.cvs
Message-ID <[email protected]>
Author: jcsston
Date: 2004-10-07 14:02:37 +0400 (Thu, 07 Oct 2004)
New Revision: 868

Added:
   trunk/JEBML/src/org/ebml/matroska/MatroskaCluster.java
Modified:
   trunk/JEBML/JEBML.vjsproj
   trunk/JEBML/src/org/ebml/EBMLReader.java
   trunk/JEBML/src/org/ebml/Element.java
   trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java
   trunk/JEBML/src/org/ebml/matroska/MatroskaDocType.java
   trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java
   trunk/JEBML/src/org/ebml/matroska/MatroskaFileFrame.java
   trunk/JEBML/src/org/ebml/matroska/MatroskaFileWriter.java
   trunk/JEBML/src/org/ebml/sample/CommandLineSample.java
   trunk/JEBML/src/org/ebml/sample/EbmlSampleAppFrame.java
   trunk/JEBML/src/org/ebml/util/ArrayCopy.java
Log:
Started Cluster writing classes.
Changed the block parsing to take place in memory instead of reading the input stream byte by byte. Very likely I broke it.

Modified: trunk/JEBML/JEBML.vjsproj
===================================================================
--- trunk/JEBML/JEBML.vjsproj	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/JEBML.vjsproj	2004-10-07 10:02:37 UTC (rev 868)
@@ -175,6 +175,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\org\ebml\matroska\MatroskaCluster.java"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\org\ebml\matroska\MatroskaDocType.java"
                     SubType = "Code"
                     BuildAction = "Compile"

Modified: trunk/JEBML/src/org/ebml/EBMLReader.java
===================================================================
--- trunk/JEBML/src/org/ebml/EBMLReader.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/EBMLReader.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -20,6 +20,7 @@
 package org.ebml;
 
 import org.ebml.io.*;
+import org.ebml.util.*;
 
 /**
  * EBMLReader.java
@@ -179,11 +180,161 @@
   }
 
   /**
+   * Reads an (Unsigned) EBML code from the DataSource and encodes it into a long.  This size should be
+   * cast into an int for actual use as Java only allows upto 32-bit file I/O operations.
+   *
+   * @return ebml size
+   */
+  static public long readEBMLCode(byte [] source) 
+  {
+    return readEBMLCode(source, 0);
+  }
+
+  /**
+   * Reads an (Unsigned) EBML code from the DataSource and encodes it into a long.  This size should be
+   * cast into an int for actual use as Java only allows upto 32-bit file I/O operations.
+   *
+   * @return ebml size
+   */
+  static public long readEBMLCode(byte [] source, int offset) 
+  {
+    //Begin loop with byte set to newly read byte.
+    byte firstByte = source[offset];
+    int numBytes = 0;
+
+    //Begin by counting the bits unset before the first '1'.
+    long mask = 0x0080;
+    for (int i = 0; i < 8; i++) 
+    {
+      //Start at left, shift to right.
+      if ((firstByte & mask) == mask) 
+      { //One found
+        //Set number of bytes in size = i+1 ( we must count the 1 too)
+        numBytes = i + 1;
+        //exit loop by pushing i out of the limit
+        i = 8;
+      }
+      mask >>>= 1;
+    }
+    if (numBytes == 0)
+      // Invalid size
+      return 0;
+
+    //Setup space to store the bits
+    byte[] data = new byte[numBytes];
+
+    //Clear the 1 at the front of this byte, all the way to the beginning of the size
+    data[0] = (byte)(firstByte & ((0xFF >>> (numBytes))));
+
+    if (numBytes > 1) 
+    {
+      //Read the rest of the size.
+      ArrayCopy.arraycopy(data, 1, source, offset+1, numBytes - 1);
+    }
+
+    //Put this into a long
+    long size = 0;
+    long n = 0;
+    for (int i = 0; i < numBytes; i++) 
+    {
+      n = ((long)data[numBytes - 1 - i] << 56) >>> 56;
+      size = size | (n << (8 * i));
+    }
+    return size;
+  }
+
+  /**
    * Reads an Signed EBML code from the DataSource and encodes it into a long.  This size should be
    * cast into an int for actual use as Java only allows upto 32-bit file I/O operations.
    *
    * @return ebml size
    */
+  static public long readSignedEBMLCode(byte [] source) 
+  {
+    return readSignedEBMLCode(source, 0);
+  }
+
+  /**
+   * Reads an Signed EBML code from the DataSource and encodes it into a long.  This size should be
+   * cast into an int for actual use as Java only allows upto 32-bit file I/O operations.
+   *
+   * @return ebml size
+   */
+  static public long readSignedEBMLCode(byte [] source, int offset) 
+  {
+    //Begin loop with byte set to newly read byte.
+    byte firstByte = source[offset];
+    int numBytes = 0;
+
+    //Begin by counting the bits unset before the first '1'.
+    long mask = 0x0080;
+    for (int i = 0; i < 8; i++) 
+    {
+      //Start at left, shift to right.
+      if ((firstByte & mask) == mask) 
+      { //One found
+        //Set number of bytes in size = i+1 ( we must count the 1 too)
+        numBytes = i + 1;
+        //exit loop by pushing i out of the limit
+        i = 8;
+      }
+      mask >>>= 1;
+    }
+    if (numBytes == 0)
+      // Invalid size
+      return 0;
+
+    //Setup space to store the bits
+    byte[] data = new byte[numBytes];
+
+    //Clear the 1 at the front of this byte, all the way to the beginning of the size
+    data[0] = (byte)(firstByte & ((0xFF >>> (numBytes))));
+
+    if (numBytes > 1) 
+    {
+      //Read the rest of the size.
+      ArrayCopy.arraycopy(data, 1, source, offset+1, numBytes - 1);
+    }
+
+    //Put this into a long
+    long size = 0;
+    long n = 0;
+    for (int i = 0; i < numBytes; i++) 
+    {
+      n = ((long)data[numBytes - 1 - i] << 56) >>> 56;
+      size = size | (n << (8 * i));
+    }
+
+    // Sign it ;)
+    if (numBytes == 1) 
+    {
+      size -= 63;
+
+    } 
+    else if (numBytes == 2) 
+    {
+      size -= 8191;
+
+    } 
+    else if (numBytes == 3) 
+    {
+      size -= 1048575;
+
+    } 
+    else if (numBytes == 4) 
+    {
+      size -= 134217727;
+    }
+
+    return size;
+  }
+
+  /**
+   * Reads an Signed EBML code from the DataSource and encodes it into a long.  This size should be
+   * cast into an int for actual use as Java only allows upto 32-bit file I/O operations.
+   *
+   * @return ebml size
+   */
   static public long readSignedEBMLCode(DataSource source) {
 
     //Begin loop with byte set to newly read byte.

Modified: trunk/JEBML/src/org/ebml/Element.java
===================================================================
--- trunk/JEBML/src/org/ebml/Element.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/Element.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -26,6 +26,7 @@
  */
 
 import org.ebml.io.*;
+import org.ebml.util.*;
 
 /**
      * Defines the basic EBML element.  Subclasses may provide child element access.
@@ -217,9 +218,9 @@
   public static byte[] makeEbmlCode(byte[] typeID, long size) {
     int codedLen = codedSizeLength(size);
     byte[] ret = new byte[typeID.length + codedLen];
-    org.ebml.util.ArrayCopy.arraycopy(typeID, 0, ret, 0, typeID.length);
+    ArrayCopy.arraycopy(typeID, 0, ret, 0, typeID.length);
     byte[] codedSize = makeEbmlCodedSize(size);
-    org.ebml.util.ArrayCopy.arraycopy(codedSize, 0, ret, typeID.length, codedSize.length);
+    ArrayCopy.arraycopy(codedSize, 0, ret, typeID.length, codedSize.length);
     return ret;
   }
 

Modified: trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaBlock.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -21,6 +21,7 @@
 
 import org.ebml.*;
 import org.ebml.io.*;
+import org.ebml.util.*;
 
 public class MatroskaBlock extends BinaryElement {
   protected int [] Sizes = null;
@@ -32,33 +33,34 @@
     super(type);
   }
 
-  public void readData(DataSource source) {
-    parseBlock(source);
-  }
+  //public void readData(DataSource source) {
+  //  parseBlock();
+  //}
 
-  public void parseBlock(DataSource source) {
+  public void parseBlock() {
+    int index = 0;
+    TrackNo = (int)EBMLReader.readEBMLCode(data);
+    index = Element.codedSizeLength(TrackNo);
+    HeaderSize += index;
 
-    TrackNo = (int)EBMLReader.readEBMLCode(source);
-    HeaderSize += Element.codedSizeLength(TrackNo);
-
-    short BlockTimecode1 = (short)(source.readByte() & 0xFF);
-    short BlockTimecode2 = (short)(source.readByte() & 0xFF);
+    short BlockTimecode1 = (short)(data[index++] & 0xFF);
+    short BlockTimecode2 = (short)(data[index++] & 0xFF);
     if (BlockTimecode1 != 0 || BlockTimecode2 != 0) {
       BlockTimecode = (BlockTimecode1 << 8) | BlockTimecode2;
     }
 
-    int LaceFlag = source.readByte() & 0x06;
+    int LaceFlag = data[index++] & 0x06;
     // Increase the HeaderSize by the number of bytes we have read
     HeaderSize += 3;
     if (LaceFlag != 0x00) {
       // We have lacing
-      byte LaceCount = source.readByte();
+      byte LaceCount = data[index++];
       HeaderSize += 1;
       if (LaceFlag == 0x02) { // Xiph Lacing
-        Sizes = readXiphLaceSizes(source, LaceCount);
+        Sizes = readXiphLaceSizes(index, LaceCount);
 
       } else if (LaceFlag == 0x06) { // EBML Lacing
-        Sizes = readEBMLLaceSizes(source, LaceCount);
+        Sizes = readEBMLLaceSizes(index, LaceCount);
 
       } else if (LaceFlag == 0x04) { // Fixed Size Lacing
         Sizes = new int[LaceCount+1];
@@ -66,29 +68,32 @@
         for (int s = 0; s < LaceCount; s++)
           Sizes[s+1] = Sizes[0];
       } else {
-        throw new java.lang.RuntimeException("Unsupported lacing type flag.");
+        throw new RuntimeException("Unsupported lacing type flag.");
       }
     }
-    data = new byte[(int)(this.getSize() - HeaderSize)];
-    source.read(data, 0, data.length);
-    this.dataRead = true;
+    //data = new byte[(int)(this.getSize() - HeaderSize)];
+    //source.read(data, 0, data.length);
+    //this.dataRead = true;
   }
 
-  public int[] readEBMLLaceSizes(DataSource source, short LaceCount) {
+  public int[] readEBMLLaceSizes(int index, 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();
+    //long ByteStartPos = source.getFilePointer();
+    int startIndex = index;
 
-    LaceSizes[0] = (int)EBMLReader.readEBMLCode(source);
+    LaceSizes[0] = (int)EBMLReader.readEBMLCode(data, index);
+    index += Element.codedSizeLength(LaceSizes[0]);
     LaceSizes[LaceCount] -= LaceSizes[0];
 
     long FirstEBMLSize = LaceSizes[0];
     long LastEBMLSize = 0;
     for (int l = 0; l < LaceCount-1; l++) {
-      LastEBMLSize = EBMLReader.readSignedEBMLCode(source);
+      LastEBMLSize = EBMLReader.readSignedEBMLCode(data, index);
+      index += Element.codedSizeLength(LastEBMLSize);
 
       FirstEBMLSize += LastEBMLSize;
       LaceSizes[l+1] = (int)FirstEBMLSize;
@@ -96,15 +101,16 @@
       // Update the size of the last block
       LaceSizes[LaceCount] -= LaceSizes[l+1];
     }
-    long ByteEndPos = source.getFilePointer();
+    //long ByteEndPos = source.getFilePointer();
 
-    HeaderSize = HeaderSize + (int)(ByteEndPos - ByteStartPos);
+    //HeaderSize = HeaderSize + (int)(ByteEndPos - ByteStartPos);
+    HeaderSize = HeaderSize + (int)(index - startIndex);
     LaceSizes[LaceCount] -= HeaderSize;
 
     return LaceSizes;
   }
 
-  public int[] readXiphLaceSizes(DataSource source, short LaceCount) {
+  public int[] readXiphLaceSizes(int index, short LaceCount) {
     int [] LaceSizes = new int[LaceCount+1];
     LaceSizes[LaceCount] = (int)this.getSize();
 
@@ -113,7 +119,7 @@
     for (int l = 0; l < LaceCount; l++) {
       short LaceSizeByte = 255;
       while (LaceSizeByte == 255) {
-        LaceSizeByte = (short)(source.readByte() & 0xFF);
+        LaceSizeByte = (short)(data[index++] & 0xFF);
         HeaderSize += 1;
         LaceSizes[l] += LaceSizeByte;
       }
@@ -137,30 +143,38 @@
   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)");
+        throw new 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;
+    int StartOffset = HeaderSize;
     for (int s = 0; s < frame; s++) {
       StartOffset += Sizes[s];
     }
 
     // Copy the frame data
-    org.ebml.util.ArrayCopy.arraycopy(data, StartOffset, FrameData, 0, FrameData.length);
+    ArrayCopy.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;
   }
+
+  public void setFrameData(short trackNo, int timecode, byte [] data) 
+  {
+
+  }
 }

Added: trunk/JEBML/src/org/ebml/matroska/MatroskaCluster.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaCluster.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaCluster.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -0,0 +1,104 @@
+/**
+ * JEBML - Java library to read/write EBML/Matroska elements.
+ * Copyright (C) 2004 Jory Stone <[email protected]>
+ * Based on Javatroska (C) 2002 John Cannon <[email protected]>
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package org.ebml.matroska;
+
+import org.ebml.*;
+import org.ebml.util.*;
+import java.util.*;
+
+/**
+ * Summary description for MatroskaCluster.
+ */
+public class MatroskaCluster extends MasterElement
+{
+  static public int NO_LACING = 0;
+  static public int XIPH_LACING = 1;
+  static public int EBML_LACING = 2;
+
+  protected int [] laceMode = null;
+  protected TLinkedList frames = new TLinkedList();
+  protected long clusterTimecode = 0;
+
+  public MatroskaCluster(byte[] type) 
+  {
+    super(type);
+  }
+
+  /**
+   * Set the current lacing mode.
+   * 
+   * @param trackNo Track Number for the track to enable lacing for. 1-based index
+   * @param laceMode The lacing moe to use. See NO_LACING, XIPH_LACING, and EBML_LACING.
+   */
+  void setLaceMode(short trackNo, int laceMode)
+  {
+    if (this.laceMode == null) 
+    {
+      this.laceMode = new int[trackNo];
+    }
+    if (this.laceMode.length < trackNo) 
+    {
+      int [] oldLaceMode = this.laceMode;
+      this.laceMode = new int[trackNo];;
+      ArrayCopy.arraycopy(this.laceMode, 0, oldLaceMode, 0, oldLaceMode.length);
+    }
+    this.laceMode[trackNo-1] = laceMode;
+  }
+
+  /**
+   * Get the current lacing mode.
+   * 
+   * @param trackNo Track Number for the track to enable lacing for. 1-based index
+   * @return -1 if the track no is invalid
+   */
+  int getLaceMode(short trackNo)
+  {
+    if (this.laceMode == null) 
+    {
+      return -1;
+    }
+    if (this.laceMode.length < trackNo) 
+    {
+      return -1;
+    }
+    
+    return this.laceMode[trackNo-1];
+  }
+
+  public void AddFrame(MatroskaFileFrame frame) 
+  {
+    // Is this the earliest timecode?
+    if (frame.Timecode < clusterTimecode) 
+    {
+      clusterTimecode = frame.Timecode;
+    }
+    frames.add(frame);
+  }
+
+  public void FlushFrames()
+  {
+    TLinkedList.IteratorImpl iter = frames.first();
+    while (iter.hasNext()) 
+    {
+      MatroskaFileFrame frame = (MatroskaFileFrame)iter.next();
+    }
+    
+  }
+}

Modified: trunk/JEBML/src/org/ebml/matroska/MatroskaDocType.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaDocType.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaDocType.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -33,6 +33,7 @@
   // Custom Element Types
   static public short BLOCK_ELEMENT = (short)(ElementType.LAST_ELEMENT_TYPE + 1);
   static public short SEGMENT_ELEMENT = (short)(ElementType.LAST_ELEMENT_TYPE + 2);
+  static public short CLUSTER_ELEMENT = (short)(ElementType.LAST_ELEMENT_TYPE + 3);
 
   // EBML Id's
   static public byte [] Void_Id = {(byte)0xEC};
@@ -621,7 +622,7 @@
       level1 = new ElementType("Cluster",
                                (short)1,
                                Cluster_Id,
-                               ElementType.MASTER_ELEMENT,
+                               MatroskaDocType.CLUSTER_ELEMENT,
                                new ArrayList());
 
       level2 = new ElementType("ClusterTimecode",
@@ -843,13 +844,18 @@
       else if (type.type == MatroskaDocType.SEGMENT_ELEMENT) 
       {
         elem = new MatroskaSegment(type.id);
-
+      }
+      else if (type.type == MatroskaDocType.CLUSTER_ELEMENT) 
+      {
+        elem = new MatroskaCluster(type.id);        
       } 
       else if (type.type == type.UNKNOWN_ELEMENT) 
       {
         elem = new BinaryElement(type.id);
 
-      } else {
+      } 
+      else 
+      {
         throw new java.lang.RuntimeException("Error: Unknown Element Type");
       }
       elem.setElementType(type);

Modified: trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaFile.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -255,7 +255,8 @@
         while (level3 != null) {
           if (level3.equals(MatroskaDocType.ClusterBlock_Id)) {
             block = (MatroskaBlock)level3;
-            block.parseBlock(ioDS);
+            block.readData(ioDS);
+            block.parseBlock();
 
           } else if (level3.equals(MatroskaDocType.ClusterBlockDuration_Id)) {
             level3.readData(ioDS);

Modified: trunk/JEBML/src/org/ebml/matroska/MatroskaFileFrame.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaFileFrame.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaFileFrame.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -19,8 +19,10 @@
  */
 package org.ebml.matroska;
 
+import org.ebml.util.*;
+
 /**
-  * Matroska Frame, holds a Matroska frame timecode, duration, and Data
+  * Matroska Frame, holds a Matroska frame timecode, duration, and data
   */
 public class MatroskaFileFrame 
 {
@@ -30,11 +32,31 @@
   public interface MatroskaFramePuller 
   {
     public void PushNewMatroskaFrame(MatroskaFileFrame frame);
-  }
+  };
+
+  /**
+   * The track this frame belongs to
+   */
   public int TrackNo;
+  /**
+   * A timecode, it should be in ms
+   */
   public long Timecode;
+  /**
+   * The duration of this frame, it should also be in ms
+   */
   public long Duration;
+  /**
+   * The first reference this frame has, set to 0 for no reference
+   */
   public long Reference;
+  /**
+   * More references, can be null if there are no more references
+   */
+  public long [] References;
+  /**
+   * The frame data
+   */
   public byte [] Data;
 
   /**
@@ -55,10 +77,16 @@
     this.TrackNo = copy.TrackNo;
     this.Timecode = copy.Timecode;
     this.Duration = copy.Duration;
+    this.Reference = copy.Reference;
+    if (copy.References != null) 
+    {
+      this.References = new long[copy.References.length];
+      ArrayCopy.arraycopy(copy.References, 0, this.References, 0, copy.References.length);
+    }
     if (copy.Data != null) 
     {
       this.Data = new byte[copy.Data.length];
-      org.ebml.util.ArrayCopy.arraycopy(copy.Data, 0, this.Data, 0, copy.Data.length);
+      ArrayCopy.arraycopy(copy.Data, 0, this.Data, 0, copy.Data.length);
     }
   }
 }

Modified: trunk/JEBML/src/org/ebml/matroska/MatroskaFileWriter.java
===================================================================
--- trunk/JEBML/src/org/ebml/matroska/MatroskaFileWriter.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/matroska/MatroskaFileWriter.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -74,7 +74,7 @@
     MasterElement segmentInfoElem = (MasterElement)doc.createElement(doc.SegmentInfo_Id);
     
     StringElement writingAppElem = (StringElement)doc.createElement(doc.WritingApp_Id);
-    writingAppElem.setValue("MatroskaFileWriter v1.0");
+    writingAppElem.setValue("Matroska File Writer v1.0");
 
     StringElement muxingAppElem = (StringElement)doc.createElement(doc.MuxingApp_Id);
     muxingAppElem.setValue("JEBML v1.0");
@@ -119,14 +119,88 @@
       StringElement trackNameElem = (StringElement)doc.createElement(doc.TrackName_Id);
       trackNameElem.setValue(track.Name);
 
+      StringElement trackLangElem = (StringElement)doc.createElement(doc.TrackLanguage_Id);
+      trackLangElem.setValue(track.Language);
+
+      StringElement trackCodecIDElem = (StringElement)doc.createElement(doc.TrackCodecID_Id);
+      trackCodecIDElem.setValue(track.CodecID);
+
+      BinaryElement trackCodecPrivateElem = (BinaryElement)doc.createElement(doc.TrackCodecPrivate_Id);
+      trackCodecPrivateElem.setData(track.CodecPrivate);
+
+      UnsignedIntegerElement trackDefaultDurationElem = (UnsignedIntegerElement)doc.createElement(doc.TrackDefaultDuration_Id);
+      trackDefaultDurationElem.setValue(track.DefaultDuration);
+
       trackEntryElem.addChildElement(trackNoElem);
       trackEntryElem.addChildElement(trackUIDElem);
       trackEntryElem.addChildElement(trackTypeElem);
       trackEntryElem.addChildElement(trackNameElem);
+      trackEntryElem.addChildElement(trackLangElem);
+      trackEntryElem.addChildElement(trackCodecIDElem);
+      trackEntryElem.addChildElement(trackCodecPrivateElem);
+      trackEntryElem.addChildElement(trackDefaultDurationElem);
 
+      // Now we add the audio/video dependant sub-elements
+      if (track.TrackType == MatroskaDocType.track_video) 
+      {
+        MasterElement trackVideoElem = (MasterElement)doc.createElement(doc.TrackVideo_Id);
+
+        UnsignedIntegerElement trackVideoPixelWidthElem = (UnsignedIntegerElement)doc.createElement(doc.PixelWidth_Id);
+        trackVideoPixelWidthElem.setValue(track.Video_PixelWidth);
+
+        UnsignedIntegerElement trackVideoPixelHeightElem = (UnsignedIntegerElement)doc.createElement(doc.PixelHeight_Id);
+        trackVideoPixelHeightElem.setValue(track.Video_PixelHeight);
+
+        UnsignedIntegerElement trackVideoDisplayWidthElem = (UnsignedIntegerElement)doc.createElement(doc.DisplayWidth_Id);
+        trackVideoDisplayWidthElem.setValue(track.Video_DisplayWidth);
+
+        UnsignedIntegerElement trackVideoDisplayHeightElem = (UnsignedIntegerElement)doc.createElement(doc.DisplayHeight_Id);
+        trackVideoDisplayHeightElem.setValue(track.Video_DisplayHeight);
+
+        trackVideoElem.addChildElement(trackVideoPixelWidthElem);
+        trackVideoElem.addChildElement(trackVideoPixelHeightElem);
+        trackVideoElem.addChildElement(trackVideoDisplayWidthElem);
+        trackVideoElem.addChildElement(trackVideoDisplayHeightElem);
+        
+        trackEntryElem.addChildElement(trackVideoElem);
+      } 
+      else if (track.TrackType == MatroskaDocType.track_audio) 
+      {
+        MasterElement trackAudioElem = (MasterElement)doc.createElement(doc.TrackVideo_Id);
+
+        UnsignedIntegerElement trackAudioChannelsElem = (UnsignedIntegerElement)doc.createElement(doc.Channels_Id);
+        trackAudioChannelsElem.setValue(track.Audio_Channels);
+
+        UnsignedIntegerElement trackAudioBitDepthElem = (UnsignedIntegerElement)doc.createElement(doc.BitDepth_Id);
+        trackAudioBitDepthElem.setValue(track.Audio_BitDepth);
+
+        FloatElement trackAudioSamplingRateElem = (FloatElement)doc.createElement(doc.SamplingFrequency_Id);
+        trackAudioSamplingRateElem.setValue(track.Audio_SamplingFrequency);
+
+        FloatElement trackAudioOutputSamplingFrequencyElem = (FloatElement)doc.createElement(doc.OutputSamplingFrequency_Id);
+        trackAudioOutputSamplingFrequencyElem.setValue(track.Audio_OutputSamplingFrequency);
+
+        trackAudioElem.addChildElement(trackAudioChannelsElem);
+        trackAudioElem.addChildElement(trackAudioBitDepthElem);
+        trackAudioElem.addChildElement(trackAudioSamplingRateElem);
+        trackAudioElem.addChildElement(trackAudioOutputSamplingFrequencyElem);
+        
+        trackEntryElem.addChildElement(trackAudioElem);
+      }
+
       tracksElem.addChildElement(trackEntryElem);
     }
 
     tracksElem.writeElement(ioDW);
   }
+
+  /**
+   * Add a frame
+   * 
+   * @param frame The frame to add
+  */
+  public void AddFrame(MatroskaFileFrame frame) 
+  {
+
+  }
 }

Modified: trunk/JEBML/src/org/ebml/sample/CommandLineSample.java
===================================================================
--- trunk/JEBML/src/org/ebml/sample/CommandLineSample.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/sample/CommandLineSample.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -107,6 +107,8 @@
       track.TrackUID = new java.util.Random().nextLong();
       track.TrackType = 1;
       track.Name = "Track " + Integer.toString(i);
+      track.Video_PixelWidth = 320;
+      track.Video_PixelHeight = 240;
       mFW.TrackList.add(track);
     }
     mFW.writeTracks();

Modified: trunk/JEBML/src/org/ebml/sample/EbmlSampleAppFrame.java
===================================================================
--- trunk/JEBML/src/org/ebml/sample/EbmlSampleAppFrame.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/sample/EbmlSampleAppFrame.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -8,7 +8,8 @@
 import javax.swing.*;
 
 import org.ebml.*;
-import org.ebml.matroska.MatroskaFile;
+import org.ebml.io.*;
+import org.ebml.matroska.*;
 
 /**
  * <p>Title: EBMLReader</p>
@@ -98,7 +99,7 @@
         FileInputStream ioF = new FileInputStream(jFileChooser1.getSelectedFile());
         jTextArea1.append("Scanning file: " + jFileChooser1.getSelectedFile().toString() + "\n");
 
-        MatroskaFile mF = new MatroskaFile(ioF);
+        MatroskaFile mF = new MatroskaFile(new InputStreamDataSource(ioF));
         mF.readFile();
         jTextArea1.append(mF.getReport());
 

Modified: trunk/JEBML/src/org/ebml/util/ArrayCopy.java
===================================================================
--- trunk/JEBML/src/org/ebml/util/ArrayCopy.java	2004-10-07 09:22:42 UTC (rev 867)
+++ trunk/JEBML/src/org/ebml/util/ArrayCopy.java	2004-10-07 10:02:37 UTC (rev 868)
@@ -40,6 +40,38 @@
     }
   }
 
+  public static void arraycopy(char [] dest, int dest_offset, char [] src, int src_offset, int count) 
+  {
+    for (int i = 0; i < count; i++) 
+    {
+      dest[dest_offset + i] = src[src_offset + i];
+    }
+  }
+
+  public static void arraycopy(short [] dest, int dest_offset, short [] src, int src_offset, int count) 
+  {
+    for (int i = 0; i < count; i++) 
+    {
+      dest[dest_offset + i] = src[src_offset + i];
+    }
+  }
+
+  public static void arraycopy(int [] dest, int dest_offset, int [] src, int src_offset, int count) 
+  {
+    for (int i = 0; i < count; i++) 
+    {
+      dest[dest_offset + i] = src[src_offset + i];
+    }
+  }
+
+  public static void arraycopy(long [] dest, int dest_offset, long [] src, int src_offset, int count) 
+  {
+    for (int i = 0; i < count; i++) 
+    {
+      dest[dest_offset + i] = src[src_offset + i];
+    }
+  }
+
   public static void arraycopy(Object [] dest, int dest_offset, Object [] src, int src_offset, int count) 
   {
     for (int i = 0; i < count; i++)
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.