德code AAC到PCM在Android的ffmpeg [英] Decode AAC to PCM with ffmpeg on android

查看:751
本文介绍了德code AAC到PCM在Android的ffmpeg的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经建立的ffmpeg 0.8.12(爱)在Ubuntu在Android NDK(R8C)。
然后,我通过JNI使用生成的库在其他Android应用程序。

I have built ffmpeg 0.8.12 (love) with the android NDK (r8c) on ubuntu. I then use the generated library in another android application through JNI.

从本质上讲就是我想要做的就是通过从Java字节流到我的C JNI的功能和使用的ffmpeg脱code它变成然后将被传递回Java使用Android的AudioTrack播放的PCM音频缓冲。我可以成功地通过对JNI通过缓冲(已检查的值)和ffmpeg的似乎正常初始化,但是当它试图去code中的第一帧,它抛出在aacdec的aac_de code_frame_int方法错误.c在信道单元0.0不分配。该AAC文件播放罚款,是有效的。

Essentially what I want to do is pass a byte stream from java to my c jni function and use ffmpeg to decode it into a PCM audio buffer which will then be passed back to java to be played using Android's AudioTrack. I can successfully pass the buffer through to jni (have checked the values) and ffmpeg seems to initialise correctly, but when it tries to decode the first frame, it throws an error in the aac_decode_frame_int method in aacdec.c "channel element 0.0 is not allocated". The aac file plays fine and is valid.

下面是我的JNI code做解码

Here is my jni code to do the decoding

jint Java_com_example_testffmpeg_MainActivity_decodeAacBytes(JNIEnv * env,
        jobject this, jbyteArray input, jint numBytes) {

    //copy bytes from java
    jbyte* bufferPtr = (*env)->GetByteArrayElements(env, input, NULL);
    uint8_t inputBytes[numBytes + FF_INPUT_BUFFER_PADDING_SIZE];
    memset(inputBytes, 0, numBytes + FF_INPUT_BUFFER_PADDING_SIZE);
    memcpy(inputBytes, bufferPtr, numBytes);
    (*env)->ReleaseByteArrayElements(env, input, bufferPtr, 0);

    av_register_all();

    AVCodec *codec = avcodec_find_decoder(CODEC_ID_AAC);

    if (codec == NULL) {
        LOGE("Cant find AAC codec\n");
        return 0;
    }
    LOGI("AAC codec found\n");

    AVCodecContext *avCtx = avcodec_alloc_context();

    if (avCtx == NULL) {
        LOGE("Could not allocate codec context\n");
        return 0;
    }
    LOGI("codec context allocated\n");

    if (avcodec_open2(avCtx, codec, NULL) < 0) {
        LOGE("Could not open codec\n");
        return 0;
    }
    LOGI("AAC codec opened");

    //the input buffer
    AVPacket avPacket;
    av_init_packet(&avPacket);

    LOGI("AVPacket initialised\n");

    avPacket.size = numBytes; //input buffer size
    avPacket.data = inputBytes; // the input buffer

    int outSize;
    int len;
    uint8_t *outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);

    while (avPacket.size > 0) {
        outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
        len = avcodec_decode_audio3(avCtx, (short *) outbuf, &outSize,
                &avPacket);

        if (len < 0) {
            LOGE("Error while decoding\n");
            return 0;
        }

        if (outSize > 0) {
            LOGI("Decoded some stuff\n");
        }

        avPacket.size -= len;
        avPacket.data += len;
    }

    LOGI("Freeing memory\n");

    av_free_packet(&avPacket);
    avcodec_close(avCtx);
    av_free(avCtx);

    return 0;
}

在调用AV codec_de code_audio3,当解码第一次出现时,会出现问题。我已经通过的ffmpeg code踩,但无法发现问题。任何帮助将大大AP preciated!

The problem occurs in the call to avcodec_decode_audio3, when the decoding first occurs. I have stepped through the ffmpeg code, but can't find the problem. Any help would be greatly appreciated!

推荐答案

在打电话之前,您必须为 AV codecContext 一些额外的设置 AV codec_open2

You must set some additional settings for AVCodecContext before you call avcodec_open2.

我通常设置这些需要的设置(与变量数'k'的意思是predefined constatns开始):

I usually set these required settings (variables beginning with 'k' mean predefined constatns):

avCtx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
avCtx->codec_type = AVMEDIA_TYPE_AUDIO;
avCtx->channels = kChannelsCount; // for example, 2
avCtx->sample_fmt = kSampleFmt; // AV_SAMPLE_FMT_S16
avCtx->sample_rate = kSampleRate; // 44100
avCtx->channel_layout = kSampleLayout; // 3
const AVRational timeBase = {1, avCtx->sample_rate};
avCtx->time_base = timeBase;

UPD

我很抱歉,我写必须为音频设置的参数的编码的。
对于音频解码通常足以设置 avCtx-&GT;渠道则将ctx-&GT; SAMPLE_RATE 或set avCtx-&GT; extrdata avCtx-方式&gt; extradata_size

I'm sorry, I wrote the parameters that must be set for audio encoding. For audio decoding usually sufficient to set avCtx->channels, ctx->sample_rate or set avCtx->extrdata and avCtx->extradata_size.

要找到错误的原因,尝试看看FFmpeg的输出。如果设备上是很难做到的,你可以重定向输出的ffmpeg和自己的回调执行记录。例如:

To find the cause of the error, try to see the ffmpeg output. If on the device is difficult to do, you can redirect the ffmpeg output and perform logging by own callback. Example:

    // initialize:
    ::av_log_set_callback(&my_ffmpeg_log);

    // callback
    void my_ffmpeg_log(void *ptr, int level, const char *fmt, va_list vl)
    {
      /// Here you can set a more detailed level
      if (level < AV_LOG_VERBOSE)
      {
        static char message[8192];
        const char *module = NULL;

        if (ptr)
        {
          AVClass *avc = *(AVClass**) ptr;
          if (avc->item_name)
            module = avc->item_name(ptr);
        }
        vsnprintf(message, sizeof message, fmt, vl);
        // you can set own function here, for example LOGI, as you have in your example
        std::cout << "ffmpeg message : " << module << " " << level << " " << message;
      }
    }

这篇关于德code AAC到PCM在Android的ffmpeg的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆