Skip to content

Commit

Permalink
Merge pull request #416 from drewnoakes/mp4-date-refactor
Browse files Browse the repository at this point in the history
Refactor date processing
  • Loading branch information
drewnoakes authored Jul 22, 2019
2 parents 6ee77ff + 9edcea9 commit 1f15c79
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 42 deletions.
33 changes: 33 additions & 0 deletions Source/com/drew/lang/DateUtil.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
/*
* Copyright 2002-2019 Drew Noakes and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* More information about this project is available at:
*
* https://drewnoakes.com/code/exif/
* https://github.com/drewnoakes/metadata-extractor
*/
package com.drew.lang;

import java.util.Date;

/**
* @author Drew Noakes http://drewnoakes.com
*/
public class DateUtil
{
private static int[] _daysInMonth365 = new int[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

/**
* The offset (in milliseconds) to add to a MP4 date/time integer value to
* align with Java's Epoch.
*/
private static final long EPOCH_1_JAN_1904 = -2082844799175L;

public static boolean isValidDate(int year, int month, int day)
{
if (year < 1 || year > 9999 || month < 0 || month > 11)
Expand All @@ -29,4 +57,9 @@ public static boolean isValidTime(int hours, int minutes, int seconds)
&& minutes >= 0 && minutes < 60
&& seconds >= 0 && seconds < 60;
}

public static Date get1Jan1904EpochDate(long seconds)
{
return new Date((seconds * 1000) + EPOCH_1_JAN_1904);
}
}
8 changes: 4 additions & 4 deletions Source/com/drew/metadata/mov/QuickTimeMediaHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@
package com.drew.metadata.mov;

import com.drew.imaging.quicktime.QuickTimeHandler;
import com.drew.lang.DateUtil;
import com.drew.lang.SequentialByteArrayReader;
import com.drew.lang.SequentialReader;
import com.drew.lang.annotations.NotNull;
import com.drew.lang.annotations.Nullable;
import com.drew.metadata.Metadata;
import com.drew.metadata.mov.atoms.Atom;
import com.drew.metadata.mov.media.QuickTimeMediaDirectory;
import com.drew.metadata.mp4.Mp4Directory;
import java.io.IOException;
import java.util.Date;

/**
* Classes that extend this class should be from the media dat atom types:
Expand All @@ -43,15 +42,16 @@ public abstract class QuickTimeMediaHandler<T extends QuickTimeDirectory> extend
public QuickTimeMediaHandler(Metadata metadata)
{
super(metadata);

if (QuickTimeHandlerFactory.HANDLER_PARAM_CREATION_TIME != null && QuickTimeHandlerFactory.HANDLER_PARAM_MODIFICATION_TIME != null) {
// Get creation/modification times
directory.setDate(
QuickTimeMediaDirectory.TAG_CREATION_TIME,
new Date(QuickTimeHandlerFactory.HANDLER_PARAM_CREATION_TIME * 1000 + Mp4Directory.MP4_EPOCH_OFFSET)
DateUtil.get1Jan1904EpochDate(QuickTimeHandlerFactory.HANDLER_PARAM_CREATION_TIME)
);
directory.setDate(
QuickTimeMediaDirectory.TAG_MODIFICATION_TIME,
new Date(QuickTimeHandlerFactory.HANDLER_PARAM_MODIFICATION_TIME * 1000 + Mp4Directory.MP4_EPOCH_OFFSET)
DateUtil.get1Jan1904EpochDate(QuickTimeHandlerFactory.HANDLER_PARAM_MODIFICATION_TIME)
);
}
}
Expand Down
42 changes: 21 additions & 21 deletions Source/com/drew/metadata/mov/atoms/MovieHeaderAtom.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@
*/
package com.drew.metadata.mov.atoms;

import com.drew.lang.DateUtil;
import com.drew.lang.Rational;
import com.drew.lang.SequentialReader;
import com.drew.metadata.mov.QuickTimeDirectory;
import com.drew.metadata.mp4.Mp4Directory;
import java.io.IOException;
import java.util.Date;
import static com.drew.metadata.mov.QuickTimeDirectory.*;

/**
Expand All @@ -35,20 +34,21 @@
*/
public class MovieHeaderAtom extends FullAtom
{
long creationTime;
long modificationTime;
long timescale;
long duration;
int preferredRate;
int preferredVolume;
int[] matrixStructure;
long previewTime;
long previewDuration;
long posterTime;
long selectionTime;
long selectionDuration;
long currentTime;
long nextTrackID;
private long creationTime;
private long modificationTime;
private long timescale;
private long duration;
private int preferredRate;
private int preferredVolume;
// TODO this matrix data is not currently used anywhere
private int[] matrixStructure;
private long previewTime;
private long previewDuration;
private long posterTime;
private long selectionTime;
private long selectionDuration;
private long currentTime;
private long nextTrackID;

public MovieHeaderAtom(SequentialReader reader, Atom atom) throws IOException
{
Expand Down Expand Up @@ -84,22 +84,22 @@ public MovieHeaderAtom(SequentialReader reader, Atom atom) throws IOException
public void addMetadata(QuickTimeDirectory directory)
{
// Get creation/modification times
directory.setDate(TAG_CREATION_TIME, new Date(creationTime * 1000 + Mp4Directory.MP4_EPOCH_OFFSET));
directory.setDate(TAG_MODIFICATION_TIME, new Date(modificationTime * 1000 + Mp4Directory.MP4_EPOCH_OFFSET));
directory.setDate(TAG_CREATION_TIME, DateUtil.get1Jan1904EpochDate(creationTime));
directory.setDate(TAG_MODIFICATION_TIME, DateUtil.get1Jan1904EpochDate(modificationTime));

// Get duration and time scale
directory.setLong(TAG_DURATION, duration);
directory.setLong(TAG_TIME_SCALE, timescale);
directory.setRational(QuickTimeDirectory.TAG_DURATION_SECONDS, new Rational(duration, timescale));
directory.setRational(TAG_DURATION_SECONDS, new Rational(duration, timescale));

// Calculate preferred rate fixed point
double preferredRateInteger = (preferredRate & 0xFFFF0000) >> 16;
double preferredRateFraction = (preferredRate & 0x0000FFFF) / Math.pow(2, 4);
double preferredRateFraction = (preferredRate & 0x0000FFFF) / 16.0d;
directory.setDouble(TAG_PREFERRED_RATE, preferredRateInteger + preferredRateFraction);

// Calculate preferred volume fixed point
double preferredVolumeInteger = (preferredVolume & 0xFF00) >> 8;
double preferredVolumeFraction = (preferredVolume & 0x00FF) / Math.pow(2, 2);
double preferredVolumeFraction = (preferredVolume & 0x00FF) / 8.0d;
directory.setDouble(TAG_PREFERRED_VOLUME, preferredVolumeInteger + preferredVolumeFraction);

directory.setLong(TAG_PREVIEW_TIME, previewTime);
Expand Down
11 changes: 0 additions & 11 deletions Source/com/drew/metadata/mp4/Mp4Directory.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ public class Mp4Directory extends Directory {
public static final int TAG_MINOR_VERSION = 2;
public static final int TAG_COMPATIBLE_BRANDS = 3;

/**
* The offset (in milliseconds) to add to a MP4 date/time integer value to
* align with Java's Epoch
*/
public static final long MP4_EPOCH_OFFSET;

@NotNull
protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();

Expand All @@ -82,11 +76,6 @@ public class Mp4Directory extends Directory {
_tagNameMap.put(TAG_ROTATION, "Rotation");

_tagNameMap.put(TAG_MEDIA_TIME_SCALE, "Media Time Scale");

// Calculate the difference between the Java Epoch and the MP4 Epoch
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.set(1904, 0, 1, 0, 0, 0); // January 1, 1904 - Macintosh/MP4/QuickTime Time Epoch
MP4_EPOCH_OFFSET = calendar.getTime().getTime();
}

public Mp4Directory()
Expand Down
6 changes: 3 additions & 3 deletions Source/com/drew/metadata/mp4/Mp4MediaHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package com.drew.metadata.mp4;

import com.drew.imaging.mp4.Mp4Handler;
import com.drew.lang.DateUtil;
import com.drew.lang.SequentialByteArrayReader;
import com.drew.lang.SequentialReader;
import com.drew.lang.annotations.NotNull;
Expand All @@ -30,7 +31,6 @@
import com.drew.metadata.mp4.media.Mp4MediaDirectory;

import java.io.IOException;
import java.util.Date;

public abstract class Mp4MediaHandler<T extends Mp4MediaDirectory> extends Mp4Handler<T>
{
Expand All @@ -41,11 +41,11 @@ public Mp4MediaHandler(Metadata metadata)
// Get creation/modification times
directory.setDate(
Mp4MediaDirectory.TAG_CREATION_TIME,
new Date(Mp4HandlerFactory.HANDLER_PARAM_CREATION_TIME * 1000 + Mp4Directory.MP4_EPOCH_OFFSET)
DateUtil.get1Jan1904EpochDate(Mp4HandlerFactory.HANDLER_PARAM_CREATION_TIME)
);
directory.setDate(
Mp4MediaDirectory.TAG_MODIFICATION_TIME,
new Date(Mp4HandlerFactory.HANDLER_PARAM_MODIFICATION_TIME * 1000 + Mp4Directory.MP4_EPOCH_OFFSET)
DateUtil.get1Jan1904EpochDate(Mp4HandlerFactory.HANDLER_PARAM_MODIFICATION_TIME)
);
directory.setString(Mp4MediaDirectory.TAG_LANGUAGE_CODE, Mp4HandlerFactory.HANDLER_PARAM_LANGUAGE);
}
Expand Down
5 changes: 3 additions & 2 deletions Source/com/drew/metadata/mp4/boxes/MovieHeaderBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
package com.drew.metadata.mp4.boxes;

import com.drew.lang.DateUtil;
import com.drew.lang.Rational;
import com.drew.lang.SequentialReader;
import com.drew.metadata.mp4.Mp4Directory;
Expand Down Expand Up @@ -76,8 +77,8 @@ public MovieHeaderBox(SequentialReader reader, Box box) throws IOException
public void addMetadata(Mp4Directory directory)
{
// Get creation/modification times
directory.setDate(Mp4Directory.TAG_CREATION_TIME, new Date(creationTime * 1000 + Mp4Directory.MP4_EPOCH_OFFSET));
directory.setDate(Mp4Directory.TAG_MODIFICATION_TIME, new Date(modificationTime * 1000 + Mp4Directory.MP4_EPOCH_OFFSET));
directory.setDate(Mp4Directory.TAG_CREATION_TIME, DateUtil.get1Jan1904EpochDate(creationTime));
directory.setDate(Mp4Directory.TAG_MODIFICATION_TIME, DateUtil.get1Jan1904EpochDate(modificationTime));

// Get duration and time scale
directory.setLong(Mp4Directory.TAG_DURATION, duration);
Expand Down
2 changes: 1 addition & 1 deletion metadata-extractor.iml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
<output url="file://$MODULE_DIR$/Output/maven/classes" />
<output-test url="file://$MODULE_DIR$/Output/maven/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/Samples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/Source" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/Tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/Output/maven" />
<excludeFolder url="file://$MODULE_DIR$/Releases" />
<excludeFolder url="file://$MODULE_DIR$/Samples" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
Expand Down

0 comments on commit 1f15c79

Please sign in to comment.