How to decode audio via FFmpeg in Android

10,236

Use audiotrack class to do the work for you. You can do something like this.

JAVA side.

            AudioTrack track;

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


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

            track.play(); 

            while(true){
            readBufferFromNative(); //update buffer from native code

                    ....................
                    ....................
                    }

On native Side : You need to read the frames and convert them into raw pcm format first and then start filling the audio buffer continuously. When the buffer is full, it will automatically play.

JNIEXPORT int JNICALL Java_com_ffmpeg_Main_jniMainEntry(JNIEnv* env, jobject obj, jstring input) {

    const char * pszFileName = (*env)->GetStringUTFChars(env, input, 0);
    AVFormatContext * m_fc;
    int err;
    AVPacket pkt;
    char * pAudioBuffer = (char *) av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE * 2);
    int i;

    avcodec_register_all ();
    avdevice_register_all ();
    av_register_all ();

    err = av_open_input_file(&m_fc, pszFileName, 0, 0, 0);
    err = av_find_stream_info(m_fc);
    for(i = 0; i<m_fc->nb_streams; i++) {
    if((m_fc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) || (m_fc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)) {
    AVCodec *codec = avcodec_find_decoder(m_fc->streams[i]->codec->codec_id);

    if (codec == 0)
            continue;
    err = avcodec_open(m_fc->streams[i]->codec, codec);
    if (err <0)
            continue;
    }
 }
    while (av_read_frame(m_fc, &pkt)>= 0) {
            if (m_fc-> streams[pkt.stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
                    int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;
                    int size=pkt->size;
                    while(size > 0) {
                            int len = avcodec_decode_audio3(m_fc->streams[pkt.stream_index]->codec, (int16_t *) pAudioBuffer, &data_size, &pkt);
                            LOGD("data_size %d len %d", data_size, len);
                            size = pkt->size-len;
                            }
            }
 }

}

Share:
10,236
Kyborg2011
Author by

Kyborg2011

Programmer on Android, web-programmer

Updated on June 04, 2022

Comments

  • Kyborg2011
    Kyborg2011 almost 2 years

    I am writing a player for Android with FFmpeg compiled for Android NDK.

    I could open the file through FFmpeg and wrote this:

    av_register_all();
    
    char* str = (*env) -> GetStringUTFChars(env, argv, 0);
    __android_log_print(ANDROID_LOG_INFO, "HelloNDK!", str, str);
    
    if (av_open_input_file (&pFormatCtx, str, NULL, 0, NULL) != 0)
        return -2; // Couldn't open file
    
    // Retrieve stream information
    if (av_find_stream_info(pFormatCtx) < 0)
        return -3; // Couldn't find stream information
    
    // Dump information about file onto standard error
    dump_format(pFormatCtx, 0, argv, 0);
    
    // Find the first video stream
    videoStream =- 1;
    audioStream =- 1;
    for (i = 0; i < pFormatCtx->nb_streams; i++) {
        if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && audioStream <0) {
            audioStream = i;
        }
    }
    
    if (audioStream == -1)
        return -5;
    
    aCodecCtx = pFormatCtx->streams[audioStream]->codec;
    // Set audio settings from codec info
    
    aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
    
    if (!aCodec) {
        fprintf (stderr, "Unsupported codec! \n");
        return -1;
    }
    
    avcodec_open (aCodecCtx, aCodec);
    

    How can I now decode the audio and return it to the Java program? Maybe somebody could give me an example

    EDIT: When using avcodec_decode_audio3 Get the following: 03-22 07:54:00.988: INFO / DEBUG (31): * ** * ** * ** * * * ** * ** * 03-22 07:54:00.988: INFO / DEBUG (31): Build fingerprint: 'generic / sdk / generic /: 2.2/FRF91/43546: eng / test-keys' 03-22 07:54:00.988: INFO / DEBUG (31): pid: 435, tid: 435>>> org.libsdl.app <<< 03-22 07:54:00.998: INFO / DEBUG (1931): signal 11 (SIGSEGV), fault addr 00000000 03-22 07:54:00.998: INFO / DEBUG (1931): r0 00000000 r1 00000000 r2 81893210 r3 00000000 03-22 07:54:01.008: INFO / DEBUG (1931): r4 8189324c r5 818931d0 r6 00000000 r7 00000000 03-22 07:54:01.008: INFO / DEBUG (1931): r8 00000200 r9 00000600 10 00000300 00000500 fp 03-22 07:54:01.019: INFO / DEBUG (1931): ip 81350868 sp bef4c438 lr 8112cb3b pc 8112cb6c cpsr 80000030 03-22 07:54:01.369: INFO / DEBUG (31): # 00 pc 0012cb6c / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.369: INFO / DEBUG (31): # 01 pc 0012db46 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.379: INFO / DEBUG (31): # 02 pc 0013052e / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.379: INFO / DEBUG (31): # 03 pc 00132142 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.389: INFO / DEBUG (31): # 04 pc 001a2836 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.399: INFO / DEBUG (31): # 05 pc 00024ee6 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.399: INFO / DEBUG (31): # 06 pc 00013974 / system / lib / libdvm.so 03-22 07:54:01.409: INFO / DEBUG (31): # 07 pc 0003de3c / system / lib / libdvm.so 03-22 07:54:01.409: INFO / DEBUG (31): # 08 pc 00037216 / system / lib / libdvm.so 03-22 07:54:01.419: INFO / DEBUG (31): # 09 pc 000432ec / system / lib / libdvm.so 03-22 07:54:01.419: INFO / DEBUG (31): # 10 pc 00018714 / system / lib / libdvm.so 03-22 07:54:01.439: INFO / DEBUG (31): # 11 pc 0001e8c4 / system / lib / libdvm.so 03-22 07:54:01.439: INFO / DEBUG (31): # 12 pc 0001d790 / system / lib / libdvm.so 03-22 07:54:01.439: INFO / DEBUG (31): # 13 pc 0005408e / system / lib / libdvm.so 03-22 07:54:01.449: INFO / DEBUG (31): # 14 pc 0005bde2 / system / lib / libdvm.so 03-22 07:54:01.449: INFO / DEBUG (31): # 15 pc 00018714 / system / lib / libdvm.so 03-22 07:54:01.459: INFO / DEBUG (31): # 16 pc 0001e8c4 / system / lib / libdvm.so 03-22 07:54:01.469: INFO / DEBUG (31): # 17 pc 0001d790 / system / lib / libdvm.so 03-22 07:54:01.469: INFO / DEBUG (31): # 18 pc 00053eec / system / lib / libdvm.so 03-22 07:54:01.479: INFO / DEBUG (31): # 19 pc 0004072c / system / lib / libdvm.so 03-22 07:54:01.479: INFO / DEBUG (31): # 20 pc 00034454 / system / lib / libdvm.so 03-22 07:54:01.489: INFO / DEBUG (31): # 21 pc 0002c930 / system / lib / libandroid_runtime.so 03-22 07:54:01.489: INFO / DEBUG (31): # 22 pc 0002d85c / system / lib / libandroid_runtime.so 03-22 07:54:01.499: INFO / DEBUG (31): # 23 pc 00008c86 / system / bin / app_process 03-22 07:54:01.519: INFO / DEBUG (31): # 24 pc 0000d362 / system / lib / libc.so

    Can I use avcodec_decode_audio2? I have in recent days has reached the following code:

    AVFormatContext * pFormatCtx; 
    int i, videoStream, audioStream; 
    AVCodecContext * pCodecCtx; 
    AVCodec * pCodec; 
    AVFrame * pFrame; 
    AVPacket packet; 
    int frameFinished; 
    float aspect_ratio; 
    
    AVCodecContext * aCodecCtx; 
    AVCodec * aCodec; 
    
    
    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]; 
    
    
    
    av_register_all (); 
    
    char * str = (* env) -> GetStringUTFChars (env, argv, 0); 
    
    
    if (av_open_input_file (& pFormatCtx, str, NULL, 0, NULL)! = 0) 
    return -150; 
    
    
    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 (packet.stream_index == videoStream) { 
    
    } Else if (packet.stream_index == audioStream) { 
    
    packet_queue_put (& audioq, & packet); 
    int len1, data_size; 
    data_size = 417; 
    
    len1 = avcodec_decode_audio2 (aCodecCtx, (int16_t *) audio_buf, & data_size, 
    packet.data, packet.size); 
    return packet.size; 
    } Else { 
    av_free_packet (& packet); 
    } 
    
    
    
    } 
    
    
    
    return 0; 
    

    In this case, when the avcodec_decode_audio2 I got -1. What I did wrong?

    Note: When I drove int data_size = 417; then DEBUG does not appear and the function returns -1, but when I drive a: int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2; then vyskakievaet DEBUG in your function so in my own! How can this be solved?

    EDIT2: My new code:

    
    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;
    }