Commit 8d90498f by Dustin

Minor Tweaks

parent 58a2ca60
...@@ -49,14 +49,16 @@ public class AviExtractor implements Extractor { ...@@ -49,14 +49,16 @@ public class AviExtractor implements Extractor {
static final int IDX1 = 'i' | ('d' << 8) | ('x' << 16) | ('1' << 24); static final int IDX1 = 'i' | ('d' << 8) | ('x' << 16) | ('1' << 24);
static final int JUNK = 'J' | ('U' << 8) | ('N' << 16) | ('K' << 24); static final int JUNK = 'J' | ('U' << 8) | ('N' << 16) | ('K' << 24);
static final int REC_ = 'r' | ('e' << 8) | ('c' << 16) | (' ' << 24);
static final long SEEK_GAP = 2_000_000L; //Time between seek points in micro seconds static final long SEEK_GAP = 2_000_000L; //Time between seek points in micro seconds
private int state; private int state;
private ExtractorOutput output; private ExtractorOutput output;
private AviHeaderBox aviHeader; private AviHeaderBox aviHeader;
private long durationUs = C.TIME_UNSET;
private SparseArray<AviTrack> idTrackMap = new SparseArray<>(); private SparseArray<AviTrack> idTrackMap = new SparseArray<>();
//After the movi position //At the start of the movi tag
private long moviOffset; private long moviOffset;
private long moviEnd; private long moviEnd;
private AviSeekMap aviSeekMap; private AviSeekMap aviSeekMap;
...@@ -154,14 +156,9 @@ public class AviExtractor implements Extractor { ...@@ -154,14 +156,9 @@ public class AviExtractor implements Extractor {
} }
return listBox; return listBox;
} }
long getDuration() { long getDuration() {
if (aviHeader == null) { return durationUs;
return C.TIME_UNSET;
}
return aviHeader.getFrames() * (long)aviHeader.getMicroSecPerFrame();
} }
@Override @Override
public void init(ExtractorOutput output) { public void init(ExtractorOutput output) {
this.state = STATE_READ_TRACKS; this.state = STATE_READ_TRACKS;
...@@ -185,6 +182,8 @@ public class AviExtractor implements Extractor { ...@@ -185,6 +182,8 @@ public class AviExtractor implements Extractor {
if (aviHeader == null) { if (aviHeader == null) {
throw new IOException("AviHeader not found"); throw new IOException("AviHeader not found");
} }
//This is usually wrong, so it will be overwritten by video if present
durationUs = aviHeader.getFrames() * (long)aviHeader.getMicroSecPerFrame();
headerChildren.remove(aviHeader); headerChildren.remove(aviHeader);
//headerChildren should only be Stream Lists now //headerChildren should only be Stream Lists now
...@@ -228,6 +227,7 @@ public class AviExtractor implements Extractor { ...@@ -228,6 +227,7 @@ public class AviExtractor implements Extractor {
idTrackMap.put('0' | (('0' + streamId) << 8) | ('d' << 16) | ('c' << 24), idTrackMap.put('0' | (('0' + streamId) << 8) | ('d' << 16) | ('c' << 24),
new AviTrack(streamId, trackOutput, new AviTrack(streamId, trackOutput,
streamHeader)); streamHeader));
durationUs = streamHeader.getUsPerSample() * streamHeader.getLength();
} else if (streamHeader.isAudio()) { } else if (streamHeader.isAudio()) {
final AudioFormat audioFormat = streamFormat.getAudioFormat(); final AudioFormat audioFormat = streamFormat.getAudioFormat();
final TrackOutput trackOutput = output.track(streamId, C.TRACK_TYPE_AUDIO); final TrackOutput trackOutput = output.track(streamId, C.TRACK_TYPE_AUDIO);
...@@ -329,7 +329,9 @@ public class AviExtractor implements Extractor { ...@@ -329,7 +329,9 @@ public class AviExtractor implements Extractor {
final int id = indexByteBuffer.getInt(); final int id = indexByteBuffer.getInt();
final AviTrack aviTrack = idTrackMap.get(id); final AviTrack aviTrack = idTrackMap.get(id);
if (aviTrack == null) { if (aviTrack == null) {
Log.w(TAG, "Unknown Track Type: " + AviUtil.toString(id)); if (id != AviExtractor.REC_) {
Log.w(TAG, "Unknown Track Type: " + AviUtil.toString(id));
}
indexByteBuffer.position(indexByteBuffer.position() + 12); indexByteBuffer.position(indexByteBuffer.position() + 12);
continue; continue;
} }
...@@ -366,14 +368,16 @@ public class AviExtractor implements Extractor { ...@@ -366,14 +368,16 @@ public class AviExtractor implements Extractor {
entry.getValue().pack(); entry.getValue().pack();
idFrameArray.put(entry.getKey(), entry.getValue().array); idFrameArray.put(entry.getKey(), entry.getValue().array);
final AviTrack aviTrack = idTrackMap.get(entry.getKey()); final AviTrack aviTrack = idTrackMap.get(entry.getKey());
//Sometimes this value is way off //If the index isn't sparse, double check the audio length
long calcUsPerSample = (getDuration()/aviTrack.frame); if (videoTrack.frame == videoTrack.streamHeaderBox.getLength()) {
float deltaPercent = Math.abs(calcUsPerSample - aviTrack.usPerSample) / (float)aviTrack.usPerSample; //Sometimes this value is way off
if (deltaPercent >.01) { long calcUsPerSample = (getDuration()/aviTrack.frame);
aviTrack.usPerSample = getDuration()/aviTrack.frame; float deltaPercent = Math.abs(calcUsPerSample - aviTrack.usPerSample) / (float)aviTrack.usPerSample;
Log.d(TAG, "Frames act=" + getDuration() + " calc=" + (aviTrack.usPerSample * aviTrack.frame)); if (deltaPercent >.01) {
aviTrack.usPerSample = getDuration()/aviTrack.frame;
Log.d(TAG, "Frames act=" + getDuration() + " calc=" + (aviTrack.usPerSample * aviTrack.frame));
}
} }
} }
final AviSeekMap seekMap = new AviSeekMap(videoTrack, seekFrameRate, videoSeekOffset.array, final AviSeekMap seekMap = new AviSeekMap(videoTrack, seekFrameRate, videoSeekOffset.array,
idFrameArray, moviOffset, getDuration()); idFrameArray, moviOffset, getDuration());
...@@ -415,8 +419,9 @@ public class AviExtractor implements Extractor { ...@@ -415,8 +419,9 @@ public class AviExtractor implements Extractor {
} }
return RESULT_SEEK; return RESULT_SEEK;
} else { } else {
//Log.d(TAG, "Sample pos=" + (input.getPosition() - 8) + " size=" + sampleSize + " video=" + sampleTrack.isVideo()); //sampleOffset = (int)(input.getPosition() - 8 - moviOffset);
sampleRemaining = sampleSize - sampleTrack.trackOutput.sampleData(input, sampleSize, false); sampleRemaining = sampleSize - sampleTrack.trackOutput.sampleData(input, sampleSize, false);
//Log.d(TAG, "Sample pos=" + (input.getPosition() - 8) + " size=" + sampleSize + " video=" + sampleTrack.isVideo());
} }
} }
if (sampleRemaining != 0) { if (sampleRemaining != 0) {
...@@ -424,7 +429,7 @@ public class AviExtractor implements Extractor { ...@@ -424,7 +429,7 @@ public class AviExtractor implements Extractor {
} }
sampleTrack.trackOutput.sampleMetadata( sampleTrack.trackOutput.sampleMetadata(
sampleTrack.getUs(), sampleTrack.isKeyFrame() ? C.BUFFER_FLAG_KEY_FRAME : 0 , sampleSize, 0, null); sampleTrack.getUs(), sampleTrack.isKeyFrame() ? C.BUFFER_FLAG_KEY_FRAME : 0 , sampleSize, 0, null);
//Log.d(TAG, "Frame: " + (sampleTrack.isVideo()? 'V' : 'A') + " us=" + sampleTrack.getUs()); //Log.d(TAG, "Frame: " + (sampleTrack.isVideo()? 'V' : 'A') + " us=" + sampleTrack.getUs() + " size=" + sampleSize);
sampleTrack.advance(); sampleTrack.advance();
return RESULT_CONTINUE; return RESULT_CONTINUE;
} }
......
...@@ -26,7 +26,10 @@ public class AviHeaderBox extends ResidentBox { ...@@ -26,7 +26,10 @@ public class AviHeaderBox extends ResidentBox {
} }
//4 = dwMaxBytesPerSec //4 = dwMaxBytesPerSec
//8 = dwPaddingGranularity //Always 0, but should be 2
// int getPaddingGranularity() {
// return byteBuffer.getInt(8);
// }
int getFlags() { int getFlags() {
return byteBuffer.getInt(12); return byteBuffer.getInt(12);
......
...@@ -55,7 +55,11 @@ public class AviTrack { ...@@ -55,7 +55,11 @@ public class AviTrack {
if (allKeyFrames) { if (allKeyFrames) {
return true; return true;
} }
return keyFrames != null && Arrays.binarySearch(keyFrames, frame) >= 0; if (keyFrames != null) {
return Arrays.binarySearch(keyFrames, frame) >= 0;
}
//Hack: Exo needs at least one frame before it starts playback
return frame == 0;
} }
public void setKeyFrames(int[] keyFrames) { public void setKeyFrames(int[] keyFrames) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment