Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
1d85bf24
authored
Jan 28, 2022
by
Dustin
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Updated seek
parent
c41dc236
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
385 additions
and
141 deletions
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AudioFormat.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AvcChunkPeeker.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviSeekMap.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/IStreamFormat.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/LinearClock.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/PicCountClock.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBox.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/UnboundedIntArray.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/VideoFormat.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviExtractorTest.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviSeekMapTest.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/DataHelper.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/LinearClockTest.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/PicCountClockTest.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBoxTest.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/UnboundedIntArrayTest.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AudioFormat.java
View file @
1d85bf24
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
android.util.SparseArray
;
import
android.util.SparseArray
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
public
class
AudioFormat
implements
IStreamFormat
{
public
class
AudioFormat
{
public
static
final
short
WAVE_FORMAT_PCM
=
1
;
public
static
final
short
WAVE_FORMAT_PCM
=
1
;
static
final
short
WAVE_FORMAT_AAC
=
0xff
;
static
final
short
WAVE_FORMAT_AAC
=
0xff
;
private
static
final
short
WAVE_FORMAT_MPEGLAYER3
=
0x55
;
private
static
final
short
WAVE_FORMAT_MPEGLAYER3
=
0x55
;
...
@@ -62,15 +61,5 @@ public class AudioFormat implements IStreamFormat {
...
@@ -62,15 +61,5 @@ public class AudioFormat implements IStreamFormat {
return
data
;
return
data
;
}
}
@Override
public
boolean
isAllKeyFrames
()
{
return
true
;
}
@Override
public
@C
.
TrackType
int
getTrackType
()
{
return
C
.
TRACK_TYPE_AUDIO
;
}
//TODO: Deal with WAVEFORMATEXTENSIBLE
//TODO: Deal with WAVEFORMATEXTENSIBLE
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AvcChunkPeeker.java
View file @
1d85bf24
...
@@ -8,6 +8,10 @@ import com.google.android.exoplayer2.util.NalUnitUtil;
...
@@ -8,6 +8,10 @@ import com.google.android.exoplayer2.util.NalUnitUtil;
import
com.google.android.exoplayer2.util.ParsableNalUnitBitArray
;
import
com.google.android.exoplayer2.util.ParsableNalUnitBitArray
;
import
java.io.IOException
;
import
java.io.IOException
;
/**
* Corrects the time and PAR for H264 streams
* H264 is very rare in AVI due to the rise of mp4
*/
public
class
AvcChunkPeeker
extends
NalChunkPeeker
{
public
class
AvcChunkPeeker
extends
NalChunkPeeker
{
private
static
final
int
NAL_TYPE_MASK
=
0x1f
;
private
static
final
int
NAL_TYPE_MASK
=
0x1f
;
private
static
final
int
NAL_TYPE_IRD
=
5
;
private
static
final
int
NAL_TYPE_IRD
=
5
;
...
@@ -22,11 +26,12 @@ public class AvcChunkPeeker extends NalChunkPeeker {
...
@@ -22,11 +26,12 @@ public class AvcChunkPeeker extends NalChunkPeeker {
private
float
pixelWidthHeightRatio
=
1
f
;
private
float
pixelWidthHeightRatio
=
1
f
;
private
NalUnitUtil
.
SpsData
spsData
;
private
NalUnitUtil
.
SpsData
spsData
;
public
AvcChunkPeeker
(
Format
.
Builder
formatBuilder
,
TrackOutput
trackOutput
,
long
usPerChunk
)
{
public
AvcChunkPeeker
(
Format
.
Builder
formatBuilder
,
TrackOutput
trackOutput
,
long
durationUs
,
int
length
)
{
super
(
16
);
super
(
16
);
this
.
formatBuilder
=
formatBuilder
;
this
.
formatBuilder
=
formatBuilder
;
this
.
trackOutput
=
trackOutput
;
this
.
trackOutput
=
trackOutput
;
picCountClock
=
new
PicCountClock
(
usPerChunk
);
picCountClock
=
new
PicCountClock
(
durationUs
,
length
);
}
}
public
PicCountClock
getPicCountClock
()
{
public
PicCountClock
getPicCountClock
()
{
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java
View file @
1d85bf24
This diff is collapsed.
Click to expand it.
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviSeekMap.java
View file @
1d85bf24
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.VisibleForTesting
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.SeekPoint
;
import
com.google.android.exoplayer2.extractor.SeekPoint
;
import
java.util.Arrays
;
public
class
AviSeekMap
implements
SeekMap
{
public
class
AviSeekMap
implements
SeekMap
{
final
int
videoId
;
final
long
videoUsPerChunk
;
final
long
videoUsPerChunk
;
final
int
videoStreamId
;
/**
* Number of frames per index
* i.e. videoFrameOffsetMap[1] is frame 1 * seekIndexFactor
*/
final
int
seekIndexFactor
;
//Seek offsets by streamId, for video, this is the actual offset, for audio, this is the chunkId
final
int
[][]
seekOffsets
;
//Holds a map of video frameIds to audioFrameIds for each audioId
final
long
moviOffset
;
final
long
duration
;
final
long
duration
;
//These are ints / 2
final
int
[]
keyFrameOffsetsDiv2
;
//Seek chunk indexes by streamId
final
int
[][]
seekIndexes
;
final
long
moviOffset
;
public
AviSeekMap
(
AviTrack
videoTrack
,
UnboundedIntArray
[]
seekOffsets
,
int
seekIndexFactor
,
long
moviOffset
,
long
duration
)
{
public
AviSeekMap
(
int
videoId
,
long
usDuration
,
int
videoChunks
,
int
[]
keyFrameOffsetsDiv2
,
videoUsPerChunk
=
videoTrack
.
getClock
().
usPerChunk
;
UnboundedIntArray
[]
seekIndexes
,
long
moviOffset
)
{
videoStreamId
=
videoTrack
.
i
d
;
this
.
videoId
=
videoI
d
;
this
.
seekIndexFactor
=
seekIndexFactor
;
this
.
videoUsPerChunk
=
usDuration
/
videoChunks
;
this
.
moviOffset
=
moviOffset
;
this
.
duration
=
usDuration
;
this
.
duration
=
duration
;
this
.
keyFrameOffsetsDiv2
=
keyFrameOffsetsDiv2
;
this
.
seek
Offsets
=
new
int
[
seekOffset
s
.
length
][];
this
.
seek
Indexes
=
new
int
[
seekIndexe
s
.
length
][];
for
(
int
i
=
0
;
i
<
seek
Offset
s
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
seek
Indexe
s
.
length
;
i
++)
{
this
.
seek
Offsets
[
i
]
=
seekOffset
s
[
i
].
getArray
();
this
.
seek
Indexes
[
i
]
=
seekIndexe
s
[
i
].
getArray
();
}
}
this
.
moviOffset
=
moviOffset
;
}
}
@Override
@Override
...
@@ -41,42 +39,55 @@ public class AviSeekMap implements SeekMap {
...
@@ -41,42 +39,55 @@ public class AviSeekMap implements SeekMap {
return
duration
;
return
duration
;
}
}
private
int
getSeek
Frame
Index
(
long
timeUs
)
{
private
int
getSeekIndex
(
long
timeUs
)
{
final
int
reqFrame
=
(
int
)(
timeUs
/
videoUsPerChunk
);
final
int
reqFrame
=
(
int
)(
timeUs
/
videoUsPerChunk
);
int
reqFrameIndex
=
reqFrame
/
seekIndexFactor
;
return
Arrays
.
binarySearch
(
seekIndexes
[
videoId
],
reqFrame
);
if
(
reqFrameIndex
>=
seekOffsets
[
videoStreamId
].
length
)
{
reqFrameIndex
=
seekOffsets
[
videoStreamId
].
length
-
1
;
}
}
return
reqFrameIndex
;
@VisibleForTesting
int
getFirstSeekIndex
(
int
index
)
{
int
firstIndex
=
-
index
-
2
;
if
(
firstIndex
<
0
)
{
firstIndex
=
0
;
}
return
firstIndex
;
}
private
SeekPoint
getSeekPoint
(
int
index
)
{
long
offset
=
keyFrameOffsetsDiv2
[
index
]
*
2L
;
final
long
outUs
=
seekIndexes
[
videoId
][
index
]
*
videoUsPerChunk
;
final
long
position
=
offset
+
moviOffset
;
return
new
SeekPoint
(
outUs
,
position
);
}
}
@NonNull
@NonNull
@Override
@Override
public
SeekPoints
getSeekPoints
(
long
timeUs
)
{
public
SeekPoints
getSeekPoints
(
long
timeUs
)
{
final
int
seekFrameIndex
=
getSeekFrameIndex
(
timeUs
);
final
int
index
=
getSeekIndex
(
timeUs
);
int
offset
=
seekOffsets
[
videoStreamId
][
seekFrameIndex
];
if
(
index
>=
0
)
{
final
long
outUs
=
seekFrameIndex
*
seekIndexFactor
*
videoUsPerChunk
;
return
new
SeekPoints
(
getSeekPoint
(
index
));
final
long
position
=
offset
+
moviOffset
;
}
//Log.d(AviExtractor.TAG, "SeekPoint: us=" + outUs + " pos=" + position);
final
int
firstSeekIndex
=
getFirstSeekIndex
(
index
);
if
(
firstSeekIndex
+
1
<
keyFrameOffsetsDiv2
.
length
)
{
return
new
SeekPoints
(
getSeekPoint
(
firstSeekIndex
),
getSeekPoint
(
firstSeekIndex
+
1
));
}
else
{
return
new
SeekPoints
(
getSeekPoint
(
firstSeekIndex
));
}
return
new
SeekPoints
(
new
SeekPoint
(
outUs
,
position
)
);
//Log.d(AviExtractor.TAG, "SeekPoint: us=" + outUs + " pos=" + position
);
}
}
public
void
setFrames
(
final
long
position
,
final
long
timeUs
,
final
AviTrack
[]
aviTracks
)
{
public
void
setFrames
(
final
long
position
,
final
long
timeUs
,
final
AviTrack
[]
aviTracks
)
{
final
int
seekFrameIndex
=
getSeekFrameIndex
(
timeUs
);
final
int
index
=
Arrays
.
binarySearch
(
keyFrameOffsetsDiv2
,
(
int
)((
position
-
moviOffset
)
/
2
));
if
(
index
<
0
)
{
throw
new
IllegalArgumentException
(
"Position: "
+
position
);
}
for
(
int
i
=
0
;
i
<
aviTracks
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
aviTracks
.
length
;
i
++)
{
final
AviTrack
aviTrack
=
aviTracks
[
i
];
final
AviTrack
aviTrack
=
aviTracks
[
i
];
if
(
aviTrack
!=
null
)
{
final
LinearClock
clock
=
aviTrack
.
getClock
();
final
LinearClock
clock
=
aviTrack
.
getClock
();
if
(
aviTrack
.
isVideo
())
{
clock
.
setIndex
(
seekIndexes
[
i
][
index
]);
//TODO: Although this works, it leads to partial frames being painted
// Log.d(AviExtractor.TAG, "Frame: " + (aviTrack.isVideo()? 'V' : 'A') + " us=" + clock.getUs() + " frame=" + clock.getIndex() + " key=" + aviTrack.isKeyFrame());
aviTrack
.
setForceKeyFrame
(
true
);
clock
.
setIndex
(
seekFrameIndex
*
seekIndexFactor
);
}
else
{
final
int
offset
=
seekOffsets
[
i
][
seekFrameIndex
];
clock
.
setIndex
(
offset
);
}
}
}
}
}
}
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java
View file @
1d85bf24
...
@@ -5,6 +5,7 @@ import androidx.annotation.Nullable;
...
@@ -5,6 +5,7 @@ import androidx.annotation.Nullable;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.extractor.ExtractorInput
;
import
com.google.android.exoplayer2.extractor.ExtractorInput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.Log
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.Arrays
;
import
java.util.Arrays
;
...
@@ -12,42 +13,68 @@ import java.util.Arrays;
...
@@ -12,42 +13,68 @@ import java.util.Arrays;
* Collection of info about a track
* Collection of info about a track
*/
*/
public
class
AviTrack
{
public
class
AviTrack
{
public
static
final
int
[]
ALL_KEY_FRAMES
=
new
int
[
0
];
final
int
id
;
final
int
id
;
final
@C
.
TrackType
int
trackType
;
@NonNull
@NonNull
final
LinearClock
clock
;
final
LinearClock
clock
;
/**
* True indicates all frames are key frames (e.g. Audio, MJPEG)
*/
final
boolean
allKeyFrames
;
final
@C
.
TrackType
int
trackType
;
@NonNull
@NonNull
final
TrackOutput
trackOutput
;
final
TrackOutput
trackOutput
;
boolean
forceKeyFrame
;
final
int
chunkId
;
final
int
chunkIdAlt
;
@Nullable
@Nullable
ChunkPeeker
chunkPeeker
;
ChunkPeeker
chunkPeeker
;
int
chunks
;
int
size
;
/**
/**
*
Key is frame number value is offset
*
Ordered list of key frame chunk indexes
*/
*/
@Nullable
int
[]
keyFrames
=
new
int
[
0
];
int
[]
keyFrames
;
transient
int
chunkSize
;
transient
int
chunkSize
;
transient
int
chunkRemaining
;
transient
int
chunkRemaining
;
AviTrack
(
int
id
,
@NonNull
IStreamFormat
streamFormat
,
@NonNull
LinearClock
clock
,
private
static
int
getChunkIdLower
(
int
id
)
{
int
tens
=
id
/
10
;
int
ones
=
id
%
10
;
return
(
'0'
+
tens
)
|
((
'0'
+
ones
)
<<
8
);
}
public
static
int
getVideoChunkId
(
int
id
)
{
return
getChunkIdLower
(
id
)
|
(
'd'
<<
16
)
|
(
'c'
<<
24
);
}
public
static
int
getAudioChunkId
(
int
id
)
{
return
getChunkIdLower
(
id
)
|
(
'w'
<<
16
)
|
(
'b'
<<
24
);
}
AviTrack
(
int
id
,
final
@C
.
TrackType
int
trackType
,
@NonNull
LinearClock
clock
,
@NonNull
TrackOutput
trackOutput
)
{
@NonNull
TrackOutput
trackOutput
)
{
this
.
id
=
id
;
this
.
id
=
id
;
this
.
clock
=
clock
;
this
.
clock
=
clock
;
this
.
allKeyFrames
=
streamFormat
.
isAllKeyFrames
();
this
.
trackType
=
trackType
;
this
.
trackType
=
streamFormat
.
getTrackType
();
this
.
trackOutput
=
trackOutput
;
this
.
trackOutput
=
trackOutput
;
if
(
isVideo
())
{
chunkId
=
getVideoChunkId
(
id
);
chunkIdAlt
=
getChunkIdLower
(
id
)
|
(
'd'
<<
16
)
|
(
'b'
<<
24
);
}
else
if
(
isAudio
())
{
chunkId
=
getAudioChunkId
(
id
);
chunkIdAlt
=
0xffff
;
}
else
{
throw
new
IllegalArgumentException
(
"Unknown Track Type: "
+
trackType
);
}
}
public
boolean
handlesChunkId
(
int
chunkId
)
{
return
this
.
chunkId
==
chunkId
||
chunkIdAlt
==
chunkId
;
}
}
public
LinearClock
getClock
()
{
public
LinearClock
getClock
()
{
...
@@ -58,30 +85,16 @@ public class AviTrack {
...
@@ -58,30 +85,16 @@ public class AviTrack {
this
.
chunkPeeker
=
chunkPeeker
;
this
.
chunkPeeker
=
chunkPeeker
;
}
}
public
boolean
isAllKeyFrames
()
{
/**
return
allKeyFrames
;
*
* @param keyFrames null means all key frames
*/
void
setKeyFrames
(
@NonNull
final
int
[]
keyFrames
)
{
this
.
keyFrames
=
keyFrames
;
}
}
public
boolean
isKeyFrame
()
{
public
boolean
isKeyFrame
()
{
if
(
allKeyFrames
)
{
return
keyFrames
==
ALL_KEY_FRAMES
||
Arrays
.
binarySearch
(
keyFrames
,
clock
.
getIndex
())
>=
0
;
return
true
;
}
if
(
forceKeyFrame
)
{
forceKeyFrame
=
false
;
return
true
;
}
if
(
keyFrames
!=
null
)
{
return
Arrays
.
binarySearch
(
keyFrames
,
clock
.
getIndex
())
>=
0
;
}
return
false
;
}
public
void
setForceKeyFrame
(
boolean
v
)
{
forceKeyFrame
=
v
;
}
public
void
setKeyFrames
(
int
[]
keyFrames
)
{
this
.
keyFrames
=
keyFrames
;
}
}
public
boolean
isVideo
()
{
public
boolean
isVideo
()
{
...
@@ -130,7 +143,8 @@ public class AviTrack {
...
@@ -130,7 +143,8 @@ public class AviTrack {
void
done
(
final
int
size
)
{
void
done
(
final
int
size
)
{
trackOutput
.
sampleMetadata
(
trackOutput
.
sampleMetadata
(
clock
.
getUs
(),
(
isKeyFrame
()
?
C
.
BUFFER_FLAG_KEY_FRAME
:
0
),
size
,
0
,
null
);
clock
.
getUs
(),
(
isKeyFrame
()
?
C
.
BUFFER_FLAG_KEY_FRAME
:
0
),
size
,
0
,
null
);
//Log.d(AviExtractor.TAG, "Frame: " + (isVideo()? 'V' : 'A') + " us=" + getUs() + " size=" + size + " frame=" + frame + " usFrame=" + getUsFrame());
final
LinearClock
clock
=
getClock
();
// Log.d(AviExtractor.TAG, "Frame: " + (isVideo()? 'V' : 'A') + " us=" + clock.getUs() + " size=" + size + " frame=" + clock.getIndex() + " key=" + isKeyFrame());
clock
.
advance
();
clock
.
advance
();
}
}
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/IStreamFormat.java
deleted
100644 → 0
View file @
c41dc236
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
com.google.android.exoplayer2.C
;
public
interface
IStreamFormat
{
String
getMimeType
();
boolean
isAllKeyFrames
();
@C
.
TrackType
int
getTrackType
();
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/LinearClock.java
View file @
1d85bf24
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
public
class
LinearClock
{
public
class
LinearClock
{
long
usPerChunk
;
long
durationUs
;
int
length
;
int
index
;
int
index
;
public
LinearClock
(
long
usPerChunk
)
{
public
LinearClock
(
long
durationUs
,
int
length
)
{
this
.
usPerChunk
=
usPerChunk
;
this
.
durationUs
=
durationUs
;
this
.
length
=
length
;
}
public
void
setDuration
(
long
durationUs
)
{
this
.
durationUs
=
durationUs
;
}
public
void
setLength
(
int
length
)
{
this
.
length
=
length
;
}
}
public
int
getIndex
()
{
public
int
getIndex
()
{
...
@@ -22,6 +32,11 @@ public class LinearClock {
...
@@ -22,6 +32,11 @@ public class LinearClock {
}
}
public
long
getUs
()
{
public
long
getUs
()
{
return
index
*
usPerChunk
;
return
getUs
(
index
);
}
long
getUs
(
int
index
)
{
//Doing this the hard way lessens round errors
return
durationUs
*
index
/
length
;
}
}
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/PicCountClock.java
View file @
1d85bf24
...
@@ -15,8 +15,8 @@ public class PicCountClock extends LinearClock {
...
@@ -15,8 +15,8 @@ public class PicCountClock extends LinearClock {
private
int
posHalf
;
private
int
posHalf
;
private
int
negHalf
;
private
int
negHalf
;
public
PicCountClock
(
long
usPerFrame
)
{
public
PicCountClock
(
long
durationUs
,
int
length
)
{
super
(
usPerFrame
);
super
(
durationUs
,
length
);
}
}
public
void
setMaxPicCount
(
int
maxPicCount
)
{
public
void
setMaxPicCount
(
int
maxPicCount
)
{
...
@@ -59,6 +59,6 @@ public class PicCountClock extends LinearClock {
...
@@ -59,6 +59,6 @@ public class PicCountClock extends LinearClock {
@Override
@Override
public
long
getUs
()
{
public
long
getUs
()
{
return
picIndex
*
usPerChunk
;
return
getUs
(
picIndex
)
;
}
}
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBox.java
View file @
1d85bf24
...
@@ -30,11 +30,8 @@ public class StreamHeaderBox extends ResidentBox {
...
@@ -30,11 +30,8 @@ public class StreamHeaderBox extends ResidentBox {
return
getRate
()
/
(
float
)
getScale
();
return
getRate
()
/
(
float
)
getScale
();
}
}
/**
public
long
getDurationUs
()
{
* @return sample duration in us
return
getScale
()
*
getLength
()
*
1_000_000L
/
getRate
();
*/
public
long
getUsPerSample
()
{
return
getScale
()
*
1_000_000L
/
getRate
();
}
}
public
int
getSteamType
()
{
public
int
getSteamType
()
{
...
@@ -59,12 +56,12 @@ public class StreamHeaderBox extends ResidentBox {
...
@@ -59,12 +56,12 @@ public class StreamHeaderBox extends ResidentBox {
public
int
getRate
()
{
public
int
getRate
()
{
return
byteBuffer
.
getInt
(
24
);
return
byteBuffer
.
getInt
(
24
);
}
}
//
28 - dwStar
t
//
28 - dwStart - doesn't seem to ever be se
t
// public int getStart() {
// public int getStart() {
// return byteBuffer.getInt(28);
// return byteBuffer.getInt(28);
// }
// }
public
long
getLength
()
{
public
int
getLength
()
{
return
byteBuffer
.
getInt
(
32
)
&
AviExtractor
.
UINT_MASK
;
return
byteBuffer
.
getInt
(
32
);
}
}
public
int
getSuggestedBufferSize
()
{
public
int
getSuggestedBufferSize
()
{
...
@@ -75,4 +72,8 @@ public class StreamHeaderBox extends ResidentBox {
...
@@ -75,4 +72,8 @@ public class StreamHeaderBox extends ResidentBox {
// public int getSampleSize() {
// public int getSampleSize() {
// return byteBuffer.getInt(44);
// return byteBuffer.getInt(44);
// }
// }
// public String toString() {
// return "scale=" + getScale() + " rate=" + getRate() + " length=" + getLength() + " us=" + getDurationUs();
// }
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/UnboundedIntArray.java
View file @
1d85bf24
...
@@ -29,6 +29,13 @@ public class UnboundedIntArray {
...
@@ -29,6 +29,13 @@ public class UnboundedIntArray {
array
[
size
++]
=
v
;
array
[
size
++]
=
v
;
}
}
public
int
get
(
final
int
index
)
{
if
(
index
>=
size
)
{
throw
new
ArrayIndexOutOfBoundsException
(
index
+
">="
+
size
);
}
return
array
[
index
];
}
public
int
getSize
()
{
public
int
getSize
()
{
return
size
;
return
size
;
}
}
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/VideoFormat.java
View file @
1d85bf24
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.HashMap
;
import
java.util.HashMap
;
public
class
VideoFormat
implements
IStreamFormat
{
public
class
VideoFormat
{
static
final
int
XVID
=
'X'
|
(
'V'
<<
8
)
|
(
'I'
<<
16
)
|
(
'D'
<<
24
);
static
final
int
XVID
=
'X'
|
(
'V'
<<
8
)
|
(
'I'
<<
16
)
|
(
'D'
<<
24
);
...
@@ -56,14 +55,4 @@ public class VideoFormat implements IStreamFormat {
...
@@ -56,14 +55,4 @@ public class VideoFormat implements IStreamFormat {
public
String
getMimeType
()
{
public
String
getMimeType
()
{
return
STREAM_MAP
.
get
(
getCompression
());
return
STREAM_MAP
.
get
(
getCompression
());
}
}
@Override
public
boolean
isAllKeyFrames
()
{
return
MimeTypes
.
VIDEO_MJPEG
.
equals
(
getMimeType
());
}
@Override
public
int
getTrackType
()
{
return
C
.
TRACK_TYPE_VIDEO
;
}
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviExtractorTest.java
View file @
1d85bf24
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorOutput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorOutput
;
import
java.io.IOException
;
import
java.io.IOException
;
...
@@ -148,4 +149,100 @@ public class AviExtractorTest {
...
@@ -148,4 +149,100 @@ public class AviExtractorTest {
Assert
.
assertEquals
(
1
,
AviExtractor
.
getStreamId
(
'0'
|
(
'1'
<<
8
)
|
(
'd'
<<
16
)
|
(
'c'
<<
24
)));
Assert
.
assertEquals
(
1
,
AviExtractor
.
getStreamId
(
'0'
|
(
'1'
<<
8
)
|
(
'd'
<<
16
)
|
(
'c'
<<
24
)));
}
}
private
void
assertIdx1
(
AviSeekMap
aviSeekMap
,
AviTrack
videoTrack
,
int
keyFrames
,
int
keyFrameRate
)
{
Assert
.
assertEquals
(
keyFrames
,
videoTrack
.
keyFrames
.
length
);
final
int
framesPerKeyFrame
=
24
*
3
;
//This indirectly verifies the number of video chunks
Assert
.
assertEquals
(
9
*
DataHelper
.
FPS
,
videoTrack
.
chunks
);
Assert
.
assertEquals
(
2
*
framesPerKeyFrame
,
videoTrack
.
keyFrames
[
2
]);
Assert
.
assertEquals
(
2
*
keyFrameRate
*
DataHelper
.
AUDIO_PER_VIDEO
,
aviSeekMap
.
seekIndexes
[
DataHelper
.
AUDIO_ID
][
2
]);
Assert
.
assertEquals
(
4L
+
2
*
keyFrameRate
*
DataHelper
.
VIDEO_SIZE
+
2
*
keyFrameRate
*
DataHelper
.
AUDIO_SIZE
*
DataHelper
.
AUDIO_PER_VIDEO
,
aviSeekMap
.
keyFrameOffsetsDiv2
[
2
]
*
2L
);
}
@Test
public
void
readIdx1_given9secsAv
()
throws
IOException
{
final
AviExtractor
aviExtractor
=
new
AviExtractor
();
final
FakeExtractorOutput
fakeExtractorOutput
=
new
FakeExtractorOutput
();
aviExtractor
.
init
(
fakeExtractorOutput
);
final
int
secs
=
9
;
final
int
keyFrameRate
=
3
*
DataHelper
.
FPS
;
// Keyframe every 3 seconds
final
int
keyFrames
=
secs
*
DataHelper
.
FPS
/
keyFrameRate
;
final
ByteBuffer
idx1
=
DataHelper
.
getIndex
(
secs
,
keyFrameRate
);
final
AviTrack
videoTrack
=
DataHelper
.
getVideoAviTrack
(
secs
);
final
AviTrack
audioTrack
=
DataHelper
.
getAudioAviTrack
(
secs
);
aviExtractor
.
setAviTracks
(
new
AviTrack
[]{
videoTrack
,
audioTrack
});
final
FakeExtractorInput
fakeExtractorInput
=
new
FakeExtractorInput
.
Builder
().
setData
(
idx1
.
array
()).
build
();
aviExtractor
.
readIdx1
(
fakeExtractorInput
,
(
int
)
fakeExtractorInput
.
getLength
());
final
AviSeekMap
aviSeekMap
=
aviExtractor
.
aviSeekMap
;
assertIdx1
(
aviSeekMap
,
videoTrack
,
keyFrames
,
keyFrameRate
);
}
@Test
public
void
readIdx1_givenNoVideo
()
throws
IOException
{
final
AviExtractor
aviExtractor
=
new
AviExtractor
();
final
FakeExtractorOutput
fakeExtractorOutput
=
new
FakeExtractorOutput
();
aviExtractor
.
init
(
fakeExtractorOutput
);
final
int
secs
=
9
;
final
int
keyFrameRate
=
3
*
DataHelper
.
FPS
;
// Keyframe every 3 seconds
final
ByteBuffer
idx1
=
DataHelper
.
getIndex
(
secs
,
keyFrameRate
);
final
AviTrack
audioTrack
=
DataHelper
.
getAudioAviTrack
(
secs
);
aviExtractor
.
setAviTracks
(
new
AviTrack
[]{
audioTrack
});
final
FakeExtractorInput
fakeExtractorInput
=
new
FakeExtractorInput
.
Builder
().
setData
(
idx1
.
array
()).
build
();
aviExtractor
.
readIdx1
(
fakeExtractorInput
,
(
int
)
fakeExtractorInput
.
getLength
());
Assert
.
assertTrue
(
fakeExtractorOutput
.
seekMap
instanceof
SeekMap
.
Unseekable
);
}
@Test
public
void
readIdx1_givenJunkInIndex
()
throws
IOException
{
final
AviExtractor
aviExtractor
=
new
AviExtractor
();
final
FakeExtractorOutput
fakeExtractorOutput
=
new
FakeExtractorOutput
();
aviExtractor
.
init
(
fakeExtractorOutput
);
final
int
secs
=
9
;
final
int
keyFrameRate
=
3
*
DataHelper
.
FPS
;
// Keyframe every 3 seconds
final
int
keyFrames
=
secs
*
DataHelper
.
FPS
/
keyFrameRate
;
final
ByteBuffer
idx1
=
DataHelper
.
getIndex
(
9
,
keyFrameRate
);
final
ByteBuffer
junk
=
AviExtractor
.
allocate
(
idx1
.
capacity
()
+
16
);
junk
.
putInt
(
AviExtractor
.
JUNK
);
junk
.
putInt
(
0
);
junk
.
putInt
(
0
);
junk
.
putInt
(
0
);
idx1
.
flip
();
junk
.
put
(
idx1
);
final
AviTrack
videoTrack
=
DataHelper
.
getVideoAviTrack
(
secs
);
final
AviTrack
audioTrack
=
DataHelper
.
getAudioAviTrack
(
secs
);
aviExtractor
.
setAviTracks
(
new
AviTrack
[]{
videoTrack
,
audioTrack
});
final
FakeExtractorInput
fakeExtractorInput
=
new
FakeExtractorInput
.
Builder
().
setData
(
junk
.
array
()).
build
();
aviExtractor
.
readIdx1
(
fakeExtractorInput
,
(
int
)
fakeExtractorInput
.
getLength
());
assertIdx1
(
aviExtractor
.
aviSeekMap
,
videoTrack
,
keyFrames
,
keyFrameRate
);
}
@Test
public
void
readIdx1_givenAllKeyFrames
()
throws
IOException
{
final
AviExtractor
aviExtractor
=
new
AviExtractor
();
final
FakeExtractorOutput
fakeExtractorOutput
=
new
FakeExtractorOutput
();
aviExtractor
.
init
(
fakeExtractorOutput
);
final
int
secs
=
4
;
final
ByteBuffer
idx1
=
DataHelper
.
getIndex
(
secs
,
1
);
final
AviTrack
videoTrack
=
DataHelper
.
getVideoAviTrack
(
secs
);
final
AviTrack
audioTrack
=
DataHelper
.
getAudioAviTrack
(
secs
);
aviExtractor
.
setAviTracks
(
new
AviTrack
[]{
videoTrack
,
audioTrack
});
final
FakeExtractorInput
fakeExtractorInput
=
new
FakeExtractorInput
.
Builder
().
setData
(
idx1
.
array
()).
build
();
aviExtractor
.
readIdx1
(
fakeExtractorInput
,
(
int
)
fakeExtractorInput
.
getLength
());
//We should be throttled to 2 key frame per second
Assert
.
assertSame
(
AviTrack
.
ALL_KEY_FRAMES
,
videoTrack
.
keyFrames
);
}
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviSeekMapTest.java
0 → 100644
View file @
1d85bf24
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
org.junit.Assert
;
import
org.junit.Test
;
public
class
AviSeekMapTest
{
@Test
public
void
setFrames_givenExactSeekPointMatch
()
{
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
final
long
position
=
aviSeekMap
.
keyFrameOffsetsDiv2
[
1
]
*
2L
+
aviSeekMap
.
moviOffset
;
final
int
secs
=
4
;
final
AviTrack
[]
aviTracks
=
new
AviTrack
[]{
DataHelper
.
getVideoAviTrack
(
secs
),
DataHelper
.
getAudioAviTrack
(
secs
)};
aviSeekMap
.
setFrames
(
position
,
1_000_000L
,
aviTracks
);
for
(
int
i
=
0
;
i
<
aviTracks
.
length
;
i
++)
{
Assert
.
assertEquals
(
aviSeekMap
.
seekIndexes
[
i
][
1
],
aviTracks
[
i
].
getClock
().
getIndex
());
}
}
@Test
public
void
setFrames_givenBadPosition
()
{
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
final
AviTrack
[]
aviTracks
=
new
AviTrack
[
2
];
try
{
aviSeekMap
.
setFrames
(
1L
,
1_000_000L
,
aviTracks
);
Assert
.
fail
();
}
catch
(
IllegalArgumentException
e
)
{
//Intentionally blank
}
}
@Test
public
void
getSeekPoints_givenNonKeyFrameUs
()
{
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
//Time before the 1st keyFrame
final
long
us
=
aviSeekMap
.
seekIndexes
[
0
][
1
]
*
aviSeekMap
.
videoUsPerChunk
-
100L
;
final
SeekMap
.
SeekPoints
seekPoints
=
aviSeekMap
.
getSeekPoints
(
us
);
Assert
.
assertEquals
(
aviSeekMap
.
seekIndexes
[
0
][
0
]
*
aviSeekMap
.
videoUsPerChunk
,
seekPoints
.
first
.
timeUs
);
Assert
.
assertEquals
(
aviSeekMap
.
seekIndexes
[
0
][
1
]
*
aviSeekMap
.
videoUsPerChunk
,
seekPoints
.
second
.
timeUs
);
}
@Test
public
void
getFirstSeekIndex_atZeroIndex
()
{
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
Assert
.
assertEquals
(
0
,
aviSeekMap
.
getFirstSeekIndex
(-
1
));
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/DataHelper.java
View file @
1d85bf24
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
java.io.File
;
import
java.io.File
;
...
@@ -11,6 +12,14 @@ import java.util.ArrayList;
...
@@ -11,6 +12,14 @@ import java.util.ArrayList;
import
java.util.Arrays
;
import
java.util.Arrays
;
public
class
DataHelper
{
public
class
DataHelper
{
static
final
int
FPS
=
24
;
static
final
long
VIDEO_US
=
1_000_000L
/
FPS
;
static
final
int
AUDIO_PER_VIDEO
=
4
;
static
final
int
VIDEO_SIZE
=
4096
;
static
final
int
AUDIO_SIZE
=
256
;
static
final
int
AUDIO_ID
=
1
;
private
static
final
long
AUDIO_US
=
VIDEO_US
/
AUDIO_PER_VIDEO
;
//Base path "\ExoPlayer\library\extractor\."
//Base path "\ExoPlayer\library\extractor\."
private
static
final
File
RELATIVE_PATH
=
new
File
(
"../../testdata/src/test/assets/extractordumps/avi/"
);
private
static
final
File
RELATIVE_PATH
=
new
File
(
"../../testdata/src/test/assets/extractordumps/avi/"
);
public
static
FakeExtractorInput
getInput
(
final
String
fileName
)
throws
IOException
{
public
static
FakeExtractorInput
getInput
(
final
String
fileName
)
throws
IOException
{
...
@@ -87,18 +96,62 @@ public class DataHelper {
...
@@ -87,18 +96,62 @@ public class DataHelper {
byteBuffer
.
put
(
nalType
);
byteBuffer
.
put
(
nalType
);
return
byteBuffer
;
return
byteBuffer
;
}
}
public
static
AviSeekMap
getAviSeekMap
()
throws
IOException
{
final
FakeTrackOutput
output
=
new
FakeTrackOutput
(
false
);
public
static
AviTrack
getVideoAviTrack
(
int
sec
)
{
final
AviTrack
videoTrack
=
new
AviTrack
(
0
,
final
FakeTrackOutput
fakeTrackOutput
=
new
FakeTrackOutput
(
false
);
DataHelper
.
getVideoStreamFormat
().
getVideoFormat
(),
new
LinearClock
(
100
),
output
);
return
new
AviTrack
(
0
,
C
.
TRACK_TYPE_VIDEO
,
new
LinearClock
(
sec
*
1_000_000L
,
sec
*
FPS
),
fakeTrackOutput
);
}
public
static
AviTrack
getAudioAviTrack
(
int
sec
)
{
final
FakeTrackOutput
fakeTrackOutput
=
new
FakeTrackOutput
(
false
);
return
new
AviTrack
(
AUDIO_ID
,
C
.
TRACK_TYPE_AUDIO
,
new
LinearClock
(
sec
*
1_000_000L
,
sec
*
FPS
*
AUDIO_PER_VIDEO
),
fakeTrackOutput
);
}
public
static
AviSeekMap
getAviSeekMap
()
{
final
int
[]
keyFrameOffsetsDiv2
=
{
4
,
1024
};
final
UnboundedIntArray
videoArray
=
new
UnboundedIntArray
();
final
UnboundedIntArray
videoArray
=
new
UnboundedIntArray
();
videoArray
.
add
(
0
);
videoArray
.
add
(
0
);
videoArray
.
add
(
102
4
);
videoArray
.
add
(
4
);
final
UnboundedIntArray
audioArray
=
new
UnboundedIntArray
();
final
UnboundedIntArray
audioArray
=
new
UnboundedIntArray
();
audioArray
.
add
(
0
);
audioArray
.
add
(
0
);
audioArray
.
add
(
128
);
audioArray
.
add
(
128
);
return
new
AviSeekMap
(
videoTrack
,
return
new
AviSeekMap
(
0
,
100L
,
8
,
keyFrameOffsetsDiv2
,
new
UnboundedIntArray
[]{
videoArray
,
audioArray
},
24
,
0L
,
0L
);
new
UnboundedIntArray
[]{
videoArray
,
audioArray
},
4096
);
}
private
static
void
putIndex
(
final
ByteBuffer
byteBuffer
,
int
chunkId
,
int
flags
,
int
offset
,
int
size
)
{
byteBuffer
.
putInt
(
chunkId
);
byteBuffer
.
putInt
(
flags
);
byteBuffer
.
putInt
(
offset
);
byteBuffer
.
putInt
(
size
);
}
/**
*
* @param secs Number of seconds
* @param keyFrameRate Key frame rate 1= every frame, 2=every other, ...
*/
public
static
ByteBuffer
getIndex
(
final
int
secs
,
final
int
keyFrameRate
)
{
final
int
videoFrames
=
secs
*
FPS
;
final
int
videoChunkId
=
AviTrack
.
getVideoChunkId
(
0
);
final
int
audioChunkId
=
AviTrack
.
getAudioChunkId
(
1
);
int
offset
=
4
;
final
ByteBuffer
byteBuffer
=
AviExtractor
.
allocate
((
videoFrames
+
videoFrames
*
AUDIO_PER_VIDEO
)
*
16
);
for
(
int
v
=
0
;
v
<
videoFrames
;
v
++)
{
putIndex
(
byteBuffer
,
videoChunkId
,
(
v
%
keyFrameRate
==
0
)
?
AviExtractor
.
AVIIF_KEYFRAME
:
0
,
offset
,
VIDEO_SIZE
);
offset
+=
VIDEO_SIZE
;
for
(
int
a
=
0
;
a
<
AUDIO_PER_VIDEO
;
a
++)
{
putIndex
(
byteBuffer
,
audioChunkId
,
AviExtractor
.
AVIIF_KEYFRAME
,
offset
,
AUDIO_SIZE
);
offset
+=
AUDIO_SIZE
;
}
}
return
byteBuffer
;
}
}
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/LinearClockTest.java
View file @
1d85bf24
...
@@ -9,7 +9,7 @@ import org.junit.Test;
...
@@ -9,7 +9,7 @@ import org.junit.Test;
public
class
LinearClockTest
{
public
class
LinearClockTest
{
@Test
@Test
public
void
advance
()
{
public
void
advance
()
{
final
LinearClock
linearClock
=
new
LinearClock
(
1
00L
);
final
LinearClock
linearClock
=
new
LinearClock
(
1
_000L
,
10
);
linearClock
.
setIndex
(
2
);
linearClock
.
setIndex
(
2
);
Assert
.
assertEquals
(
200
,
linearClock
.
getUs
());
Assert
.
assertEquals
(
200
,
linearClock
.
getUs
());
linearClock
.
advance
();
linearClock
.
advance
();
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/PicCountClockTest.java
View file @
1d85bf24
...
@@ -6,7 +6,7 @@ import org.junit.Test;
...
@@ -6,7 +6,7 @@ import org.junit.Test;
public
class
PicCountClockTest
{
public
class
PicCountClockTest
{
@Test
@Test
public
void
us_givenTwoStepsForward
()
{
public
void
us_givenTwoStepsForward
()
{
final
PicCountClock
picCountClock
=
new
PicCountClock
(
100
);
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10
_000L
,
10
0
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setPicCount
(
2
*
2
);
picCountClock
.
setPicCount
(
2
*
2
);
Assert
.
assertEquals
(
2
*
100
,
picCountClock
.
getUs
());
Assert
.
assertEquals
(
2
*
100
,
picCountClock
.
getUs
());
...
@@ -14,7 +14,7 @@ public class PicCountClockTest {
...
@@ -14,7 +14,7 @@ public class PicCountClockTest {
@Test
@Test
public
void
us_givenThreeStepsBackwards
()
{
public
void
us_givenThreeStepsBackwards
()
{
final
PicCountClock
picCountClock
=
new
PicCountClock
(
100
);
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10
_000L
,
10
0
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setPicCount
(
4
*
2
);
// 400ms
picCountClock
.
setPicCount
(
4
*
2
);
// 400ms
Assert
.
assertEquals
(
400
,
picCountClock
.
getUs
());
Assert
.
assertEquals
(
400
,
picCountClock
.
getUs
());
...
@@ -24,14 +24,14 @@ public class PicCountClockTest {
...
@@ -24,14 +24,14 @@ public class PicCountClockTest {
@Test
@Test
public
void
setIndex_given3Chunks
()
{
public
void
setIndex_given3Chunks
()
{
final
PicCountClock
picCountClock
=
new
PicCountClock
(
100
);
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10
_000L
,
10
0
);
picCountClock
.
setIndex
(
3
);
picCountClock
.
setIndex
(
3
);
Assert
.
assertEquals
(
3
*
100
,
picCountClock
.
getUs
());
Assert
.
assertEquals
(
3
*
100
,
picCountClock
.
getUs
());
}
}
@Test
@Test
public
void
us_giveWrapBackwards
()
{
public
void
us_giveWrapBackwards
()
{
final
PicCountClock
picCountClock
=
new
PicCountClock
(
100
);
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10
_000L
,
10
0
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
//Need to walk up no faster than maxPicCount / 2
//Need to walk up no faster than maxPicCount / 2
picCountClock
.
setPicCount
(
7
*
2
);
picCountClock
.
setPicCount
(
7
*
2
);
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBoxTest.java
View file @
1d85bf24
...
@@ -22,7 +22,6 @@ public class StreamHeaderBoxTest {
...
@@ -22,7 +22,6 @@ public class StreamHeaderBoxTest {
Assert
.
assertEquals
(
VideoFormat
.
XVID
,
streamHeaderBox
.
getFourCC
());
Assert
.
assertEquals
(
VideoFormat
.
XVID
,
streamHeaderBox
.
getFourCC
());
Assert
.
assertEquals
(
0
,
streamHeaderBox
.
getInitialFrames
());
Assert
.
assertEquals
(
0
,
streamHeaderBox
.
getInitialFrames
());
Assert
.
assertEquals
(
FPS24
,
streamHeaderBox
.
getFrameRate
(),
0.1
);
Assert
.
assertEquals
(
FPS24
,
streamHeaderBox
.
getFrameRate
(),
0.1
);
Assert
.
assertEquals
(
US_SAMPLE24FPS
,
streamHeaderBox
.
getUsPerSample
());
Assert
.
assertEquals
(
11805L
,
streamHeaderBox
.
getLength
());
Assert
.
assertEquals
(
11805L
,
streamHeaderBox
.
getLength
());
Assert
.
assertEquals
(
0
,
streamHeaderBox
.
getSuggestedBufferSize
());
Assert
.
assertEquals
(
0
,
streamHeaderBox
.
getSuggestedBufferSize
());
}
}
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/UnboundedIntArrayTest.java
View file @
1d85bf24
...
@@ -51,4 +51,23 @@ public class UnboundedIntArrayTest {
...
@@ -51,4 +51,23 @@ public class UnboundedIntArrayTest {
//Intentionally blank
//Intentionally blank
}
}
}
}
@Test
public
void
get_givenValidIndex
()
{
final
UnboundedIntArray
unboundedIntArray
=
new
UnboundedIntArray
(
4
);
unboundedIntArray
.
add
(
1
);
unboundedIntArray
.
add
(
2
);
Assert
.
assertEquals
(
1
,
unboundedIntArray
.
get
(
0
));
}
@Test
public
void
get_givenOutOfBounds
()
{
final
UnboundedIntArray
unboundedIntArray
=
new
UnboundedIntArray
(
4
);
try
{
unboundedIntArray
.
get
(
0
);
Assert
.
fail
();
}
catch
(
ArrayIndexOutOfBoundsException
e
)
{
//Intentionally blank
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment