gpt4 book ai didi

android-ndk - 在android上使用ffmpeg将AAC解码为PCM

转载 作者:行者123 更新时间:2023-12-04 22:46:46 26 4
gpt4 key购买 nike

我在 ubuntu 上使用 android NDK (r8c) 构建了 ffmpeg 0.8.12 (love)。
然后我通过 JNI 在另一个 android 应用程序中使用生成的库。

基本上我想要做的是将一个字节流从java传递给我的c jni函数,并使用ffmpeg将其解码为PCM音频缓冲区,然后将其传递回java以使用Android的AudioTrack播放。我可以成功地将缓冲区传递给 jni(已经检查了值)并且 ffmpeg 似乎正确初始化,但是当它尝试解码第一帧时,它在 aacdec.c 中的 aac_decode_frame_int 方法中引发错误“ channel 元素 0.0 不是分配”。 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 代码,但找不到问题。任何帮助将不胜感激!

最佳答案

您必须为 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;

更新

对不起,我写了音频编码必须设置的参数。
对于音频解码,通常设置 avCtx->channels 就足够了, ctx->sample_rate或设置 avCtx->extrdataavCtx->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;
}
}

关于android-ndk - 在android上使用ffmpeg将AAC解码为PCM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13499480/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com