react-native-compressor 1.7.2 → 1.8.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/README.md +30 -7
- package/android/build.gradle +8 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt +527 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt +31 -0
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.kt +157 -0
- package/android/src/main/java/com/reactnativecompressor/CompressorPackage.kt +34 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressor.kt +199 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressorOptions.kt +57 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageMain.kt +31 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageSize.kt +3 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Downloader.kt +119 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/EventEmitterHandler.kt +66 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/MediaCache.kt +61 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/RealPathUtil.kt +177 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Uploader.kt +117 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +162 -0
- package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression.kt +63 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.kt +125 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoMain.kt +86 -0
- package/android/src/newarch/CompressorSpec.kt +5 -0
- package/android/src/oldarch/CompressorSpec.kt +32 -0
- package/ios/Audio/AudioMain.swift +115 -0
- package/ios/Compressor-Bridging-Header.h +1 -2
- package/ios/Compressor.h +0 -8
- package/ios/Compressor.mm +28 -389
- package/ios/CompressorManager.swift +96 -0
- package/ios/Image/ImageCompressor.swift +354 -0
- package/ios/Image/ImageCompressorOptions.swift +93 -0
- package/ios/Image/ImageMain.swift +27 -0
- package/ios/Utils/Downloader.swift +157 -0
- package/ios/Utils/EventEmitterHandler.swift +54 -0
- package/ios/Utils/MediaCache.swift +48 -0
- package/ios/Utils/Uploader.swift +99 -0
- package/ios/Utils/Utils.swift +110 -0
- package/ios/Video/{VideoCompressor.swift → VideoMain.swift} +167 -146
- package/lib/commonjs/Image/index.js +1 -1
- package/lib/commonjs/Image/index.js.map +1 -1
- package/lib/commonjs/Main.js +1 -8
- package/lib/commonjs/Main.js.map +1 -1
- package/lib/commonjs/Spec/NativeCompressor.js.map +1 -1
- package/lib/commonjs/Video/index.js +4 -33
- package/lib/commonjs/Video/index.js.map +1 -1
- package/lib/commonjs/expo-plugin/compressor.js.map +1 -1
- package/lib/commonjs/index.js +11 -6
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/utils/Downloader.js +38 -0
- package/lib/commonjs/utils/Downloader.js.map +1 -0
- package/lib/commonjs/utils/Uploader.js +40 -0
- package/lib/commonjs/utils/Uploader.js.map +1 -0
- package/lib/commonjs/utils/index.js +35 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/Image/index.js +1 -1
- package/lib/module/Image/index.js.map +1 -1
- package/lib/module/Main.js +1 -7
- package/lib/module/Main.js.map +1 -1
- package/lib/module/Spec/NativeCompressor.js.map +1 -1
- package/lib/module/Video/index.js +5 -33
- package/lib/module/Video/index.js.map +1 -1
- package/lib/module/expo-plugin/compressor.js.map +1 -1
- package/lib/module/index.js +6 -6
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/Downloader.js +31 -0
- package/lib/module/utils/Downloader.js.map +1 -0
- package/lib/module/utils/Uploader.js +33 -0
- package/lib/module/utils/Uploader.js.map +1 -0
- package/lib/module/utils/index.js +2 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/Image/index.d.ts +4 -0
- package/lib/typescript/Image/index.d.ts.map +1 -1
- package/lib/typescript/Main.d.ts +1 -2
- package/lib/typescript/Main.d.ts.map +1 -1
- package/lib/typescript/Spec/NativeCompressor.d.ts +8 -2
- package/lib/typescript/Spec/NativeCompressor.d.ts.map +1 -1
- package/lib/typescript/Video/index.d.ts +4 -28
- package/lib/typescript/Video/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +5 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/utils/Downloader.d.ts +2 -0
- package/lib/typescript/utils/Downloader.d.ts.map +1 -0
- package/lib/typescript/utils/Uploader.d.ts +28 -0
- package/lib/typescript/utils/Uploader.d.ts.map +1 -0
- package/lib/typescript/utils/index.d.ts +2 -1
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/Image/index.tsx +5 -1
- package/src/Main.tsx +1 -15
- package/src/Spec/NativeCompressor.ts +14 -2
- package/src/Video/index.tsx +11 -84
- package/src/expo-plugin/compressor.ts +1 -1
- package/src/index.tsx +6 -3
- package/src/utils/Downloader.tsx +38 -0
- package/src/utils/Uploader.tsx +78 -0
- package/src/utils/index.tsx +2 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.java +0 -605
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.java +0 -220
- package/android/src/main/java/com/reactnativecompressor/CompressorPackage.java +0 -58
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressor.java +0 -257
- package/android/src/main/java/com/reactnativecompressor/Image/utils/ImageCompressorOptions.java +0 -69
- package/android/src/main/java/com/reactnativecompressor/Image/utils/ImageSize.java +0 -13
- package/android/src/main/java/com/reactnativecompressor/Utils/FileUplaoder/FileUploadHelper.java +0 -39
- package/android/src/main/java/com/reactnativecompressor/Utils/FileUplaoder/FileUploader.java +0 -129
- package/android/src/main/java/com/reactnativecompressor/Utils/MediaCache.java +0 -65
- package/android/src/main/java/com/reactnativecompressor/Utils/RealPathUtil.java +0 -210
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.java +0 -272
- package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression/AutoVideoCompression.java +0 -87
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.java +0 -182
- package/android/src/main/java/com/reactnativecompressor/Video/VideoModule.java +0 -112
- package/android/src/newarch/CompressorSpec.java +0 -9
- package/android/src/newarch/VideoCompressorSpec.java +0 -9
- package/android/src/oldarch/CompressorSpec.java +0 -34
- package/android/src/oldarch/VideoCompressorSpec.java +0 -26
- package/ios/Image/ImageCompressor.h +0 -22
- package/ios/Image/ImageCompressor.m +0 -540
- package/ios/Image/ImageCompressorOptions.h +0 -28
- package/ios/Image/ImageCompressorOptions.m +0 -97
- package/ios/Utils/Downloader.h +0 -16
- package/ios/Utils/Downloader.m +0 -150
- package/ios/Utils/MediaCache.h +0 -11
- package/ios/Utils/MediaCache.m +0 -51
- package/ios/Video/VideoCompressor.h +0 -5
- package/ios/Video/VideoCompressor.m +0 -1
- package/lib/commonjs/Spec/NativeVideoCompressor.js +0 -10
- package/lib/commonjs/Spec/NativeVideoCompressor.js.map +0 -1
- package/lib/module/Spec/NativeVideoCompressor.js +0 -3
- package/lib/module/Spec/NativeVideoCompressor.js.map +0 -1
- package/lib/typescript/Spec/NativeVideoCompressor.d.ts +0 -13
- package/lib/typescript/Spec/NativeVideoCompressor.d.ts.map +0 -1
- package/src/Spec/NativeVideoCompressor.ts +0 -14
package/README.md
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
**REACT-NATIVE-COMPRESSOR** is a react-native package, which helps us to Compress `Image`, `Video`, and `Audio` before uploading, same like **Whatsapp** without knowing the compression `algorithm`
|
|
18
18
|
|
|
19
19
|
<div align="center">
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
<pre>
|
|
21
|
+
<img height="90" src="/media/whatsapp_logo.png"/> <img height="90" src="/media/compress_media.png"/>
|
|
22
|
+
</pre>
|
|
23
23
|
<h2 align="center">🗜️Compress Image, Video, and Audio same like Whatsapp</h2>
|
|
24
24
|
</div>
|
|
25
25
|
|
|
@@ -53,9 +53,7 @@ We should use **react-native-compressor** instead of **FFmpeg** because **react-
|
|
|
53
53
|
<summary>Open Table of Contents</summary>
|
|
54
54
|
|
|
55
55
|
- [Installation](#installation)
|
|
56
|
-
- [For React Native](#
|
|
57
|
-
- [For React Native<0.65](#for-react-native065)
|
|
58
|
-
- [For React Native 0.65 or greater](#for-react-native-065-or-greater)
|
|
56
|
+
- [For React Native](#Installation)
|
|
59
57
|
- [Managed Expo](#managed-expo)
|
|
60
58
|
- [Usage](#usage)
|
|
61
59
|
- [Image](#image)
|
|
@@ -69,6 +67,7 @@ We should use **react-native-compressor** instead of **FFmpeg** because **react-
|
|
|
69
67
|
- [Video Api Docs](#video-1)
|
|
70
68
|
- [Audio](#audio)
|
|
71
69
|
- [Background Upload](#background-upload)
|
|
70
|
+
- [Download File](#download)
|
|
72
71
|
|
|
73
72
|
* [Other Utilities](#api)
|
|
74
73
|
- [Background Upload](#background-upload-1)
|
|
@@ -164,6 +163,7 @@ import { Image } from 'react-native-compressor';
|
|
|
164
163
|
const result = await Image.compress('file://path_of_file/image.jpg');
|
|
165
164
|
// OR
|
|
166
165
|
const result = await Image.compress('https://path_of_file/image.jpg', {
|
|
166
|
+
progressDivider: 10,
|
|
167
167
|
downloadProgress: (progress) => {
|
|
168
168
|
console.log('downloadProgress: ', progress);
|
|
169
169
|
},
|
|
@@ -204,6 +204,7 @@ const result = await Video.compress(
|
|
|
204
204
|
const result = await Video.compress(
|
|
205
205
|
'https://example.com/video.mp4',
|
|
206
206
|
{
|
|
207
|
+
progressDivider: 10,
|
|
207
208
|
downloadProgress: (progress) => {
|
|
208
209
|
console.log('downloadProgress: ', progress);
|
|
209
210
|
},
|
|
@@ -288,6 +289,16 @@ const uploadResult = await backgroundUpload(
|
|
|
288
289
|
);
|
|
289
290
|
```
|
|
290
291
|
|
|
292
|
+
### Download File
|
|
293
|
+
|
|
294
|
+
```js
|
|
295
|
+
import { download } from 'react-native-compressor';
|
|
296
|
+
|
|
297
|
+
const downloadFileUrl = await download(url, (progress) => {
|
|
298
|
+
console.log('downloadProgress: ', progress);
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
291
302
|
# API
|
|
292
303
|
|
|
293
304
|
## Image
|
|
@@ -308,6 +319,10 @@ const uploadResult = await backgroundUpload(
|
|
|
308
319
|
|
|
309
320
|
it is callback, only trigger when we pass image url from server
|
|
310
321
|
|
|
322
|
+
- ##### `progressDivider?: number` (default: 0)
|
|
323
|
+
|
|
324
|
+
we uses it when we use downloadProgress
|
|
325
|
+
|
|
311
326
|
- ###### `maxWidth: number` (default: 1280)
|
|
312
327
|
|
|
313
328
|
The maximum width boundary used as the main boundary in resizing a landscape image.
|
|
@@ -348,6 +363,10 @@ const uploadResult = await backgroundUpload(
|
|
|
348
363
|
|
|
349
364
|
it is callback, only trigger when we pass image url from server
|
|
350
365
|
|
|
366
|
+
- ##### `progressDivider?: number` (default: 0)
|
|
367
|
+
|
|
368
|
+
we uses it when we use downloadProgress/onProgress
|
|
369
|
+
|
|
351
370
|
- ###### `maxSize: number` (default: 640)
|
|
352
371
|
|
|
353
372
|
The maximum size can be height in case of portrait video or can be width in case of landscape video.
|
|
@@ -376,7 +395,7 @@ const uploadResult = await backgroundUpload(
|
|
|
376
395
|
|
|
377
396
|
## Background Upload
|
|
378
397
|
|
|
379
|
-
- ######
|
|
398
|
+
- ###### backgroundUpload: (url: string, fileUrl: string, options: FileSystemUploadOptions, onProgress?: ((writtem: number, total: number) => void) | undefined) => Promise< any >
|
|
380
399
|
|
|
381
400
|
- ###### ` FileSystemUploadOptions`
|
|
382
401
|
|
|
@@ -398,6 +417,10 @@ type FileSystemUploadOptions = (
|
|
|
398
417
|
};
|
|
399
418
|
```
|
|
400
419
|
|
|
420
|
+
### Download
|
|
421
|
+
|
|
422
|
+
- ##### download: ( fileUrl: string, downloadProgress?: (progress: number) => void, progressDivider?: number ) => Promise< string >
|
|
423
|
+
|
|
401
424
|
### Get Metadata Of Video
|
|
402
425
|
|
|
403
426
|
if you want to get metadata of video than you can use this function
|
package/android/build.gradle
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
buildscript {
|
|
2
|
+
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
|
3
|
+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["Compressor_kotlinVersion"]
|
|
4
|
+
|
|
2
5
|
repositories {
|
|
3
6
|
google()
|
|
4
7
|
mavenCentral()
|
|
@@ -6,6 +9,8 @@ buildscript {
|
|
|
6
9
|
|
|
7
10
|
dependencies {
|
|
8
11
|
classpath "com.android.tools.build:gradle:7.2.1"
|
|
12
|
+
// noinspection DifferentKotlinGradleVersion
|
|
13
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
9
14
|
}
|
|
10
15
|
}
|
|
11
16
|
|
|
@@ -14,6 +19,7 @@ def isNewArchitectureEnabled() {
|
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: "kotlin-android"
|
|
17
23
|
|
|
18
24
|
|
|
19
25
|
def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
|
|
@@ -96,12 +102,14 @@ repositories {
|
|
|
96
102
|
google()
|
|
97
103
|
}
|
|
98
104
|
|
|
105
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
99
106
|
|
|
100
107
|
dependencies {
|
|
101
108
|
// For < 0.71, this will be from the local maven repo
|
|
102
109
|
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
103
110
|
//noinspection GradleDynamicVersion
|
|
104
111
|
implementation "com.facebook.react:react-native:+"
|
|
112
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
105
113
|
implementation 'io.github.lizhangqu:coreprogress:1.0.2'
|
|
106
114
|
implementation 'com.github.numandev1:VideoCompressor:1a262bba37'
|
|
107
115
|
}
|
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
package com.reactnativecompressor.Audio
|
|
2
|
+
|
|
3
|
+
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 numan.dev.videocompressor.codecinputsurface.CodecInputSurface
|
|
15
|
+
import java.io.File
|
|
16
|
+
import java.io.IOException
|
|
17
|
+
import java.nio.ByteBuffer
|
|
18
|
+
|
|
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: CodecInputSurface? = 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
|
|
44
|
+
}
|
|
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
|
|
267
|
+
}
|
|
268
|
+
Log.e(TAG, "time = " + (System.currentTimeMillis() - time))
|
|
269
|
+
}
|
|
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
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private fun checkParmsError(sourcePath: String?, destinationPath: String?, nbitrate: Int): Boolean {
|
|
278
|
+
return if (nbitrate <= 0) true else false
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@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
|
+
}
|
|
334
|
+
|
|
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
|
+
}
|
|
428
|
+
|
|
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
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return MEDIATYPE_NOT_AUDIO_VIDEO
|
|
445
|
+
}
|
|
446
|
+
|
|
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
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return null
|
|
460
|
+
}
|
|
461
|
+
|
|
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...")
|
|
481
|
+
} catch (e: IOException) {
|
|
482
|
+
e.printStackTrace()
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
mDecoder = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME)!!)
|
|
486
|
+
} catch (e: IOException) {
|
|
487
|
+
e.printStackTrace()
|
|
488
|
+
}
|
|
489
|
+
mDecoder!!.configure(format, null, null, 0)
|
|
490
|
+
mDecoder!!.start()
|
|
491
|
+
// mTrackIndex = -1;
|
|
492
|
+
}
|
|
493
|
+
|
|
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
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
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
|
+
}
|
|
527
|
+
}
|