StackOverflowed
StackOverflowed

Reputation: 5975

Getting jibberish while using ffmpeg in android

I'm trying decode an audio file into PCM to use with AudioTrack. The audio is squeeky, squelchy, and just plain jibberish and for a random second sounds like it should but mainly is completely muddled. I'm not sure where my mistake is, is it in how the array is passed back to playSound?

Thank you in advance, I would really appreciate help on this matter as it's been kicking my ass for a while.

This is my java code:

public void init() {
int bufSize = AudioTrack.getMinBufferSize(44100, 
                AudioFormat.CHANNEL_OUT_STEREO,  
                AudioFormat.ENCODING_PCM_16BIT); 


        track = new AudioTrack(AudioManager.STREAM_MUSIC,  
        44100,  
        AudioFormat.CHANNEL_OUT_STEREO,  
        AudioFormat.ENCODING_PCM_16BIT,  
        bufSize, 
        AudioTrack.MODE_STREAM); 
        log("STARTING!!! _________________________ <--");

        byte[] array = new byte[bufSize];

        try {

            fos  = new FileOutputStream("/sdcard/acdc.bin");

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        decoder("/sdcard/acdc.ogg", array); 
}

void playSound(byte[] buf, int size) {   

    try {
        fos.write(buf, 0, size);
    } catch (IOException e) {
        e.printStackTrace();
    }
    if(track.getPlayState()!=AudioTrack.PLAYSTATE_PLAYING) {   
        track.play();                       
    }
    int wrote =  track.write(buf, 0, size);
    if (wrote != size)
        log("WRITING: " + wrote  + " but size was: " + size); 
}

This is my c function:

void Java_com_example_ffmpegsample_MainActivity_decoder(JNIEnv* env, jobject obj,jstring file,jbyteArray array)
    {
        jboolean            isfilenameCopy;
        const char *        filename = (*env)->GetStringUTFChars(env, file, &isfilenameCopy);
        AVCodec *codec;
        AVCodecContext *c= NULL;
        AVFormatContext *pFormatCtx;
        AVCodecContext *pCodecCtx;

        int out_size, len;
        FILE *f, *outfile;
        uint8_t *outbuf;
        uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
        AVPacket avpkt;
        LOGI("HERE");
        jclass              cls = (*env)->GetObjectClass(env, obj);
        LOGI(cls);
        jmethodID           play = (*env)->GetMethodID(env, cls, "playSound", "([BI)V");//At the begining of your main function

        av_init_packet(&avpkt);



        av_register_all();
        LOGI("AUDIO DECODER");
        printf("Audio decoding\n");
        int err;
        err = av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL);
        if (err!=0) {
            LOGI("COULD NOT AV_OPEN file");
            return;
        }
        if(av_find_stream_info(pFormatCtx)<0) {
                LOGE("Unable to get stream info");
                return;
        }
        int audioStream = -1;
        int i;

        for (i=0; i<pFormatCtx->nb_streams; i++) {
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) {
                    audioStream = i;
                    break;
                }
            }
            if(audioStream==-1) {
                LOGE("Unable to find audio stream");
                return;
            }
        LOGI("Audio stream is [%d]", audioStream);

        pCodecCtx=pFormatCtx->streams[audioStream]->codec;
        codec = avcodec_find_decoder(pCodecCtx->codec_id);
        /* find the mpeg audio decoder */
       // codec = avcodec_find_decoder(CODEC_ID_AAC);
        if (!codec) {
            LOGI("NO CODEC");
            fprintf(stderr, "codec not found\n");
            return;
        }

        //c= avcodec_alloc_context();
        c = pCodecCtx;

        /* open it */
        if (avcodec_open(c, codec) < 0) {
            fprintf(stderr, "could not open codec\n");
            LOGI("NOT LOADING CODEC");
            return;
        }

        outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);

        f = fopen(filename, "rb");
        if (!f) {
            fprintf(stderr, "could not open %s\n", filename);
            LOGI("COULD NOT OPEN FILE");
            return;
        }

        /* decode until eof */
        avpkt.data = inbuf;
        avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);

        while (avpkt.size > 0) {
            LOGI("............................." + avpkt.size);
            out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
            len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);
            if (len < 0) {
                fprintf(stderr, "Error while decoding\n");
                LOGI("ERROR DECODING, error: %d", len);
                return;
            }
            if (out_size > 0) {
                /* if a frame has been decoded, output it */
                jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
                memcpy(bytes, outbuf, out_size); //
                (*env)->ReleaseByteArrayElements(env, array, bytes, 0);
                (*env)->CallVoidMethod(env, obj, play, array, out_size);

            }
            avpkt.size -= len;
            avpkt.data += len;
            if (avpkt.size < AUDIO_REFILL_THRESH) {
                /* Refill the input buffer, to avoid trying to decode
                 * incomplete frames. Instead of this, one could also use
                 * a parser, or use a proper container format through
                 * libavformat. */
                memmove(inbuf, avpkt.data, avpkt.size);
                avpkt.data = inbuf;
                len = fread(avpkt.data + avpkt.size, 1,
                            AUDIO_INBUF_SIZE - avpkt.size, f);
                if (len > 0)
                    avpkt.size += len;
            }
        }

        fclose(f);
        free(outbuf);

        avcodec_close(c);
        av_free(c);
    }

Upvotes: 0

Views: 465

Answers (2)

hack_on
hack_on

Reputation: 2520

You create an AudioTrack in Streaming mode with a min size buffer. It may be that if it is converting some data, then writing some data that gaps are happening in the audio playback. This would be especially true if the conversion has to keep reading from the SDcard. You could increase the size of the AudioTrack buffer to see if this is a factor.

Also, I'm not sure but I think avcodec_decode_audio3 may set &out_size as size in shorts, but this is then sent to AudioTrack as size in bytes.(No just checked API and its bytes).

Upvotes: 1

Robert Rowntree
Robert Rowntree

Reputation: 6289

have u tried using plain CLI interface in android like this project? You could use a simple fileProcesssor interface: IN=ogg OUT=raw-pcm

see below on CLI for conversion of .ogg to PCM format. Then do whatever with the output

 rob@ Downloads$ ffmpeg -i Example.ogg -f s16le -acodec pcm_s16le output.raw

ffmpeg version N-35901-g27a3415 Copyright (c) 2000-2012 the FFmpeg developers
  built on Oct  7 2012 12:06:43 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5)
  configuration: --enable-gpl --enable-libfaac --enable-libfdk-aac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libtheora --enable-libvorbis --enable-libvpx --enable-x11grab --enable-libx264 --enable-nonfree --enable-version3
  libavutil      51. 73.102 / 51. 73.102
  libavcodec     54. 64.100 / 54. 64.100
  libavformat    54. 29.105 / 54. 29.105
  libavdevice    54.  3.100 / 54.  3.100
  libavfilter     3. 19.102 /  3. 19.102
  libswscale      2.  1.101 /  2.  1.101
  libswresample   0. 16.100 /  0. 16.100
  libpostproc    52.  1.100 / 52.  1.100
[NULL @ 0x186b840] Invalid packet
Input #0, ogg, from 'Example.ogg':
  Duration: 00:00:06.10, start: 0.000000, bitrate: 137 kb/s
    Stream #0:0: Audio: vorbis, 44100 Hz, stereo, s16, 160 kb/s
Output #0, s16le, to 'output.raw':
  Metadata:
    encoder         : Lavf54.29.105
    Stream #0:0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (vorbis -> pcm_s16le)
Press [q] to stop, [?] for help
size=    1054kB time=00:00:06.11 bitrate=1411.2kbits/s    
video:0kB audio:1054kB subtitle:0 global headers:0kB muxing overhead 0.000000%

This assumes you can config/make ffmpeg for android with OGG LIB dependencies , which may be a tricky process...

Upvotes: 1

Related Questions