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
c4cf876d
authored
Jan 22, 2022
by
Dustin
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Tests for Mp4vAviTrack and StreamHeaderBox
parent
3ce652ea
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
156 additions
and
22 deletions
library/extractor/build.gradle
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/Mp4vAviTrack.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBox.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/Mp4vAviTrackTest.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBoxTest.java
testdata/src/test/assets/extractordumps/avi/mp4v_sequence.dump
testdata/src/test/assets/extractordumps/avi/vids_stream_header.dump
library/extractor/build.gradle
View file @
c4cf876d
...
@@ -19,7 +19,11 @@ android {
...
@@ -19,7 +19,11 @@ android {
testCoverageEnabled
=
true
testCoverageEnabled
=
true
}
}
}
}
testOptions
{
unitTests
.
all
{
jvmArgs
'-noverify'
}
}
sourceSets
.
test
.
assets
.
srcDir
'../../testdata/src/test/assets/'
sourceSets
.
test
.
assets
.
srcDir
'../../testdata/src/test/assets/'
}
}
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/Mp4vAviTrack.java
View file @
c4cf876d
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.Nullable
;
import
androidx.annotation.VisibleForTesting
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
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
;
...
@@ -13,7 +15,7 @@ public class Mp4vAviTrack extends AviTrack {
...
@@ -13,7 +15,7 @@ public class Mp4vAviTrack extends AviTrack {
private
static
final
float
[]
ASPECT_RATIO
=
{
0
f
,
1
f
,
12
f
/
11
f
,
10
f
/
11
f
,
16
f
/
11
f
,
40
f
/
33
f
};
private
static
final
float
[]
ASPECT_RATIO
=
{
0
f
,
1
f
,
12
f
/
11
f
,
10
f
/
11
f
,
16
f
/
11
f
,
40
f
/
33
f
};
private
static
final
int
Extended_PAR
=
0xf
;
private
static
final
int
Extended_PAR
=
0xf
;
private
final
Format
.
Builder
formatBuilder
;
private
final
Format
.
Builder
formatBuilder
;
private
float
pixelWidthHeightRatio
=
1
f
;
float
pixelWidthHeightRatio
=
1
f
;
Mp4vAviTrack
(
int
id
,
@NonNull
StreamHeaderBox
streamHeaderBox
,
@NonNull
TrackOutput
trackOutput
,
Mp4vAviTrack
(
int
id
,
@NonNull
StreamHeaderBox
streamHeaderBox
,
@NonNull
TrackOutput
trackOutput
,
@NonNull
Format
.
Builder
formatBuilder
)
{
@NonNull
Format
.
Builder
formatBuilder
)
{
...
@@ -21,8 +23,8 @@ public class Mp4vAviTrack extends AviTrack {
...
@@ -21,8 +23,8 @@ public class Mp4vAviTrack extends AviTrack {
this
.
formatBuilder
=
formatBuilder
;
this
.
formatBuilder
=
formatBuilder
;
}
}
private
void
processLayerStart
(
byte
[]
peek
,
int
offset
)
{
@VisibleForTesting
final
ParsableNalUnitBitArray
in
=
new
ParsableNalUnitBitArray
(
peek
,
offset
,
peek
.
length
);
void
processLayerStart
(
@NonNull
final
ParsableNalUnitBitArray
in
)
{
in
.
skipBit
();
// random_accessible_vol
in
.
skipBit
();
// random_accessible_vol
in
.
skipBits
(
8
);
// video_object_type_indication
in
.
skipBits
(
8
);
// video_object_type_indication
boolean
is_object_layer_identifier
=
in
.
readBit
();
boolean
is_object_layer_identifier
=
in
.
readBit
();
...
@@ -44,23 +46,35 @@ public class Mp4vAviTrack extends AviTrack {
...
@@ -44,23 +46,35 @@ public class Mp4vAviTrack extends AviTrack {
}
}
}
}
private
void
seekLayerStart
(
ExtractorInput
input
)
throws
IOException
{
@VisibleForTesting
byte
[]
peek
=
new
byte
[
128
];
@Nullable
input
.
peekFully
(
peek
,
0
,
peek
.
length
);
static
ParsableNalUnitBitArray
findLayerStart
(
ExtractorInput
input
,
final
int
peekSize
)
throws
IOException
{
byte
[]
peek
=
new
byte
[
peekSize
];
input
.
peekFully
(
peek
,
0
,
peekSize
);
for
(
int
i
=
4
;
i
<
peek
.
length
-
4
;
i
++)
{
for
(
int
i
=
4
;
i
<
peek
.
length
-
4
;
i
++)
{
if
(
peek
[
i
]
==
0
&&
peek
[
i
+
1
]
==
0
&&
peek
[
i
+
2
]
==
1
&&
(
peek
[
i
+
3
]
&
0xf0
)
==
LAYER_START_CODE
)
{
if
(
peek
[
i
]
==
0
&&
peek
[
i
+
1
]
==
0
&&
peek
[
i
+
2
]
==
1
&&
(
peek
[
i
+
3
]
&
0xf0
)
==
LAYER_START_CODE
)
{
processLayerStart
(
peek
,
i
+
4
);
return
new
ParsableNalUnitBitArray
(
peek
,
i
+
4
,
peek
.
length
);
break
;
}
}
}
}
return
null
;
}
}
@
Override
@
VisibleForTesting
public
boolean
newChunk
(
int
tag
,
int
size
,
ExtractorInput
input
)
throws
IOException
{
static
boolean
isSequenceStart
(
ExtractorInput
input
)
throws
IOException
{
final
byte
[]
peek
=
new
byte
[
4
];
final
byte
[]
peek
=
new
byte
[
4
];
input
.
peekFully
(
peek
,
0
,
peek
.
length
);
input
.
peekFully
(
peek
,
0
,
peek
.
length
);
if
(
peek
[
0
]
==
0
&&
peek
[
1
]
==
0
&&
peek
[
2
]
==
1
&&
peek
[
3
]
==
SEQUENCE_START_CODE
)
{
return
peek
[
0
]
==
0
&&
peek
[
1
]
==
0
&&
peek
[
2
]
==
1
&&
peek
[
3
]
==
SEQUENCE_START_CODE
;
seekLayerStart
(
input
);
}
@Override
public
boolean
newChunk
(
int
tag
,
int
size
,
ExtractorInput
input
)
throws
IOException
{
if
(
isSequenceStart
(
input
))
{
// -4 because isSequenceStart peeks 4
final
ParsableNalUnitBitArray
layerStart
=
findLayerStart
(
input
,
Math
.
min
(
size
-
4
,
128
));
if
(
layerStart
!=
null
)
{
processLayerStart
(
layerStart
);
}
}
}
return
super
.
newChunk
(
tag
,
size
,
input
);
return
super
.
newChunk
(
tag
,
size
,
input
);
}
}
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBox.java
View file @
c4cf876d
...
@@ -11,10 +11,12 @@ public class StreamHeaderBox extends ResidentBox {
...
@@ -11,10 +11,12 @@ public class StreamHeaderBox extends ResidentBox {
public
static
final
int
STRH
=
's'
|
(
't'
<<
8
)
|
(
'r'
<<
16
)
|
(
'h'
<<
24
);
public
static
final
int
STRH
=
's'
|
(
't'
<<
8
)
|
(
'r'
<<
16
)
|
(
'h'
<<
24
);
//Audio Stream
//Audio Stream
private
static
final
int
AUDS
=
'a'
|
(
'u'
<<
8
)
|
(
'd'
<<
16
)
|
(
's'
<<
24
);
static
final
int
AUDS
=
'a'
|
(
'u'
<<
8
)
|
(
'd'
<<
16
)
|
(
's'
<<
24
);
//Videos Stream
//Videos Stream
private
static
final
int
VIDS
=
'v'
|
(
'i'
<<
8
)
|
(
'd'
<<
16
)
|
(
's'
<<
24
);
static
final
int
VIDS
=
'v'
|
(
'i'
<<
8
)
|
(
'd'
<<
16
)
|
(
's'
<<
24
);
static
final
int
XVID
=
'X'
|
(
'V'
<<
8
)
|
(
'I'
<<
16
)
|
(
'D'
<<
24
);
private
static
final
SparseArray
<
String
>
STREAM_MAP
=
new
SparseArray
<>();
private
static
final
SparseArray
<
String
>
STREAM_MAP
=
new
SparseArray
<>();
...
@@ -30,7 +32,7 @@ public class StreamHeaderBox extends ResidentBox {
...
@@ -30,7 +32,7 @@ public class StreamHeaderBox extends ResidentBox {
STREAM_MAP
.
put
(
'A'
|
(
'V'
<<
8
)
|
(
'C'
<<
16
)
|
(
'1'
<<
24
),
MimeTypes
.
VIDEO_H264
);
STREAM_MAP
.
put
(
'A'
|
(
'V'
<<
8
)
|
(
'C'
<<
16
)
|
(
'1'
<<
24
),
MimeTypes
.
VIDEO_H264
);
STREAM_MAP
.
put
(
'3'
|
(
'V'
<<
8
)
|
(
'I'
<<
16
)
|
(
'D'
<<
24
),
mimeType
);
STREAM_MAP
.
put
(
'3'
|
(
'V'
<<
8
)
|
(
'I'
<<
16
)
|
(
'D'
<<
24
),
mimeType
);
STREAM_MAP
.
put
(
'x'
|
(
'v'
<<
8
)
|
(
'i'
<<
16
)
|
(
'd'
<<
24
),
mimeType
);
STREAM_MAP
.
put
(
'x'
|
(
'v'
<<
8
)
|
(
'i'
<<
16
)
|
(
'd'
<<
24
),
mimeType
);
STREAM_MAP
.
put
(
'X'
|
(
'V'
<<
8
)
|
(
'I'
<<
16
)
|
(
'D'
<<
24
)
,
mimeType
);
STREAM_MAP
.
put
(
XVID
,
mimeType
);
STREAM_MAP
.
put
(
'D'
|
(
'X'
<<
8
)
|
(
'5'
<<
16
)
|
(
'0'
<<
24
),
mimeType
);
STREAM_MAP
.
put
(
'D'
|
(
'X'
<<
8
)
|
(
'5'
<<
16
)
|
(
'0'
<<
24
),
mimeType
);
STREAM_MAP
.
put
(
'm'
|
(
'j'
<<
8
)
|
(
'p'
<<
16
)
|
(
'g'
<<
24
),
MimeTypes
.
VIDEO_JPEG
);
STREAM_MAP
.
put
(
'm'
|
(
'j'
<<
8
)
|
(
'p'
<<
16
)
|
(
'g'
<<
24
),
MimeTypes
.
VIDEO_JPEG
);
...
@@ -86,15 +88,17 @@ public class StreamHeaderBox extends ResidentBox {
...
@@ -86,15 +88,17 @@ public class StreamHeaderBox extends ResidentBox {
public
int
getRate
()
{
public
int
getRate
()
{
return
byteBuffer
.
getInt
(
24
);
return
byteBuffer
.
getInt
(
24
);
}
}
public
int
getStart
()
{
// 28 - dwStart
return
byteBuffer
.
getInt
(
28
);
// public int getStart() {
}
// return byteBuffer.getInt(28);
// }
public
long
getLength
()
{
public
long
getLength
()
{
return
byteBuffer
.
getInt
(
32
)
&
AviExtractor
.
UINT_MASK
;
return
byteBuffer
.
getInt
(
32
)
&
AviExtractor
.
UINT_MASK
;
}
}
//36 - dwSuggestedBufferSize
//36 - dwSuggestedBufferSize
//40 - dwQuality
//40 - dwQuality
public
int
getSampleSize
()
{
//44 - dwSampleSize
return
byteBuffer
.
getInt
(
44
);
// public int getSampleSize() {
}
// return byteBuffer.getInt(44);
// }
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/DataHelper.java
0 → 100644
View file @
c4cf876d
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
public
class
DataHelper
{
//Base path "\ExoPlayer\library\extractor\."
private
static
final
File
RELATIVE_PATH
=
new
File
(
"../../testdata/src/test/assets/extractordumps/avi/"
);
public
static
FakeExtractorInput
getInput
(
final
String
fileName
)
throws
IOException
{
return
new
FakeExtractorInput
.
Builder
().
setData
(
getBytes
(
fileName
)).
build
();
}
public
static
byte
[]
getBytes
(
final
String
fileName
)
throws
IOException
{
final
File
file
=
new
File
(
RELATIVE_PATH
,
fileName
);
try
(
FileInputStream
in
=
new
FileInputStream
(
file
))
{
final
byte
[]
buffer
=
new
byte
[
in
.
available
()];
in
.
read
(
buffer
);
return
buffer
;
}
}
public
static
StreamHeaderBox
getVidsStreamHeader
()
throws
IOException
{
final
byte
[]
buffer
=
getBytes
(
"vids_stream_header.dump"
);
final
ByteBuffer
byteBuffer
=
ByteBuffer
.
wrap
(
buffer
);
byteBuffer
.
order
(
ByteOrder
.
LITTLE_ENDIAN
);
return
new
StreamHeaderBox
(
StreamHeaderBox
.
STRH
,
buffer
.
length
,
byteBuffer
);
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/Mp4vAviTrackTest.java
0 → 100644
View file @
c4cf876d
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
com.google.android.exoplayer2.util.ParsableNalUnitBitArray
;
import
java.io.IOException
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
@RunWith
(
AndroidJUnit4
.
class
)
public
class
Mp4vAviTrackTest
{
@Test
public
void
isSequenceStart_givenSequence
()
throws
IOException
{
final
FakeExtractorInput
input
=
DataHelper
.
getInput
(
"mp4v_sequence.dump"
);
Assert
.
assertTrue
(
Mp4vAviTrack
.
isSequenceStart
(
input
));
}
@Test
public
void
findLayerStart_givenSequence
()
throws
IOException
{
final
FakeExtractorInput
input
=
DataHelper
.
getInput
(
"mp4v_sequence.dump"
);
final
ParsableNalUnitBitArray
bitArray
=
Mp4vAviTrack
.
findLayerStart
(
input
,
(
int
)
input
.
getLength
());
//Offset 0x12
Assert
.
assertEquals
(
8
,
bitArray
.
readBits
(
8
));
}
@Test
public
void
findLayerStart_givenAllZeros
()
throws
IOException
{
final
FakeExtractorInput
fakeExtractorInput
=
new
FakeExtractorInput
.
Builder
().
setData
(
new
byte
[
128
]).
build
();
Assert
.
assertNull
(
Mp4vAviTrack
.
findLayerStart
(
fakeExtractorInput
,
128
));
}
@Test
public
void
pixelWidthHeightRatio_givenSequence
()
throws
IOException
{
final
FakeTrackOutput
fakeTrackOutput
=
new
FakeTrackOutput
(
false
);
final
Format
.
Builder
formatBuilder
=
new
Format
.
Builder
();
final
Mp4vAviTrack
mp4vAviTrack
=
new
Mp4vAviTrack
(
0
,
DataHelper
.
getVidsStreamHeader
(),
fakeTrackOutput
,
formatBuilder
);
final
FakeExtractorInput
input
=
DataHelper
.
getInput
(
"mp4v_sequence.dump"
);
mp4vAviTrack
.
newChunk
(
0
,
(
int
)
input
.
getLength
(),
input
);
// final ParsableNalUnitBitArray bitArray = Mp4vAviTrack.findLayerStart(input,
// (int)input.getLength());
// mp4vAviTrack.processLayerStart(bitArray);
Assert
.
assertEquals
(
mp4vAviTrack
.
pixelWidthHeightRatio
,
1.2121212
,
0.01
);
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/StreamHeaderBoxTest.java
0 → 100644
View file @
c4cf876d
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
java.io.IOException
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
@RunWith
(
AndroidJUnit4
.
class
)
public
class
StreamHeaderBoxTest
{
private
static
float
FPS24
=
24000
f
/
1001
f
;
private
static
final
long
US_SAMPLE24FPS
=
(
long
)(
1_000_000L
/
FPS24
);
@Test
public
void
getters_givenXvidStreamHeader
()
throws
IOException
{
final
StreamHeaderBox
streamHeaderBox
=
DataHelper
.
getVidsStreamHeader
();
Assert
.
assertTrue
(
streamHeaderBox
.
isVideo
());
Assert
.
assertFalse
(
streamHeaderBox
.
isAudio
());
Assert
.
assertEquals
(
StreamHeaderBox
.
VIDS
,
streamHeaderBox
.
getSteamType
());
Assert
.
assertEquals
(
StreamHeaderBox
.
XVID
,
streamHeaderBox
.
getFourCC
());
Assert
.
assertEquals
(
0
,
streamHeaderBox
.
getInitialFrames
());
Assert
.
assertEquals
(
FPS24
,
streamHeaderBox
.
getFrameRate
(),
0.1
);
Assert
.
assertEquals
(
US_SAMPLE24FPS
,
streamHeaderBox
.
getUsPerSample
());
Assert
.
assertEquals
(
MimeTypes
.
VIDEO_MP4V
,
streamHeaderBox
.
getMimeType
());
Assert
.
assertEquals
(
11805L
,
streamHeaderBox
.
getLength
());
}
}
testdata/src/test/assets/extractordumps/avi/mp4v_sequence.dump
0 → 100644
View file @
c4cf876d
No preview for this file type
testdata/src/test/assets/extractordumps/avi/vids_stream_header.dump
0 → 100644
View file @
c4cf876d
No preview for this file type
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