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
23b54a95
authored
Dec 03, 2019
by
kimvde
Committed by
bachinger
Dec 04, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Allow no output frame holder BinarySearchSeeker
PiperOrigin-RevId: 283544187
parent
f28a17f9
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
59 additions
and
63 deletions
extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacBinarySearchSeekerTest.java
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacBinarySearchSeeker.java
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/PsBinarySearchSeeker.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsBinarySearchSeeker.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacBinarySearchSeekerTest.java
View file @
23b54a95
...
...
@@ -20,10 +20,12 @@ import static org.junit.Assert.fail;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.ext.flac.FlacBinarySearchSeeker.OutputFrameHolder
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.TestUtil
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -47,19 +49,20 @@ public final class FlacBinarySearchSeekerTest {
throws
IOException
,
FlacDecoderException
,
InterruptedException
{
byte
[]
data
=
TestUtil
.
getByteArray
(
ApplicationProvider
.
getApplicationContext
(),
NOSEEKTABLE_FLAC
);
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
data
).
build
();
FlacDecoderJni
decoderJni
=
new
FlacDecoderJni
();
decoderJni
.
setData
(
input
);
OutputFrameHolder
outputFrameHolder
=
new
OutputFrameHolder
(
ByteBuffer
.
allocateDirect
(
0
));
FlacBinarySearchSeeker
seeker
=
new
FlacBinarySearchSeeker
(
decoderJni
.
decodeStreamMetadata
(),
/* firstFramePosition= */
0
,
data
.
length
,
decoderJni
);
decoderJni
,
outputFrameHolder
);
SeekMap
seekMap
=
seeker
.
getSeekMap
();
assertThat
(
seekMap
).
isNotNull
();
assertThat
(
seekMap
.
getDurationUs
()).
isEqualTo
(
DURATION_US
);
assertThat
(
seekMap
.
isSeekable
()).
isTrue
();
...
...
@@ -70,18 +73,20 @@ public final class FlacBinarySearchSeekerTest {
throws
IOException
,
FlacDecoderException
,
InterruptedException
{
byte
[]
data
=
TestUtil
.
getByteArray
(
ApplicationProvider
.
getApplicationContext
(),
NOSEEKTABLE_FLAC
);
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
data
).
build
();
FlacDecoderJni
decoderJni
=
new
FlacDecoderJni
();
decoderJni
.
setData
(
input
);
OutputFrameHolder
outputFrameHolder
=
new
OutputFrameHolder
(
ByteBuffer
.
allocateDirect
(
0
));
FlacBinarySearchSeeker
seeker
=
new
FlacBinarySearchSeeker
(
decoderJni
.
decodeStreamMetadata
(),
/* firstFramePosition= */
0
,
data
.
length
,
decoderJni
);
decoderJni
,
outputFrameHolder
);
seeker
.
setSeekTargetUs
(
/* timeUs= */
1000
);
assertThat
(
seeker
.
isSeeking
()).
isTrue
();
}
}
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacBinarySearchSeeker.java
View file @
23b54a95
...
...
@@ -31,16 +31,33 @@ import java.nio.ByteBuffer;
*/
/* package */
final
class
FlacBinarySearchSeeker
extends
BinarySearchSeeker
{
/**
* Holds a frame extracted from a stream, together with the time stamp of the frame in
* microseconds.
*/
public
static
final
class
OutputFrameHolder
{
public
final
ByteBuffer
byteBuffer
;
public
long
timeUs
;
/** Constructs an instance, wrapping the given byte buffer. */
public
OutputFrameHolder
(
ByteBuffer
outputByteBuffer
)
{
this
.
timeUs
=
0
;
this
.
byteBuffer
=
outputByteBuffer
;
}
}
private
final
FlacDecoderJni
decoderJni
;
public
FlacBinarySearchSeeker
(
FlacStreamMetadata
streamMetadata
,
long
firstFramePosition
,
long
inputLength
,
FlacDecoderJni
decoderJni
)
{
FlacDecoderJni
decoderJni
,
OutputFrameHolder
outputFrameHolder
)
{
super
(
new
FlacSeekTimestampConverter
(
streamMetadata
),
new
FlacTimestampSeeker
(
decoderJni
),
new
FlacTimestampSeeker
(
decoderJni
,
outputFrameHolder
),
streamMetadata
.
getDurationUs
(),
/* floorTimePosition= */
0
,
/* ceilingTimePosition= */
streamMetadata
.
totalSamples
,
...
...
@@ -63,14 +80,15 @@ import java.nio.ByteBuffer;
private
static
final
class
FlacTimestampSeeker
implements
TimestampSeeker
{
private
final
FlacDecoderJni
decoderJni
;
private
final
OutputFrameHolder
outputFrameHolder
;
private
FlacTimestampSeeker
(
FlacDecoderJni
decoderJni
)
{
private
FlacTimestampSeeker
(
FlacDecoderJni
decoderJni
,
OutputFrameHolder
outputFrameHolder
)
{
this
.
decoderJni
=
decoderJni
;
this
.
outputFrameHolder
=
outputFrameHolder
;
}
@Override
public
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetSampleIndex
,
OutputFrameHolder
outputFrameHolder
)
public
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetSampleIndex
)
throws
IOException
,
InterruptedException
{
ByteBuffer
outputBuffer
=
outputFrameHolder
.
byteBuffer
;
long
searchPosition
=
input
.
getPosition
();
...
...
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java
View file @
23b54a95
...
...
@@ -21,7 +21,7 @@ import androidx.annotation.IntDef;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.ext
ractor.
BinarySearchSeeker.OutputFrameHolder
;
import
com.google.android.exoplayer2.ext
.flac.Flac
BinarySearchSeeker.OutputFrameHolder
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.ExtractorInput
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
...
...
@@ -190,11 +190,12 @@ public final class FlacExtractor implements Extractor {
return
;
}
FlacDecoderJni
flacDecoderJni
=
decoderJni
;
FlacStreamMetadata
streamMetadata
;
try
{
streamMetadata
=
d
ecoderJni
.
decodeStreamMetadata
();
streamMetadata
=
flacD
ecoderJni
.
decodeStreamMetadata
();
}
catch
(
IOException
e
)
{
d
ecoderJni
.
reset
(
/* newPosition= */
0
);
flacD
ecoderJni
.
reset
(
/* newPosition= */
0
);
input
.
setRetryPosition
(
/* position= */
0
,
e
);
throw
e
;
}
...
...
@@ -202,12 +203,17 @@ public final class FlacExtractor implements Extractor {
streamMetadataDecoded
=
true
;
if
(
this
.
streamMetadata
==
null
)
{
this
.
streamMetadata
=
streamMetadata
;
outputBuffer
.
reset
(
streamMetadata
.
getMaxDecodedFrameSize
());
outputFrameHolder
=
new
OutputFrameHolder
(
ByteBuffer
.
wrap
(
outputBuffer
.
data
));
binarySearchSeeker
=
outputSeekMap
(
decoderJni
,
streamMetadata
,
input
.
getLength
(),
extractorOutput
);
outputSeekMap
(
flacDecoderJni
,
streamMetadata
,
input
.
getLength
(),
extractorOutput
,
outputFrameHolder
);
Metadata
metadata
=
streamMetadata
.
getMetadataCopyWithAppendedEntriesFrom
(
id3Metadata
);
outputFormat
(
streamMetadata
,
metadata
,
trackOutput
);
outputBuffer
.
reset
(
streamMetadata
.
getMaxDecodedFrameSize
());
outputFrameHolder
=
new
OutputFrameHolder
(
ByteBuffer
.
wrap
(
outputBuffer
.
data
));
}
}
...
...
@@ -219,7 +225,7 @@ public final class FlacExtractor implements Extractor {
OutputFrameHolder
outputFrameHolder
,
TrackOutput
trackOutput
)
throws
InterruptedException
,
IOException
{
int
seekResult
=
binarySearchSeeker
.
handlePendingSeek
(
input
,
seekPosition
,
outputFrameHolder
);
int
seekResult
=
binarySearchSeeker
.
handlePendingSeek
(
input
,
seekPosition
);
ByteBuffer
outputByteBuffer
=
outputFrameHolder
.
byteBuffer
;
if
(
seekResult
==
RESULT_CONTINUE
&&
outputByteBuffer
.
limit
()
>
0
)
{
outputSample
(
outputBuffer
,
outputByteBuffer
.
limit
(),
outputFrameHolder
.
timeUs
,
trackOutput
);
...
...
@@ -236,7 +242,8 @@ public final class FlacExtractor implements Extractor {
FlacDecoderJni
decoderJni
,
FlacStreamMetadata
streamMetadata
,
long
streamLength
,
ExtractorOutput
output
)
{
ExtractorOutput
output
,
OutputFrameHolder
outputFrameHolder
)
{
boolean
haveSeekTable
=
decoderJni
.
getSeekPoints
(
/* timeUs= */
0
)
!=
null
;
FlacBinarySearchSeeker
binarySearchSeeker
=
null
;
SeekMap
seekMap
;
...
...
@@ -245,7 +252,8 @@ public final class FlacExtractor implements Extractor {
}
else
if
(
streamLength
!=
C
.
LENGTH_UNSET
)
{
long
firstFramePosition
=
decoderJni
.
getDecodePosition
();
binarySearchSeeker
=
new
FlacBinarySearchSeeker
(
streamMetadata
,
firstFramePosition
,
streamLength
,
decoderJni
);
new
FlacBinarySearchSeeker
(
streamMetadata
,
firstFramePosition
,
streamLength
,
decoderJni
,
outputFrameHolder
);
seekMap
=
binarySearchSeeker
.
getSeekMap
();
}
else
{
seekMap
=
new
SeekMap
.
Unseekable
(
streamMetadata
.
getDurationUs
());
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java
View file @
23b54a95
...
...
@@ -24,7 +24,6 @@ import java.io.IOException;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.nio.ByteBuffer
;
/**
* A seeker that supports seeking within a stream by searching for the target frame using binary
...
...
@@ -48,15 +47,11 @@ public abstract class BinarySearchSeeker {
*
* @param input The {@link ExtractorInput} from which data should be peeked.
* @param targetTimestamp The target timestamp.
* @param outputFrameHolder If {@link TimestampSearchResult#TYPE_TARGET_TIMESTAMP_FOUND} is
* returned, this holder may be updated to hold the extracted frame that contains the target
* frame/sample associated with the target timestamp.
* @return A {@link TimestampSearchResult} that describes the result of the search.
* @throws IOException If an error occurred reading from the input.
* @throws InterruptedException If the thread was interrupted.
*/
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetTimestamp
,
OutputFrameHolder
outputFrameHolder
)
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetTimestamp
)
throws
IOException
,
InterruptedException
;
/** Called when a seek operation finishes. */
...
...
@@ -64,23 +59,6 @@ public abstract class BinarySearchSeeker {
}
/**
* Holds a frame extracted from a stream, together with the time stamp of the frame in
* microseconds.
*/
public
static
final
class
OutputFrameHolder
{
public
final
ByteBuffer
byteBuffer
;
public
long
timeUs
;
/** Constructs an instance, wrapping the given byte buffer. */
public
OutputFrameHolder
(
ByteBuffer
outputByteBuffer
)
{
this
.
timeUs
=
0
;
this
.
byteBuffer
=
outputByteBuffer
;
}
}
/**
* A {@link SeekTimestampConverter} implementation that returns the seek time itself as the
* timestamp for a seek time position.
*/
...
...
@@ -189,15 +167,11 @@ public abstract class BinarySearchSeeker {
* @param input The {@link ExtractorInput} from which data should be read.
* @param seekPositionHolder If {@link Extractor#RESULT_SEEK} is returned, this holder is updated
* to hold the position of the required seek.
* @param outputFrameHolder If {@link Extractor#RESULT_CONTINUE} is returned, this holder may be
* updated to hold the extracted frame that contains the target sample. The caller needs to
* check the byte buffer limit to see if an extracted frame is available.
* @return One of the {@code RESULT_} values defined in {@link Extractor}.
* @throws IOException If an error occurred reading from the input.
* @throws InterruptedException If the thread was interrupted.
*/
public
int
handlePendingSeek
(
ExtractorInput
input
,
PositionHolder
seekPositionHolder
,
OutputFrameHolder
outputFrameHolder
)
public
int
handlePendingSeek
(
ExtractorInput
input
,
PositionHolder
seekPositionHolder
)
throws
InterruptedException
,
IOException
{
TimestampSeeker
timestampSeeker
=
Assertions
.
checkNotNull
(
this
.
timestampSeeker
);
while
(
true
)
{
...
...
@@ -217,8 +191,7 @@ public abstract class BinarySearchSeeker {
input
.
resetPeekPosition
();
TimestampSearchResult
timestampSearchResult
=
timestampSeeker
.
searchForTimestamp
(
input
,
seekOperationParams
.
getTargetTimePosition
(),
outputFrameHolder
);
timestampSeeker
.
searchForTimestamp
(
input
,
seekOperationParams
.
getTargetTimePosition
());
switch
(
timestampSearchResult
.
type
)
{
case
TimestampSearchResult
.
TYPE_POSITION_OVERESTIMATED
:
...
...
@@ -419,7 +392,7 @@ public abstract class BinarySearchSeeker {
/**
* Represents possible search results for {@link
* TimestampSeeker#searchForTimestamp(ExtractorInput, long
, OutputFrameHolder
)}.
* TimestampSeeker#searchForTimestamp(ExtractorInput, long)}.
*/
public
static
final
class
TimestampSearchResult
{
...
...
@@ -495,10 +468,6 @@ public abstract class BinarySearchSeeker {
/**
* Returns a result to signal that the target timestamp has been found at {@code
* resultBytePosition}, and the seek operation can stop.
*
* <p>Note that when this value is returned from {@link
* TimestampSeeker#searchForTimestamp(ExtractorInput, long, OutputFrameHolder)}, the {@link
* OutputFrameHolder} may be updated to hold the target frame as an optimization.
*/
public
static
TimestampSearchResult
targetFoundResult
(
long
resultBytePosition
)
{
return
new
TimestampSearchResult
(
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/PsBinarySearchSeeker.java
View file @
23b54a95
...
...
@@ -69,8 +69,7 @@ import java.io.IOException;
}
@Override
public
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetTimestamp
,
OutputFrameHolder
outputFrameHolder
)
public
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetTimestamp
)
throws
IOException
,
InterruptedException
{
long
inputPosition
=
input
.
getPosition
();
int
bytesToSearch
=
(
int
)
Math
.
min
(
TIMESTAMP_SEARCH_BYTES
,
input
.
getLength
()
-
inputPosition
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java
View file @
23b54a95
...
...
@@ -168,8 +168,7 @@ public final class PsExtractor implements Extractor {
}
maybeOutputSeekMap
(
inputLength
);
if
(
psBinarySearchSeeker
!=
null
&&
psBinarySearchSeeker
.
isSeeking
())
{
return
psBinarySearchSeeker
.
handlePendingSeek
(
input
,
seekPosition
,
/* outputFrameHolder= */
null
);
return
psBinarySearchSeeker
.
handlePendingSeek
(
input
,
seekPosition
);
}
input
.
resetPeekPosition
();
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsBinarySearchSeeker.java
View file @
23b54a95
...
...
@@ -73,8 +73,7 @@ import java.io.IOException;
}
@Override
public
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetTimestamp
,
OutputFrameHolder
outputFrameHolder
)
public
TimestampSearchResult
searchForTimestamp
(
ExtractorInput
input
,
long
targetTimestamp
)
throws
IOException
,
InterruptedException
{
long
inputPosition
=
input
.
getPosition
();
int
bytesToSearch
=
(
int
)
Math
.
min
(
TIMESTAMP_SEARCH_BYTES
,
input
.
getLength
()
-
inputPosition
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
View file @
23b54a95
...
...
@@ -268,8 +268,7 @@ public final class TsExtractor implements Extractor {
}
if
(
tsBinarySearchSeeker
!=
null
&&
tsBinarySearchSeeker
.
isSeeking
())
{
return
tsBinarySearchSeeker
.
handlePendingSeek
(
input
,
seekPosition
,
/* outputFrameHolder= */
null
);
return
tsBinarySearchSeeker
.
handlePendingSeek
(
input
,
seekPosition
);
}
}
...
...
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