@imgly/editor-react-native 1.81.0-rc.0 → 1.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +4 -1
- package/package.json +1 -1
- package/src/NativeIMGLYEditor.ts +1 -1
- package/android/src/main/assets/ly.img.memories.style/content.json +0 -50
- package/android/src/main/assets/ly.img.memories.style/thumbnails/bubblegum.png +0 -0
- package/android/src/main/assets/ly.img.memories.style/thumbnails/hologram.png +0 -0
- package/android/src/main/assets/ly.img.memories.style/thumbnails/noir.png +0 -0
- package/android/src/main/assets/ly.img.memories.style/videos/bubblegum.mp4 +0 -0
- package/android/src/main/assets/ly.img.memories.style/videos/hologram.mp4 +0 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesApp.kt +0 -77
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesConfiguration.kt +0 -38
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesEditor.kt +0 -79
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesViewModel.kt +0 -469
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/callback/OnCreate.kt +0 -69
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/callback/OnExport.kt +0 -46
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/BottomPanel.kt +0 -151
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/Dock.kt +0 -145
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/ExportOverlay.kt +0 -229
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/NavigationBar.kt +0 -80
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/Overlay.kt +0 -138
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/extension/EditorScopeExt.kt +0 -111
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/AddPhotoAlternate.kt +0 -79
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/ArrowForward.kt +0 -45
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Audiotrack.kt +0 -43
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Check.kt +0 -39
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/CheckCircle.kt +0 -44
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Close.kt +0 -43
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Delete.kt +0 -54
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/DeleteOutline.kt +0 -53
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Fullscreen.kt +0 -74
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Image.kt +0 -51
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Info.kt +0 -48
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Pause.kt +0 -46
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/PlayArrow.kt +0 -38
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/RepeatOff.kt +0 -80
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/RepeatOn.kt +0 -59
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/SkipPrevious.kt +0 -46
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Sort.kt +0 -55
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Style.kt +0 -59
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Title.kt +0 -43
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/TouchTriple.kt +0 -134
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/VolumeDown.kt +0 -48
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/VolumeUp.kt +0 -60
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/model/ExportStatus.kt +0 -20
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/model/ImageItem.kt +0 -8
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/model/TimelineImage.kt +0 -18
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Events.kt +0 -59
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Playback.kt +0 -29
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/SceneSetup.kt +0 -79
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Timeline.kt +0 -27
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Title.kt +0 -162
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/TrackEditor.kt +0 -740
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/screen/ImageSelectionScreen.kt +0 -387
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/screen/LoadingScreen.kt +0 -258
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/sheet/FilterStylesSheet.kt +0 -167
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/sheet/FilterStylesSheetType.kt +0 -21
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/sheet/VolumeSheet.kt +0 -104
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/style/StyleApplier.kt +0 -220
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/style/StyleAssetSource.kt +0 -43
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/style/VideoStyle.kt +0 -118
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/Animations.kt +0 -58
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/Constants.kt +0 -20
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/ImageDate.kt +0 -81
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/Utils.kt +0 -27
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/CenteredAddImageButton.kt +0 -82
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/DraggableImageItem.kt +0 -145
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/FullscreenVideoControls.kt +0 -136
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageGrid.kt +0 -122
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageGridOverlay.kt +0 -149
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageTimelineStrip.kt +0 -323
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageToolbar.kt +0 -401
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ReorderableGridState.kt +0 -183
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/VideoControlPanel.kt +0 -180
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/VideoThumbnail.kt +0 -110
package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/VideoControlPanel.kt
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
package ly.img.editor.configuration.memories.widget
|
|
2
|
-
|
|
3
|
-
import androidx.compose.foundation.clickable
|
|
4
|
-
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
5
|
-
import androidx.compose.foundation.layout.Arrangement
|
|
6
|
-
import androidx.compose.foundation.layout.Box
|
|
7
|
-
import androidx.compose.foundation.layout.Column
|
|
8
|
-
import androidx.compose.foundation.layout.Row
|
|
9
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
10
|
-
import androidx.compose.foundation.layout.padding
|
|
11
|
-
import androidx.compose.foundation.layout.size
|
|
12
|
-
import androidx.compose.material.ripple.rememberRipple
|
|
13
|
-
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
14
|
-
import androidx.compose.material3.Icon
|
|
15
|
-
import androidx.compose.material3.MaterialTheme
|
|
16
|
-
import androidx.compose.runtime.Composable
|
|
17
|
-
import androidx.compose.runtime.getValue
|
|
18
|
-
import androidx.compose.runtime.mutableStateOf
|
|
19
|
-
import androidx.compose.runtime.remember
|
|
20
|
-
import androidx.compose.runtime.setValue
|
|
21
|
-
import androidx.compose.ui.Alignment
|
|
22
|
-
import androidx.compose.ui.Modifier
|
|
23
|
-
import androidx.compose.ui.tooling.preview.Preview
|
|
24
|
-
import androidx.compose.ui.unit.dp
|
|
25
|
-
import ly.img.editor.configuration.memories.iconPack.Fullscreen
|
|
26
|
-
import ly.img.editor.configuration.memories.iconPack.Pause
|
|
27
|
-
import ly.img.editor.configuration.memories.iconPack.PlayArrow
|
|
28
|
-
import ly.img.editor.configuration.memories.iconPack.RepeatOff
|
|
29
|
-
import ly.img.editor.configuration.memories.iconPack.RepeatOn
|
|
30
|
-
import ly.img.editor.configuration.memories.iconPack.SkipPrevious
|
|
31
|
-
import ly.img.editor.configuration.memories.iconPack.VolumeUp
|
|
32
|
-
import ly.img.editor.core.iconpack.IconPack
|
|
33
|
-
|
|
34
|
-
@OptIn(ExperimentalMaterial3Api::class)
|
|
35
|
-
@Composable
|
|
36
|
-
fun VideoControlPanel(
|
|
37
|
-
isPlaying: Boolean,
|
|
38
|
-
isLooping: Boolean,
|
|
39
|
-
onPlayPauseClick: () -> Unit,
|
|
40
|
-
onRestartClick: () -> Unit,
|
|
41
|
-
onLoopClick: () -> Unit,
|
|
42
|
-
onVolumeClick: () -> Unit,
|
|
43
|
-
onFullscreenClick: () -> Unit,
|
|
44
|
-
modifier: Modifier = Modifier,
|
|
45
|
-
) {
|
|
46
|
-
Column(
|
|
47
|
-
modifier = modifier.fillMaxWidth(),
|
|
48
|
-
) {
|
|
49
|
-
Box(
|
|
50
|
-
modifier = Modifier
|
|
51
|
-
.fillMaxWidth()
|
|
52
|
-
.padding(horizontal = 12.dp, vertical = 0.dp),
|
|
53
|
-
) {
|
|
54
|
-
// Left: Volume button (where the time used to be)
|
|
55
|
-
Icon(
|
|
56
|
-
imageVector = IconPack.VolumeUp,
|
|
57
|
-
contentDescription = "Volume",
|
|
58
|
-
tint = MaterialTheme.colorScheme.onBackground,
|
|
59
|
-
modifier = Modifier
|
|
60
|
-
.align(Alignment.CenterStart)
|
|
61
|
-
.size(32.dp)
|
|
62
|
-
.clickable(
|
|
63
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
64
|
-
indication = rememberRipple(
|
|
65
|
-
bounded = false,
|
|
66
|
-
radius = 20.dp,
|
|
67
|
-
),
|
|
68
|
-
) { onVolumeClick() }
|
|
69
|
-
.padding(vertical = 4.dp),
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
// Center: Play controls
|
|
73
|
-
Box(
|
|
74
|
-
modifier = Modifier.align(Alignment.Center),
|
|
75
|
-
contentAlignment = Alignment.Center,
|
|
76
|
-
) {
|
|
77
|
-
Row(
|
|
78
|
-
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
|
79
|
-
verticalAlignment = Alignment.CenterVertically,
|
|
80
|
-
) {
|
|
81
|
-
// Restart button
|
|
82
|
-
Icon(
|
|
83
|
-
imageVector = IconPack.SkipPrevious,
|
|
84
|
-
contentDescription = "Restart",
|
|
85
|
-
tint = MaterialTheme.colorScheme.onBackground,
|
|
86
|
-
modifier = Modifier
|
|
87
|
-
.size(48.dp)
|
|
88
|
-
.clickable(
|
|
89
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
90
|
-
indication = rememberRipple(
|
|
91
|
-
bounded = false,
|
|
92
|
-
radius = 28.dp,
|
|
93
|
-
),
|
|
94
|
-
) { onRestartClick() }
|
|
95
|
-
.padding(vertical = 8.dp),
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
// Play/Pause button
|
|
99
|
-
Icon(
|
|
100
|
-
imageVector = if (isPlaying) {
|
|
101
|
-
IconPack.Pause
|
|
102
|
-
} else {
|
|
103
|
-
IconPack.PlayArrow
|
|
104
|
-
},
|
|
105
|
-
contentDescription = if (isPlaying) "Pause" else "Play",
|
|
106
|
-
tint = MaterialTheme.colorScheme.onBackground,
|
|
107
|
-
modifier = Modifier
|
|
108
|
-
.size(48.dp)
|
|
109
|
-
.clickable(
|
|
110
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
111
|
-
indication = rememberRipple(
|
|
112
|
-
bounded = false,
|
|
113
|
-
radius = 28.dp,
|
|
114
|
-
),
|
|
115
|
-
) { onPlayPauseClick() }
|
|
116
|
-
.padding(vertical = 8.dp),
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
// Loop button
|
|
120
|
-
Icon(
|
|
121
|
-
imageVector = if (isLooping) IconPack.RepeatOn else IconPack.RepeatOff,
|
|
122
|
-
contentDescription = if (isLooping) "Disable Loop" else "Enable Loop",
|
|
123
|
-
tint = if (isLooping) {
|
|
124
|
-
MaterialTheme.colorScheme.primary
|
|
125
|
-
} else {
|
|
126
|
-
MaterialTheme.colorScheme.onBackground
|
|
127
|
-
},
|
|
128
|
-
modifier = Modifier
|
|
129
|
-
.size(48.dp)
|
|
130
|
-
.clickable(
|
|
131
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
132
|
-
indication = rememberRipple(
|
|
133
|
-
bounded = false,
|
|
134
|
-
radius = 28.dp,
|
|
135
|
-
),
|
|
136
|
-
) { onLoopClick() }
|
|
137
|
-
.padding(vertical = 8.dp),
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Right: Fullscreen button (moved from the top navigation bar)
|
|
143
|
-
Icon(
|
|
144
|
-
imageVector = IconPack.Fullscreen,
|
|
145
|
-
contentDescription = "Fullscreen",
|
|
146
|
-
tint = MaterialTheme.colorScheme.onBackground,
|
|
147
|
-
modifier = Modifier
|
|
148
|
-
.align(Alignment.CenterEnd)
|
|
149
|
-
.size(32.dp)
|
|
150
|
-
.clickable(
|
|
151
|
-
interactionSource = remember { MutableInteractionSource() },
|
|
152
|
-
indication = rememberRipple(
|
|
153
|
-
bounded = false,
|
|
154
|
-
radius = 20.dp,
|
|
155
|
-
),
|
|
156
|
-
) { onFullscreenClick() }
|
|
157
|
-
.padding(vertical = 4.dp),
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
@Preview(showBackground = true)
|
|
164
|
-
@Composable
|
|
165
|
-
fun VideoControlPanelPreview() {
|
|
166
|
-
var isPlaying by remember { mutableStateOf(false) }
|
|
167
|
-
var isLooping by remember { mutableStateOf(true) }
|
|
168
|
-
|
|
169
|
-
MaterialTheme {
|
|
170
|
-
VideoControlPanel(
|
|
171
|
-
isPlaying = isPlaying,
|
|
172
|
-
isLooping = isLooping,
|
|
173
|
-
onPlayPauseClick = { isPlaying = !isPlaying },
|
|
174
|
-
onRestartClick = { isPlaying = false },
|
|
175
|
-
onLoopClick = { isLooping = !isLooping },
|
|
176
|
-
onVolumeClick = { /* Volume control */ },
|
|
177
|
-
onFullscreenClick = { /* Enter fullscreen */ },
|
|
178
|
-
)
|
|
179
|
-
}
|
|
180
|
-
}
|
package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/VideoThumbnail.kt
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
package ly.img.editor.configuration.memories.widget
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.graphics.Bitmap
|
|
5
|
-
import android.media.MediaMetadataRetriever
|
|
6
|
-
import android.net.Uri
|
|
7
|
-
import android.os.Build
|
|
8
|
-
import android.util.LruCache
|
|
9
|
-
import androidx.compose.runtime.Composable
|
|
10
|
-
import androidx.compose.runtime.getValue
|
|
11
|
-
import androidx.compose.runtime.produceState
|
|
12
|
-
import androidx.compose.ui.platform.LocalContext
|
|
13
|
-
import kotlinx.coroutines.Dispatchers
|
|
14
|
-
import kotlinx.coroutines.withContext
|
|
15
|
-
import java.io.File
|
|
16
|
-
import java.io.FileOutputStream
|
|
17
|
-
import java.util.concurrent.ConcurrentHashMap
|
|
18
|
-
|
|
19
|
-
private const val ANDROID_ASSET_PREFIX = "file:///android_asset/"
|
|
20
|
-
|
|
21
|
-
// Small process-wide cache so scrolling / recomposition doesn't re-decode, and the grid and the
|
|
22
|
-
// timeline strip share frames for the same video.
|
|
23
|
-
private val thumbnailCache = LruCache<String, Bitmap>(16)
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Returns a single still frame from the middle of the video at [url] for use as a thumbnail, or
|
|
27
|
-
* null while it is still being decoded. Uses the platform [MediaMetadataRetriever] (no extra
|
|
28
|
-
* dependency) off the main thread, and caches the result by URL.
|
|
29
|
-
*
|
|
30
|
-
* Handles `content://` (picked media), `file://`, and bundled `file:///android_asset/...` URIs.
|
|
31
|
-
*/
|
|
32
|
-
@Composable
|
|
33
|
-
fun rememberVideoThumbnail(
|
|
34
|
-
url: String,
|
|
35
|
-
targetPx: Int = 256,
|
|
36
|
-
): Bitmap? {
|
|
37
|
-
val context = LocalContext.current
|
|
38
|
-
return produceState<Bitmap?>(initialValue = thumbnailCache.get(url), key1 = url) {
|
|
39
|
-
if (value != null) return@produceState
|
|
40
|
-
value = withContext(Dispatchers.IO) {
|
|
41
|
-
extractMiddleFrame(context, url, targetPx)?.also { thumbnailCache.put(url, it) }
|
|
42
|
-
}
|
|
43
|
-
}.value
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Cache of already-written thumbnail files (video URL -> file:// URI) so a repeated request reuses
|
|
47
|
-
// the PNG on disk instead of decoding another frame. Concurrent because several thumbnail requests
|
|
48
|
-
// run on Dispatchers.IO threads at once.
|
|
49
|
-
private val thumbnailFileCache = ConcurrentHashMap<String, String>()
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Extract the middle frame of the video at [url], write it to a PNG in the app cache, and return its
|
|
53
|
-
* `file://` URI (suitable for an engine image fill), or null if a frame can't be decoded. Cached by
|
|
54
|
-
* URL. Runs its decode + write off the main thread.
|
|
55
|
-
*/
|
|
56
|
-
suspend fun videoThumbnailFileUri(
|
|
57
|
-
context: Context,
|
|
58
|
-
url: String,
|
|
59
|
-
targetPx: Int = 512,
|
|
60
|
-
): String? {
|
|
61
|
-
thumbnailFileCache[url]?.let { cached ->
|
|
62
|
-
if (Uri.parse(cached).path?.let { File(it).exists() } == true) return cached
|
|
63
|
-
}
|
|
64
|
-
return withContext(Dispatchers.IO) {
|
|
65
|
-
val bitmap = extractMiddleFrame(context, url, targetPx) ?: return@withContext null
|
|
66
|
-
try {
|
|
67
|
-
val dir = File(context.cacheDir, "burst_thumbs").apply { mkdirs() }
|
|
68
|
-
val file = File(dir, "thumb_${url.hashCode()}.png")
|
|
69
|
-
FileOutputStream(file).use { bitmap.compress(Bitmap.CompressFormat.PNG, 90, it) }
|
|
70
|
-
Uri.fromFile(file).toString().also { thumbnailFileCache[url] = it }
|
|
71
|
-
} catch (e: Exception) {
|
|
72
|
-
null
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
private fun extractMiddleFrame(
|
|
78
|
-
context: Context,
|
|
79
|
-
url: String,
|
|
80
|
-
targetPx: Int,
|
|
81
|
-
): Bitmap? {
|
|
82
|
-
val retriever = MediaMetadataRetriever()
|
|
83
|
-
return try {
|
|
84
|
-
if (url.startsWith(ANDROID_ASSET_PREFIX)) {
|
|
85
|
-
// Bundled assets aren't real files: open via an asset file descriptor.
|
|
86
|
-
context.assets.openFd(url.removePrefix(ANDROID_ASSET_PREFIX)).use { afd ->
|
|
87
|
-
retriever.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length)
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
retriever.setDataSource(context, Uri.parse(url))
|
|
91
|
-
}
|
|
92
|
-
val durationMs = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() ?: 0L
|
|
93
|
-
val middleUs = (durationMs / 2) * 1000
|
|
94
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
95
|
-
// Decode straight to a small bitmap to keep memory low.
|
|
96
|
-
retriever.getScaledFrameAtTime(
|
|
97
|
-
middleUs,
|
|
98
|
-
MediaMetadataRetriever.OPTION_CLOSEST_SYNC,
|
|
99
|
-
targetPx,
|
|
100
|
-
targetPx,
|
|
101
|
-
)
|
|
102
|
-
} else {
|
|
103
|
-
retriever.getFrameAtTime(middleUs, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)
|
|
104
|
-
}
|
|
105
|
-
} catch (e: Exception) {
|
|
106
|
-
null
|
|
107
|
-
} finally {
|
|
108
|
-
runCatching { retriever.release() }
|
|
109
|
-
}
|
|
110
|
-
}
|