Skip to content

Commit

Permalink
Added Multiple video downloads by api
Browse files Browse the repository at this point in the history
  • Loading branch information
PruthiviRaj27 committed Dec 30, 2022
1 parent 39b73c4 commit a897aff
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 51 deletions.
24 changes: 24 additions & 0 deletions app/src/main/java/com/tpstream/app/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import com.tpstream.player.TpInitParams
import com.tpstream.player.TpStreamDownloadManager

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -34,4 +36,26 @@ class MainActivity : AppCompatActivity() {
startActivity(myIntent)
}

fun apiDownload(view: View) {
val drmVideo = TpInitParams.Builder()
.setVideoId("C3XLe1CCcOq")
.setAccessToken("c381512b-7337-4d8e-a8cf-880f4f08fd08")
.setOrgCode("demoveranda")
.build()

val aesEncryptedVideo = TpInitParams.Builder()
.setVideoId("o7pOsacWaJt")
.setAccessToken("143a0c71-567e-4ecd-b22d-06177228c25b")
.setOrgCode("demoveranda")
.build()

val clearVideo = TpInitParams.Builder()
.setVideoId("qJQlWGLJvNv")
.setAccessToken("70f61402-3724-4ed8-99de-5473b2310efe")
.setOrgCode("demoveranda")
.build()

TpStreamDownloadManager(this).startDownloads(listOf(drmVideo,aesEncryptedVideo,clearVideo),2)
}

}
13 changes: 13 additions & 0 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
</LinearLayout>

<LinearLayout
android:id="@+id/downloadListLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
Expand All @@ -79,4 +80,16 @@

</LinearLayout>

<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:onClick="apiDownload"
android:text="ApiDownload"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/downloadListLayout" />

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ class OfflineVideoInfoRepository(context: Context) {
return offlineVideoInfoDao.getAllDownloadInLiveData()
}

fun getAllDownloads():List<OfflineVideoInfo>?{
return offlineVideoInfoDao.getAllDownload()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package com.tpstream.player
import android.content.Context
import androidx.lifecycle.LiveData
import com.tpstream.player.models.OfflineVideoInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import com.tpstream.player.models.VideoInfo
import kotlinx.coroutines.*
import okhttp3.internal.wait

class TpStreamDownloadManager(val context: Context) {

Expand Down Expand Up @@ -40,11 +39,30 @@ class TpStreamDownloadManager(val context: Context) {
return offlineVideoInfo.url
}

private fun startDownloads(paramsList: List<TpInitParams>,videoResolution:Int){




fun startDownloads(paramsList: List<TpInitParams>,videoResolution:Int){
CoroutineScope(Dispatchers.IO).launch {
val downloadedList = offlineVideoInfoRepository.getAllDownloads()
val paramsList1 = if (downloadedList != null){
(paramsList.filter { big -> !downloadedList.map { it.videoId }.contains ( big.videoId!! ) }).toMutableList()
} else {
paramsList.toMutableList()
}
for (params in paramsList1){
val videoDownloadRequestCreationHandler = VideoDownloadRequestCreationHandler(context,null,params,videoResolution).init()
videoDownloadRequestCreationHandler.setOnDownloadRequestCreation { downloadRequest, videoInfo ->
DownloadTask(context).start(downloadRequest)
saveOfflineVideoInfo(params,videoInfo)
}
}
}
}

private fun saveOfflineVideoInfo(params: TpInitParams,videoInfo: VideoInfo){
CoroutineScope(Dispatchers.IO).launch {
val offlineVideoInfo = videoInfo.asOfflineVideoInfo()
offlineVideoInfo.videoId = params.videoId!!
ImageSaver(context).save(offlineVideoInfo.thumbnail,offlineVideoInfo.videoId)
OfflineVideoInfoRepository(context).insert(offlineVideoInfo)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import androidx.media3.exoplayer.drm.DefaultDrmSessionManager
import androidx.media3.exoplayer.offline.DownloadHelper
import androidx.media3.exoplayer.offline.DownloadRequest
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
import com.tpstream.player.models.OfflineVideoInfo
import com.google.common.collect.ImmutableList
import com.tpstream.player.models.VideoInfo
import com.tpstream.player.views.TrackInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -23,44 +24,55 @@ typealias OnDownloadRequestCreation = (DownloadRequest, VideoInfo) -> Unit
class VideoDownloadRequestCreationHandler(
val context: Context,
private val player: TpStreamPlayer? = null,
private var params: TpInitParams? = null
private var params: TpInitParams? = null,
private val downloadResolution: Int = 0
) :
DownloadHelper.Callback, DRMLicenseFetchCallback {
private lateinit var downloadHelper: DownloadHelper
private lateinit var trackSelectionParameters: DefaultTrackSelector.Parameters
var listener: Listener? = null
private var keySetId: ByteArray? = null
private lateinit var videoInfo:VideoInfo
private lateinit var videoInfo: VideoInfo
private var url: String? = null
private var onDownloadRequestCreation :OnDownloadRequestCreation? = null
private var onDownloadRequestCreation: OnDownloadRequestCreation? = null

fun init(): VideoDownloadRequestCreationHandler{
if (player == null){
fun init(): VideoDownloadRequestCreationHandler {
if (player == null) {
CoroutineScope(Dispatchers.IO).launch {
getVideoInfo(params!!)
}
} else {
url = player.videoInfo?.getPlaybackURL()!!
params = player.params
videoInfo = player.videoInfo!!
prepareDownloadHelper()
}
url = player?.videoInfo?.getPlaybackURL()!!
params = player.params
videoInfo = player.videoInfo!!
return this
}

private fun prepareDownloadHelper() {
trackSelectionParameters = DownloadHelper.getDefaultTrackSelectorParameters(context)
downloadHelper = getDownloadHelper()
downloadHelper.prepare(this)
return this
}

private fun getVideoInfo(params: TpInitParams){
val url =
"/api/v2.5/video_info/${params.videoId}/?access_token=${params.accessToken}"
Network<VideoInfo>(params.orgCode).get(url, object : Network.TPResponse<VideoInfo> {
override fun onSuccess(result: VideoInfo) {
videoInfo = result
}
private fun getVideoInfo(params: TpInitParams) {
val url =
"/api/v2.5/video_info/${params.videoId}/?access_token=${params.accessToken}"
Network<VideoInfo>(params.orgCode).get(url, object : Network.TPResponse<VideoInfo> {
override fun onSuccess(result: VideoInfo) {
videoInfo = result
this@VideoDownloadRequestCreationHandler.url = videoInfo.getPlaybackURL()
EncryptionKeyRepository(context).fetchAndStore(params, this@VideoDownloadRequestCreationHandler.url!!)
prepareDownloadHelper()
}

override fun onFailure(exception: TPException) {
Toast.makeText(context,"Download Failed",Toast.LENGTH_SHORT).show()
}
})
override fun onFailure(exception: TPException) {
CoroutineScope(Dispatchers.Main).launch{
Toast.makeText(context, "Download Failed", Toast.LENGTH_SHORT).show()
}
}
})
}

private fun getDownloadHelper(): DownloadHelper {
Expand All @@ -78,7 +90,7 @@ class VideoDownloadRequestCreationHandler(
)
}

private fun getMediaItem(url: String):MediaItem{
private fun getMediaItem(url: String): MediaItem {
return MediaItem.Builder()
.setUri(url)
.setDrmConfiguration(
Expand All @@ -90,21 +102,39 @@ class VideoDownloadRequestCreationHandler(
}

override fun onPrepared(helper: DownloadHelper) {
val videoOrAudioData = VideoPlayerUtil.getAudioOrVideoInfoWithDrmInitData(helper)
val isDRMProtectedVideo = videoOrAudioData != null
if (isDRMProtectedVideo) {
if (hasDRMSchemaData(videoOrAudioData!!.drmInitData!!)) {
OfflineDRMLicenseHelper.fetchLicense(context, params!!, downloadHelper, this)
} else {
Toast.makeText(
context,
"Error in downloading video",
Toast.LENGTH_LONG
).show()
if (player == null) {
val videoOrAudioData = VideoPlayerUtil.getAudioOrVideoInfoWithDrmInitData(helper)
val isDRMProtectedVideo = videoOrAudioData != null
if (isDRMProtectedVideo) {
if (hasDRMSchemaData(videoOrAudioData!!.drmInitData!!)) {
OfflineDRMLicenseHelper.fetchLicense(context, params!!, downloadHelper, this)
} else {
Toast.makeText(
context,
"Error in downloading video",
Toast.LENGTH_LONG
).show()
}
return
}
return
createDownloadOverrides(downloadResolution)
} else {
val videoOrAudioData = VideoPlayerUtil.getAudioOrVideoInfoWithDrmInitData(helper)
val isDRMProtectedVideo = videoOrAudioData != null
if (isDRMProtectedVideo) {
if (hasDRMSchemaData(videoOrAudioData!!.drmInitData!!)) {
OfflineDRMLicenseHelper.fetchLicense(context, params!!, downloadHelper, this)
} else {
Toast.makeText(
context,
"Error in downloading video",
Toast.LENGTH_LONG
).show()
}
return
}
listener?.onDownloadRequestHandlerPrepared(true, helper)
}
listener?.onDownloadRequestHandlerPrepared(true, helper)
}

private fun hasDRMSchemaData(drmInitData: DrmInitData): Boolean {
Expand All @@ -121,6 +151,31 @@ class VideoDownloadRequestCreationHandler(
listener?.onDownloadRequestHandlerPrepareError(helper, e)
}

private fun createDownloadOverrides(int: Int){
val trackGroup = downloadHelper.getTracks(0).groups
val overrides = trackSelectionParameters.overrides.toMutableMap()
val trackInfos = getTrackInfos(trackGroup)
val resolution = trackInfos[int]
val mediaTrackGroup: TrackGroup = resolution.trackGroup.mediaTrackGroup
overrides.clear()
overrides[mediaTrackGroup] =
TrackSelectionOverride(mediaTrackGroup, ImmutableList.of(resolution.trackIndex))
onDownloadRequestCreation?.invoke(buildDownloadRequest(overrides),videoInfo)
}

private fun getTrackInfos(trackGroups: List<Tracks.Group>): ArrayList<TrackInfo> {
val trackInfos = arrayListOf<TrackInfo>()
if (trackGroups.none { it.mediaTrackGroup.type == C.TRACK_TYPE_VIDEO }) {
return trackInfos
}

val trackGroup = trackGroups.first { it.mediaTrackGroup.type == C.TRACK_TYPE_VIDEO }
for (trackIndex in 0 until trackGroup.length) {
trackInfos.add(TrackInfo(trackGroup, trackIndex))
}
return trackInfos
}

fun buildDownloadRequest(overrides: MutableMap<TrackGroup, TrackSelectionOverride>): DownloadRequest {
setSelectedTracks(overrides)
val name = videoInfo.title!!
Expand All @@ -140,6 +195,7 @@ class VideoDownloadRequestCreationHandler(

override fun onLicenseFetchSuccess(keySetId: ByteArray) {
this.keySetId = keySetId
createDownloadOverrides(downloadResolution)
CoroutineScope(Dispatchers.Main).launch {
Log.d("TAG", "onLicenseFetchSuccess: Success")
listener?.onDownloadRequestHandlerPrepared(true, downloadHelper)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ interface OfflineVideoInfoDao {
@Query("SELECT * FROM OfflineVideoInfo")
fun getAllDownloadInLiveData():LiveData<List<OfflineVideoInfo>?>


@Query("SELECT * FROM OfflineVideoInfo")
fun getAllDownload():List<OfflineVideoInfo>?
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class DownloadResolutionSelectionSheet(
VideoDownloadRequestCreationHandler(
requireContext(),
player
)
).init()
videoDownloadRequestCreateHandler.listener = this
}

Expand Down Expand Up @@ -189,13 +189,13 @@ class DownloadResolutionSelectionSheet(
}
}

inner class TrackInfo(val trackGroup: Tracks.Group, val trackIndex: Int) {
val format: Format
get() = trackGroup.getTrackFormat(trackIndex)
}

fun setOnSubmitListener(listener: OnSubmitListener) {
onSubmitListener = listener
}

}

class TrackInfo(val trackGroup: Tracks.Group, val trackIndex: Int) {
val format: Format
get() = trackGroup.getTrackFormat(trackIndex)
}

0 comments on commit a897aff

Please sign in to comment.