2

ubuntuでAndroid NDK(r8c)を使用してffmpeg 0.8.12(愛)を構築しました。次に、生成されたライブラリを JNI を介して別の Android アプリケーションで使用します。

基本的に、私がやりたいことは、Java から C jni 関数にバイト ストリームを渡し、ffmpeg を使用して PCM オーディオ バッファにデコードし、それを Java に戻して Android の AudioTrack を使用して再生することです。バッファを jni に正常に渡すことができ (値を確認しました)、ffmpeg は正しく初期化されているようですが、最初のフレームをデコードしようとすると、aacdec.c の aac_decode_frame_int メソッドでエラーがスローされます。割り当てられた」。aac ファイルは正常に再生され、有効です。

これがデコードを行うための私のjniコードです

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

この問題は、最初にデコードが行われるときに、avcodec_decode_audio3 の呼び出しで発生します。ffmpeg コードを確認しましたが、問題が見つかりません。どんな助けでも大歓迎です!

4

1 に答える 1

4

AVCodecContextを呼び出す前に、いくつかの追加設定を行う必要がありますavcodec_open2

私は通常、これらの必要な設定を設定します (「k」で始まる変数は、定義済みの定数を意味します)。

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->channelsオーディオのデコードでは、通常、 、ctx->sample_rateまたはavCtx->extrdataとを設定するだけで十分avCtx->extradata_sizeです。

エラーの原因を見つけるには、ffmpeg の出力を確認してください。デバイス上で行うのが難しい場合は、ffmpeg の出力をリダイレクトして、独自のコールバックでログを記録することができます。例:

    // 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;
      }
    }
于 2012-11-21T23:01:39.780 に答える