Skip to content

Commit e937f93

Browse files
authored
Merge pull request #7 from Novage/feat/p2p-events
Feat: add p2p engine events
2 parents 3294e59 + c5511b9 commit e937f93

File tree

15 files changed

+2618
-1817
lines changed

15 files changed

+2618
-1817
lines changed

README.md

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,23 @@ class MainActivity : ComponentActivity() {
116116
coreConfigJson = CORE_CONFIG_JSON,
117117
serverPort = SERVER_PORT,
118118
)
119+
120+
// Event listeners for P2P Media Loader
121+
p2pml.addEventListener(CoreEventMap.OnPeerConnect) { params ->
122+
// Implement logic to handle peer connection
123+
Log.d("P2PML", "Peer connected: ${params.peerId} - ${params.streamType}")
124+
}
125+
126+
p2pml.addEventListener(CoreEventMap.OnSegmentLoaded) { params ->
127+
// Implement logic to handle loaded segment
128+
Log.d("P2PML", "Segment loaded: ${params.segmentUrl} - ${params.bytesLength} - ${params.downloadSource}")
129+
}
119130

131+
p2pml.addEventListener(CoreEventMap.OnChunkDownloaded) { params ->
132+
// Implement logic to handle downloaded chunk
133+
Log.d("P2PML", "Chunk downloaded: ${params.bytesLength} - ${params.downloadSource} - ${params.downloadSource}")
134+
}
135+
120136
// Start P2P Media Loader with the activity context and ExoPlayer instance
121137
p2pml.start(this, exoPlayer)
122138

@@ -190,21 +206,21 @@ public class MainActivity extends AppCompatActivity {
190206
// URL to the media manifest
191207
private static final String MANIFEST_URL = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8";
192208

193-
// JSON configuration for P2P Media Loader
209+
// Port on which the P2P server will run
194210
private static final int SERVER_PORT = 8081;
195211

196-
// Port on which the P2P server will run
212+
// JSON configuration for P2P Media Loader
197213
private static final String CORE_CONFIG_JSON = "{\"swarmId\":\"TEST_KOTLIN\"}";
198214

199215
private ExoPlayer exoPlayer;
200-
private P2PMediaLoader p2pMediaLoader;
216+
private P2PMediaLoader p2pml;
201217

202218
private PlayerView playerView;
203219
private ProgressBar loadingIndicator;
204220
private TextView videoTitle;
205221

206222
private void initializePlayback() {
207-
String manifestUrl = p2pMediaLoader.getManifestUrl(MANIFEST_URL);
223+
String manifestUrl = p2pml.getManifestUrl(MANIFEST_URL);
208224

209225
DefaultHttpDataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory()
210226
.setConnectTimeoutMs(15000) // Set the connection timeout
@@ -254,15 +270,31 @@ public class MainActivity extends AppCompatActivity {
254270
exoPlayer = new ExoPlayer.Builder(this).build();
255271

256272
// Initialize P2P Media Loader with callbacks
257-
p2pMediaLoader = new P2PMediaLoader(
273+
p2pml = new P2PMediaLoader(
258274
this::initializePlayback,
259275
this::onP2PReadyErrorCallback,
260276
SERVER_PORT,
261277
CORE_CONFIG_JSON
262278
);
263279

280+
// Event listeners for P2P Media Loader
281+
p2pml.addEventListener(CoreEventMap.OnPeerConnect, (params) -> {
282+
// Implement logic to handle peer connection
283+
System.out.println("Peer connected: " + params.getPeerId() + " - " + params.getStreamType());
284+
});
285+
286+
p2pml.addEventListener(CoreEventMap.OnSegmentLoaded, (params) -> {
287+
// Implement logic to handle loaded segment
288+
System.out.println("Segment loaded: " + params.getSegmentUrl() + " - " + params.getBytesLength() + " - " + params.getDownloadSource());
289+
});
290+
291+
p2pml.addEventListener(CoreEventMap.OnChunkDownloaded, (params) -> {
292+
// Implement logic to handle downloaded chunk
293+
System.out.println("Chunk downloaded: " + params.getBytesLength() + " - " + params.getDownloadSource() + " - " + params.getDownloadSource());
294+
});
295+
264296
// Start P2P Media Loader with the activity context and ExoPlayer instance
265-
p2pMediaLoader.start(this, exoPlayer);
297+
p2pml.start(this, exoPlayer);
266298

267299
// Listener to update UI based on playback state
268300
exoPlayer.addListener(new Player.Listener() {
@@ -284,26 +316,26 @@ public class MainActivity extends AppCompatActivity {
284316
protected void onRestart() {
285317
super.onRestart();
286318
// Disable P2P features when the activity stops
287-
if (p2pMediaLoader != null) {
288-
p2pMediaLoader.applyDynamicConfig("{ \"isP2PDisabled\": false }");
319+
if (p2pml != null) {
320+
p2pml.applyDynamicConfig("{ \"isP2PDisabled\": false }");
289321
}
290322
}
291323

292324
@Override
293325
protected void onStop() {
294326
super.onStop();
295327
// Re-enable P2P features when the activity restarts
296-
if (p2pMediaLoader != null) {
297-
p2pMediaLoader.applyDynamicConfig("{ \"isP2PDisabled\": true }");
328+
if (p2pml != null) {
329+
p2pml.applyDynamicConfig("{ \"isP2PDisabled\": true }");
298330
}
299331
}
300332

301333
@Override
302334
protected void onDestroy() {
303335
super.onDestroy();
304336
// Release ExoPlayer resources and stop P2P Media Loader
305-
if (p2pMediaLoader != null) {
306-
p2pMediaLoader.stop();
337+
if (p2pml != null) {
338+
p2pml.stop();
307339
}
308340
if (exoPlayer != null) {
309341
exoPlayer.release();

app/src/main/java/com/novage/demo/viewmodel/ExoPlayerViewModel.kt

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ import kotlinx.coroutines.flow.StateFlow
2323
import kotlinx.coroutines.launch
2424

2525
@UnstableApi
26-
class ExoPlayerViewModel(application: Application) : AndroidViewModel(application) {
26+
class ExoPlayerViewModel(
27+
application: Application,
28+
) : AndroidViewModel(application) {
2729
private val context: Context
2830
get() = getApplication()
2931

@@ -36,36 +38,43 @@ class ExoPlayerViewModel(application: Application) : AndroidViewModel(applicatio
3638
val loadingState: StateFlow<Boolean> get() = _loadingState
3739

3840
fun setupP2PML() {
39-
p2pml = P2PMediaLoader(
40-
onP2PReadyCallback = { initializePlayback() },
41-
onP2PReadyErrorCallback = { onReadyError(it) },
42-
coreConfigJson = "{\"swarmId\":\"TEST_KOTLIN\"}",
43-
serverPort = 8081,
44-
)
41+
p2pml =
42+
P2PMediaLoader(
43+
onP2PReadyCallback = { initializePlayback() },
44+
onP2PReadyErrorCallback = { onReadyError(it) },
45+
coreConfigJson = "{\"swarmId\":\"TEST_KOTLIN\"}",
46+
serverPort = 8081,
47+
)
48+
4549
p2pml!!.start(context, player)
4650
}
4751

4852
private fun initializePlayback() {
49-
val manifest = p2pml?.getManifestUrl(Streams.HLS_BIG_BUCK_BUNNY)
50-
?: throw IllegalStateException("P2PML is not started")
53+
val manifest =
54+
p2pml?.getManifestUrl(Streams.HLS_BIG_BUCK_BUNNY)
55+
?: throw IllegalStateException("P2PML is not started")
5156
val loggingDataSourceFactory = LoggingDataSourceFactory(context)
5257

53-
val mediaSource = HlsMediaSource.Factory(loggingDataSourceFactory)
54-
.createMediaSource(MediaItem.fromUri(manifest))
58+
val mediaSource =
59+
HlsMediaSource
60+
.Factory(loggingDataSourceFactory)
61+
.createMediaSource(MediaItem.fromUri(manifest))
5562

5663
player.apply {
5764
playWhenReady = true
5865
setMediaSource(mediaSource)
5966
prepare()
60-
addListener(object : Player.Listener {
61-
override fun onPlaybackStateChanged(playbackState: Int) {
62-
if (playbackState == Player.STATE_READY) {
63-
viewModelScope.launch {
64-
_loadingState.value = false
67+
addListener(
68+
object : Player.Listener {
69+
override fun onPlaybackStateChanged(playbackState: Int) {
70+
if (playbackState == Player.STATE_READY) {
71+
viewModelScope.launch {
72+
_loadingState.value = false
73+
}
6574
}
6675
}
67-
}
68-
})
76+
},
77+
)
6978
}
7079
}
7180

@@ -85,7 +94,6 @@ class ExoPlayerViewModel(application: Application) : AndroidViewModel(applicatio
8594
}
8695
}
8796

88-
8997
@UnstableApi
9098
class LoggingDataSourceFactory(
9199
context: Context,
@@ -100,11 +108,9 @@ class LoggingDataSourceFactory(
100108

101109
private val baseDataSourceFactory = DefaultDataSource.Factory(context, httpDataSourceFactory)
102110

103-
override fun createDataSource(): DataSource =
104-
LoggingDataSource(baseDataSourceFactory.createDataSource())
111+
override fun createDataSource(): DataSource = LoggingDataSource(baseDataSourceFactory.createDataSource())
105112
}
106113

107-
108114
@UnstableApi
109115
class LoggingDataSource(
110116
private val wrappedDataSource: DataSource,
@@ -119,7 +125,11 @@ class LoggingDataSource(
119125
}
120126
}
121127

122-
override fun read(buffer: ByteArray, offset: Int, length: Int): Int =
128+
override fun read(
129+
buffer: ByteArray,
130+
offset: Int,
131+
length: Int,
132+
): Int =
123133
try {
124134
wrappedDataSource.read(buffer, offset, length)
125135
} catch (e: Exception) {

0 commit comments

Comments
 (0)