react-native-compressor 1.8.0 → 1.8.2

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.
Files changed (47) hide show
  1. package/README.md +22 -1
  2. package/android/build.gradle +6 -2
  3. package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt +2 -2
  4. package/android/src/main/java/com/reactnativecompressor/CompressorModule.kt +12 -0
  5. package/android/src/main/java/com/reactnativecompressor/Utils/Uploader.kt +11 -11
  6. package/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +42 -36
  7. package/android/src/main/java/com/reactnativecompressor/Utils/createVideoThumbnail.kt +158 -0
  8. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/CompressionInterface.kt +73 -0
  9. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/VideoCompressorClass.kt +148 -0
  10. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/compressor/Compressor.kt +562 -0
  11. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/Atoms.kt +55 -0
  12. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/CompressorUtils.kt +196 -0
  13. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/NumbersUtils.kt +47 -0
  14. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/StreamableVideo.kt +209 -0
  15. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/InputSurface.kt +128 -0
  16. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/MP4Builder.kt +388 -0
  17. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Mdat.kt +74 -0
  18. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Mp4Movie.kt +54 -0
  19. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/OutputSurface.kt +102 -0
  20. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Result.kt +9 -0
  21. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Sample.kt +3 -0
  22. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/TextureRenderer.kt +214 -0
  23. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Track.kt +286 -0
  24. package/android/src/oldarch/CompressorSpec.kt +2 -0
  25. package/ios/Compressor.mm +9 -0
  26. package/ios/CompressorManager.swift +11 -0
  27. package/ios/Utils/CreateVideoThumbnail.swift +111 -0
  28. package/lib/commonjs/Spec/NativeCompressor.js.map +1 -1
  29. package/lib/commonjs/index.js +14 -0
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/utils/index.js +12 -1
  32. package/lib/commonjs/utils/index.js.map +1 -1
  33. package/lib/module/Spec/NativeCompressor.js.map +1 -1
  34. package/lib/module/index.js +4 -2
  35. package/lib/module/index.js.map +1 -1
  36. package/lib/module/utils/index.js +7 -0
  37. package/lib/module/utils/index.js.map +1 -1
  38. package/lib/typescript/Spec/NativeCompressor.d.ts +8 -0
  39. package/lib/typescript/Spec/NativeCompressor.d.ts.map +1 -1
  40. package/lib/typescript/index.d.ts +15 -3
  41. package/lib/typescript/index.d.ts.map +1 -1
  42. package/lib/typescript/utils/index.d.ts +16 -1
  43. package/lib/typescript/utils/index.d.ts.map +1 -1
  44. package/package.json +1 -1
  45. package/src/Spec/NativeCompressor.ts +11 -0
  46. package/src/index.tsx +6 -0
  47. package/src/utils/index.tsx +28 -1
@@ -0,0 +1,388 @@
1
+ package com.reactnativecompressor.Video.VideoCompressor.video
2
+
3
+ import android.media.MediaCodec
4
+ import android.media.MediaFormat
5
+ import com.coremedia.iso.boxes.*
6
+ import com.googlecode.mp4parser.util.Matrix
7
+ import java.io.FileOutputStream
8
+ import java.nio.ByteBuffer
9
+ import java.nio.channels.FileChannel
10
+ import java.util.*
11
+
12
+ class MP4Builder {
13
+
14
+ private lateinit var mdat: Mdat
15
+ private lateinit var currentMp4Movie: Mp4Movie
16
+ private lateinit var fos: FileOutputStream
17
+ private lateinit var fc: FileChannel
18
+ private var dataOffset: Long = 0
19
+ private var wroteSinceLastMdat: Long = 0
20
+ private var writeNewMdat = true
21
+ private val track2SampleSizes = HashMap<Track, LongArray>()
22
+ private lateinit var sizeBuffer: ByteBuffer
23
+
24
+ @Throws(Exception::class)
25
+ fun createMovie(mp4Movie: Mp4Movie): MP4Builder {
26
+ currentMp4Movie = mp4Movie
27
+
28
+ fos = FileOutputStream(mp4Movie.getCacheFile())
29
+ fc = fos.channel
30
+
31
+ val fileTypeBox: FileTypeBox = createFileTypeBox()
32
+ fileTypeBox.getBox(fc)
33
+ dataOffset += fileTypeBox.size
34
+ wroteSinceLastMdat = dataOffset
35
+
36
+ mdat = Mdat()
37
+ sizeBuffer = ByteBuffer.allocateDirect(4)
38
+
39
+ return this
40
+ }
41
+
42
+ @Throws(Exception::class)
43
+ private fun flushCurrentMdat() {
44
+ val oldPosition = fc.position()
45
+ fc.position(mdat.offset)
46
+ mdat.getBox(fc)
47
+ fc.position(oldPosition)
48
+ mdat.setDataOffset(0)
49
+ mdat.setContentSize(0)
50
+ fos.flush()
51
+ }
52
+
53
+ @Throws(Exception::class)
54
+ fun writeSampleData(
55
+ trackIndex: Int,
56
+ byteBuf: ByteBuffer,
57
+ bufferInfo: MediaCodec.BufferInfo,
58
+ isAudio: Boolean
59
+ ) {
60
+
61
+ if (writeNewMdat) {
62
+ mdat.apply {
63
+ setContentSize(0)
64
+ getBox(fc)
65
+ setDataOffset(dataOffset)
66
+ }
67
+ dataOffset += 16
68
+ wroteSinceLastMdat += 16
69
+ writeNewMdat = false
70
+ }
71
+
72
+ mdat.setContentSize(mdat.getContentSize() + bufferInfo.size)
73
+ wroteSinceLastMdat += bufferInfo.size.toLong()
74
+
75
+ var flush = false
76
+ if (wroteSinceLastMdat >= 32 * 1024) {
77
+ flushCurrentMdat()
78
+ writeNewMdat = true
79
+ flush = true
80
+ wroteSinceLastMdat = 0
81
+ }
82
+
83
+ currentMp4Movie.addSample(trackIndex, dataOffset, bufferInfo)
84
+
85
+ if (!isAudio) {
86
+ byteBuf.position(bufferInfo.offset + 4)
87
+ byteBuf.limit(bufferInfo.offset + bufferInfo.size)
88
+
89
+ sizeBuffer.position(0)
90
+ sizeBuffer.putInt(bufferInfo.size - 4)
91
+ sizeBuffer.position(0)
92
+ fc.write(sizeBuffer)
93
+ } else {
94
+ byteBuf.position(bufferInfo.offset + 0)
95
+ byteBuf.limit(bufferInfo.offset + bufferInfo.size)
96
+ }
97
+
98
+ fc.write(byteBuf)
99
+ dataOffset += bufferInfo.size.toLong()
100
+
101
+ if (flush) {
102
+ fos.flush()
103
+ }
104
+ }
105
+
106
+ fun addTrack(mediaFormat: MediaFormat, isAudio: Boolean): Int =
107
+ currentMp4Movie.addTrack(mediaFormat, isAudio)
108
+
109
+ @Throws(Exception::class)
110
+ fun finishMovie() {
111
+ if (mdat.getContentSize() != 0L) {
112
+ flushCurrentMdat()
113
+ }
114
+
115
+ for (track in currentMp4Movie.getTracks()) {
116
+ val samples: List<Sample> = track.getSamples()
117
+ val sizes = LongArray(samples.size)
118
+ for (i in sizes.indices) {
119
+ sizes[i] = samples[i].size
120
+ }
121
+ track2SampleSizes[track] = sizes
122
+ }
123
+
124
+ val moov: Box = createMovieBox(currentMp4Movie)
125
+ moov.getBox(fc)
126
+
127
+ fos.flush()
128
+ fc.close()
129
+ fos.close()
130
+ }
131
+
132
+ private fun createFileTypeBox(): FileTypeBox {
133
+ // completed list can be found at https://www.ftyps.com/
134
+ val minorBrands = listOf(
135
+ "isom", "iso2", "mp41"
136
+ )
137
+
138
+ return FileTypeBox("isom", 0, minorBrands)
139
+ }
140
+
141
+ private fun gcd(a: Long, b: Long): Long {
142
+ return if (b == 0L) a
143
+ else gcd(b, a % b)
144
+ }
145
+
146
+ private fun getTimescale(mp4Movie: Mp4Movie): Long {
147
+ var timescale: Long = 0
148
+ if (mp4Movie.getTracks().isNotEmpty()) {
149
+ timescale = mp4Movie.getTracks().iterator().next().getTimeScale().toLong()
150
+ }
151
+
152
+ for (track in mp4Movie.getTracks()) {
153
+ timescale = gcd(
154
+ track.getTimeScale().toLong(),
155
+ timescale
156
+ )
157
+ }
158
+
159
+ return timescale
160
+ }
161
+
162
+ private fun createMovieBox(movie: Mp4Movie): MovieBox {
163
+ val movieBox = MovieBox()
164
+ val mvhd = MovieHeaderBox()
165
+
166
+ mvhd.apply {
167
+ creationTime = Date()
168
+ modificationTime = Date()
169
+ matrix = Matrix.ROTATE_0
170
+ }
171
+
172
+ val movieTimeScale = getTimescale(movie)
173
+ var duration: Long = 0
174
+
175
+ for (track in movie.getTracks()) {
176
+ val tracksDuration = track.getDuration() * movieTimeScale / track.getTimeScale()
177
+ if (tracksDuration > duration) {
178
+ duration = tracksDuration
179
+ }
180
+ }
181
+
182
+ mvhd.duration = duration
183
+ mvhd.timescale = movieTimeScale
184
+ mvhd.nextTrackId = (movie.getTracks().size + 1).toLong()
185
+ movieBox.addBox(mvhd)
186
+
187
+ for (track in movie.getTracks()) {
188
+ movieBox.addBox(createTrackBox(track, movie))
189
+ }
190
+
191
+ return movieBox
192
+ }
193
+
194
+ private fun createTrackBox(track: Track, movie: Mp4Movie): TrackBox {
195
+ val trackBox = TrackBox()
196
+ val tkhd = TrackHeaderBox()
197
+ tkhd.apply {
198
+ isEnabled = true
199
+ isInPreview = true
200
+ isInMovie = true
201
+ matrix = if (track.isAudio()) {
202
+ Matrix.ROTATE_0
203
+ } else {
204
+ movie.getMatrix()
205
+ }
206
+ alternateGroup = 0
207
+ creationTime = track.getCreationTime()
208
+ duration = track.getDuration() * getTimescale(movie) / track.getTimeScale()
209
+ height = track.getHeight().toDouble()
210
+ width = track.getWidth().toDouble()
211
+ layer = 0
212
+ modificationTime = Date()
213
+ trackId = track.getTrackId() + 1
214
+ volume = track.getVolume()
215
+ }
216
+ trackBox.addBox(tkhd)
217
+
218
+ val mdia = MediaBox()
219
+ trackBox.addBox(mdia)
220
+
221
+ val mdhd = MediaHeaderBox()
222
+ mdhd.apply {
223
+ creationTime = track.getCreationTime()
224
+ duration = track.getDuration()
225
+ timescale = track.getTimeScale().toLong()
226
+ language = "eng"
227
+ }
228
+ mdia.addBox(mdhd)
229
+
230
+ val hdlr = HandlerBox()
231
+ hdlr.apply {
232
+ name = if (track.isAudio()) "SoundHandle" else "VideoHandle"
233
+ handlerType = track.getHandler()
234
+ }
235
+ mdia.addBox(hdlr)
236
+
237
+ val minf = MediaInformationBox()
238
+ when {
239
+ track.getHandler() == "vide" -> {
240
+ minf.addBox(VideoMediaHeaderBox())
241
+ }
242
+ track.getHandler() == "soun" -> {
243
+ minf.addBox(SoundMediaHeaderBox())
244
+ }
245
+ track.getHandler() == "text" -> {
246
+ minf.addBox(NullMediaHeaderBox())
247
+ }
248
+ track.getHandler() == "subt" -> {
249
+ minf.addBox(SubtitleMediaHeaderBox())
250
+ }
251
+ track.getHandler() == "hint" -> {
252
+ minf.addBox(HintMediaHeaderBox())
253
+ }
254
+ track.getHandler() == "sbtl" -> {
255
+ minf.addBox(NullMediaHeaderBox())
256
+ }
257
+ }
258
+
259
+ val dinf = DataInformationBox()
260
+ val dref = DataReferenceBox()
261
+ dinf.addBox(dref)
262
+
263
+ val url = DataEntryUrlBox()
264
+ url.flags = 1
265
+
266
+ dref.addBox(url)
267
+ minf.addBox(dinf)
268
+
269
+ val stbl: Box = createStbl(track)
270
+ minf.addBox(stbl)
271
+ mdia.addBox(minf)
272
+
273
+ return trackBox
274
+ }
275
+
276
+ private fun createStbl(track: Track): Box {
277
+ val stbl = SampleTableBox()
278
+ createStsd(track, stbl)
279
+ createStts(track, stbl)
280
+ createStss(track, stbl)
281
+ createStsc(track, stbl)
282
+ createStsz(track, stbl)
283
+ createStco(track, stbl)
284
+ return stbl
285
+ }
286
+
287
+ private fun createStsd(track: Track, stbl: SampleTableBox) {
288
+ stbl.addBox(track.getSampleDescriptionBox())
289
+ }
290
+
291
+ private fun createStts(track: Track, stbl: SampleTableBox) {
292
+ var lastEntry: TimeToSampleBox.Entry? = null
293
+ val entries: MutableList<TimeToSampleBox.Entry> = ArrayList()
294
+ for (delta in track.getSampleDurations()) {
295
+ if (lastEntry != null && lastEntry.delta == delta) {
296
+ lastEntry.count = lastEntry.count + 1
297
+ } else {
298
+ lastEntry = TimeToSampleBox.Entry(1, delta)
299
+ entries.add(lastEntry)
300
+ }
301
+ }
302
+ val stts = TimeToSampleBox()
303
+ stts.entries = entries
304
+ stbl.addBox(stts)
305
+ }
306
+
307
+ private fun createStss(track: Track, stbl: SampleTableBox) {
308
+ val syncSamples = track.getSyncSamples()
309
+ if (syncSamples != null && syncSamples.isNotEmpty()) {
310
+ val stss = SyncSampleBox()
311
+ stss.sampleNumber = syncSamples
312
+ stbl.addBox(stss)
313
+ }
314
+ }
315
+
316
+ private fun createStsc(track: Track, stbl: SampleTableBox) {
317
+ val stsc = SampleToChunkBox()
318
+ stsc.entries = LinkedList()
319
+
320
+ var lastOffset: Long
321
+ var lastChunkNumber = 1
322
+ var lastSampleCount = 0
323
+ var previousWrittenChunkCount = -1
324
+
325
+ val samplesCount = track.getSamples().size
326
+ for (a in 0 until samplesCount) {
327
+ val sample = track.getSamples()[a]
328
+ val offset = sample.offset
329
+ val size = sample.size
330
+
331
+ lastOffset = offset + size
332
+ lastSampleCount++
333
+
334
+ var write = false
335
+ if (a != samplesCount - 1) {
336
+ val nextSample = track.getSamples()[a + 1]
337
+ if (lastOffset != nextSample.offset) {
338
+ write = true
339
+ }
340
+ } else {
341
+ write = true
342
+ }
343
+
344
+ if (write) {
345
+ if (previousWrittenChunkCount != lastSampleCount) {
346
+ stsc.entries.add(
347
+ SampleToChunkBox.Entry(
348
+ lastChunkNumber.toLong(),
349
+ lastSampleCount.toLong(), 1
350
+ )
351
+ )
352
+ previousWrittenChunkCount = lastSampleCount
353
+ }
354
+ lastSampleCount = 0
355
+ lastChunkNumber++
356
+ }
357
+ }
358
+ stbl.addBox(stsc)
359
+ }
360
+
361
+ private fun createStsz(track: Track, stbl: SampleTableBox) {
362
+ val stsz = SampleSizeBox()
363
+ stsz.sampleSizes = track2SampleSizes[track]
364
+ stbl.addBox(stsz)
365
+ }
366
+
367
+ private fun createStco(track: Track, stbl: SampleTableBox) {
368
+ val chunksOffsets = ArrayList<Long>()
369
+ var lastOffset: Long = -1
370
+ for (sample in track.getSamples()) {
371
+ val offset = sample.offset
372
+ if (lastOffset != -1L && lastOffset != offset) {
373
+ lastOffset = -1
374
+ }
375
+ if (lastOffset == -1L) {
376
+ chunksOffsets.add(offset)
377
+ }
378
+ lastOffset = offset + sample.size
379
+ }
380
+ val chunkOffsetsLong = LongArray(chunksOffsets.size)
381
+ for (a in chunksOffsets.indices) {
382
+ chunkOffsetsLong[a] = chunksOffsets[a]
383
+ }
384
+ val stco = StaticChunkOffsetBox()
385
+ stco.chunkOffsets = chunkOffsetsLong
386
+ stbl.addBox(stco)
387
+ }
388
+ }
@@ -0,0 +1,74 @@
1
+ package com.reactnativecompressor.Video.VideoCompressor.video
2
+
3
+ import com.coremedia.iso.BoxParser
4
+ import com.coremedia.iso.IsoFile
5
+ import com.coremedia.iso.IsoTypeWriter
6
+ import com.coremedia.iso.boxes.Box
7
+ import com.coremedia.iso.boxes.Container
8
+ import com.googlecode.mp4parser.DataSource
9
+ import java.nio.ByteBuffer
10
+ import java.nio.channels.WritableByteChannel
11
+
12
+ class Mdat : Box {
13
+
14
+ private lateinit var parent: Container
15
+ private var contentSize = (1024 * 1024 * 1024).toLong()
16
+ private var dataOffset: Long = 0
17
+
18
+ override fun getParent(): Container = parent
19
+
20
+ override fun setParent(parent: Container) {
21
+ this.parent = parent
22
+ }
23
+
24
+ override fun getSize(): Long = 16 + contentSize
25
+
26
+ override fun getOffset(): Long = dataOffset
27
+
28
+ fun setDataOffset(offset: Long) {
29
+ dataOffset = offset
30
+ }
31
+
32
+ fun setContentSize(contentSize: Long) {
33
+ this.contentSize = contentSize
34
+ }
35
+
36
+ fun getContentSize(): Long {
37
+ return contentSize
38
+ }
39
+
40
+ override fun getType(): String = "mdat"
41
+
42
+ private fun isSmallBox(contentSize: Long): Boolean = contentSize + 8 < 4294967296L
43
+
44
+ override fun getBox(writableByteChannel: WritableByteChannel) {
45
+ val bb = ByteBuffer.allocate(16)
46
+ val size = size
47
+ if (isSmallBox(size)) {
48
+ if (size >= 0 && size <= 1L shl 32) {
49
+ IsoTypeWriter.writeUInt32(bb, size)
50
+ } else {
51
+ // TODO(ABED): Investigate when this could happen.
52
+ IsoTypeWriter.writeUInt32(bb, 1)
53
+ }
54
+ } else {
55
+ IsoTypeWriter.writeUInt32(bb, 1)
56
+ }
57
+ bb.put(IsoFile.fourCCtoBytes("mdat"))
58
+ if (isSmallBox(size)) {
59
+ bb.put(ByteArray(8))
60
+ } else {
61
+ IsoTypeWriter.writeUInt64(bb, if (size >= 0) size else 1)
62
+ }
63
+ bb.rewind()
64
+ writableByteChannel.write(bb)
65
+ }
66
+
67
+ override fun parse(
68
+ dataSource: DataSource?,
69
+ header: ByteBuffer?,
70
+ contentSize: Long,
71
+ boxParser: BoxParser?
72
+ ) {
73
+ }
74
+ }
@@ -0,0 +1,54 @@
1
+ package com.reactnativecompressor.Video.VideoCompressor.video
2
+
3
+ import android.media.MediaCodec
4
+ import android.media.MediaFormat
5
+ import com.googlecode.mp4parser.util.Matrix
6
+ import java.io.File
7
+ import java.util.*
8
+
9
+ class Mp4Movie {
10
+
11
+ private var matrix = Matrix.ROTATE_0
12
+ private val tracks = ArrayList<Track>()
13
+ private var cacheFile: File? = null
14
+
15
+ fun getMatrix(): Matrix? = matrix
16
+
17
+ fun setCacheFile(file: File) {
18
+ cacheFile = file
19
+ }
20
+
21
+ fun setRotation(angle: Int) {
22
+ when (angle) {
23
+ 0 -> {
24
+ matrix = Matrix.ROTATE_0
25
+ }
26
+ 90 -> {
27
+ matrix = Matrix.ROTATE_90
28
+ }
29
+ 180 -> {
30
+ matrix = Matrix.ROTATE_180
31
+ }
32
+ 270 -> {
33
+ matrix = Matrix.ROTATE_270
34
+ }
35
+ }
36
+ }
37
+
38
+ fun getTracks(): ArrayList<Track> = tracks
39
+
40
+ fun getCacheFile(): File? = cacheFile
41
+
42
+ fun addSample(trackIndex: Int, offset: Long, bufferInfo: MediaCodec.BufferInfo) {
43
+ if (trackIndex < 0 || trackIndex >= tracks.size) {
44
+ return
45
+ }
46
+ val track = tracks[trackIndex]
47
+ track.addSample(offset, bufferInfo)
48
+ }
49
+
50
+ fun addTrack(mediaFormat: MediaFormat, isAudio: Boolean): Int {
51
+ tracks.add(Track(tracks.size, mediaFormat, isAudio))
52
+ return tracks.size - 1
53
+ }
54
+ }
@@ -0,0 +1,102 @@
1
+ package com.reactnativecompressor.Video.VideoCompressor.video
2
+
3
+ import android.graphics.SurfaceTexture
4
+ import android.graphics.SurfaceTexture.OnFrameAvailableListener
5
+ import android.view.Surface
6
+
7
+ class OutputSurface : OnFrameAvailableListener {
8
+
9
+ private var mSurfaceTexture: SurfaceTexture? = null
10
+ private var mSurface: Surface? = null
11
+ private val mFrameSyncObject = Object()
12
+ private var mFrameAvailable = false
13
+ private var mTextureRender: TextureRenderer? = null
14
+
15
+ /**
16
+ * Creates an OutputSurface using the current EGL context. This Surface will be
17
+ * passed to MediaCodec.configure().
18
+ */
19
+ init {
20
+ setup()
21
+ }
22
+
23
+ /**
24
+ * Creates instances of TextureRender and SurfaceTexture, and a Surface associated
25
+ * with the SurfaceTexture.
26
+ */
27
+ private fun setup() {
28
+ mTextureRender = TextureRenderer()
29
+ mTextureRender?.let {
30
+ it.surfaceCreated()
31
+
32
+ // Even if we don't access the SurfaceTexture after the constructor returns, we
33
+ // still need to keep a reference to it. The Surface doesn't retain a reference
34
+ // at the Java level, so if we don't either then the object can get GCed, which
35
+ // causes the native finalizer to run.
36
+ mSurfaceTexture = SurfaceTexture(it.getTextureId())
37
+ mSurfaceTexture?.let { surfaceTexture ->
38
+ surfaceTexture.setOnFrameAvailableListener(this)
39
+ mSurface = Surface(mSurfaceTexture)
40
+ }
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Discards all resources held by this class, notably the EGL context.
46
+ */
47
+ fun release() {
48
+ mSurface?.release()
49
+
50
+ mTextureRender = null
51
+ mSurface = null
52
+ mSurfaceTexture = null
53
+ }
54
+
55
+ /**
56
+ * Returns the Surface that we draw onto.
57
+ */
58
+ fun getSurface(): Surface? = mSurface
59
+
60
+ /**
61
+ * Latches the next buffer into the texture. Must be called from the thread that created
62
+ * the OutputSurface object, after the onFrameAvailable callback has signaled that new
63
+ * data is available.
64
+ */
65
+ fun awaitNewImage() {
66
+ val timeOutMS = 100
67
+ synchronized(mFrameSyncObject) {
68
+ while (!mFrameAvailable) {
69
+ try {
70
+ // Wait for onFrameAvailable() to signal us. Use a timeout to avoid
71
+ // stalling the test if it doesn't arrive.
72
+ mFrameSyncObject.wait(timeOutMS.toLong())
73
+ if (!mFrameAvailable) {
74
+ throw RuntimeException("Surface frame wait timed out")
75
+ }
76
+ } catch (ie: InterruptedException) {
77
+ throw RuntimeException(ie)
78
+ }
79
+ }
80
+ mFrameAvailable = false
81
+ }
82
+ mTextureRender?.checkGlError("before updateTexImage")
83
+ mSurfaceTexture?.updateTexImage()
84
+ }
85
+
86
+ /**
87
+ * Draws the data from SurfaceTexture onto the current EGL surface.
88
+ */
89
+ fun drawImage() {
90
+ mTextureRender?.drawFrame(mSurfaceTexture!!)
91
+ }
92
+
93
+ override fun onFrameAvailable(p0: SurfaceTexture?) {
94
+ synchronized(mFrameSyncObject) {
95
+ if (mFrameAvailable) {
96
+ throw RuntimeException("mFrameAvailable already set, frame could be dropped")
97
+ }
98
+ mFrameAvailable = true
99
+ mFrameSyncObject.notifyAll()
100
+ }
101
+ }
102
+ }
@@ -0,0 +1,9 @@
1
+ package com.reactnativecompressor.Video.VideoCompressor.video
2
+
3
+ data class Result(
4
+ val index: Int,
5
+ val success: Boolean,
6
+ val failureMessage: String?,
7
+ val size: Long = 0,
8
+ val path: String? = null,
9
+ )
@@ -0,0 +1,3 @@
1
+ package com.reactnativecompressor.Video.VideoCompressor.video
2
+
3
+ data class Sample(var offset: Long, var size: Long)