android m4c 转化为mp4

来源:互联网 发布:人工智能板块龙头股 编辑:程序博客网 时间:2024/06/11 12:08

多媒体软件开发的人几乎没有不知道FFmpeg的, 最近一直在尝试 FFmpeg 的项目,去看的编解码,很费劲。最终我在一个外国的技术贴上看到了这一解决方案,是将一个m4a格式的音频直接转化为mp4, 我使用了完美解决我的问题, 不需要c++ 或 C 实现,直接由android 内置的MediaMuxer 和 MediaCodec实现。

public static final int COMPRESSED_AUDIO_FILE_BIT_RATE = 128000; // 128kbps
public static final int SAMPLING_RATE = 44100;
public static final int CODEC_TIMEOUT_IN_MS = 5000;
public static final int BUFFER_SIZE = 88200;
public static String AUDIO_RECORDING_FILE_NAME;
public static String COMPRESSED_AUDIO_FILE_NAME;
public static String COMPRESSED_AUDIO_FILE_MIME_TYPE = “audio/mp4a-latm”;
private static String LOGTAG = “m4a > mp4”;

COMPRESSED_AUDIO_FILE_NAME = getFileDirectory(); // m4a 文件格式路径
AUDIO_RECORDING_FILE_NAME = getAudioFilePath(); // pcm 文件格式路径

assert (null == COMPRESSED_AUDIO_FILE_NAME);
assert (null == AUDIO_RECORDING_FILE_NAME);

final File filePcm = new File(AUDIO_RECORDING_FILE_NAME);

new Thread(new Runnable() {
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
Log.e(LOGTAG, “PCM” + AUDIO_RECORDING_FILE_NAME);
File inputFile = new File(AUDIO_RECORDING_FILE_NAME);
try {
FileInputStream fis = new FileInputStream(inputFile);
File outputFile = new File(COMPRESSED_AUDIO_FILE_NAME + “audio.m4a”);
if (outputFile.exists()) {
outputFile.delete();
}
try {
MediaMuxer mux = new MediaMuxer(outputFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
MediaFormat outputFormat = MediaFormat.createAudioFormat(COMPRESSED_AUDIO_FILE_MIME_TYPE, SAMPLING_RATE, 1);
outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, COMPRESSED_AUDIO_FILE_BIT_RATE);

            MediaCodec codec = MediaCodec.createEncoderByType(COMPRESSED_AUDIO_FILE_MIME_TYPE);            codec.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);            codec.start();            ByteBuffer[] codecInputBuffers = codec.getInputBuffers(); // Note: Array of buffers            ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();            MediaCodec.BufferInfo outBuffInfo = new MediaCodec.BufferInfo();            byte[] tempBuffer = new byte[BUFFER_SIZE];            boolean hasMoreData = true;            double presentationTimeUs = 0;            int audioTrackIdx = 0;            int totalBytesRead = 0;            int percentComplete;            do {                int inputBufIndex = 0;                while (inputBufIndex != -1 && hasMoreData) {                    inputBufIndex = codec.dequeueInputBuffer(CODEC_TIMEOUT_IN_MS);                    if (inputBufIndex >= 0) {                        ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];                        dstBuf.clear();                        int bytesRead = fis.read(tempBuffer, 0, dstBuf.limit());                        if (bytesRead == -1) { // -1 implies EOS                            hasMoreData = false;                            codec.queueInputBuffer(inputBufIndex, 0, 0, (long) presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);                        } else {                            totalBytesRead += bytesRead;                            dstBuf.put(tempBuffer, 0, bytesRead);                            codec.queueInputBuffer(inputBufIndex, 0, bytesRead, (long) presentationTimeUs, 0);                            presentationTimeUs = 1000000l * (totalBytesRead / 2) / SAMPLING_RATE;                        }                    }                }                // Drain audio                int outputBufIndex = 0;                while (outputBufIndex != MediaCodec.INFO_TRY_AGAIN_LATER) {                    outputBufIndex = codec.dequeueOutputBuffer(outBuffInfo, CODEC_TIMEOUT_IN_MS);                    if (outputBufIndex >= 0) {                        ByteBuffer encodedData = codecOutputBuffers[outputBufIndex];                        encodedData.position(outBuffInfo.offset);                        encodedData.limit(outBuffInfo.offset + outBuffInfo.size);                        if ((outBuffInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 && outBuffInfo.size != 0) {                            codec.releaseOutputBuffer(outputBufIndex, false);                        } else {                            mux.writeSampleData(audioTrackIdx, codecOutputBuffers[outputBufIndex], outBuffInfo);                            codec.releaseOutputBuffer(outputBufIndex, false);                        }                    } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {                        outputFormat = codec.getOutputFormat();                        Log.e(LOGTAG, "Output format changed - " + outputFormat);                        audioTrackIdx = mux.addTrack(outputFormat);                        mux.start();                    } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {                        Log.e(LOGTAG, "Output buffers changed during encode!");                    } else if (outputBufIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {                        // NO OP                    } else {                        Log.e(LOGTAG, "Unknown return code from dequeueOutputBuffer - " + outputBufIndex);                    }                }                percentComplete = (int) Math.round(((float) totalBytesRead / (float) inputFile.length()) * 100.0);                Log.e(LOGTAG, "Conversion % - " + percentComplete);            }            while (outBuffInfo.flags != MediaCodec.BUFFER_FLAG_END_OF_STREAM && !mStop);            fis.close();            mux.stop();            mux.release();            filePcm.delete();            Log.v(LOGTAG, "Compression done ...");        } catch (IOException e) {            Log.e(LOGTAG, "IO Exception");            e.printStackTrace();        }    } catch (FileNotFoundException e) {        Log.e(LOGTAG, "FileNotFound Exception");        e.printStackTrace();    }    mStop = false;    // Notify UI thread...}

}).start();

0 0