/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.restcomm.media.resource.player.video.mpeg; import java.io.DataInputStream; import java.io.IOException; /** * <b>8.3.2.1 Definition</b> * <ul> * <li> Box Type: �?tkhd’</li> * <li> Container: {@link TrackBox} (�?trak’)</li> * <li> Mandatory: Yes</li> * <li> Quantity: Exactly one</li> * </ul> * <p> * This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track. In * the absence of an edit list, the presentation of a track starts at the beginning of the overall presentation. An * empty edit is used to offset the start time of a track. * </p> * <p> * The default value of the track header flags for media tracks is 7 (track_enabled, track_in_movie, track_in_preview). * If in a presentation all tracks have neither track_in_movie nor track_in_preview set, then all tracks shall be * treated as if both flags were set on all tracks. Hint tracks should have the track header flags set to 0, so that * they are ignored for local playback and preview. * </p> * <p> * The width and height in the track header are measured on a notional �?square’ (uniform) grid. Track video data is * normalized to these dimensions (logically) before any transformation or placement caused by a layup or composition * system. Track (and movie) matrices, if used, also operate in this uniformly-scaled space. * </p> * * @author kulikov * @author amit bhayani */ public class TrackHeaderBox extends FullBox { // File Type = tkhd static byte[] TYPE = new byte[] { AsciiTable.ALPHA_t, AsciiTable.ALPHA_k, AsciiTable.ALPHA_h, AsciiTable.ALPHA_d }; static String TYPE_S = "tkhd"; static { bytetoTypeMap.put(TYPE, TYPE_S); } // creation_time is an integer that declares the creation time of this track (in seconds since midnight, Jan. 1, // 1904, in UTC time) private long creationTime; // modification_time is an integer that declares the most recent time the track was modified (in seconds since // midnight, Jan. 1, 1904, in UTC time) private long modificationTime; // duration is an integer that indicates the duration of this track (in the timescale indicated in the Movie Header // Box). The value of this field is equal to the sum of the durations of all of the track’s edits. If there is no // edit list, then the duration is the sum of the sample durations, converted into the timescale in the Movie Header // Box. If the duration of this track cannot be determined then duration is set to all 1s (32-bit maxint). private long duration; // track_ID is an integer that uniquely identifies this track over the entire life-time of this presentation. Track // IDs are never re-used and cannot be zero. private long trackID; // layer specifies the front-to-back ordering of video tracks; tracks with lower numbers are closer to the viewer. 0 // is the normal value, and -1 would be in front of track 0, and so on. private int layer; // alternate_group is an integer that specifies a group or collection of tracks. If this field is 0 there is no // information on possible relations to other tracks. If this field is not 0, it should be the same for tracks that // contain alternate data for one another and different for tracks belonging to different such groups. Only one // track within an alternate group should be played or streamed at any one time, and must be distinguishable from // other tracks in the group via attributes such as bitrate, codec, language, packet size etc. A group may have only // one member. private int alternateGroup; // volume is a fixed 8.8 value specifying the track's relative audio volume. Full volume is 1.0 (0x0100) and is the // normal value. Its value is irrelevant for a purely visual track. Tracks may be composed by combining them // according to their volume, and then using the overall Movie Header Box volume setting; or more complex audio // composition (e.g. MPEG-4 BIFS) may be used. private float volume; // matrix provides a transformation matrix for the video; (u,v,w) are restricted here to (0,0,1), hex // (0,0,0x40000000) private int[] matrix = new int[9]; // width and height specify the track's visual presentation size as fixed-point 16.16 values. These need not be the // same as the pixel dimensions of the images, which is documented in the sample description(s); all images in the // sequence are scaled to this size, before any overall transformation of the track represented by the matrix. The // pixel dimensions of the images are the default values. private double width; private double height; public TrackHeaderBox(long size) { super(size, TYPE_S); } @Override protected int load(DataInputStream fin) throws IOException { super.load(fin); if (this.getVersion() == 1) { this.creationTime = read64(fin); this.modificationTime = read64(fin); this.trackID = fin.readInt(); fin.readInt(); // spare this.duration = read64(fin); } else { this.creationTime = fin.readInt(); this.modificationTime = fin.readInt(); this.trackID = fin.readInt(); fin.readInt(); // spare this.duration = fin.readInt(); } // reserved fin.readInt(); fin.readInt(); // reading layer. layer = (fin.readByte() << 8) | fin.readByte(); alternateGroup = (fin.readByte() << 8) | fin.readByte(); // reading volume. it is a fixed 8.8 number volume = fin.readByte() + fin.readByte() / 10; // skip reserved 16bits fin.readByte(); fin.readByte(); for (int i = 0; i < matrix.length; i++) { matrix[i] = fin.readInt(); } width = readFixedPoint1616(fin); height = readFixedPoint1616(fin); return (int) getSize(); } public long getCreationTime() { return creationTime; } public long getModificationTime() { return modificationTime; } public long getDuration() { return duration; } public long getTrackID() { return trackID; } public int getLayer() { return layer; } public int getAlternateGroup() { return alternateGroup; } public float getVolume() { return volume; } public int[] getMatrix() { return matrix; } public double getWidth() { return width; } public double getHeight() { return height; } }