react-native-compressor 1.8.5 → 1.8.6

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.
@@ -1,527 +1,205 @@
1
1
  package com.reactnativecompressor.Audio
2
2
 
3
+
3
4
  import android.annotation.SuppressLint
4
- import android.media.MediaCodec
5
- import android.media.MediaCodecInfo
6
- import android.media.MediaCodecList
7
- import android.media.MediaExtractor
8
- import android.media.MediaFormat
9
- import android.media.MediaMetadataRetriever
10
- import android.media.MediaMuxer
11
- import android.os.Build
12
- import android.util.Log
13
- import androidx.annotation.RequiresApi
14
- import com.reactnativecompressor.Video.VideoCompressor.video.OutputSurface
5
+ import com.facebook.react.bridge.Promise
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.naman14.androidlame.LameBuilder
8
+ import com.naman14.androidlame.WaveReader
9
+ import com.reactnativecompressor.Utils.MediaCache
10
+ import com.reactnativecompressor.Utils.Utils
11
+ import com.reactnativecompressor.Utils.Utils.addLog
12
+ import javazoom.jl.converter.Converter
13
+ import java.io.BufferedOutputStream
15
14
  import java.io.File
15
+ import java.io.FileNotFoundException
16
+ import java.io.FileOutputStream
16
17
  import java.io.IOException
17
- import java.nio.ByteBuffer
18
18
 
19
19
  class AudioCompressor {
20
- var path: String? = null
21
- private var outputPath: String? = null
22
- private var mBufferInfo: MediaCodec.BufferInfo? = null
23
- private var mMuxer: MediaMuxer? = null
24
- private var mEncoder: MediaCodec? = null
25
- private var mDecoder: MediaCodec? = null
26
- private var mTrackIndex = 0
27
- private var mInputSurface: OutputSurface? = null
28
-
29
- // bit rate, in bits per second
30
- private var mBitRate = -1
31
- private val TIMEOUT_USEC = 2500
32
-
33
- /***
34
- * trans video and audio by mediacodec
35
- *
36
- */
37
- @SuppressLint("LongLogTag")
38
- @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
39
- fun CompressAudio(sourcePath: String?, destinationPath: String?, nbitrate: Int): Boolean {
40
- path = sourcePath
41
- outputPath = destinationPath
42
- if (checkParmsError(sourcePath, destinationPath, nbitrate)) {
43
- return false
20
+ companion object {
21
+ val TAG="AudioMain"
22
+ private const val OUTPUT_STREAM_BUFFER = 8192
23
+
24
+ var outputStream: BufferedOutputStream? = null
25
+ var waveReader: WaveReader? = null
26
+ @JvmStatic
27
+ fun CompressAudio(
28
+ fileUrl: String,
29
+ quality: String,
30
+ context: ReactApplicationContext,
31
+ promise: Promise,
32
+ ) {
33
+ try {
34
+ val filePath = fileUrl.replace("file://", "")
35
+ var wavPath=filePath;
36
+ var isNonWav:Boolean=false
37
+ if (!fileUrl.endsWith(".waw", ignoreCase = true))
38
+ {
39
+ addLog("mp3 file found")
40
+ wavPath= Utils.generateCacheFilePath("wav", context)
41
+ val converter = Converter()
42
+ converter.convert(filePath, wavPath)
43
+ isNonWav=true
44
44
  }
45
45
 
46
- //get origin video info
47
- val retriever = MediaMetadataRetriever()
48
- retriever.setDataSource(path)
49
- // String framecount = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT);
50
- val duration = java.lang.Long.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)) * 1000
51
- val startTime: Long = -1
52
- val endTime: Long = -1
53
- mBitRate = nbitrate
54
- // NUM_FRAMES = Integer.getInteger(framecount);
55
- //IFRAME_INTERVAL = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
56
- var error = false
57
- val videoStartTime: Long = -1
58
- val time = System.currentTimeMillis()
59
- val cacheFile = File(destinationPath)
60
- val inputFile = File(path)
61
- if (!inputFile.canRead()) {
62
- return false
63
- }
64
- var extractor: MediaExtractor? = null
65
- var mAudioExtractor: MediaExtractor? = null
66
- try {
67
- // video MediaExtractor
68
- extractor = MediaExtractor()
69
- extractor.setDataSource(inputFile.toString())
70
-
71
- // audio MediaExtractor
72
- mAudioExtractor = MediaExtractor()
73
- mAudioExtractor.setDataSource(inputFile.toString())
74
- mMuxer = try {
75
- MediaMuxer(outputPath!!, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
76
- } catch (ioe: IOException) {
77
- throw RuntimeException("MediaMuxer creation failed", ioe)
78
- }
79
- val muxerAudioTrackIndex = 0
80
- val audioIndex = selectTrack(mAudioExtractor, true)
81
- if (audioIndex >= 0) {
82
- mAudioExtractor.selectTrack(audioIndex)
83
- mAudioExtractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC)
84
- val trackFormat = mAudioExtractor.getTrackFormat(audioIndex)
85
- // muxerAudioTrackIndex = mMuxer.addTrack(trackFormat);
86
-
87
- // extractor.unselectTrack(muxerAudioTrackIndex);
88
- }
89
- /**
90
- * mediacodec + surface + opengl
91
- */
92
- Log.d("CompressAudio", "CompressAudio: ")
93
- val videoIndex = selectTrack(extractor, true)
94
- if (videoIndex >= 0) {
95
- var videoTime: Long = -1
96
- var outputDone = false
97
- var inputDone = false
98
- var decoderDone = false
99
- val swapUV = 0
100
- var videoTrackIndex = MEDIATYPE_NOT_AUDIO_VIDEO
101
- extractor.selectTrack(videoIndex)
102
- if (startTime > 0) {
103
- extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC)
104
- } else {
105
- extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC)
106
- }
107
- val inputFormat = extractor.getTrackFormat(videoIndex)
108
- /**
109
- * init mediacodec / encoder and decoder
110
- */
111
- prepareEncoder(inputFormat)
112
- var decoderInputBuffers: Array<ByteBuffer?>? = null
113
- var encoderOutputBuffers: Array<ByteBuffer?>? = null
114
- decoderInputBuffers = mDecoder!!.inputBuffers
115
- encoderOutputBuffers = mEncoder!!.outputBuffers
116
- while (!outputDone) {
117
- if (!inputDone) {
118
- var eof = false
119
- val index = extractor.sampleTrackIndex
120
- if (index == videoIndex) {
121
- val inputBufIndex = mDecoder!!.dequeueInputBuffer(TIMEOUT_USEC.toLong())
122
- if (inputBufIndex >= 0) {
123
- var inputBuf: ByteBuffer?
124
- inputBuf = if (Build.VERSION.SDK_INT < 21) {
125
- decoderInputBuffers[inputBufIndex]
126
- } else {
127
- mDecoder!!.getInputBuffer(inputBufIndex)
128
- }
129
- val chunkSize = extractor.readSampleData(inputBuf!!, 0)
130
- if (chunkSize < 0) {
131
- mDecoder!!.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
132
- inputDone = true
133
- } else {
134
- mDecoder!!.queueInputBuffer(inputBufIndex, 0, chunkSize, extractor.sampleTime, 0)
135
- extractor.advance()
136
- }
137
- }
138
- } else if (index == -1) {
139
- eof = true
140
- }
141
- if (eof) {
142
- val inputBufIndex = mDecoder!!.dequeueInputBuffer(TIMEOUT_USEC.toLong())
143
- if (inputBufIndex >= 0) {
144
- mDecoder!!.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
145
- inputDone = true
146
- }
147
- }
148
- }
149
- var decoderOutputAvailable = !decoderDone
150
- var encoderOutputAvailable = true
151
- while (decoderOutputAvailable || encoderOutputAvailable) {
152
- val encoderStatus = mEncoder!!.dequeueOutputBuffer(mBufferInfo!!, TIMEOUT_USEC.toLong())
153
- if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
154
- encoderOutputAvailable = false
155
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
156
- if (Build.VERSION.SDK_INT < 21) {
157
- encoderOutputBuffers = mEncoder!!.outputBuffers
158
- }
159
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
160
- val newFormat = mEncoder!!.outputFormat
161
- if (videoTrackIndex == MEDIATYPE_NOT_AUDIO_VIDEO) {
162
- videoTrackIndex = mMuxer!!.addTrack(newFormat)
163
- mTrackIndex = videoTrackIndex
164
- mMuxer!!.start()
165
- }
166
- } else if (encoderStatus < 0) {
167
- throw RuntimeException("unexpected result from mEncoder.dequeueOutputBuffer: $encoderStatus")
168
- } else {
169
- var encodedData: ByteBuffer?
170
- encodedData = if (Build.VERSION.SDK_INT < 21) {
171
- encoderOutputBuffers!![encoderStatus]
172
- } else {
173
- mEncoder!!.getOutputBuffer(encoderStatus)
174
- }
175
- if (encodedData == null) {
176
- throw RuntimeException("encoderOutputBuffer $encoderStatus was null")
177
- }
178
- if (mBufferInfo!!.size > 1) {
179
- if (mBufferInfo!!.flags and MediaCodec.BUFFER_FLAG_CODEC_CONFIG == 0) {
180
- mMuxer!!.writeSampleData(videoTrackIndex, encodedData, mBufferInfo!!)
181
- } else if (videoTrackIndex == MEDIATYPE_NOT_AUDIO_VIDEO) {
182
- val csd = ByteArray(mBufferInfo!!.size)
183
- encodedData.limit(mBufferInfo!!.offset + mBufferInfo!!.size)
184
- encodedData.position(mBufferInfo!!.offset)
185
- encodedData[csd]
186
- var sps: ByteBuffer? = null
187
- var pps: ByteBuffer? = null
188
- for (a in mBufferInfo!!.size - 1 downTo 0) {
189
- if (a > 3) {
190
- if (csd[a].toInt() == 1 && csd[a - 1].toInt() == 0 && csd[a - 2].toInt() == 0 && csd[a - 3].toInt() == 0) {
191
- sps = ByteBuffer.allocate(a - 3)
192
- pps = ByteBuffer.allocate(mBufferInfo!!.size - (a - 3))
193
- sps.put(csd, 0, a - 3).position(0)
194
- pps.put(csd, a - 3, mBufferInfo!!.size - (a - 3)).position(0)
195
- break
196
- }
197
- } else {
198
- break
199
- }
200
- }
201
- val newFormat = MediaFormat.createAudioFormat(MIME_TYPE, nbitrate, 1)
202
- if (sps != null && pps != null) {
203
- newFormat.setByteBuffer("csd-0", sps)
204
- newFormat.setByteBuffer("csd-1", pps)
205
- }
206
- videoTrackIndex = mMuxer!!.addTrack(newFormat)
207
- mMuxer!!.start()
208
- }
209
- }
210
- outputDone = mBufferInfo!!.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0
211
- mEncoder!!.releaseOutputBuffer(encoderStatus, false)
212
- }
213
- if (encoderStatus != MediaCodec.INFO_TRY_AGAIN_LATER) {
214
- continue
215
- }
216
- if (!decoderDone) {
217
- val decoderStatus = mDecoder!!.dequeueOutputBuffer(mBufferInfo!!, TIMEOUT_USEC.toLong())
218
- if (decoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
219
- decoderOutputAvailable = false
220
- } else if (decoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
221
- } else if (decoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
222
- val newFormat = mDecoder!!.outputFormat
223
- Log.e(TAG, "newFormat = $newFormat")
224
- } else if (decoderStatus < 0) {
225
- throw RuntimeException("unexpected result from mDecoder.dequeueOutputBuffer: $decoderStatus")
226
- } else {
227
- var doRender = false
228
- doRender = mBufferInfo!!.size != 0
229
- if (endTime > 0 && mBufferInfo!!.presentationTimeUs >= endTime) {
230
- inputDone = true
231
- decoderDone = true
232
- doRender = false
233
- mBufferInfo!!.flags = mBufferInfo!!.flags or MediaCodec.BUFFER_FLAG_END_OF_STREAM
234
- }
235
- if (startTime > 0 && videoTime == -1L) {
236
- if (mBufferInfo!!.presentationTimeUs < startTime) {
237
- doRender = false
238
- Log.e(TAG, "drop frame startTime = " + startTime + " present time = " + mBufferInfo!!.presentationTimeUs)
239
- } else {
240
- videoTime = mBufferInfo!!.presentationTimeUs
241
- }
242
- }
243
- mDecoder!!.releaseOutputBuffer(decoderStatus, doRender)
244
- if (mBufferInfo!!.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) {
245
- decoderOutputAvailable = false
246
- outputDone = true
247
- Log.e(TAG, "decoder stream end")
248
- }
249
- }
250
- }
251
- }
252
- }
253
- }
254
- extractor.unselectTrack(videoIndex)
255
- writeAudioTrack(mAudioExtractor, mMuxer!!, mBufferInfo, cacheFile, muxerAudioTrackIndex)
256
- } catch (e: Exception) {
257
- error = true
258
- Log.e(TAG, e.message!!)
259
- } finally {
260
- if (extractor != null) {
261
- extractor.release()
262
- extractor = null
263
- }
264
- if (mAudioExtractor != null) {
265
- mAudioExtractor.release()
266
- mAudioExtractor = null
46
+
47
+ autoCompressHelper(wavPath, quality,context) { mp3Path, finished ->
48
+ if (finished) {
49
+ val returnableFilePath:String="file://$mp3Path"
50
+ addLog("finished: " + returnableFilePath)
51
+ MediaCache.removeCompletedImagePath(fileUrl)
52
+ if(isNonWav)
53
+ {
54
+ File(wavPath).delete()
267
55
  }
268
- Log.e(TAG, "time = " + (System.currentTimeMillis() - time))
56
+ promise.resolve(returnableFilePath)
57
+ } else {
58
+ addLog("error: "+mp3Path)
59
+ promise.resolve(fileUrl)
60
+ }
269
61
  }
270
- Log.e(TAG + " Path", path + "")
271
- Log.e(TAG + " Path", cacheFile.path + "")
272
- Log.e(TAG + " Path", inputFile.path + "")
273
- releaseCoder()
274
- return if (error) false else true
62
+ } catch (e: Exception) {
63
+ promise.resolve(fileUrl)
64
+ }
275
65
  }
276
66
 
277
- private fun checkParmsError(sourcePath: String?, destinationPath: String?, nbitrate: Int): Boolean {
278
- return if (nbitrate <= 0) true else false
67
+ private fun getAudioBitrateByQuality(quality: String): Int {
68
+ return when (quality) {
69
+ "low" -> 64 // Set your low bitrate value here
70
+ "medium" -> 128 // Set your medium bitrate value here
71
+ "high" -> 256 // Set your high bitrate value here
72
+ else -> 128 // Default to medium bitrate if quality is not recognized
73
+ }
279
74
  }
280
75
 
281
76
  @SuppressLint("WrongConstant")
282
- @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
283
- @Throws(Exception::class)
284
- private fun simpleReadAndWriteTrack(extractor: MediaExtractor, mediaMuxer: MediaMuxer, info: MediaCodec.BufferInfo, start: Long, end: Long, file: File, isAudio: Boolean): Long {
285
- val trackIndex = selectTrack(extractor, isAudio)
286
- if (trackIndex >= 0) {
287
- extractor.selectTrack(trackIndex)
288
- val trackFormat = extractor.getTrackFormat(trackIndex)
289
- val muxerTrackIndex = mediaMuxer.addTrack(trackFormat)
290
- if (!isAudio) mediaMuxer.start()
291
- val maxBufferSize = trackFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
292
- var inputDone = false
293
- if (start > 0) {
294
- extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC)
295
- } else {
296
- extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC)
297
- }
298
- val buffer = ByteBuffer.allocateDirect(maxBufferSize)
299
- var startTime: Long = -1
300
- while (!inputDone) {
301
- var eof = false
302
- val index = extractor.sampleTrackIndex
303
- if (index == trackIndex) {
304
- info.size = extractor.readSampleData(buffer, 0)
305
- if (info.size < 0) {
306
- info.size = 0
307
- eof = true
308
- } else {
309
- info.presentationTimeUs = extractor.sampleTime
310
- if (start > 0 && startTime == -1L) {
311
- startTime = info.presentationTimeUs
312
- }
313
- if (end < 0 || info.presentationTimeUs < end) {
314
- info.offset = 0
315
- info.flags = extractor.sampleFlags
316
- mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info)
317
- extractor.advance()
318
- } else {
319
- eof = true
320
- }
321
- }
322
- } else if (index == -1) {
323
- eof = true
324
- }
325
- if (eof) {
326
- inputDone = true
327
- }
328
- }
329
- extractor.unselectTrack(trackIndex)
330
- return startTime
331
- }
332
- return -1
333
- }
77
+ private fun autoCompressHelper(
78
+ fileUrl: String,
79
+ quality: String,
80
+ context: ReactApplicationContext,
81
+ completeCallback: (String, Boolean) -> Unit
82
+ ) {
83
+ try {
84
+ var mp3Path = Utils.generateCacheFilePath("mp3", context)
85
+ val input = File(fileUrl)
86
+ val output = File(mp3Path)
87
+ val audioBitrate= getAudioBitrateByQuality(quality)
88
+
89
+ val CHUNK_SIZE = 8192
90
+ addLog("Initialising wav reader")
91
+
92
+ waveReader = WaveReader(input)
93
+
94
+ try {
95
+ waveReader!!.openWave()
96
+ } catch (e: IOException) {
97
+ e.printStackTrace()
98
+ }
99
+
100
+ addLog("Intitialising encoder")
101
+ val androidLame = LameBuilder()
102
+ .setInSampleRate(waveReader!!.sampleRate)
103
+ .setOutChannels(waveReader!!.channels)
104
+ .setOutBitrate(audioBitrate)
105
+ .setOutSampleRate(waveReader!!.sampleRate)
106
+ .build()
107
+
108
+ try {
109
+ outputStream = BufferedOutputStream(FileOutputStream(output), OUTPUT_STREAM_BUFFER)
110
+ } catch (e: FileNotFoundException) {
111
+ e.printStackTrace()
112
+ }
113
+
114
+ var bytesRead = 0
115
+
116
+ val buffer_l = ShortArray(CHUNK_SIZE)
117
+ val buffer_r = ShortArray(CHUNK_SIZE)
118
+ val mp3Buf = ByteArray(CHUNK_SIZE)
119
+
120
+ val channels = waveReader!!.channels
121
+
122
+ addLog("started encoding")
123
+ while (true) {
124
+ try {
125
+ if (channels == 2) {
334
126
 
335
- @SuppressLint("WrongConstant")
336
- @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
337
- @Throws(Exception::class)
338
- private fun writeAudioTrack(extractor: MediaExtractor, mediaMuxer: MediaMuxer, info: MediaCodec.BufferInfo?, file: File, muxerTrackIndex: Int): Long {
339
- val trackIndex = selectTrack(extractor, true)
340
- if (trackIndex >= 0) {
341
- val trackFormat = extractor.getTrackFormat(trackIndex)
342
- val maxBufferSize = info!!.size
343
- val byteBuffer = ByteBuffer.allocate(maxBufferSize)
344
- var audioPresentationTimeUs: Long = 0
345
- val audioBufferInfo = MediaCodec.BufferInfo()
346
- extractor.selectTrack(mTrackIndex)
347
- /*
348
- * the last audio presentation time.
349
- */
350
- var lastEndAudioTimeUs: Long = 0
351
- while (true) {
352
- val readAudioSampleSize = extractor.readSampleData(byteBuffer, 0)
353
- if (readAudioSampleSize < 0) {
354
- //if end of the stream, unselect
355
- extractor.unselectTrack(mTrackIndex)
356
- if (audioPresentationTimeUs >= 0) {
357
- //if has reach the end of the video time ,just exit
358
- break
359
- } else {
360
- //if not the end of the video time, just repeat.
361
- lastEndAudioTimeUs += audioPresentationTimeUs
362
- extractor.selectTrack(trackIndex)
363
- continue
364
- }
365
- }
366
- val audioSampleTime = extractor.sampleTime
367
- audioBufferInfo.size = readAudioSampleSize
368
- audioBufferInfo.presentationTimeUs = audioSampleTime + lastEndAudioTimeUs
369
- if (audioBufferInfo.presentationTimeUs > 0) {
370
- extractor.unselectTrack(trackIndex)
371
- break
372
- }
373
- audioPresentationTimeUs = 0
374
- audioBufferInfo.offset = 0
375
- audioBufferInfo.flags = extractor.sampleFlags
376
- mediaMuxer.writeSampleData(trackIndex, byteBuffer, audioBufferInfo)
377
- extractor.advance()
378
- }
379
- //
380
-
381
-
382
- // boolean inputDone = false;
383
- // if (start > 0) {
384
- // extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
385
- // } else {
386
- // extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
387
- // }
388
- // ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
389
- // long startTime = -1;
390
- //
391
- // while (!inputDone) {
392
- //
393
- // boolean eof = false;
394
- // int index = extractor.getSampleTrackIndex();
395
- // if (index == trackIndex) {
396
- // info.size = extractor.readSampleData(buffer, 0);
397
- //
398
- // if (info.size < 0) {
399
- // info.size = 0;
400
- // eof = true;
401
- // } else {
402
- // info.presentationTimeUs = extractor.getSampleTime();
403
- // if (start > 0 && startTime == -1) {
404
- // startTime = info.presentationTimeUs;
405
- // }
406
- // if (end < 0 || info.presentationTimeUs < end) {
407
- // info.offset = 0;
408
- // info.flags = extractor.getSampleFlags();
409
- // mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info);
410
- // extractor.advance();
411
- // } else {
412
- // eof = true;
413
- // }
414
- // }
415
- // } else if (index == -1) {
416
- // eof = true;
417
- // }
418
- // if (eof) {
419
- // inputDone = true;
420
- // }
421
- // }
422
- //
423
- // extractor.unselectTrack(trackIndex);
424
- // return startTime;
425
- }
426
- return -1
427
- }
127
+ bytesRead = waveReader!!.read(buffer_l, buffer_r, CHUNK_SIZE)
128
+ addLog("bytes read=$bytesRead")
428
129
 
429
- private fun selectTrack(extractor: MediaExtractor, audio: Boolean): Int {
430
- val numTracks = extractor.trackCount
431
- for (i in 0 until numTracks) {
432
- val format = extractor.getTrackFormat(i)
433
- val mime = format.getString(MediaFormat.KEY_MIME)
434
- if (audio) {
435
- if (mime!!.startsWith("audio/")) {
436
- return i
437
- }
438
- } else {
439
- if (mime!!.startsWith("video/")) {
440
- return i
130
+ if (bytesRead > 0) {
131
+
132
+ var bytesEncoded = 0
133
+ bytesEncoded = androidLame.encode(buffer_l, buffer_r, bytesRead, mp3Buf)
134
+ addLog("bytes encoded=$bytesEncoded")
135
+
136
+ if (bytesEncoded > 0) {
137
+ try {
138
+ addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes")
139
+ outputStream!!.write(mp3Buf, 0, bytesEncoded)
140
+ } catch (e: IOException) {
141
+ e.printStackTrace()
441
142
  }
442
- }
443
- }
444
- return MEDIATYPE_NOT_AUDIO_VIDEO
445
- }
446
143
 
447
- private fun selectEncoder(mime: String): String? {
448
- for (index in 0 until MediaCodecList.getCodecCount()) {
449
- val codecInfo = MediaCodecList.getCodecInfoAt(index)
450
- if (!codecInfo.isEncoder) {
451
- continue
452
- }
453
- for (type in codecInfo.supportedTypes) {
454
- if (type.equals(mime, ignoreCase = true)) {
455
- return MIME_TYPE
144
+ }
145
+
146
+ } else
147
+ break
148
+ } else {
149
+
150
+ bytesRead = waveReader!!.read(buffer_l, CHUNK_SIZE)
151
+ addLog("bytes read=$bytesRead")
152
+
153
+ if (bytesRead > 0) {
154
+ var bytesEncoded = 0
155
+
156
+ bytesEncoded = androidLame.encode(buffer_l, buffer_l, bytesRead, mp3Buf)
157
+ addLog("bytes encoded=$bytesEncoded")
158
+
159
+ if (bytesEncoded > 0) {
160
+ try {
161
+ addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes")
162
+ outputStream!!.write(mp3Buf, 0, bytesEncoded)
163
+ } catch (e: IOException) {
164
+ e.printStackTrace()
456
165
  }
457
- }
458
- }
459
- return null
460
- }
461
166
 
462
- /**
463
- * Configures encoder and muxer state, and prepares the input Surface.
464
- */
465
- @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
466
- private fun prepareEncoder(format: MediaFormat) {
467
- mBufferInfo = MediaCodec.BufferInfo()
468
- val mAudioFormat = MediaFormat.createAudioFormat(MIME_TYPE, mBitRate, 1)
469
- if (VERBOSE) Log.d(TAG, "format: $mAudioFormat")
470
- mAudioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, format.getInteger(MediaFormat.KEY_SAMPLE_RATE))
471
- mAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, format.getInteger(MediaFormat.KEY_BIT_RATE))
472
- mAudioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, format.getInteger(MediaFormat.KEY_CHANNEL_COUNT))
473
- mAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC)
474
- mAudioFormat.setString(MediaFormat.KEY_MIME, MIME_TYPE)
475
- mAudioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 10 * 1024)
476
- try {
477
- mEncoder = MediaCodec.createEncoderByType(MIME_TYPE)
478
- mEncoder!!.configure(mAudioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
479
- mEncoder!!.start()
480
- Log.d(TAG, "prepareEncoder...")
167
+ }
168
+
169
+ } else
170
+ break
171
+ }
172
+
173
+
481
174
  } catch (e: IOException) {
482
- e.printStackTrace()
175
+ e.printStackTrace()
483
176
  }
177
+
178
+ }
179
+
180
+ addLog("flushing final mp3buffer")
181
+ val outputMp3buf = androidLame.flush(mp3Buf)
182
+ addLog("flushed $outputMp3buf bytes")
183
+
184
+ if (outputMp3buf > 0) {
484
185
  try {
485
- mDecoder = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME)!!)
186
+ addLog("writing final mp3buffer to outputstream")
187
+ outputStream!!.write(mp3Buf, 0, outputMp3buf)
188
+ addLog("closing output stream")
189
+ outputStream!!.close()
190
+ completeCallback(output.absolutePath, true)
486
191
  } catch (e: IOException) {
487
- e.printStackTrace()
192
+ completeCallback(e.localizedMessage, false)
193
+ e.printStackTrace()
488
194
  }
489
- mDecoder!!.configure(format, null, null, 0)
490
- mDecoder!!.start()
491
- // mTrackIndex = -1;
492
- }
195
+ }
493
196
 
494
- /**
495
- * Releases encoder resources. May be called after partial / failed initialization.
496
- */
497
- @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
498
- private fun releaseCoder() {
499
- if (VERBOSE) Log.d(TAG, "releasing encoder objects")
500
- if (mEncoder != null) {
501
- mEncoder!!.stop()
502
- mEncoder!!.release()
503
- mEncoder = null
504
- }
505
- if (mDecoder != null) {
506
- mDecoder!!.stop()
507
- mDecoder!!.release()
508
- mDecoder = null
509
- }
510
- if (mInputSurface != null) {
511
- mInputSurface!!.release()
512
- mInputSurface = null
513
- }
514
- if (mMuxer != null) {
515
- mMuxer!!.stop()
516
- mMuxer!!.release()
517
- mMuxer = null
518
- }
197
+ } catch (e: IOException) {
198
+ completeCallback(e.localizedMessage, false)
199
+ }
519
200
  }
520
201
 
521
- companion object {
522
- private const val TAG = "AudioCompressor"
523
- private const val VERBOSE = true // lots of logging
524
- const val MIME_TYPE = MediaFormat.MIMETYPE_AUDIO_AAC
525
- private const val MEDIATYPE_NOT_AUDIO_VIDEO = -233
526
- }
202
+
203
+
204
+ }
527
205
  }