Decoding audio via Android using FFMpeg

后端 未结 2 1471
傲寒
傲寒 2021-02-01 11:36

I can play Wav files using the below code without issues. When trying to play the exact same media in Mp3 format I only get garbled junk. I believe I am fundamentally misunder

2条回答
  •  清酒与你
    2021-02-01 11:52

    I was able to solve my problem by taking the audio_decode_example code found in the api_example.c file in libavcodec of the ffmpeg source and modify it to suit my needs. Below is the code. Just to note, it doesn't dynamically pick the correct codec to decode with, that is something I'll have to fix next along with a few other items. The java code remains untouched.

    void Java_com_rohaupt_RRD2_player_Example(JNIEnv* env, jobject obj,jstring file,jbyteArray array)
        {
            jboolean            isfilenameCopy;
            const char *        filename = (*env)->GetStringUTFChars(env, file, &isfilenameCopy);
            AVCodec *codec;
            AVCodecContext *c= NULL;
            int out_size, len;
            FILE *f, *outfile;
            uint8_t *outbuf;
            uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
            AVPacket avpkt;
            jclass              cls = (*env)->GetObjectClass(env, obj);
            jmethodID           play = (*env)->GetMethodID(env, cls, "playSound", "([BI)V");//At the begining of your main function
    
            av_init_packet(&avpkt);
    
            printf("Audio decoding\n");
    
            /* find the mpeg audio decoder */
            codec = avcodec_find_decoder(CODEC_ID_MP3);
            if (!codec) {
                fprintf(stderr, "codec not found\n");
                exit(1);
            }
    
            c= avcodec_alloc_context();
    
            /* open it */
            if (avcodec_open(c, codec) < 0) {
                fprintf(stderr, "could not open codec\n");
                exit(1);
            }
    
            outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
    
            f = fopen(filename, "rb");
            if (!f) {
                fprintf(stderr, "could not open %s\n", filename);
                exit(1);
            }
    
            /* decode until eof */
            avpkt.data = inbuf;
            avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
    
            while (avpkt.size > 0) {
                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");
                    exit(1);
                }
                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);
        }
    

提交回复
热议问题