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
3a9f1f9a
authored
Feb 05, 2022
by
Dustin
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Improved comments, improved naming consistency.
parent
14c842e5
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
147 additions
and
124 deletions
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AvcChunkHandler.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/ChunkHandler.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/Mp4vChunkHandler.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/Mp3ChunkHandler.java → library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/MpegAudioChunkHandler.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/NalChunkPeeker.java → library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/NalChunkHandler.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/ResidentBox.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/StreamNameBox.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AvcChunkPeekerTest.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/ChunkHandlerTest.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/MockNalChunkPeeker.java → library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/MockNalChunkHandler.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/NalChunkPeekerTest.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AvcChunkHandler.java
View file @
3a9f1f9a
...
@@ -29,7 +29,7 @@ import java.io.IOException;
...
@@ -29,7 +29,7 @@ import java.io.IOException;
* Corrects the time and PAR for H264 streams
* Corrects the time and PAR for H264 streams
* AVC is very rare in AVI due to the rise of the mp4 container
* AVC is very rare in AVI due to the rise of the mp4 container
*/
*/
public
class
AvcChunkHandler
extends
NalChunk
Peek
er
{
public
class
AvcChunkHandler
extends
NalChunk
Handl
er
{
private
static
final
int
NAL_TYPE_MASK
=
0x1f
;
private
static
final
int
NAL_TYPE_MASK
=
0x1f
;
private
static
final
int
NAL_TYPE_IDR
=
5
;
//I Frame
private
static
final
int
NAL_TYPE_IDR
=
5
;
//I Frame
private
static
final
int
NAL_TYPE_SEI
=
6
;
private
static
final
int
NAL_TYPE_SEI
=
6
;
...
@@ -63,7 +63,7 @@ public class AvcChunkHandler extends NalChunkPeeker {
...
@@ -63,7 +63,7 @@ public class AvcChunkHandler extends NalChunkPeeker {
if
(
clock
instanceof
PicCountClock
)
{
if
(
clock
instanceof
PicCountClock
)
{
return
false
;
return
false
;
}
else
{
}
else
{
//If the clock is
regular c
lock, skip "normal" frames
//If the clock is
ChunkC
lock, skip "normal" frames
return
nalType
>=
0
&&
nalType
<=
NAL_TYPE_IDR
;
return
nalType
>=
0
&&
nalType
<=
NAL_TYPE_IDR
;
}
}
}
}
...
@@ -107,10 +107,12 @@ public class AvcChunkHandler extends NalChunkPeeker {
...
@@ -107,10 +107,12 @@ public class AvcChunkHandler extends NalChunkPeeker {
final
int
spsStart
=
nalTypeOffset
+
1
;
final
int
spsStart
=
nalTypeOffset
+
1
;
nalTypeOffset
=
seekNextNal
(
input
,
spsStart
);
nalTypeOffset
=
seekNextNal
(
input
,
spsStart
);
spsData
=
NalUnitUtil
.
parseSpsNalUnitPayload
(
buffer
,
spsStart
,
pos
);
spsData
=
NalUnitUtil
.
parseSpsNalUnitPayload
(
buffer
,
spsStart
,
pos
);
//If we have B Frames, upgrade to PicCountClock
//If we
can
have B Frames, upgrade to PicCountClock
final
PicCountClock
picCountClock
;
final
PicCountClock
picCountClock
;
if
(
spsData
.
maxNumRefFrames
>
1
&&
!(
clock
instanceof
PicCountClock
))
{
if
(
spsData
.
maxNumRefFrames
>
1
&&
!(
clock
instanceof
PicCountClock
))
{
clock
=
picCountClock
=
new
PicCountClock
(
clock
.
durationUs
,
clock
.
chunks
);
picCountClock
=
new
PicCountClock
(
clock
.
durationUs
,
clock
.
chunks
);
picCountClock
.
setIndex
(
clock
.
getIndex
());
clock
=
picCountClock
;
}
else
{
}
else
{
picCountClock
=
getPicCountClock
();
picCountClock
=
getPicCountClock
();
}
}
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java
View file @
3a9f1f9a
...
@@ -291,7 +291,7 @@ public class AviExtractor implements Extractor {
...
@@ -291,7 +291,7 @@ public class AviExtractor implements Extractor {
}
}
trackOutput
.
format
(
builder
.
build
());
trackOutput
.
format
(
builder
.
build
());
if
(
MimeTypes
.
AUDIO_MPEG
.
equals
(
mimeType
))
{
if
(
MimeTypes
.
AUDIO_MPEG
.
equals
(
mimeType
))
{
chunkHandler
=
new
Mp
3
ChunkHandler
(
streamId
,
trackOutput
,
clock
,
chunkHandler
=
new
Mp
egAudio
ChunkHandler
(
streamId
,
trackOutput
,
clock
,
audioFormat
.
getSamplesPerSecond
());
audioFormat
.
getSamplesPerSecond
());
}
else
{
}
else
{
chunkHandler
=
new
ChunkHandler
(
streamId
,
ChunkHandler
.
TYPE_AUDIO
,
chunkHandler
=
new
ChunkHandler
(
streamId
,
ChunkHandler
.
TYPE_AUDIO
,
...
@@ -367,7 +367,7 @@ public class AviExtractor implements Extractor {
...
@@ -367,7 +367,7 @@ public class AviExtractor implements Extractor {
}
}
void
fixTimings
(
final
int
[]
keyFrameCounts
,
final
long
videoDuration
)
{
void
fixTimings
(
final
int
[]
keyFrameCounts
,
final
long
videoDuration
)
{
for
(
final
ChunkHandler
chunkHandler
:
chunkHandlers
)
{
for
(
@Nullable
final
ChunkHandler
chunkHandler
:
chunkHandlers
)
{
if
(
chunkHandler
!=
null
)
{
if
(
chunkHandler
!=
null
)
{
if
(
chunkHandler
.
isAudio
())
{
if
(
chunkHandler
.
isAudio
())
{
final
long
durationUs
=
chunkHandler
.
getClock
().
durationUs
;
final
long
durationUs
=
chunkHandler
.
getClock
().
durationUs
;
...
@@ -452,7 +452,7 @@ public class AviExtractor implements Extractor {
...
@@ -452,7 +452,7 @@ public class AviExtractor implements Extractor {
int
indexSize
=
seekIndexes
[
videoId
].
getSize
();
int
indexSize
=
seekIndexes
[
videoId
].
getSize
();
if
(
indexSize
==
0
||
chunkHandler
.
chunks
-
seekIndexes
[
videoId
].
get
(
indexSize
-
1
)
>=
chunksPerKeyFrame
)
{
if
(
indexSize
==
0
||
chunkHandler
.
chunks
-
seekIndexes
[
videoId
].
get
(
indexSize
-
1
)
>=
chunksPerKeyFrame
)
{
keyFrameOffsetsDiv2
.
add
(
offset
/
2
);
keyFrameOffsetsDiv2
.
add
(
offset
/
2
);
for
(
ChunkHandler
seekTrack
:
chunkHandlers
)
{
for
(
@Nullable
ChunkHandler
seekTrack
:
chunkHandlers
)
{
if
(
seekTrack
!=
null
)
{
if
(
seekTrack
!=
null
)
{
seekIndexes
[
seekTrack
.
getId
()].
add
(
seekTrack
.
chunks
);
seekIndexes
[
seekTrack
.
getId
()].
add
(
seekTrack
.
chunks
);
}
}
...
@@ -487,7 +487,7 @@ public class AviExtractor implements Extractor {
...
@@ -487,7 +487,7 @@ public class AviExtractor implements Extractor {
@Nullable
@Nullable
@VisibleForTesting
@VisibleForTesting
ChunkHandler
getChunkHandler
(
int
chunkId
)
{
ChunkHandler
getChunkHandler
(
int
chunkId
)
{
for
(
ChunkHandler
chunkHandler
:
chunkHandlers
)
{
for
(
@Nullable
ChunkHandler
chunkHandler
:
chunkHandlers
)
{
if
(
chunkHandler
!=
null
&&
chunkHandler
.
handlesChunkId
(
chunkId
))
{
if
(
chunkHandler
!=
null
&&
chunkHandler
.
handlesChunkId
(
chunkId
))
{
return
chunkHandler
;
return
chunkHandler
;
}
}
...
@@ -536,7 +536,7 @@ public class AviExtractor implements Extractor {
...
@@ -536,7 +536,7 @@ public class AviExtractor implements Extractor {
+
" size="
+
size
+
" moviEnd="
+
moviEnd
);
+
" size="
+
size
+
" moviEnd="
+
moviEnd
);
return
RESULT_CONTINUE
;
return
RESULT_CONTINUE
;
}
}
if
(
chunkHandler
.
newChunk
(
chunkId
,
size
,
input
))
{
if
(
chunkHandler
.
newChunk
(
size
,
input
))
{
alignInput
(
input
);
alignInput
(
input
);
}
else
{
}
else
{
this
.
chunkHandler
=
chunkHandler
;
this
.
chunkHandler
=
chunkHandler
;
...
@@ -587,20 +587,20 @@ public class AviExtractor implements Extractor {
...
@@ -587,20 +587,20 @@ public class AviExtractor implements Extractor {
chunkHandler
=
null
;
chunkHandler
=
null
;
if
(
position
<=
0
)
{
if
(
position
<=
0
)
{
if
(
moviOffset
!=
0
)
{
if
(
moviOffset
!=
0
)
{
resetClocks
(
);
setIndexes
(
new
int
[
chunkHandlers
.
length
]
);
state
=
STATE_SEEK_START
;
state
=
STATE_SEEK_START
;
}
}
}
else
{
}
else
{
if
(
aviSeekMap
!=
null
)
{
if
(
aviSeekMap
!=
null
)
{
aviSeekMap
.
setFrames
(
position
,
timeUs
,
chunkHandlers
);
setIndexes
(
aviSeekMap
.
getIndexes
(
position
)
);
}
}
}
}
}
}
void
resetClocks
(
)
{
private
void
setIndexes
(
@NonNull
int
[]
indexes
)
{
for
(
@Nullable
ChunkHandler
chunkHandler
:
chunkHandlers
)
{
for
(
@Nullable
ChunkHandler
chunkHandler
:
chunkHandlers
)
{
if
(
chunkHandler
!=
null
)
{
if
(
chunkHandler
!=
null
)
{
chunkHandler
.
getClock
().
setIndex
(
0
);
chunkHandler
.
setIndex
(
indexes
[
chunkHandler
.
getId
()]
);
}
}
}
}
}
}
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviSeekMap.java
View file @
3a9f1f9a
...
@@ -99,18 +99,23 @@ public class AviSeekMap implements SeekMap {
...
@@ -99,18 +99,23 @@ public class AviSeekMap implements SeekMap {
//Log.d(AviExtractor.TAG, "SeekPoint: us=" + outUs + " pos=" + position);
//Log.d(AviExtractor.TAG, "SeekPoint: us=" + outUs + " pos=" + position);
}
}
public
void
setFrames
(
final
long
position
,
final
long
timeUs
,
final
ChunkHandler
[]
chunkHandlers
)
{
/**
* Get the ChunkClock indexes by stream id
* @param position seek position in the file
*/
@NonNull
public
int
[]
getIndexes
(
final
long
position
)
{
final
int
index
=
Arrays
.
binarySearch
(
keyFrameOffsetsDiv2
,
(
int
)((
position
-
seekOffset
)
/
2
));
final
int
index
=
Arrays
.
binarySearch
(
keyFrameOffsetsDiv2
,
(
int
)((
position
-
seekOffset
)
/
2
));
if
(
index
<
0
)
{
if
(
index
<
0
)
{
throw
new
IllegalArgumentException
(
"Position: "
+
position
);
throw
new
IllegalArgumentException
(
"Position: "
+
position
);
}
}
for
(
int
i
=
0
;
i
<
chunkHandlers
.
length
;
i
++)
{
final
int
[]
indexes
=
new
int
[
seekIndexes
.
length
];
final
ChunkHandler
chunkHandler
=
chunkHandlers
[
i
];
for
(
int
i
=
0
;
i
<
indexes
.
length
;
i
++)
{
if
(
chunkHandler
!=
null
)
{
if
(
seekIndexes
[
i
].
length
>
index
)
{
// Log.d(AviExtractor.TAG, "Frame: " + (chunkHandler.isVideo()? 'V' : 'A') + " us=" + clock.getUs() + " frame=" + clock.getIndex() + " key=" + chunkHandler.isKeyFrame());
indexes
[
i
]
=
seekIndexes
[
i
][
index
];
chunkHandler
.
setIndex
(
seekIndexes
[
i
][
index
]);
}
}
}
}
return
indexes
;
}
}
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/ChunkHandler.java
View file @
3a9f1f9a
...
@@ -25,11 +25,16 @@ import java.io.IOException;
...
@@ -25,11 +25,16 @@ import java.io.IOException;
import
java.util.Arrays
;
import
java.util.Arrays
;
/**
/**
*
Collection of info about a track
.
*
Handles chunk data from a given stream
.
* This acts a bridge between AVI and ExoPlayer
structures
* This acts a bridge between AVI and ExoPlayer
*/
*/
public
class
ChunkHandler
{
public
class
ChunkHandler
{
/**
* Constant meaning all frames are considered key frames
*/
public
static
final
int
[]
ALL_KEY_FRAMES
=
new
int
[
0
];
public
static
final
int
[]
ALL_KEY_FRAMES
=
new
int
[
0
];
public
static
int
TYPE_VIDEO
=
(
'd'
<<
16
)
|
(
'c'
<<
24
);
public
static
int
TYPE_VIDEO
=
(
'd'
<<
16
)
|
(
'c'
<<
24
);
public
static
int
TYPE_AUDIO
=
(
'w'
<<
16
)
|
(
'b'
<<
24
);
public
static
int
TYPE_AUDIO
=
(
'w'
<<
16
)
|
(
'b'
<<
24
);
...
@@ -39,10 +44,24 @@ public class ChunkHandler {
...
@@ -39,10 +44,24 @@ public class ChunkHandler {
@NonNull
@NonNull
final
TrackOutput
trackOutput
;
final
TrackOutput
trackOutput
;
/**
* The chunk id as it appears in the index and the movi
*/
final
int
chunkId
;
final
int
chunkId
;
/**
* Secondary chunk id. Bad muxers sometimes use uncompressed for key frames
*/
final
int
chunkIdAlt
;
final
int
chunkIdAlt
;
/**
* Number of chunks as calculated by the index
*/
int
chunks
;
int
chunks
;
/**
* Size total size of the stream in bytes calculated by the index
*/
int
size
;
int
size
;
/**
/**
...
@@ -50,9 +69,18 @@ public class ChunkHandler {
...
@@ -50,9 +69,18 @@ public class ChunkHandler {
*/
*/
int
[]
keyFrames
=
new
int
[
0
];
int
[]
keyFrames
=
new
int
[
0
];
/**
* Size of the current chunk in bytes
*/
transient
int
chunkSize
;
transient
int
chunkSize
;
/**
* Bytes remaining in the chunk to be processed
*/
transient
int
chunkRemaining
;
transient
int
chunkRemaining
;
/**
* Get stream id in ASCII
*/
@VisibleForTesting
@VisibleForTesting
static
int
getChunkIdLower
(
int
id
)
{
static
int
getChunkIdLower
(
int
id
)
{
int
tens
=
id
/
10
;
int
tens
=
id
/
10
;
...
@@ -71,6 +99,10 @@ public class ChunkHandler {
...
@@ -71,6 +99,10 @@ public class ChunkHandler {
}
}
}
}
/**
*
* @return true if this can handle the chunkId
*/
public
boolean
handlesChunkId
(
int
chunkId
)
{
public
boolean
handlesChunkId
(
int
chunkId
)
{
return
this
.
chunkId
==
chunkId
||
chunkIdAlt
==
chunkId
;
return
this
.
chunkId
==
chunkId
||
chunkIdAlt
==
chunkId
;
}
}
...
@@ -80,13 +112,9 @@ public class ChunkHandler {
...
@@ -80,13 +112,9 @@ public class ChunkHandler {
return
clock
;
return
clock
;
}
}
public
void
setClock
(
@NonNull
ChunkClock
clock
)
{
this
.
clock
=
clock
;
}
/**
/**
*
*
Sets the list of key frames
* @param keyFrames
null means all key frames
* @param keyFrames
list of frame indexes or {@link #ALL_KEY_FRAMES}
*/
*/
void
setKeyFrames
(
@NonNull
final
int
[]
keyFrames
)
{
void
setKeyFrames
(
@NonNull
final
int
[]
keyFrames
)
{
this
.
keyFrames
=
keyFrames
;
this
.
keyFrames
=
keyFrames
;
...
@@ -104,23 +132,27 @@ public class ChunkHandler {
...
@@ -104,23 +132,27 @@ public class ChunkHandler {
return
(
chunkId
&
TYPE_AUDIO
)
==
TYPE_AUDIO
;
return
(
chunkId
&
TYPE_AUDIO
)
==
TYPE_AUDIO
;
}
}
public
boolean
newChunk
(
int
tag
,
int
size
,
ExtractorInput
input
)
throws
IOException
{
/**
final
int
remaining
=
size
-
trackOutput
.
sampleData
(
input
,
size
,
false
);
* Process a new chunk
if
(
remaining
==
0
)
{
* @param size total size of the chunk
* @return True if the chunk has been completely processed. False implies {@link #resume}
* will be called
*/
public
boolean
newChunk
(
int
size
,
@NonNull
ExtractorInput
input
)
throws
IOException
{
final
int
sampled
=
trackOutput
.
sampleData
(
input
,
size
,
false
);
if
(
sampled
==
size
)
{
done
(
size
);
done
(
size
);
return
true
;
return
true
;
}
else
{
}
else
{
chunkSize
=
size
;
chunkSize
=
size
;
chunkRemaining
=
remaining
;
chunkRemaining
=
size
-
sampled
;
return
false
;
return
false
;
}
}
}
}
/**
/**
* Resume a partial read of a chunk
* Resume a partial read of a chunk
* @param input
* May be called multiple times
* @return
* @throws IOException
*/
*/
boolean
resume
(
ExtractorInput
input
)
throws
IOException
{
boolean
resume
(
ExtractorInput
input
)
throws
IOException
{
chunkRemaining
-=
trackOutput
.
sampleData
(
input
,
chunkRemaining
,
false
);
chunkRemaining
-=
trackOutput
.
sampleData
(
input
,
chunkRemaining
,
false
);
...
@@ -133,25 +165,29 @@ public class ChunkHandler {
...
@@ -133,25 +165,29 @@ public class ChunkHandler {
}
}
/**
/**
* Done reading a chunk
* Done reading a chunk
. Send the timing info and advance the clock
* @param size
* @param size
the amount of data passed to the trackOutput
*/
*/
void
done
(
final
int
size
)
{
void
done
(
final
int
size
)
{
if
(
size
>
0
)
{
if
(
size
>
0
)
{
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
);
}
}
final
ChunkClock
clock
=
getClock
();
//Log.d(AviExtractor.TAG, "Frame: " + (isVideo()? 'V' : 'A') + " us=" + clock.getUs() + " size=" + size + " frame=" + clock.getIndex() + " key=" + isKeyFrame());
//Log.d(AviExtractor.TAG, "Frame: " + (isVideo()? 'V' : 'A') + " us=" + clock.getUs() + " size=" + size + " frame=" + clock.getIndex() + " key=" + isKeyFrame());
clock
.
advance
();
clock
.
advance
();
}
}
/**
* Gets the streamId.
* @return The unique stream id for this file
*/
public
int
getId
()
{
public
int
getId
()
{
return
((
chunkId
>>
8
)
&
0xf
)
+
(
chunkId
&
0xf
)
*
10
;
return
((
chunkId
>>
8
)
&
0xf
)
+
(
chunkId
&
0xf
)
*
10
;
}
}
/**
/**
* A seek occurred
* A seek occurred
* @param index of the chunk
*/
*/
public
void
setIndex
(
int
index
)
{
public
void
setIndex
(
int
index
)
{
getClock
().
setIndex
(
index
);
getClock
().
setIndex
(
index
);
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/Mp4vChunkHandler.java
View file @
3a9f1f9a
...
@@ -26,7 +26,7 @@ import java.io.IOException;
...
@@ -26,7 +26,7 @@ import java.io.IOException;
/**
/**
* Peeks an MP4V stream looking for pixelWidthHeightRatio data
* Peeks an MP4V stream looking for pixelWidthHeightRatio data
*/
*/
public
class
Mp4vChunkHandler
extends
NalChunk
Peek
er
{
public
class
Mp4vChunkHandler
extends
NalChunk
Handl
er
{
@VisibleForTesting
@VisibleForTesting
static
final
byte
SEQUENCE_START_CODE
=
(
byte
)
0xb0
;
static
final
byte
SEQUENCE_START_CODE
=
(
byte
)
0xb0
;
@VisibleForTesting
@VisibleForTesting
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/Mp
3
ChunkHandler.java
→
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/Mp
egAudio
ChunkHandler.java
View file @
3a9f1f9a
...
@@ -16,37 +16,45 @@
...
@@ -16,37 +16,45 @@
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.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.audio.MpegAudioUtil
;
import
com.google.android.exoplayer2.audio.MpegAudioUtil
;
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
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
java.io.IOException
;
import
java.io.IOException
;
public
class
Mp3ChunkHandler
extends
ChunkHandler
{
/**
* Resolves several issues with Mpeg Audio
* 1. That muxers don't always mux MPEG audio on the frame boundary
* 2. That some codecs can't handle multiple or partial frames (Pixels)
*/
public
class
MpegAudioChunkHandler
extends
ChunkHandler
{
private
final
MpegAudioUtil
.
Header
header
=
new
MpegAudioUtil
.
Header
();
private
final
MpegAudioUtil
.
Header
header
=
new
MpegAudioUtil
.
Header
();
private
final
ParsableByteArray
scratch
=
new
ParsableByteArray
(
0
);
private
final
ParsableByteArray
scratch
=
new
ParsableByteArray
(
8
);
private
final
int
fps
;
private
final
int
samplesPerSecond
;
//Bytes remaining in the Mpeg Audio frame
private
int
frameRemaining
;
private
int
frameRemaining
;
private
long
u
s
=
0L
;
private
long
timeU
s
=
0L
;
Mp3ChunkHandler
(
int
id
,
@NonNull
TrackOutput
trackOutput
,
@NonNull
ChunkClock
clock
,
int
fps
)
{
MpegAudioChunkHandler
(
int
id
,
@NonNull
TrackOutput
trackOutput
,
@NonNull
ChunkClock
clock
,
int
samplesPerSecond
)
{
super
(
id
,
TYPE_AUDIO
,
trackOutput
,
clock
);
super
(
id
,
TYPE_AUDIO
,
trackOutput
,
clock
);
this
.
fps
=
fps
;
this
.
samplesPerSecond
=
samplesPerSecond
;
}
}
@Override
@Override
public
boolean
newChunk
(
int
tag
,
int
size
,
ExtractorInput
input
)
throws
IOException
{
public
boolean
newChunk
(
int
size
,
@NonNull
ExtractorInput
input
)
throws
IOException
{
if
(
size
==
0
)
{
if
(
size
==
0
)
{
//Empty frame, advance the clock and sync
clock
.
advance
();
clock
.
advance
();
syncUs
();
syncTime
();
//Log.d(AviExtractor.TAG, "Blank Frame: us=" + us);
return
true
;
return
true
;
}
}
chunkRemaining
=
size
;
chunkRemaining
=
size
;
if
(
process
(
input
))
{
if
(
process
(
input
))
{
//If we scratch is the entire buffer, we didn't find a MP3 header, so just dump the chunk
// Fail Over: If the scratch is the entire chunk, we didn't find a MP3 header.
// Dump the chunk as is and hope the decoder can handle it.
if
(
scratch
.
limit
()
==
size
)
{
if
(
scratch
.
limit
()
==
size
)
{
scratch
.
setPosition
(
0
);
scratch
.
setPosition
(
0
);
trackOutput
.
sampleData
(
scratch
,
size
);
trackOutput
.
sampleData
(
scratch
,
size
);
...
@@ -59,7 +67,7 @@ public class Mp3ChunkHandler extends ChunkHandler {
...
@@ -59,7 +67,7 @@ public class Mp3ChunkHandler extends ChunkHandler {
}
}
@Override
@Override
boolean
resume
(
ExtractorInput
input
)
throws
IOException
{
boolean
resume
(
@NonNull
ExtractorInput
input
)
throws
IOException
{
if
(
process
(
input
))
{
if
(
process
(
input
))
{
clock
.
advance
();
clock
.
advance
();
return
true
;
return
true
;
...
@@ -67,6 +75,11 @@ public class Mp3ChunkHandler extends ChunkHandler {
...
@@ -67,6 +75,11 @@ public class Mp3ChunkHandler extends ChunkHandler {
return
false
;
return
false
;
}
}
/**
* Read from input to scratch
* @param bytes to attempt to read
* @return {@link C#RESULT_END_OF_INPUT} or number of bytes read.
*/
int
readScratch
(
ExtractorInput
input
,
int
bytes
)
throws
IOException
{
int
readScratch
(
ExtractorInput
input
,
int
bytes
)
throws
IOException
{
final
int
toRead
=
Math
.
min
(
bytes
,
chunkRemaining
);
final
int
toRead
=
Math
.
min
(
bytes
,
chunkRemaining
);
final
int
read
=
input
.
read
(
scratch
.
getData
(),
scratch
.
limit
(),
toRead
);
final
int
read
=
input
.
read
(
scratch
.
getData
(),
scratch
.
limit
(),
toRead
);
...
@@ -78,7 +91,12 @@ public class Mp3ChunkHandler extends ChunkHandler {
...
@@ -78,7 +91,12 @@ public class Mp3ChunkHandler extends ChunkHandler {
return
read
;
return
read
;
}
}
private
boolean
findFrame
(
ExtractorInput
input
)
throws
IOException
{
/**
* Attempt to find a frame header in the input
* @return true if a frame header was found
*/
@VisibleForTesting
boolean
findFrame
(
ExtractorInput
input
)
throws
IOException
{
scratch
.
reset
(
0
);
scratch
.
reset
(
0
);
scratch
.
ensureCapacity
(
scratch
.
limit
()
+
chunkRemaining
);
scratch
.
ensureCapacity
(
scratch
.
limit
()
+
chunkRemaining
);
int
toRead
=
4
;
int
toRead
=
4
;
...
@@ -96,8 +114,14 @@ public class Mp3ChunkHandler extends ChunkHandler {
...
@@ -96,8 +114,14 @@ public class Mp3ChunkHandler extends ChunkHandler {
return
false
;
return
false
;
}
}
private
boolean
process
(
ExtractorInput
input
)
throws
IOException
{
/**
* Process the chunk by breaking it in Mpeg audio frames
* @return true if the chunk has been completely processed
*/
@VisibleForTesting
boolean
process
(
ExtractorInput
input
)
throws
IOException
{
if
(
frameRemaining
==
0
)
{
if
(
frameRemaining
==
0
)
{
//Find the next frame
if
(
findFrame
(
input
))
{
if
(
findFrame
(
input
))
{
final
int
scratchBytes
=
scratch
.
bytesLeft
();
final
int
scratchBytes
=
scratch
.
bytesLeft
();
trackOutput
.
sampleData
(
scratch
,
scratchBytes
);
trackOutput
.
sampleData
(
scratch
,
scratchBytes
);
...
@@ -107,14 +131,11 @@ public class Mp3ChunkHandler extends ChunkHandler {
...
@@ -107,14 +131,11 @@ public class Mp3ChunkHandler extends ChunkHandler {
}
}
}
}
final
int
bytes
=
trackOutput
.
sampleData
(
input
,
Math
.
min
(
frameRemaining
,
chunkRemaining
),
false
);
final
int
bytes
=
trackOutput
.
sampleData
(
input
,
Math
.
min
(
frameRemaining
,
chunkRemaining
),
false
);
if
(
bytes
==
C
.
RESULT_END_OF_INPUT
)
{
return
true
;
}
frameRemaining
-=
bytes
;
frameRemaining
-=
bytes
;
if
(
frameRemaining
==
0
)
{
if
(
frameRemaining
==
0
)
{
trackOutput
.
sampleMetadata
(
u
s
,
C
.
BUFFER_FLAG_KEY_FRAME
,
header
.
frameSize
,
0
,
null
);
trackOutput
.
sampleMetadata
(
timeU
s
,
C
.
BUFFER_FLAG_KEY_FRAME
,
header
.
frameSize
,
0
,
null
);
//Log.d(AviExtractor.TAG, "MP3: us=" + us);
//Log.d(AviExtractor.TAG, "MP3: us=" + us);
us
+=
header
.
samplesPerFrame
*
C
.
MICROS_PER_SECOND
/
fps
;
timeUs
+=
header
.
samplesPerFrame
*
C
.
MICROS_PER_SECOND
/
samplesPerSecond
;
}
}
chunkRemaining
-=
bytes
;
chunkRemaining
-=
bytes
;
return
chunkRemaining
==
0
;
return
chunkRemaining
==
0
;
...
@@ -123,11 +144,11 @@ public class Mp3ChunkHandler extends ChunkHandler {
...
@@ -123,11 +144,11 @@ public class Mp3ChunkHandler extends ChunkHandler {
@Override
@Override
public
void
setIndex
(
int
index
)
{
public
void
setIndex
(
int
index
)
{
super
.
setIndex
(
index
);
super
.
setIndex
(
index
);
sync
Us
();
sync
Time
();
}
}
private
void
sync
Us
()
{
private
void
sync
Time
()
{
u
s
=
clock
.
getUs
();
timeU
s
=
clock
.
getUs
();
frameRemaining
=
0
;
frameRemaining
=
0
;
}
}
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/NalChunk
Peek
er.java
→
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/NalChunk
Handl
er.java
View file @
3a9f1f9a
...
@@ -25,7 +25,7 @@ import java.util.Arrays;
...
@@ -25,7 +25,7 @@ import java.util.Arrays;
* Generic base class for NAL (0x00 0x00 0x01) chunk headers
* Generic base class for NAL (0x00 0x00 0x01) chunk headers
* Theses are used by AVC and MP4V (XVID)
* Theses are used by AVC and MP4V (XVID)
*/
*/
public
abstract
class
NalChunk
Peek
er
extends
ChunkHandler
{
public
abstract
class
NalChunk
Handl
er
extends
ChunkHandler
{
private
static
final
int
SEEK_PEEK_SIZE
=
256
;
private
static
final
int
SEEK_PEEK_SIZE
=
256
;
private
final
int
peekSize
;
private
final
int
peekSize
;
...
@@ -33,7 +33,7 @@ public abstract class NalChunkPeeker extends ChunkHandler {
...
@@ -33,7 +33,7 @@ public abstract class NalChunkPeeker extends ChunkHandler {
transient
byte
[]
buffer
;
transient
byte
[]
buffer
;
transient
int
pos
;
transient
int
pos
;
NalChunk
Peek
er
(
int
id
,
@NonNull
TrackOutput
trackOutput
,
NalChunk
Handl
er
(
int
id
,
@NonNull
TrackOutput
trackOutput
,
@NonNull
ChunkClock
clock
,
int
peakSize
)
{
@NonNull
ChunkClock
clock
,
int
peakSize
)
{
super
(
id
,
TYPE_VIDEO
,
trackOutput
,
clock
);
super
(
id
,
TYPE_VIDEO
,
trackOutput
,
clock
);
if
(
peakSize
<
5
)
{
if
(
peakSize
<
5
)
{
...
@@ -113,9 +113,9 @@ public abstract class NalChunkPeeker extends ChunkHandler {
...
@@ -113,9 +113,9 @@ public abstract class NalChunkPeeker extends ChunkHandler {
abstract
boolean
skip
(
byte
nalType
);
abstract
boolean
skip
(
byte
nalType
);
public
boolean
newChunk
(
int
tag
,
int
size
,
ExtractorInput
input
)
throws
IOException
{
public
boolean
newChunk
(
int
size
,
ExtractorInput
input
)
throws
IOException
{
peek
(
input
,
size
);
peek
(
input
,
size
);
return
super
.
newChunk
(
tag
,
size
,
input
);
return
super
.
newChunk
(
size
,
input
);
}
}
public
void
peek
(
ExtractorInput
input
,
final
int
size
)
throws
IOException
{
public
void
peek
(
ExtractorInput
input
,
final
int
size
)
throws
IOException
{
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/ResidentBox.java
View file @
3a9f1f9a
...
@@ -16,13 +16,6 @@
...
@@ -16,13 +16,6 @@
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
com.google.android.exoplayer2.extractor.ExtractorInput
;
import
com.google.android.exoplayer2.util.Log
;
import
java.io.IOException
;
import
java.lang.reflect.Constructor
;
import
java.nio.BufferOverflowException
;
import
java.nio.BufferUnderflowException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.nio.ByteOrder
;
...
@@ -39,7 +32,6 @@ public class ResidentBox extends Box {
...
@@ -39,7 +32,6 @@ public class ResidentBox extends Box {
/**
/**
* Returns shallow copy of this ByteBuffer with the position at 0
* Returns shallow copy of this ByteBuffer with the position at 0
* @return
*/
*/
@NonNull
@NonNull
public
ByteBuffer
getByteBuffer
()
{
public
ByteBuffer
getByteBuffer
()
{
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/StreamNameBox.java
View file @
3a9f1f9a
...
@@ -18,7 +18,7 @@ package com.google.android.exoplayer2.extractor.avi;
...
@@ -18,7 +18,7 @@ package com.google.android.exoplayer2.extractor.avi;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
/**
/**
*
H
uman readable stream name
*
Box containing a h
uman readable stream name
*/
*/
public
class
StreamNameBox
extends
ResidentBox
{
public
class
StreamNameBox
extends
ResidentBox
{
public
static
final
int
STRN
=
's'
|
(
't'
<<
8
)
|
(
'r'
<<
16
)
|
(
'n'
<<
24
);
public
static
final
int
STRN
=
's'
|
(
't'
<<
8
)
|
(
'r'
<<
16
)
|
(
'n'
<<
24
);
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AvcChunkPeekerTest.java
View file @
3a9f1f9a
...
@@ -39,12 +39,12 @@ public class AvcChunkPeekerTest {
...
@@ -39,12 +39,12 @@ public class AvcChunkPeekerTest {
(
byte
)
0xFE
,(
byte
)
0x9E
,
0x10
,
0
,
0
};
(
byte
)
0xFE
,(
byte
)
0x9E
,
0x10
,
0
,
0
};
private
FakeTrackOutput
fakeTrackOutput
;
private
FakeTrackOutput
fakeTrackOutput
;
private
AvcChunkHandler
avcChunk
Peek
er
;
private
AvcChunkHandler
avcChunk
Handl
er
;
@Before
@Before
public
void
before
()
{
public
void
before
()
{
fakeTrackOutput
=
new
FakeTrackOutput
(
false
);
fakeTrackOutput
=
new
FakeTrackOutput
(
false
);
avcChunk
Peek
er
=
new
AvcChunkHandler
(
0
,
fakeTrackOutput
,
avcChunk
Handl
er
=
new
AvcChunkHandler
(
0
,
fakeTrackOutput
,
new
ChunkClock
(
10_000_000L
,
24
*
10
),
FORMAT_BUILDER_AVC
);
new
ChunkClock
(
10_000_000L
,
24
*
10
),
FORMAT_BUILDER_AVC
);
}
}
...
@@ -55,26 +55,26 @@ public class AvcChunkPeekerTest {
...
@@ -55,26 +55,26 @@ public class AvcChunkPeekerTest {
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
bytes
).
build
();
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
bytes
).
build
();
avcChunk
Peek
er
.
peek
(
input
,
bytes
.
length
);
avcChunk
Handl
er
.
peek
(
input
,
bytes
.
length
);
}
}
@Test
@Test
public
void
peek_givenStreamHeader
()
throws
IOException
{
public
void
peek_givenStreamHeader
()
throws
IOException
{
peekStreamHeader
();
peekStreamHeader
();
final
PicCountClock
picCountClock
=
avcChunk
Peek
er
.
getPicCountClock
();
final
PicCountClock
picCountClock
=
avcChunk
Handl
er
.
getPicCountClock
();
Assert
.
assertNotNull
(
picCountClock
);
Assert
.
assertNotNull
(
picCountClock
);
Assert
.
assertEquals
(
64
,
picCountClock
.
getMaxPicCount
());
Assert
.
assertEquals
(
64
,
picCountClock
.
getMaxPicCount
());
Assert
.
assertEquals
(
0
,
avcChunk
Peek
er
.
getSpsData
().
picOrderCountType
);
Assert
.
assertEquals
(
0
,
avcChunk
Handl
er
.
getSpsData
().
picOrderCountType
);
Assert
.
assertEquals
(
1.18f
,
fakeTrackOutput
.
lastFormat
.
pixelWidthHeightRatio
,
0.01f
);
Assert
.
assertEquals
(
1.18f
,
fakeTrackOutput
.
lastFormat
.
pixelWidthHeightRatio
,
0.01f
);
}
}
@Test
@Test
public
void
newChunk_givenStreamHeaderAndPSlice
()
throws
IOException
{
public
void
newChunk_givenStreamHeaderAndPSlice
()
throws
IOException
{
peekStreamHeader
();
peekStreamHeader
();
final
PicCountClock
picCountClock
=
avcChunk
Peek
er
.
getPicCountClock
();
final
PicCountClock
picCountClock
=
avcChunk
Handl
er
.
getPicCountClock
();
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
P_SLICE
).
build
();
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
P_SLICE
).
build
();
avcChunk
Peeker
.
newChunk
(
0
,
P_SLICE
.
length
,
input
);
avcChunk
Handler
.
newChunk
(
P_SLICE
.
length
,
input
);
Assert
.
assertEquals
(
12
,
picCountClock
.
getLastPicCount
());
Assert
.
assertEquals
(
12
,
picCountClock
.
getLastPicCount
());
}
}
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/AviSeekMapTest.java
View file @
3a9f1f9a
...
@@ -15,7 +15,6 @@
...
@@ -15,7 +15,6 @@
*/
*/
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.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
org.junit.Assert
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.junit.Test
;
...
@@ -23,26 +22,25 @@ import org.junit.Test;
...
@@ -23,26 +22,25 @@ import org.junit.Test;
public
class
AviSeekMapTest
{
public
class
AviSeekMapTest
{
@Test
@Test
public
void
s
etFrames_givenExactSeekPointMatch
()
{
public
void
g
etFrames_givenExactSeekPointMatch
()
{
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
final
long
position
=
aviSeekMap
.
keyFrameOffsetsDiv2
[
1
]
*
2L
+
aviSeekMap
.
seekOffset
;
final
long
position
=
aviSeekMap
.
keyFrameOffsetsDiv2
[
1
]
*
2L
+
aviSeekMap
.
seekOffset
;
final
int
secs
=
4
;
final
int
secs
=
4
;
final
ChunkHandler
[]
chunkHandlers
=
new
ChunkHandler
[]{
DataHelper
.
getVideoChunkHandler
(
secs
),
final
ChunkHandler
[]
chunkHandlers
=
new
ChunkHandler
[]{
DataHelper
.
getVideoChunkHandler
(
secs
),
DataHelper
.
getAudioChunkHandler
(
secs
)};
DataHelper
.
getAudioChunkHandler
(
secs
)};
aviSeekMap
.
setFrames
(
position
,
C
.
MICROS_PER_SECOND
,
chunkHandlers
);
int
[]
indexes
=
aviSeekMap
.
getIndexes
(
position
);
for
(
int
i
=
0
;
i
<
chunkHandlers
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
chunkHandlers
.
length
;
i
++)
{
Assert
.
assertEquals
(
aviSeekMap
.
seekIndexes
[
i
][
1
],
chunkHandlers
[
i
].
getClock
().
getIndex
()
);
Assert
.
assertEquals
(
aviSeekMap
.
seekIndexes
[
i
][
1
],
indexes
[
i
]
);
}
}
}
}
@Test
@Test
public
void
setFrames_givenBadPosition
()
{
public
void
setFrames_givenBadPosition
()
{
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
final
AviSeekMap
aviSeekMap
=
DataHelper
.
getAviSeekMap
();
final
ChunkHandler
[]
chunkHandlers
=
new
ChunkHandler
[
2
];
try
{
try
{
aviSeekMap
.
setFrames
(
1L
,
C
.
MICROS_PER_SECOND
,
chunkHandlers
);
aviSeekMap
.
getIndexes
(
1L
);
Assert
.
fail
();
Assert
.
fail
();
}
catch
(
IllegalArgumentException
e
)
{
}
catch
(
IllegalArgumentException
e
)
{
//Intentionally blank
//Intentionally blank
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/ChunkHandlerTest.java
deleted
100644 → 0
View file @
14c842e5
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
org.junit.Assert
;
import
org.junit.Test
;
public
class
ChunkHandlerTest
{
@Test
public
void
setClock_givenLinearClock
()
{
final
ChunkClock
linearClock
=
new
ChunkClock
(
1_000_000L
,
30
);
final
ChunkHandler
chunkHandler
=
DataHelper
.
getVideoChunkHandler
(
1
);
chunkHandler
.
setClock
(
linearClock
);
Assert
.
assertSame
(
linearClock
,
chunkHandler
.
getClock
());
}
}
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/MockNalChunk
Peek
er.java
→
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/MockNalChunk
Handl
er.java
View file @
3a9f1f9a
...
@@ -19,9 +19,9 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
...
@@ -19,9 +19,9 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
java.io.IOException
;
import
java.io.IOException
;
public
class
MockNalChunk
Peeker
extends
NalChunkPeek
er
{
public
class
MockNalChunk
Handler
extends
NalChunkHandl
er
{
private
boolean
skip
;
private
boolean
skip
;
public
MockNalChunk
Peek
er
(
int
peakSize
,
boolean
skip
)
{
public
MockNalChunk
Handl
er
(
int
peakSize
,
boolean
skip
)
{
super
(
0
,
new
FakeTrackOutput
(
false
),
new
ChunkClock
(
1_000_000L
,
24
),
peakSize
);
super
(
0
,
new
FakeTrackOutput
(
false
),
new
ChunkClock
(
1_000_000L
,
24
),
peakSize
);
this
.
skip
=
skip
;
this
.
skip
=
skip
;
}
}
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/NalChunkPeekerTest.java
View file @
3a9f1f9a
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
avi
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
java.io.EOFException
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
org.junit.Assert
;
import
org.junit.Assert
;
...
@@ -26,7 +25,7 @@ public class NalChunkPeekerTest {
...
@@ -26,7 +25,7 @@ public class NalChunkPeekerTest {
@Test
@Test
public
void
construct_givenTooSmallPeekSize
()
{
public
void
construct_givenTooSmallPeekSize
()
{
try
{
try
{
new
MockNalChunk
Peek
er
(
4
,
false
);
new
MockNalChunk
Handl
er
(
4
,
false
);
Assert
.
fail
();
Assert
.
fail
();
}
catch
(
IllegalArgumentException
e
)
{
}
catch
(
IllegalArgumentException
e
)
{
//Intentionally blank
//Intentionally blank
...
@@ -36,7 +35,7 @@ public class NalChunkPeekerTest {
...
@@ -36,7 +35,7 @@ public class NalChunkPeekerTest {
@Test
@Test
public
void
peek_givenNoData
()
{
public
void
peek_givenNoData
()
{
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
build
();
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
build
();
final
MockNalChunk
Peeker
peeker
=
new
MockNalChunkPeek
er
(
5
,
false
);
final
MockNalChunk
Handler
peeker
=
new
MockNalChunkHandl
er
(
5
,
false
);
try
{
try
{
peeker
.
peek
(
input
,
10
);
peeker
.
peek
(
input
,
10
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
...
@@ -46,7 +45,7 @@ public class NalChunkPeekerTest {
...
@@ -46,7 +45,7 @@ public class NalChunkPeekerTest {
@Test
@Test
public
void
peek_givenNoNal
()
{
public
void
peek_givenNoNal
()
{
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
new
byte
[
10
]).
build
();
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
new
byte
[
10
]).
build
();
final
MockNalChunk
Peeker
peeker
=
new
MockNalChunkPeek
er
(
5
,
false
);
final
MockNalChunk
Handler
peeker
=
new
MockNalChunkHandl
er
(
5
,
false
);
try
{
try
{
peeker
.
peek
(
input
,
10
);
peeker
.
peek
(
input
,
10
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
...
@@ -59,7 +58,7 @@ public class NalChunkPeekerTest {
...
@@ -59,7 +58,7 @@ public class NalChunkPeekerTest {
DataHelper
.
appendNal
(
byteBuffer
,
(
byte
)
32
);
DataHelper
.
appendNal
(
byteBuffer
,
(
byte
)
32
);
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
byteBuffer
.
array
()).
build
();
final
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
byteBuffer
.
array
()).
build
();
final
MockNalChunk
Peeker
peeker
=
new
MockNalChunkPeek
er
(
5
,
true
);
final
MockNalChunk
Handler
peeker
=
new
MockNalChunkHandl
er
(
5
,
true
);
try
{
try
{
peeker
.
peek
(
input
,
10
);
peeker
.
peek
(
input
,
10
);
Assert
.
assertEquals
(
0
,
input
.
getPeekPosition
());
Assert
.
assertEquals
(
0
,
input
.
getPeekPosition
());
...
...
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