android - 通过音轨在 Android 中播放音乐

标签 android audio ffmpeg decode

我编写了一个使用 FFmpeg 解码 aydio 的脚本。这是代码:


JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_main( JNIEnv* env, jobject obj, int argc, jstring argv, jbyteArray array) {
      AVFormatContext *pFormatCtx;
      int             i, videoStream, audioStream;
      AVCodecContext  *pCodecCtx;
      AVCodec         *pCodec;
      AVFrame         *pFrame;
      AVPacket        packet;
      int             frameFinished;
      float           aspect_ratio;

      AVCodecContext  *aCodecCtx;
      AVCodec         *aCodec;

      SDL_Overlay     *bmp;
      SDL_Surface     *screen;
      SDL_Rect        rect;
      SDL_Event       event;
      SDL_AudioSpec   wanted_spec, spec;
      AVCodecContext *c= NULL;
         int out_size, len;
         int16_t *audio_buf;
         uint8_t *outbuf;
         uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
         char *pAudioBuffer = (char *) av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE * 2);






      av_register_all();

      char *str = (*env)->GetStringUTFChars(env, argv, 0);


      if(av_open_input_file(&pFormatCtx, str, NULL, 0, NULL)!=0)
        return -150; // Couldn't open file


      if(av_find_stream_info(pFormatCtx)nb_streams; i++) {
        if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO &&
           videoStream streams[i]->codec->codec_type==CODEC_TYPE_AUDIO &&
           audioStream streams[audioStream]->codec;



      aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
      if(!aCodec) {
        fprintf(stderr, "Unsupported codec!\n");
        return -45;
      }

      avcodec_open(aCodecCtx, aCodec);
      c=avcodec_alloc_context();
      packet_queue_init(&audioq);
        while (av_read_frame(pFormatCtx, &packet)>= 0) {
            if (aCodecCtx->codec_type == AVMEDIA_TYPE_AUDIO) {
                        int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;
                        int size=packet.size;
                        while(size > 0) {
                                int len = avcodec_decode_audio3(aCodecCtx, (int16_t *) pAudioBuffer, &data_size, &packet);

                                jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
                                memcpy(bytes, (int16_t *) pAudioBuffer, size);
                                (*env)->ReleaseByteArrayElements(env, array, bytes, 0);


                                size = packet.size-len;
                                }
            }

     }


 return 5;
}

程序的Java代码如下:


package org.libsdl.app;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.*;

import android.app.*;
import android.content.*;
import android.view.*;
import android.os.*;
import android.util.Log;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;

import java.lang.*;

public class SDLActivity extends Activity {

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        AudioTrack track;

        int bufSize = AudioTrack.getMinBufferSize(44100,                                AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
                        AudioFormat.ENCODING_PCM_16BIT);


        track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
                    AudioFormat.ENCODING_PCM_16BIT, bufSize, AudioTrack.MODE_STREAM);

        track.play(); 

            byte[] bytes = new byte[bufSize];

            int res = main(2, "/sdcard/muzika_iz_reklami_bmw_5_series_-_bmw_5_series.mp3", bytes);

            track.write(bytes, 0, bytes.length);
            System.out.println(res);





    }
    native int main(int count, String file, byte[] array);

    static {

        System.loadLibrary("test");
    }



/**
    Simple nativeInit() runnable
*/



}

当我运行时,音乐没有播放。我做错了什么?

最佳答案

每次将新的解码数据复制到数组时,您都应该连续调用 track.write(bytes, 0, bytes.length),而不是只调用一次。

在您的 Java 代码中添加一个新方法

void playSound(byte[] buf, int size) {  
    track.write(buf, 0, size);  
}

然后在您的 C 代码中这样调用它:

jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID play = (*env)->GetMethodID(env, cls, "playsound", "([BI)V");//At the begining of your main function

(*env)->CallVoidMethod(env, obj, play, array, size);//After (*env)->ReleaseByteArrayElements(env, array, bytes, 0);

祝你好运!

关于android - 通过音轨在 Android 中播放音乐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5429729/

相关文章:

安卓 : Full Screen Activity with Title bar

android - 如何以编程方式通过 Main Activity 在 ViewPager 中更新刷新 fragment

java - 语言更改后 onActivityResult 崩溃

java - Google map api 不显示我当前的位置

python - 使用 ffmpeg 调整大小后文件损坏

Nginx 只允许我的域访问视频 url

c# - 如何使用 ffmpeg 调整图像大小

bash - 如果 #channels 为 2,则连接 wav 文件将忽略

android - AudioTrack 没有正确播放音频文件,因为它发出噪音

android - 通过自己的IP通过RTP进行Android实时音频流传输