mirror of
https://github.com/samsonjs/media.git
synced 2026-04-01 10:35:48 +00:00
Refactor, remove dead code
This commit is contained in:
parent
8d90498f79
commit
d9afe5105b
8 changed files with 37 additions and 173 deletions
|
|
@ -26,8 +26,23 @@ import java.util.Map;
|
|||
* https://docs.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference
|
||||
*/
|
||||
public class AviExtractor implements Extractor {
|
||||
static final long UINT_MASK = 0xffffffffL;
|
||||
|
||||
static long getUInt(ByteBuffer byteBuffer) {
|
||||
return byteBuffer.getInt() & UINT_MASK;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String toString(int tag) {
|
||||
final StringBuilder sb = new StringBuilder(4);
|
||||
for (int i=0;i<4;i++) {
|
||||
sb.append((char)(tag & 0xff));
|
||||
tag >>=8;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static final String TAG = "AviExtractor";
|
||||
static final int KEY_FRAME_MASK = Integer.MIN_VALUE;
|
||||
private static final int PEEK_BYTES = 28;
|
||||
|
||||
private static final int STATE_READ_TRACKS = 0;
|
||||
|
|
@ -39,8 +54,8 @@ public class AviExtractor implements Extractor {
|
|||
private static final int AVIIF_KEYFRAME = 16;
|
||||
|
||||
|
||||
static final int RIFF = AviUtil.toInt(new byte[]{'R','I','F','F'});
|
||||
static final int AVI_ = AviUtil.toInt(new byte[]{'A','V','I',' '});
|
||||
static final int RIFF = 'R' | ('I' << 8) | ('F' << 16) | ('F' << 24);
|
||||
static final int AVI_ = 'A' | ('V' << 8) | ('I' << 16) | (' ' << 24);
|
||||
//Stream List
|
||||
static final int STRL = 's' | ('t' << 8) | ('r' << 16) | ('l' << 24);
|
||||
//movie data box
|
||||
|
|
@ -103,7 +118,7 @@ public class AviExtractor implements Extractor {
|
|||
if (riff != AviExtractor.RIFF) {
|
||||
return false;
|
||||
}
|
||||
long reportedLen = AviUtil.getUInt(byteBuffer) + byteBuffer.position();
|
||||
long reportedLen = getUInt(byteBuffer) + byteBuffer.position();
|
||||
final long inputLen = input.getLength();
|
||||
if (inputLen != C.LENGTH_UNSET && inputLen != reportedLen) {
|
||||
Log.w(TAG, "Header length doesn't match stream length");
|
||||
|
|
@ -136,7 +151,7 @@ public class AviExtractor implements Extractor {
|
|||
if (riff != AviExtractor.RIFF) {
|
||||
return null;
|
||||
}
|
||||
long reportedLen = AviUtil.getUInt(byteBuffer) + byteBuffer.position();
|
||||
long reportedLen = getUInt(byteBuffer) + byteBuffer.position();
|
||||
final long inputLen = input.getLength();
|
||||
if (inputLen != C.LENGTH_UNSET && inputLen != reportedLen) {
|
||||
Log.w(TAG, "Header length doesn't match stream length");
|
||||
|
|
@ -177,18 +192,15 @@ public class AviExtractor implements Extractor {
|
|||
if (headerList == null) {
|
||||
throw new IOException("AVI Header List not found");
|
||||
}
|
||||
final List<Box> headerChildren = headerList.getChildren();
|
||||
aviHeader = AviUtil.getBox(headerChildren, AviHeaderBox.class);
|
||||
aviHeader = headerList.getChild(AviHeaderBox.class);
|
||||
if (aviHeader == null) {
|
||||
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 should only be Stream Lists now
|
||||
|
||||
int streamId = 0;
|
||||
for (Box box : headerChildren) {
|
||||
for (Box box : headerList.getChildren()) {
|
||||
if (box instanceof ListBox && ((ListBox) box).getListType() == STRL) {
|
||||
final ListBox streamList = (ListBox) box;
|
||||
final List<Box> streamChildren = streamList.getChildren();
|
||||
|
|
@ -238,7 +250,6 @@ public class AviExtractor implements Extractor {
|
|||
builder.setChannelCount(audioFormat.getChannels());
|
||||
builder.setSampleRate(audioFormat.getSamplesPerSecond());
|
||||
if (audioFormat.getFormatTag() == AudioFormat.WAVE_FORMAT_PCM) {
|
||||
//TODO: Determine if this is LE or BE - Most likely LE
|
||||
final short bps = audioFormat.getBitsPerSample();
|
||||
if (bps == 8) {
|
||||
builder.setPcmEncoding(C.ENCODING_PCM_8BIT);
|
||||
|
|
@ -268,7 +279,7 @@ public class AviExtractor implements Extractor {
|
|||
ByteBuffer byteBuffer = allocate(12);
|
||||
input.readFully(byteBuffer.array(), 0,12);
|
||||
final int tag = byteBuffer.getInt();
|
||||
final long size = byteBuffer.getInt() & AviUtil.UINT_MASK;
|
||||
final long size = getUInt(byteBuffer);
|
||||
final long position = input.getPosition();
|
||||
//-4 because we over read for the LIST type
|
||||
long nextBox = position + size - 4;
|
||||
|
|
@ -330,7 +341,7 @@ public class AviExtractor implements Extractor {
|
|||
final AviTrack aviTrack = idTrackMap.get(id);
|
||||
if (aviTrack == null) {
|
||||
if (id != AviExtractor.REC_) {
|
||||
Log.w(TAG, "Unknown Track Type: " + AviUtil.toString(id));
|
||||
Log.w(TAG, "Unknown Track Type: " + toString(id));
|
||||
}
|
||||
indexByteBuffer.position(indexByteBuffer.position() + 12);
|
||||
continue;
|
||||
|
|
@ -413,7 +424,7 @@ public class AviExtractor implements Extractor {
|
|||
} else {
|
||||
seekPosition.position = input.getPosition() + sampleSize;
|
||||
if (id != JUNK) {
|
||||
Log.w(TAG, "Unknown tag=" + AviUtil.toString(id) + " pos=" + (input.getPosition() - 8)
|
||||
Log.w(TAG, "Unknown tag=" + toString(id) + " pos=" + (input.getPosition() - 8)
|
||||
+ " size=" + sampleSize + " moviEnd=" + moviEnd);
|
||||
}
|
||||
}
|
||||
|
|
@ -470,7 +481,6 @@ public class AviExtractor implements Extractor {
|
|||
|
||||
@Override
|
||||
public void seek(long position, long timeUs) {
|
||||
Log.d("Test", "Seek: pos=" + position + " us=" + timeUs);
|
||||
if (position == 0) {
|
||||
if (moviOffset != 0) {
|
||||
resetFrames();
|
||||
|
|
|
|||
|
|
@ -12,11 +12,6 @@ public class AviHeaderBox extends ResidentBox {
|
|||
super(type, size, byteBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean assertType() {
|
||||
return simpleAssert(AVIH);
|
||||
}
|
||||
|
||||
boolean hasIndex() {
|
||||
return (getFlags() & AVIF_HASINDEX) > 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
package com.google.android.exoplayer2.extractor.avi;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
public class AviUtil {
|
||||
|
||||
static final long UINT_MASK = 0xffffffffL;
|
||||
|
||||
static int toInt(byte[] bytes) {
|
||||
int i = 0;
|
||||
for (int b=bytes.length - 1;b>=0;b--) {
|
||||
i <<=8;
|
||||
i |= bytes[b];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static long getUInt(ByteBuffer byteBuffer) {
|
||||
return byteBuffer.getInt() & UINT_MASK;
|
||||
}
|
||||
|
||||
static void copy(ByteBuffer source, ByteBuffer dest, int bytes) {
|
||||
final int inLimit = source.limit();
|
||||
source.limit(source.position() + bytes);
|
||||
dest.put(source);
|
||||
source.limit(inLimit);
|
||||
}
|
||||
|
||||
static ByteBuffer getByteBuffer(final ByteBuffer source, final int size,
|
||||
final ExtractorInput input) throws IOException {
|
||||
final ByteBuffer byteBuffer = AviExtractor.allocate(size);
|
||||
if (size < source.remaining()) {
|
||||
copy(source, byteBuffer, size);
|
||||
} else {
|
||||
final int copy = source.remaining();
|
||||
copy(source, byteBuffer, copy);
|
||||
int remaining = size - copy;
|
||||
final int offset = byteBuffer.position() + byteBuffer.arrayOffset();
|
||||
input.readFully(byteBuffer.array(), offset, remaining, false);
|
||||
}
|
||||
return byteBuffer;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String toString(int tag) {
|
||||
final StringBuilder sb = new StringBuilder(4);
|
||||
for (int i=0;i<4;i++) {
|
||||
sb.append((char)(tag & 0xff));
|
||||
tag >>=8;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static <T extends Box> T getBox(List<? extends Box> list, Class<T> clazz) {
|
||||
for (Box box : list) {
|
||||
if (box.getClass() == clazz) {
|
||||
return (T)box;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,11 +13,7 @@ public class Box {
|
|||
}
|
||||
|
||||
public long getSize() {
|
||||
return size & AviUtil.UINT_MASK;
|
||||
}
|
||||
|
||||
public int getSizeInt() {
|
||||
return size;
|
||||
return size & AviExtractor.UINT_MASK;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
|
|
@ -28,8 +24,4 @@ public class Box {
|
|||
return getType() == expected;
|
||||
}
|
||||
|
||||
boolean assertType() {
|
||||
//Generic box, nothing to assert
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.google.android.exoplayer2.extractor.avi;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -16,25 +15,6 @@ public class BoxFactory {
|
|||
return Arrays.binarySearch(types, type) < 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ResidentBox createBox(final int type, final int size, final ByteBuffer byteBuffer) {
|
||||
final ByteBuffer boxBuffer = AviExtractor.allocate(size);
|
||||
AviUtil.copy(byteBuffer, boxBuffer, size);
|
||||
//TODO: Deal with list
|
||||
switch (type) {
|
||||
case AviHeaderBox.AVIH:
|
||||
return new AviHeaderBox(type, size, boxBuffer);
|
||||
case StreamHeaderBox.STRH:
|
||||
return new StreamHeaderBox(type, size, boxBuffer);
|
||||
case StreamFormatBox.STRF:
|
||||
return new StreamFormatBox(type, size, boxBuffer);
|
||||
case StreamDataBox.STRD:
|
||||
return new StreamDataBox(type, size, boxBuffer);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ResidentBox createBoxImpl(final int type, final int size, final ByteBuffer boxBuffer) {
|
||||
switch (type) {
|
||||
case AviHeaderBox.AVIH:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.google.android.exoplayer2.extractor.avi;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -29,26 +30,20 @@ public class ListBox extends Box {
|
|||
return listType;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean assertType() {
|
||||
return simpleAssert(LIST);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Box> getChildren() {
|
||||
return new ArrayList<>(children);
|
||||
}
|
||||
|
||||
// static List<ResidentBox> realizeChildren(final ByteBuffer byteBuffer, final BoxFactory boxFactory) {
|
||||
// final List<ResidentBox> list = new ArrayList<>();
|
||||
// while (byteBuffer.hasRemaining()) {
|
||||
// final int type = byteBuffer.getInt();
|
||||
// final int size = byteBuffer.getInt();
|
||||
// final ResidentBox residentBox = boxFactory.createBox(type, size, byteBuffer);
|
||||
// list.add(residentBox);
|
||||
// }
|
||||
// return list;
|
||||
// }
|
||||
@Nullable
|
||||
public <T extends Box> T getChild(Class<T> c) {
|
||||
for (Box box : children) {
|
||||
if (box.getClass() == c) {
|
||||
return (T)box;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assume the input is pointing to the list type
|
||||
|
|
|
|||
|
|
@ -24,46 +24,6 @@ public class ResidentBox extends Box {
|
|||
this.byteBuffer = byteBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* List is not yet populated
|
||||
* @param byteBuffer
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends ResidentBox> T getInstance(final ByteBuffer byteBuffer,
|
||||
ExtractorInput input, Class<T> boxClass) throws IOException {
|
||||
if (byteBuffer.remaining() < 8) {
|
||||
//Should not happen
|
||||
throw new BufferUnderflowException();
|
||||
}
|
||||
final int type = byteBuffer.getInt();
|
||||
final long size = AviUtil.getUInt(byteBuffer);
|
||||
if (size > MAX_RESIDENT) {
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
final ByteBuffer boxBuffer = AviUtil.getByteBuffer(byteBuffer, (int)size, input);
|
||||
return newInstance(type, (int)size, boxBuffer, boxClass);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <T extends ResidentBox> T newInstance(int type, int size, ByteBuffer boxBuffer,
|
||||
Class<T> boxClass) {
|
||||
try {
|
||||
final Constructor<T> constructor =
|
||||
boxClass.getDeclaredConstructor(int.class, int.class, ByteBuffer.class);
|
||||
T box = constructor.newInstance(type, size, boxBuffer);
|
||||
if (!box.assertType()) {
|
||||
Log.e(TAG, "Expected " + AviUtil.toString(type) + " got " + AviUtil.toString(box.getType()));
|
||||
return null;
|
||||
}
|
||||
return box;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Create box failed " + AviUtil.toString(type));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns shallow copy of this ByteBuffer with the position at 0
|
||||
* @return
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class StreamHeaderBox extends ResidentBox {
|
|||
return byteBuffer.getInt(28);
|
||||
}
|
||||
public long getLength() {
|
||||
return byteBuffer.getInt(32) & AviUtil.UINT_MASK;
|
||||
return byteBuffer.getInt(32) & AviExtractor.UINT_MASK;
|
||||
}
|
||||
//36 - dwSuggestedBufferSize
|
||||
//40 - dwQuality
|
||||
|
|
|
|||
Loading…
Reference in a new issue