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
0d69a2ea
authored
Apr 13, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Implement event reporting from HlsSampleSource.
Issue: #275
parent
e21f7801
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
180 additions
and
50 deletions
demo/src/main/java/com/google/android/exoplayer/demo/PlayerActivity.java
demo/src/main/java/com/google/android/exoplayer/demo/player/DashRendererBuilder.java
demo/src/main/java/com/google/android/exoplayer/demo/player/DebugTrackRenderer.java
demo/src/main/java/com/google/android/exoplayer/demo/player/DefaultRendererBuilder.java
demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java
demo/src/main/java/com/google/android/exoplayer/demo/player/ExtractorRendererBuilder.java
demo/src/main/java/com/google/android/exoplayer/demo/player/HlsRendererBuilder.java
demo/src/main/java/com/google/android/exoplayer/demo/player/SmoothStreamingRendererBuilder.java
library/src/main/java/com/google/android/exoplayer/CodecCounters.java
library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java
library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java
library/src/main/java/com/google/android/exoplayer/hls/HlsExtractorWrapper.java
library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java
demo/src/main/java/com/google/android/exoplayer/demo/PlayerActivity.java
View file @
0d69a2ea
...
...
@@ -217,7 +217,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
return
new
DashRendererBuilder
(
userAgent
,
contentUri
.
toString
(),
new
WidevineTestMediaDrmCallback
(
contentId
),
debugTextView
,
audioCapabilities
);
case
DemoUtil
.
TYPE_HLS
:
return
new
HlsRendererBuilder
(
userAgent
,
contentUri
.
toString
());
return
new
HlsRendererBuilder
(
userAgent
,
contentUri
.
toString
()
,
debugTextView
);
case
DemoUtil
.
TYPE_MP4
:
return
new
ExtractorRendererBuilder
(
userAgent
,
contentUri
,
debugTextView
,
new
Mp4Extractor
());
...
...
demo/src/main/java/com/google/android/exoplayer/demo/player/DashRendererBuilder.java
View file @
0d69a2ea
...
...
@@ -248,7 +248,7 @@ public class DashRendererBuilder implements RendererBuilder,
videoRenderer
=
new
MediaCodecVideoTrackRenderer
(
videoSampleSource
,
drmSessionManager
,
true
,
MediaCodec
.
VIDEO_SCALING_MODE_SCALE_TO_FIT
,
5000
,
null
,
mainHandler
,
player
,
50
);
debugRenderer
=
debugTextView
!=
null
?
new
DebugTrackRenderer
(
debugTextView
,
videoRenderer
,
videoSampleSource
)
:
null
;
?
new
DebugTrackRenderer
(
debugTextView
,
player
,
videoRenderer
)
:
null
;
}
// Build the audio chunk sources.
...
...
demo/src/main/java/com/google/android/exoplayer/demo/player/DebugTrackRenderer.java
View file @
0d69a2ea
...
...
@@ -18,7 +18,6 @@ package com.google.android.exoplayer.demo.player;
import
com.google.android.exoplayer.ExoPlaybackException
;
import
com.google.android.exoplayer.MediaCodecTrackRenderer
;
import
com.google.android.exoplayer.TrackRenderer
;
import
com.google.android.exoplayer.chunk.ChunkSampleSource
;
import
com.google.android.exoplayer.chunk.Format
;
import
android.widget.TextView
;
...
...
@@ -30,21 +29,17 @@ import android.widget.TextView;
/* package */
class
DebugTrackRenderer
extends
TrackRenderer
implements
Runnable
{
private
final
TextView
textView
;
private
final
DemoPlayer
player
;
private
final
MediaCodecTrackRenderer
renderer
;
private
final
ChunkSampleSource
videoSampleSource
;
private
volatile
boolean
pendingFailure
;
private
volatile
long
currentPositionUs
;
public
DebugTrackRenderer
(
TextView
textView
,
MediaCodecTrackRenderer
renderer
)
{
this
(
textView
,
renderer
,
null
);
}
public
DebugTrackRenderer
(
TextView
textView
,
MediaCodecTrackRenderer
renderer
,
ChunkSampleSource
videoSampleSource
)
{
public
DebugTrackRenderer
(
TextView
textView
,
DemoPlayer
player
,
MediaCodecTrackRenderer
renderer
)
{
this
.
textView
=
textView
;
this
.
player
=
player
;
this
.
renderer
=
renderer
;
this
.
videoSampleSource
=
videoSampleSource
;
}
public
void
injectFailure
()
{
...
...
@@ -82,13 +77,13 @@ import android.widget.TextView;
}
private
String
getRenderString
()
{
return
"ms("
+
(
currentPositionUs
/
1000
)
+
"), "
+
getQualityString
()
+
", "
+
renderer
.
codecCounters
.
getDebugString
();
return
getQualityString
()
+
" "
+
renderer
.
codecCounters
.
getDebugString
();
}
private
String
getQualityString
()
{
Format
format
=
videoSampleSource
==
null
?
null
:
videoSampleSource
.
getFormat
();
return
format
==
null
?
"null"
:
"height("
+
format
.
height
+
"), itag("
+
format
.
id
+
")"
;
Format
format
=
player
.
getVideoFormat
();
return
format
==
null
?
"id:? br:? h:?"
:
"id:"
+
format
.
id
+
" br:"
+
format
.
bitrate
+
" h:"
+
format
.
height
;
}
@Override
...
...
demo/src/main/java/com/google/android/exoplayer/demo/player/DefaultRendererBuilder.java
View file @
0d69a2ea
...
...
@@ -55,8 +55,7 @@ public class DefaultRendererBuilder implements RendererBuilder {
// Build the debug renderer.
TrackRenderer
debugRenderer
=
debugTextView
!=
null
?
new
DebugTrackRenderer
(
debugTextView
,
videoRenderer
)
:
null
;
?
new
DebugTrackRenderer
(
debugTextView
,
player
,
videoRenderer
)
:
null
;
// Invoke the callback.
TrackRenderer
[]
renderers
=
new
TrackRenderer
[
DemoPlayer
.
RENDERER_COUNT
];
...
...
demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java
View file @
0d69a2ea
...
...
@@ -28,6 +28,7 @@ import com.google.android.exoplayer.chunk.ChunkSampleSource;
import
com.google.android.exoplayer.chunk.Format
;
import
com.google.android.exoplayer.chunk.MultiTrackChunkSource
;
import
com.google.android.exoplayer.drm.StreamingDrmSessionManager
;
import
com.google.android.exoplayer.hls.HlsSampleSource
;
import
com.google.android.exoplayer.metadata.MetadataTrackRenderer
;
import
com.google.android.exoplayer.text.TextRenderer
;
import
com.google.android.exoplayer.upstream.DefaultBandwidthMeter
;
...
...
@@ -48,9 +49,10 @@ import java.util.concurrent.CopyOnWriteArrayList;
* SmoothStreaming and so on).
*/
public
class
DemoPlayer
implements
ExoPlayer
.
Listener
,
ChunkSampleSource
.
EventListener
,
DefaultBandwidthMeter
.
EventListener
,
MediaCodecVideoTrackRenderer
.
EventListener
,
MediaCodecAudioTrackRenderer
.
EventListener
,
Ac3PassthroughAudioTrackRenderer
.
EventListener
,
TextRenderer
,
StreamingDrmSessionManager
.
EventListener
{
HlsSampleSource
.
EventListener
,
DefaultBandwidthMeter
.
EventListener
,
MediaCodecVideoTrackRenderer
.
EventListener
,
MediaCodecAudioTrackRenderer
.
EventListener
,
Ac3PassthroughAudioTrackRenderer
.
EventListener
,
StreamingDrmSessionManager
.
EventListener
,
TextRenderer
{
/**
* Builds renderers for the player.
...
...
@@ -181,6 +183,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
private
Surface
surface
;
private
InternalRendererBuilderCallback
builderCallback
;
private
TrackRenderer
videoRenderer
;
private
Format
videoFormat
;
private
int
videoTrackToRestore
;
private
MultiTrackChunkSource
[]
multiTrackSources
;
...
...
@@ -268,6 +271,10 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
}
}
public
Format
getVideoFormat
()
{
return
videoFormat
;
}
public
void
setBackgrounded
(
boolean
backgrounded
)
{
if
(
this
.
backgrounded
==
backgrounded
)
{
return
;
...
...
@@ -291,6 +298,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
}
rendererBuildingState
=
RENDERER_BUILDING_STATE_BUILDING
;
maybeReportPlayerState
();
videoFormat
=
null
;
builderCallback
=
new
InternalRendererBuilderCallback
();
rendererBuilder
.
buildRenderers
(
this
,
builderCallback
);
}
...
...
@@ -437,6 +445,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
return
;
}
if
(
sourceId
==
TYPE_VIDEO
)
{
videoFormat
=
format
;
infoListener
.
onVideoFormatEnabled
(
format
,
trigger
,
mediaTimeMs
);
}
else
if
(
sourceId
==
TYPE_AUDIO
)
{
infoListener
.
onAudioFormatEnabled
(
format
,
trigger
,
mediaTimeMs
);
...
...
demo/src/main/java/com/google/android/exoplayer/demo/player/ExtractorRendererBuilder.java
View file @
0d69a2ea
...
...
@@ -63,8 +63,7 @@ public class ExtractorRendererBuilder implements RendererBuilder {
// Build the debug renderer.
TrackRenderer
debugRenderer
=
debugTextView
!=
null
?
new
DebugTrackRenderer
(
debugTextView
,
videoRenderer
)
:
null
;
?
new
DebugTrackRenderer
(
debugTextView
,
player
,
videoRenderer
)
:
null
;
// Invoke the callback.
TrackRenderer
[]
renderers
=
new
TrackRenderer
[
DemoPlayer
.
RENDERER_COUNT
];
...
...
demo/src/main/java/com/google/android/exoplayer/demo/player/HlsRendererBuilder.java
View file @
0d69a2ea
...
...
@@ -35,6 +35,8 @@ import com.google.android.exoplayer.util.ManifestFetcher;
import
com.google.android.exoplayer.util.ManifestFetcher.ManifestCallback
;
import
android.media.MediaCodec
;
import
android.os.Handler
;
import
android.widget.TextView
;
import
java.io.IOException
;
import
java.util.Map
;
...
...
@@ -46,13 +48,15 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
private
final
String
userAgent
;
private
final
String
url
;
private
final
TextView
debugTextView
;
private
DemoPlayer
player
;
private
RendererBuilderCallback
callback
;
public
HlsRendererBuilder
(
String
userAgent
,
String
url
)
{
public
HlsRendererBuilder
(
String
userAgent
,
String
url
,
TextView
debugTextView
)
{
this
.
userAgent
=
userAgent
;
this
.
url
=
url
;
this
.
debugTextView
=
debugTextView
;
}
@Override
...
...
@@ -72,28 +76,35 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
@Override
public
void
onSingleManifest
(
HlsPlaylist
manifest
)
{
Handler
mainHandler
=
player
.
getMainHandler
();
DefaultBandwidthMeter
bandwidthMeter
=
new
DefaultBandwidthMeter
();
DataSource
dataSource
=
new
UriDataSource
(
userAgent
,
bandwidthMeter
);
HlsChunkSource
chunkSource
=
new
HlsChunkSource
(
dataSource
,
url
,
manifest
,
bandwidthMeter
,
null
,
HlsChunkSource
.
ADAPTIVE_MODE_SPLICE
);
HlsSampleSource
sampleSource
=
new
HlsSampleSource
(
chunkSource
,
true
,
3
);
HlsSampleSource
sampleSource
=
new
HlsSampleSource
(
chunkSource
,
true
,
3
,
mainHandler
,
player
,
DemoPlayer
.
TYPE_VIDEO
);
MediaCodecVideoTrackRenderer
videoRenderer
=
new
MediaCodecVideoTrackRenderer
(
sampleSource
,
MediaCodec
.
VIDEO_SCALING_MODE_SCALE_TO_FIT
,
5000
,
player
.
getMainHandler
()
,
player
,
50
);
MediaCodec
.
VIDEO_SCALING_MODE_SCALE_TO_FIT
,
5000
,
mainHandler
,
player
,
50
);
MediaCodecAudioTrackRenderer
audioRenderer
=
new
MediaCodecAudioTrackRenderer
(
sampleSource
);
MetadataTrackRenderer
<
Map
<
String
,
Object
>>
id3Renderer
=
new
MetadataTrackRenderer
<
Map
<
String
,
Object
>>(
sampleSource
,
new
Id3Parser
(),
player
.
getId3MetadataRenderer
(),
player
.
getMainHandler
()
.
getLooper
());
player
.
getId3MetadataRenderer
(),
mainHandler
.
getLooper
());
Eia608TrackRenderer
closedCaptionRenderer
=
new
Eia608TrackRenderer
(
sampleSource
,
player
,
player
.
getMainHandler
().
getLooper
());
mainHandler
.
getLooper
());
// Build the debug renderer.
TrackRenderer
debugRenderer
=
debugTextView
!=
null
?
new
DebugTrackRenderer
(
debugTextView
,
player
,
videoRenderer
)
:
null
;
TrackRenderer
[]
renderers
=
new
TrackRenderer
[
DemoPlayer
.
RENDERER_COUNT
];
renderers
[
DemoPlayer
.
TYPE_VIDEO
]
=
videoRenderer
;
renderers
[
DemoPlayer
.
TYPE_AUDIO
]
=
audioRenderer
;
renderers
[
DemoPlayer
.
TYPE_TIMED_METADATA
]
=
id3Renderer
;
renderers
[
DemoPlayer
.
TYPE_TEXT
]
=
closedCaptionRenderer
;
renderers
[
DemoPlayer
.
TYPE_DEBUG
]
=
debugRenderer
;
callback
.
onRenderers
(
null
,
null
,
renderers
);
}
...
...
demo/src/main/java/com/google/android/exoplayer/demo/player/SmoothStreamingRendererBuilder.java
View file @
0d69a2ea
...
...
@@ -174,8 +174,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
videoRenderer
=
new
MediaCodecVideoTrackRenderer
(
videoSampleSource
,
drmSessionManager
,
true
,
MediaCodec
.
VIDEO_SCALING_MODE_SCALE_TO_FIT
,
5000
,
null
,
mainHandler
,
player
,
50
);
debugRenderer
=
debugTextView
!=
null
?
new
DebugTrackRenderer
(
debugTextView
,
videoRenderer
,
videoSampleSource
)
:
null
;
?
new
DebugTrackRenderer
(
debugTextView
,
player
,
videoRenderer
)
:
null
;
}
// Build the audio renderer.
...
...
library/src/main/java/com/google/android/exoplayer/CodecCounters.java
View file @
0d69a2ea
...
...
@@ -45,13 +45,13 @@ public final class CodecCounters {
public
String
getDebugString
()
{
ensureUpdated
();
StringBuilder
builder
=
new
StringBuilder
();
builder
.
append
(
"cic
("
).
append
(
codecInitCount
).
append
(
")"
);
builder
.
append
(
"
crc("
).
append
(
codecReleaseCount
).
append
(
")"
);
builder
.
append
(
"
ofc("
).
append
(
outputFormatChangedCount
).
append
(
")"
);
builder
.
append
(
"
obc("
).
append
(
outputBuffersChangedCount
).
append
(
")"
);
builder
.
append
(
"
ren("
).
append
(
renderedOutputBufferCount
).
append
(
")"
);
builder
.
append
(
"
sob("
).
append
(
skippedOutputBufferCount
).
append
(
")"
);
builder
.
append
(
"
dob("
).
append
(
droppedOutputBufferCount
).
append
(
")"
);
builder
.
append
(
"cic
:"
).
append
(
codecInitCount
);
builder
.
append
(
"
crc:"
).
append
(
codecReleaseCount
);
builder
.
append
(
"
ofc:"
).
append
(
outputFormatChangedCount
);
builder
.
append
(
"
obc:"
).
append
(
outputBuffersChangedCount
);
builder
.
append
(
"
ren:"
).
append
(
renderedOutputBufferCount
);
builder
.
append
(
"
sob:"
).
append
(
skippedOutputBufferCount
);
builder
.
append
(
"
dob:"
).
append
(
droppedOutputBufferCount
);
return
builder
.
toString
();
}
...
...
library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java
View file @
0d69a2ea
...
...
@@ -124,6 +124,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
*
* @return The current downstream format.
*/
@Deprecated
public
Format
getFormat
()
{
return
downstreamFormat
;
}
...
...
library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java
View file @
0d69a2ea
...
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer.hls;
import
com.google.android.exoplayer.C
;
import
com.google.android.exoplayer.MediaFormat
;
import
com.google.android.exoplayer.chunk.BaseChunkSampleSourceEventListener
;
import
com.google.android.exoplayer.chunk.Chunk
;
import
com.google.android.exoplayer.chunk.DataChunk
;
import
com.google.android.exoplayer.chunk.Format
;
...
...
@@ -56,6 +57,11 @@ import java.util.Locale;
public
class
HlsChunkSource
{
/**
* Interface definition for a callback to be notified of {@link HlsChunkSource} events.
*/
public
interface
EventListener
extends
BaseChunkSampleSourceEventListener
{}
/**
* Adaptive switching is disabled.
* <p>
* The initially selected variant will be used throughout playback.
...
...
@@ -349,6 +355,8 @@ public class HlsChunkSource {
}
long
endTimeUs
=
startTimeUs
+
(
long
)
(
segment
.
durationSecs
*
C
.
MICROS_PER_SECOND
);
boolean
isLastChunk
=
!
mediaPlaylist
.
live
&&
chunkIndex
==
mediaPlaylist
.
segments
.
size
()
-
1
;
int
trigger
=
Chunk
.
TRIGGER_UNSPECIFIED
;
Format
format
=
enabledFormats
[
formatIndex
];
// Configure the extractor that will read the chunk.
HlsExtractorWrapper
extractorWrapper
;
...
...
@@ -356,13 +364,14 @@ public class HlsChunkSource {
Extractor
extractor
=
chunkUri
.
getLastPathSegment
().
endsWith
(
AAC_FILE_EXTENSION
)
?
new
AdtsExtractor
(
startTimeUs
)
:
new
TsExtractor
(
startTimeUs
);
extractorWrapper
=
new
HlsExtractorWrapper
(
bufferPool
,
extractor
,
switchingVariantSpliced
);
extractorWrapper
=
new
HlsExtractorWrapper
(
trigger
,
format
,
startTimeUs
,
bufferPool
,
extractor
,
switchingVariantSpliced
);
}
else
{
extractorWrapper
=
previousTsChunk
.
extractorWrapper
;
}
return
new
TsChunk
(
dataSource
,
dataSpec
,
Chunk
.
TRIGGER_UNSPECIFIED
,
enabledFormats
[
formatIndex
]
,
startTimeUs
,
endTimeUs
,
chunkMediaSequence
,
isLastChunk
,
extractorWrapper
,
encryptionKey
,
return
new
TsChunk
(
dataSource
,
dataSpec
,
trigger
,
format
,
startTimeUs
,
endTimeUs
,
chunkMediaSequence
,
isLastChunk
,
extractorWrapper
,
encryptionKey
,
encryptionIv
);
}
...
...
library/src/main/java/com/google/android/exoplayer/hls/HlsExtractorWrapper.java
View file @
0d69a2ea
...
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer.hls;
import
com.google.android.exoplayer.MediaFormat
;
import
com.google.android.exoplayer.SampleHolder
;
import
com.google.android.exoplayer.chunk.Format
;
import
com.google.android.exoplayer.drm.DrmInitData
;
import
com.google.android.exoplayer.extractor.DefaultTrackOutput
;
import
com.google.android.exoplayer.extractor.Extractor
;
...
...
@@ -36,6 +37,10 @@ import java.io.IOException;
*/
public
final
class
HlsExtractorWrapper
implements
ExtractorOutput
{
public
final
int
trigger
;
public
final
Format
format
;
public
final
long
startTimeUs
;
private
final
BufferPool
bufferPool
;
private
final
Extractor
extractor
;
private
final
SparseArray
<
DefaultTrackOutput
>
sampleQueues
;
...
...
@@ -47,7 +52,11 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
private
boolean
prepared
;
private
boolean
spliceConfigured
;
public
HlsExtractorWrapper
(
BufferPool
bufferPool
,
Extractor
extractor
,
boolean
shouldSpliceIn
)
{
public
HlsExtractorWrapper
(
int
trigger
,
Format
format
,
long
startTimeUs
,
BufferPool
bufferPool
,
Extractor
extractor
,
boolean
shouldSpliceIn
)
{
this
.
trigger
=
trigger
;
this
.
format
=
format
;
this
.
startTimeUs
=
startTimeUs
;
this
.
bufferPool
=
bufferPool
;
this
.
extractor
=
extractor
;
this
.
shouldSpliceIn
=
shouldSpliceIn
;
...
...
@@ -98,14 +107,14 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
}
/**
* Gets the
format
of the specified track.
* Gets the
{@link MediaFormat}
of the specified track.
* <p>
* This method must only be called after the extractor has been prepared.
*
* @param track The track index.
* @return The corresponding format.
*/
public
MediaFormat
getFormat
(
int
track
)
{
public
MediaFormat
get
Media
Format
(
int
track
)
{
return
sampleQueues
.
valueAt
(
track
).
getFormat
();
}
...
...
library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java
View file @
0d69a2ea
...
...
@@ -22,11 +22,14 @@ import com.google.android.exoplayer.SampleHolder;
import
com.google.android.exoplayer.SampleSource
;
import
com.google.android.exoplayer.TrackInfo
;
import
com.google.android.exoplayer.TrackRenderer
;
import
com.google.android.exoplayer.chunk.BaseChunkSampleSourceEventListener
;
import
com.google.android.exoplayer.chunk.Chunk
;
import
com.google.android.exoplayer.chunk.Format
;
import
com.google.android.exoplayer.upstream.Loader
;
import
com.google.android.exoplayer.upstream.Loader.Loadable
;
import
com.google.android.exoplayer.util.Assertions
;
import
android.os.Handler
;
import
android.os.SystemClock
;
import
java.io.IOException
;
...
...
@@ -38,6 +41,11 @@ import java.util.LinkedList;
public
class
HlsSampleSource
implements
SampleSource
,
Loader
.
Callback
{
/**
* Interface definition for a callback to be notified of {@link HlsSampleSource} events.
*/
public
interface
EventListener
extends
BaseChunkSampleSourceEventListener
{}
/**
* The default minimum number of times to retry loading data prior to failing.
*/
public
static
final
int
DEFAULT_MIN_LOADABLE_RETRY_COUNT
=
3
;
...
...
@@ -49,6 +57,10 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
private
final
boolean
frameAccurateSeeking
;
private
final
int
minLoadableRetryCount
;
private
final
int
eventSourceId
;
private
final
Handler
eventHandler
;
private
final
EventListener
eventListener
;
private
int
remainingReleaseCount
;
private
boolean
prepared
;
private
int
trackCount
;
...
...
@@ -57,6 +69,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
private
boolean
[]
pendingDiscontinuities
;
private
TrackInfo
[]
trackInfos
;
private
MediaFormat
[]
downstreamMediaFormats
;
private
Format
downstreamFormat
;
private
long
downstreamPositionUs
;
private
long
lastSeekPositionUs
;
...
...
@@ -74,16 +87,26 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
public
HlsSampleSource
(
HlsChunkSource
chunkSource
,
boolean
frameAccurateSeeking
,
int
downstreamRendererCount
)
{
this
(
chunkSource
,
frameAccurateSeeking
,
downstreamRendererCount
,
DEFAULT_MIN_LOADABLE_RETRY_COUNT
);
this
(
chunkSource
,
frameAccurateSeeking
,
downstreamRendererCount
,
null
,
null
,
0
);
}
public
HlsSampleSource
(
HlsChunkSource
chunkSource
,
boolean
frameAccurateSeeking
,
int
downstreamRendererCount
,
int
minLoadableRetryCount
)
{
int
downstreamRendererCount
,
Handler
eventHandler
,
EventListener
eventListener
,
int
eventSourceId
)
{
this
(
chunkSource
,
frameAccurateSeeking
,
downstreamRendererCount
,
eventHandler
,
eventListener
,
eventSourceId
,
DEFAULT_MIN_LOADABLE_RETRY_COUNT
);
}
public
HlsSampleSource
(
HlsChunkSource
chunkSource
,
boolean
frameAccurateSeeking
,
int
downstreamRendererCount
,
Handler
eventHandler
,
EventListener
eventListener
,
int
eventSourceId
,
int
minLoadableRetryCount
)
{
this
.
chunkSource
=
chunkSource
;
this
.
frameAccurateSeeking
=
frameAccurateSeeking
;
this
.
remainingReleaseCount
=
downstreamRendererCount
;
this
.
minLoadableRetryCount
=
minLoadableRetryCount
;
this
.
eventHandler
=
eventHandler
;
this
.
eventListener
=
eventListener
;
this
.
eventSourceId
=
eventSourceId
;
this
.
pendingResetPositionUs
=
NO_RESET_PENDING
;
extractors
=
new
LinkedList
<
HlsExtractorWrapper
>();
}
...
...
@@ -106,7 +129,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
downstreamMediaFormats
=
new
MediaFormat
[
trackCount
];
trackInfos
=
new
TrackInfo
[
trackCount
];
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
MediaFormat
format
=
extractor
.
getFormat
(
i
);
MediaFormat
format
=
extractor
.
get
Media
Format
(
i
);
trackInfos
[
i
]
=
new
TrackInfo
(
format
.
mimeType
,
chunkSource
.
getDurationUs
());
}
prepared
=
true
;
...
...
@@ -137,6 +160,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
enabledTrackCount
++;
trackEnabledStates
[
track
]
=
true
;
downstreamMediaFormats
[
track
]
=
null
;
downstreamFormat
=
null
;
if
(
enabledTrackCount
==
1
)
{
seekToUs
(
positionUs
);
}
...
...
@@ -202,6 +226,13 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
}
HlsExtractorWrapper
extractor
=
getCurrentExtractor
();
if
(
downstreamFormat
==
null
||
!
downstreamFormat
.
equals
(
extractor
.
format
))
{
// Notify a change in the downstream format.
notifyDownstreamFormatChanged
(
extractor
.
format
,
extractor
.
trigger
,
extractor
.
startTimeUs
);
downstreamFormat
=
extractor
.
format
;
}
if
(
extractors
.
size
()
>
1
)
{
// If there's more than one extractor, attempt to configure a seamless splice from the
// current one to the next one.
...
...
@@ -220,7 +251,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
return
NOTHING_READ
;
}
MediaFormat
mediaFormat
=
extractor
.
getFormat
(
track
);
MediaFormat
mediaFormat
=
extractor
.
get
Media
Format
(
track
);
if
(
mediaFormat
!=
null
&&
!
mediaFormat
.
equals
(
downstreamMediaFormats
[
track
],
true
))
{
chunkSource
.
getMaxVideoDimensions
(
mediaFormat
);
formatHolder
.
format
=
mediaFormat
;
...
...
@@ -286,6 +317,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
@Override
public
void
onLoadCompleted
(
Loadable
loadable
)
{
chunkSource
.
onChunkLoadCompleted
(
currentLoadable
);
notifyLoadCompleted
(
currentLoadable
.
bytesLoaded
());
if
(
isTsChunk
(
currentLoadable
))
{
TsChunk
tsChunk
=
(
TsChunk
)
loadable
;
loadingFinished
=
tsChunk
.
isLastChunk
;
...
...
@@ -298,6 +330,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
@Override
public
void
onLoadCanceled
(
Loadable
loadable
)
{
notifyLoadCanceled
(
currentLoadable
.
bytesLoaded
());
if
(
enabledTrackCount
>
0
)
{
restartFrom
(
pendingResetPositionUs
);
}
else
{
...
...
@@ -315,6 +348,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
currentLoadableExceptionCount
++;
currentLoadableExceptionTimestamp
=
SystemClock
.
elapsedRealtime
();
}
notifyLoadError
(
e
);
maybeStartLoading
();
}
...
...
@@ -418,13 +452,19 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
currentLoadable
=
nextLoadable
;
if
(
isTsChunk
(
currentLoadable
))
{
previousTsLoadable
=
(
TsChunk
)
currentLoadable
;
TsChunk
tsChunk
=
(
TsChunk
)
currentLoadable
;
if
(
isPendingReset
())
{
pendingResetPositionUs
=
NO_RESET_PENDING
;
}
if
(
extractors
.
isEmpty
()
||
extractors
.
getLast
()
!=
previousTsLoadable
.
extractorWrapper
)
{
extractors
.
addLast
(
previousTsLoadable
.
extractorWrapper
);
if
(
extractors
.
isEmpty
()
||
extractors
.
getLast
()
!=
tsChunk
.
extractorWrapper
)
{
extractors
.
addLast
(
tsChunk
.
extractorWrapper
);
}
notifyLoadStarted
(
tsChunk
.
dataSpec
.
length
,
tsChunk
.
type
,
tsChunk
.
trigger
,
tsChunk
.
format
,
tsChunk
.
startTimeUs
,
tsChunk
.
endTimeUs
);
previousTsLoadable
=
tsChunk
;
}
else
{
notifyLoadStarted
(
currentLoadable
.
dataSpec
.
length
,
currentLoadable
.
type
,
currentLoadable
.
trigger
,
currentLoadable
.
format
,
-
1
,
-
1
);
}
loader
.
startLoading
(
currentLoadable
,
this
);
}
...
...
@@ -445,4 +485,63 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
return
(
int
)
(
timeUs
/
1000
);
}
private
void
notifyLoadStarted
(
final
long
length
,
final
int
type
,
final
int
trigger
,
final
Format
format
,
final
long
mediaStartTimeUs
,
final
long
mediaEndTimeUs
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onLoadStarted
(
eventSourceId
,
length
,
type
,
trigger
,
format
,
usToMs
(
mediaStartTimeUs
),
usToMs
(
mediaEndTimeUs
));
}
});
}
}
private
void
notifyLoadCompleted
(
final
long
bytesLoaded
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onLoadCompleted
(
eventSourceId
,
bytesLoaded
);
}
});
}
}
private
void
notifyLoadCanceled
(
final
long
bytesLoaded
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onLoadCanceled
(
eventSourceId
,
bytesLoaded
);
}
});
}
}
private
void
notifyLoadError
(
final
IOException
e
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onLoadError
(
eventSourceId
,
e
);
}
});
}
}
private
void
notifyDownstreamFormatChanged
(
final
Format
format
,
final
int
trigger
,
final
long
positionUs
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onDownstreamFormatChanged
(
eventSourceId
,
format
,
trigger
,
usToMs
(
positionUs
));
}
});
}
}
}
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