增加mp3转码

增加mp3转码,使用mp3lame进行编码
pull/107/head
xufulong 5 years ago
parent 083c306d2b
commit d4b5956a81
  1. 1
      OnLive/src/main/AndroidManifest.xml
  2. 12
      app/CMakeLists.txt
  3. BIN
      app/libs/arm64-v8a/libmp3lame.so
  4. BIN
      app/libs/armeabi-v7a/libmp3lame.so
  5. 224
      app/src/main/cpp/audio_lame.c
  6. 1323
      app/src/main/cpp/include/lame/lame.h
  7. 4
      app/src/main/cpp/openSL_audio_player.c
  8. 20
      app/src/main/java/com/frank/ffmpeg/AudioPlayer.java
  9. 10
      app/src/main/java/com/frank/ffmpeg/activity/AudioHandleActivity.java
  10. 340
      app/src/main/java/com/frank/ffmpeg/mp3/Mp3Converter.java
  11. 71
      app/src/main/java/com/frank/ffmpeg/mp3/Mp3Lame.java
  12. 147
      app/src/main/java/com/frank/ffmpeg/mp3/Mp3LameBuilder.java
  13. 2
      build.gradle
  14. 2
      gradle/wrapper/gradle-wrapper.properties

@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"

@ -29,7 +29,9 @@ add_library( # Sets the name of the library.
src/main/cpp/ffmpeg_pusher.cpp src/main/cpp/ffmpeg_pusher.cpp
src/main/cpp/AVpacket_queue.c src/main/cpp/AVpacket_queue.c
src/main/cpp/media_player.c src/main/cpp/media_player.c
src/main/cpp/video_filter.c) src/main/cpp/video_filter.c
src/main/cpp/audio_lame.c
)
add_library( ffmpeg add_library( ffmpeg
SHARED SHARED
@ -38,6 +40,13 @@ set_target_properties( ffmpeg
PROPERTIES IMPORTED_LOCATION PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libffmpeg.so ) ../../../../libs/armeabi-v7a/libffmpeg.so )
add_library( mp3lame
SHARED
IMPORTED )
set_target_properties( mp3lame
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libmp3lame.so )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(src/main/cpp) include_directories(src/main/cpp)
@ -49,6 +58,7 @@ find_library( # Sets the name of the path variable.
target_link_libraries( # Specifies the target library. target_link_libraries( # Specifies the target library.
media-handle media-handle
mp3lame
ffmpeg ffmpeg
-landroid #native_window -landroid #native_window
-ljnigraphics #bitmap -ljnigraphics #bitmap

Binary file not shown.

@ -0,0 +1,224 @@
#include "include/lame/lame.h"
#include <jni.h>
lame_global_flags *glf;
lame_global_flags *initializeDefault(JNIEnv *env) {
lame_global_flags *glf = lame_init();
lame_init_params(glf);
return glf;
}
lame_global_flags *initialize(
JNIEnv *env,
jint inSamplerate, jint outChannel,
jint outSamplerate, jint outBitrate, jfloat scaleInput, jint mode, jint vbrMode,
jint quality, jint vbrQuality, jint abrMeanBitrate, jint lowpassFreq, jint highpassFreq,
jstring id3tagTitle, jstring id3tagArtist, jstring id3tagAlbum,
jstring id3tagYear, jstring id3tagComment) {
lame_global_flags *glf = lame_init();
lame_set_in_samplerate(glf, inSamplerate);
lame_set_num_channels(glf, outChannel);
lame_set_out_samplerate(glf, outSamplerate);
lame_set_brate(glf, outBitrate);
lame_set_quality(glf, quality);
lame_set_scale(glf, scaleInput);
lame_set_VBR_q(glf, vbrQuality);
lame_set_VBR_mean_bitrate_kbps(glf, abrMeanBitrate);
lame_set_lowpassfreq(glf, lowpassFreq);
lame_set_highpassfreq(glf, highpassFreq);
switch (mode) {
case 0:
lame_set_mode(glf, STEREO);
break;
case 1:
lame_set_mode(glf, JOINT_STEREO);
break;
case 3:
lame_set_mode(glf, MONO);
break;
case 4:
lame_set_mode(glf, NOT_SET);
break;
default:
lame_set_mode(glf, NOT_SET);
break;
}
switch (vbrMode) {
case 0:
lame_set_VBR(glf, vbr_off);
break;
case 2:
lame_set_VBR(glf, vbr_rh);
break;
case 3:
lame_set_VBR(glf, vbr_abr);
break;
case 4:
lame_set_VBR(glf, vbr_mtrh);
break;
case 6:
lame_set_VBR(glf, vbr_default);
break;
default:
lame_set_VBR(glf, vbr_off);
break;
}
const jchar *title = NULL;
const jchar *artist = NULL;
const jchar *album = NULL;
const jchar *year = NULL;
const jchar *comment = NULL;
if (id3tagTitle) {
title = (*env)->GetStringChars(env, id3tagTitle, NULL);
}
if (id3tagArtist) {
artist = (*env)->GetStringChars(env, id3tagArtist, NULL);
}
if (id3tagAlbum) {
album = (*env)->GetStringChars(env, id3tagAlbum, NULL);
}
if (id3tagYear) {
year = (*env)->GetStringChars(env, id3tagYear, NULL);
}
if (id3tagComment) {
comment = (*env)->GetStringChars(env, id3tagComment, NULL);
}
if (title || artist || album || year || comment) {
id3tag_init(glf);
if (title) {
id3tag_set_title(glf, (const char *) title);
(*env)->ReleaseStringChars(env, id3tagTitle, title);
}
if (artist) {
id3tag_set_artist(glf, (const char *) artist);
(*env)->ReleaseStringChars(env, id3tagArtist, artist);
}
if (album) {
id3tag_set_album(glf, (const char *) album);
(*env)->ReleaseStringChars(env, id3tagAlbum, album);
}
if (year) {
id3tag_set_year(glf, (const char *) year);
(*env)->ReleaseStringChars(env, id3tagYear, year);
}
if (comment) {
id3tag_set_comment(glf, (const char *) comment);
(*env)->ReleaseStringChars(env, id3tagComment, comment);
}
}
lame_init_params(glf);
return glf;
}
jint encode(
JNIEnv *env, lame_global_flags *glf,
jshortArray buffer_l, jshortArray buffer_r,
jint samples, jbyteArray mp3buf) {
jshort *j_buffer_l = (*env)->GetShortArrayElements(env, buffer_l, NULL);
jshort *j_buffer_r = (*env)->GetShortArrayElements(env, buffer_r, NULL);
const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
jbyte *j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);
int result = lame_encode_buffer(glf, j_buffer_l, j_buffer_r,
samples, j_mp3buf, mp3buf_size);
(*env)->ReleaseShortArrayElements(env, buffer_l, j_buffer_l, 0);
(*env)->ReleaseShortArrayElements(env, buffer_r, j_buffer_r, 0);
(*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);
return result;
}
jint encodeBufferInterleaved(
JNIEnv *env, lame_global_flags *glf,
jshortArray pcm, jint samples, jbyteArray mp3buf) {
jshort *j_pcm = (*env)->GetShortArrayElements(env, pcm, NULL);
const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
jbyte *j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);
int result = lame_encode_buffer_interleaved(glf, j_pcm,
samples, j_mp3buf, mp3buf_size);
(*env)->ReleaseShortArrayElements(env, pcm, j_pcm, 0);
(*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);
return result;
}
jint flush(
JNIEnv *env, lame_global_flags *glf,
jbyteArray mp3buf) {
const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
jbyte *j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);
int result = lame_encode_flush(glf, j_mp3buf, mp3buf_size);
(*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);
return result;
}
void close_lame(lame_global_flags *glf) {
lame_close(glf);
glf = NULL;
}
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameInitDefault
(JNIEnv *env, jclass jclazz) {
glf = initializeDefault(env);
}
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameInit(
JNIEnv *env, jclass cls, jint inSampleRate, jint outChannel,
jint outSampleRate, jint outBitrate, jfloat scaleInput, jint mode, jint vbrMode,
jint quality, jint vbrQuality, jint abrMeanBitrate, jint lowPassFreq, jint highPassFreq,
jstring id3tagTitle, jstring id3tagArtist, jstring id3tagAlbum,
jstring id3tagYear, jstring id3tagComment) {
glf = initialize(env, inSampleRate, outChannel, outSampleRate, outBitrate, scaleInput, mode,
vbrMode,
quality, vbrQuality, abrMeanBitrate, lowPassFreq, highPassFreq, id3tagTitle,
id3tagArtist, id3tagAlbum,
id3tagYear,
id3tagComment);
}
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameEncode(
JNIEnv *env, jclass cls, jshortArray buffer_l,
jshortArray buffer_r, jint samples, jbyteArray mp3buf) {
return encode(env, glf, buffer_l, buffer_r, samples, mp3buf);
}
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_encodeBufferInterleaved(
JNIEnv *env, jclass cls, jshortArray pcm,
jint samples, jbyteArray mp3buf) {
return encodeBufferInterleaved(env, glf, pcm, samples, mp3buf);
}
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameFlush(
JNIEnv *env, jclass cls, jbyteArray mp3buf) {
return flush(env, glf, mp3buf);
}
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameClose(
JNIEnv *env, jclass cls) {
close_lame(glf);
}

File diff suppressed because it is too large Load Diff

@ -271,7 +271,7 @@ int releaseAudioPlayer() {
} }
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_playAudio JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_playAudio
(JNIEnv * env, jclass jobject, jstring filePath) { (JNIEnv * env, jclass jclazz, jstring filePath) {
int rate, channel; int rate, channel;
const char *file_name = (*env)->GetStringUTFChars(env, filePath, NULL); const char *file_name = (*env)->GetStringUTFChars(env, filePath, NULL);
@ -292,7 +292,7 @@ JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_playAudio
//停止播放,释放相关资源 //停止播放,释放相关资源
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_stop JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_stop
(JNIEnv * env, jclass jobject) { (JNIEnv * env, jclass jclazz) {
if (bqPlayerObject != NULL) { if (bqPlayerObject != NULL) {
(*bqPlayerObject)->Destroy(bqPlayerObject); (*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = NULL; bqPlayerObject = NULL;

@ -18,7 +18,25 @@ public class AudioPlayer {
//调用OpenSL ES播放 //调用OpenSL ES播放
public native void playAudio(String audioPath); public native void playAudio(String audioPath);
//调用OpenSL ES播放 //调用OpenSL ES播放
public native void stop(String audioPath); public native int stop();
public native static void lameInitDefault();
public native static void lameInit(int inSamplerate, int outChannel,
int outSamplerate, int outBitrate, float scaleInput, int mode, int vbrMode,
int quality, int vbrQuality, int abrMeanBitrate, int lowpassFreq, int highpassFreq, String id3tagTitle,
String id3tagArtist, String id3tagAlbum, String id3tagYear,
String id3tagComment);
public native static int lameEncode(short[] buffer_l, short[] buffer_r,
int samples, byte[] mp3buf);
public native static int encodeBufferInterleaved(short[] pcm, int samples,
byte[] mp3buf);
public native static int lameFlush(byte[] mp3buf);
public native static void lameClose();
/** /**
* 创建一个AudioTrack对象 * 创建一个AudioTrack对象

@ -14,6 +14,7 @@ import java.io.File;
import com.frank.ffmpeg.AudioPlayer; import com.frank.ffmpeg.AudioPlayer;
import com.frank.ffmpeg.FFmpegCmd; import com.frank.ffmpeg.FFmpegCmd;
import com.frank.ffmpeg.R; import com.frank.ffmpeg.R;
import com.frank.ffmpeg.mp3.Mp3Converter;
import com.frank.ffmpeg.util.FFmpegUtil; import com.frank.ffmpeg.util.FFmpegUtil;
import com.frank.ffmpeg.util.FileUtil; import com.frank.ffmpeg.util.FileUtil;
@ -140,8 +141,13 @@ public class AudioHandleActivity extends AppCompatActivity implements View.OnCli
} }
switch (handleType){ switch (handleType){
case 0://转码 case 0://转码
String transformFile = PATH + File.separator + "transform.aac"; // String transformFile = PATH + File.separator + "transform.aac";
commandLine = FFmpegUtil.transformAudio(srcFile, transformFile); // commandLine = FFmpegUtil.transformAudio(srcFile, transformFile);
//使用mp3lame进行转码
String inputFile = PATH + File.separator + "hello.aac";
String transformFile = PATH + File.separator + "transform.mp3";
Mp3Converter mp3Converter = new Mp3Converter();
mp3Converter.convertToMp3(inputFile, transformFile);
break; break;
case 1://剪切 case 1://剪切
String cutFile = PATH + File.separator + "cut.mp3"; String cutFile = PATH + File.separator + "cut.mp3";

@ -0,0 +1,340 @@
package com.frank.ffmpeg.mp3;
import android.annotation.TargetApi;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Build;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class Mp3Converter {
private final static String TAG = Mp3Converter.class.getSimpleName();
private MediaCodec mMediaCodec;
private MediaExtractor mediaExtractor;
private BufferInfo bufferInfo;
private ByteBuffer[] rawInputBuffers;
private ByteBuffer[] encodedOutputBuffers;
private int inSampleRate;
private int channels;
private final static int DEFAULT_QUEUE_SIZE = 512;
private BlockingDeque<BufferEncoded> writeQueue = new LinkedBlockingDeque<>(DEFAULT_QUEUE_SIZE);
private BlockingDeque<BufferDecoded> encodeQueue = new LinkedBlockingDeque<>(DEFAULT_QUEUE_SIZE);
private byte[] mp3buf;
private boolean decodeFinished;
private boolean encodeFinished;
private long readSize;
private long decodeSize;
private long encodeSize;
private Mp3Lame mp3Lame;
private WriteThread writeThread;
private EncodeThread encodeThread;
private long lastPts;
private class BufferDecoded {
int channels;
short[] leftBuffer;
short[] rightBuffer;
short[] pcm;
long pts;
}
private class BufferEncoded {
byte[] buffer;
int length;
}
private class WriteThread extends Thread {
private String mp3Path;
private FileOutputStream fos;
private BufferedOutputStream bos;
WriteThread(String path) {
super();
mp3Path = path;
}
@Override
public void run() {
try {
Log.i(TAG, "WriteThread start");
fos = new FileOutputStream(new File(mp3Path));
bos = new BufferedOutputStream(fos, 200 * 1024);
while (true) {
if (encodeFinished && writeQueue.size() == 0) {
break;
}
BufferEncoded buffer = null;
try {
buffer = writeQueue.take();
} catch (InterruptedException e) {
Log.e(TAG, "WriteThread InterruptedException=" + e.toString());
}
if(buffer != null) {
bos.write(buffer.buffer, 0, buffer.length);
}
}
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Log.i(TAG, "WriteThread end");
}
}
private class EncodeThread extends Thread {
@Override
public void run() {
Log.i(TAG, "EncodeThread start");
while (true) {
if (decodeFinished && encodeQueue.size() == 0) {
break;
}
BufferDecoded buffer = null;
try {
buffer = encodeQueue.take();
} catch (InterruptedException e) {
Log.e(TAG, "EncodeThread InterruptedException=" + e.toString());
}
if (buffer != null) {
encodeToMp3(buffer);
}
}
encodeFinished = true;
writeThread.interrupt();
Log.i(TAG, "EncodeThread end");
}
}
private class DecodeThread extends Thread {
@Override
public void run() {
long startTime = System.currentTimeMillis();
try {
Log.i(TAG, "DecodeThread start");
while (true) {
int outputBufIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, -1);
if (outputBufIndex >= 0) {
ByteBuffer buffer = encodedOutputBuffers[outputBufIndex];
decodeSize += bufferInfo.size;
ShortBuffer shortBuffer = buffer.order(ByteOrder.nativeOrder()).asShortBuffer();
short[] leftBuffer = null;
short[] rightBuffer = null;
short[] pcm = null;
if (channels == 2) {
pcm = new short[shortBuffer.remaining()];
shortBuffer.get(pcm);
} else {
leftBuffer = new short[shortBuffer.remaining()];
rightBuffer = leftBuffer;
shortBuffer.get(leftBuffer);
Log.e(TAG, "single channel leftBuffer.length = " + leftBuffer.length);
}
buffer.clear();
BufferDecoded bufferDecoded = new BufferDecoded();
bufferDecoded.leftBuffer = leftBuffer;
bufferDecoded.rightBuffer = rightBuffer;
bufferDecoded.pcm = pcm;
bufferDecoded.channels = channels;
bufferDecoded.pts = bufferInfo.presentationTimeUs;
encodeQueue.put(bufferDecoded);
mMediaCodec.releaseOutputBuffer(outputBufIndex, false);
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.e(TAG, "DecodeThread get BUFFER_FLAG_END_OF_STREAM");
decodeFinished = true;
break;
}
} else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
encodedOutputBuffers = mMediaCodec.getOutputBuffers();
} else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
final MediaFormat oformat = mMediaCodec.getOutputFormat();
Log.d(TAG, "Output format has changed to " + oformat);
}
}
} catch (Exception e) {
e.printStackTrace();
}
encodeThread.interrupt();
long endTime = System.currentTimeMillis();
Log.i(TAG, "DecodeThread finished time=" + (endTime - startTime) / 1000);
}
}
public void convertToMp3(String srcPath, String mp3Path) {
long startTime = System.currentTimeMillis();
long endTime;
encodeThread = new EncodeThread();
writeThread = new WriteThread(mp3Path);
DecodeThread decodeThread = new DecodeThread();
encodeThread.start();
writeThread.start();
prepareDecode(srcPath);
decodeThread.start();
readSampleData();
try {
writeThread.join();
} catch (InterruptedException e) {
Log.e(TAG, "convertToMp3 InterruptedException=" + e.toString());
}
double mReadSize = readSize / 1024.0 / 1024.0;
double mDecodeSize = decodeSize / 1024.0 / 1024.0;
double mEncodeSize = encodeSize / 1024.0 / 1024.0;
Log.i(TAG, "readSize=" + mReadSize + ", decodeSize=" + mDecodeSize + ",encodeSize=" + mEncodeSize);
endTime = System.currentTimeMillis();
Log.i(TAG, "convertToMp3 finish time=" + (endTime - startTime) / 1000);
}
private void prepareDecode(String path) {
try {
mediaExtractor = new MediaExtractor();
mediaExtractor.setDataSource(path);
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
MediaFormat mMediaFormat = mediaExtractor.getTrackFormat(i);
Log.i(TAG, "prepareDecode get mMediaFormat=" + mMediaFormat);
String mime = mMediaFormat.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("audio")) {
mMediaCodec = MediaCodec.createDecoderByType(mime);
mMediaCodec.configure(mMediaFormat, null, null, 0);
mediaExtractor.selectTrack(i);
inSampleRate = mMediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
channels = mMediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
break;
}
}
mMediaCodec.start();
bufferInfo = new BufferInfo();
rawInputBuffers = mMediaCodec.getInputBuffers();
encodedOutputBuffers = mMediaCodec.getOutputBuffers();
Log.i(TAG, "--channel=" + channels + "--sampleRate=" + inSampleRate);
mp3Lame = new Mp3LameBuilder()
.setInSampleRate(inSampleRate)
.setOutChannels(channels)
.setOutBitrate(128)
.setOutSampleRate(inSampleRate)
.setQuality(9)
.setVbrMode(Mp3LameBuilder.VbrMode.VBR_MTRH)
.build();
} catch (IOException e) {
e.printStackTrace();
}
}
private void readSampleData() {
boolean rawInputEOS = false;
while (!rawInputEOS) {
for (int i = 0; i < rawInputBuffers.length; i++) {
int inputBufIndex = mMediaCodec.dequeueInputBuffer(-1);
if (inputBufIndex >= 0) {
ByteBuffer buffer = rawInputBuffers[inputBufIndex];
int sampleSize = mediaExtractor.readSampleData(buffer, 0);
long presentationTimeUs = 0;
if (sampleSize < 0) {
rawInputEOS = true;
sampleSize = 0;
} else {
readSize += sampleSize;
presentationTimeUs = mediaExtractor.getSampleTime();
}
mMediaCodec.queueInputBuffer(inputBufIndex, 0,
sampleSize, presentationTimeUs,
rawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
if (!rawInputEOS) {
mediaExtractor.advance();
} else {
break;
}
} else {
Log.e(TAG, "wrong inputBufIndex=" + inputBufIndex);
}
}
}
}
private void encodeToMp3(BufferDecoded buffer) {
if (buffer == null || buffer.pts == lastPts) {
return;
}
lastPts = buffer.pts;
int bufferLength = buffer.pcm.length / 2;
if (mp3buf == null) {
mp3buf = new byte[(int) (bufferLength * 1.25 + 7200)];
}
if (bufferLength > 0) {
int bytesEncoded;
if (channels == 2) {
bytesEncoded = mp3Lame.encodeBufferInterLeaved(buffer.pcm, bufferLength, mp3buf);
}else {
bytesEncoded = mp3Lame.encode(buffer.leftBuffer, buffer.leftBuffer, bufferLength, mp3buf);
}
Log.d(TAG, "mp3Lame encodeSize=" + bytesEncoded);
if (bytesEncoded > 0) {
BufferEncoded be = new BufferEncoded();
be.buffer = mp3buf;
be.length = bytesEncoded;
try {
writeQueue.put(be);
} catch (InterruptedException e) {
e.printStackTrace();
}
encodeSize += bytesEncoded;
}
}
}
}

@ -0,0 +1,71 @@
package com.frank.ffmpeg.mp3;
import com.frank.ffmpeg.AudioPlayer;
public class Mp3Lame {
public Mp3Lame() {
AudioPlayer.lameInitDefault();
}
Mp3Lame(Mp3LameBuilder builder) {
initialize(builder);
}
private void initialize(Mp3LameBuilder builder) {
AudioPlayer.lameInit(builder.inSampleRate, builder.outChannel, builder.outSampleRate,
builder.outBitrate, builder.scaleInput, getIntForMode(builder.mode), getIntForVbrMode(builder.vbrMode), builder.quality, builder.vbrQuality, builder.abrMeanBitrate,
builder.lowPassFreq, builder.highPassFreq, builder.id3tagTitle, builder.id3tagArtist,
builder.id3tagAlbum, builder.id3tagYear, builder.id3tagComment);
}
public int encode(short[] buffer_l, short[] buffer_r,
int samples, byte[] mp3buf) {
return AudioPlayer.lameEncode(buffer_l, buffer_r, samples, mp3buf);
}
int encodeBufferInterLeaved(short[] pcm, int samples,
byte[] mp3buf) {
return AudioPlayer.encodeBufferInterleaved(pcm, samples, mp3buf);
}
public int flush(byte[] mp3buf) {
return AudioPlayer.lameFlush(mp3buf);
}
public void close() {
AudioPlayer.lameClose();
}
private static int getIntForMode(Mp3LameBuilder.Mode mode) {
switch (mode) {
case STEREO:
return 0;
case JSTEREO:
return 1;
case MONO:
return 3;
case DEFAULT:
return 4;
}
return -1;
}
private static int getIntForVbrMode(Mp3LameBuilder.VbrMode mode) {
switch (mode) {
case VBR_OFF:
return 0;
case VBR_RH:
return 2;
case VBR_ABR:
return 3;
case VBR_MTRH:
return 4;
case VBR_DEFAUT:
return 6;
}
return -1;
}
}

@ -0,0 +1,147 @@
package com.frank.ffmpeg.mp3;
public class Mp3LameBuilder {
public enum Mode {
STEREO, JSTEREO, MONO, DEFAULT
}
public enum VbrMode {
VBR_OFF, VBR_RH, VBR_MTRH, VBR_ABR, VBR_DEFAUT
}
int inSampleRate;
int outSampleRate;
int outBitrate;
int outChannel;
public int quality;
int vbrQuality;
int abrMeanBitrate;
int lowPassFreq;
int highPassFreq;
float scaleInput;
Mode mode;
VbrMode vbrMode;
String id3tagTitle;
String id3tagArtist;
String id3tagAlbum;
String id3tagComment;
String id3tagYear;
Mp3LameBuilder() {
this.id3tagTitle = null;
this.id3tagAlbum = null;
this.id3tagArtist = null;
this.id3tagComment = null;
this.id3tagYear = null;
this.inSampleRate = 44100;
this.outSampleRate = 0;
this.outChannel = 2;
this.outBitrate = 128;
this.scaleInput = 1;
this.quality = 5;
this.mode = Mode.DEFAULT;
this.vbrMode = VbrMode.VBR_OFF;
this.vbrQuality = 5;
this.abrMeanBitrate = 128;
this.lowPassFreq = 0;
this.highPassFreq = 0;
}
Mp3LameBuilder setQuality(int quality) {
this.quality = quality;
return this;
}
Mp3LameBuilder setInSampleRate(int inSampleRate) {
this.inSampleRate = inSampleRate;
return this;
}
Mp3LameBuilder setOutSampleRate(int outSampleRate) {
this.outSampleRate = outSampleRate;
return this;
}
Mp3LameBuilder setOutBitrate(int bitrate) {
this.outBitrate = bitrate;
return this;
}
Mp3LameBuilder setOutChannels(int channels) {
this.outChannel = channels;
return this;
}
Mp3LameBuilder setId3tagTitle(String title) {
this.id3tagTitle = title;
return this;
}
Mp3LameBuilder setId3tagArtist(String artist) {
this.id3tagArtist = artist;
return this;
}
Mp3LameBuilder setId3tagAlbum(String album) {
this.id3tagAlbum = album;
return this;
}
Mp3LameBuilder setId3tagComment(String comment) {
this.id3tagComment = comment;
return this;
}
Mp3LameBuilder setId3tagYear(String year) {
this.id3tagYear = year;
return this;
}
Mp3LameBuilder setScaleInput(float scaleAmount) {
this.scaleInput = scaleAmount;
return this;
}
Mp3LameBuilder setMode(Mode mode) {
this.mode = mode;
return this;
}
Mp3LameBuilder setVbrMode(VbrMode mode) {
this.vbrMode = mode;
return this;
}
Mp3LameBuilder setVbrQuality(int quality) {
this.vbrQuality = quality;
return this;
}
Mp3LameBuilder setAbrMeanBitrate(int bitrate) {
this.abrMeanBitrate = bitrate;
return this;
}
Mp3LameBuilder setLowpassFreqency(int freq) {
this.lowPassFreq = freq;
return this;
}
Mp3LameBuilder setHighpassFreqency(int freq) {
this.highPassFreq = freq;
return this;
}
Mp3Lame build() {
return new Mp3Lame(this);
}
}

@ -9,7 +9,7 @@ buildscript {
} }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.2.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip

Loading…
Cancel
Save