2023-01-21 297
我已经在Ubuntu上使用Android NDK(R8C)构建了FFMPEG 0.8.12(Love).
然后,我通过JNI在另一个Android应用程序中使用生成的库.
本质上,我要做的是将字节流从Java传递到我的C JNI功能,并使用FFMPEG将其解码到PCM音频缓冲区中,然后将其传递回Java,以使用Android的Idiotrack播放.我可以成功地将缓冲区传递到JNI(已检查了值),并且FFMPEG似乎正确初始化了,但是当它试图解码第一个帧时,它会在AAC_DECODE_FRAME_INT中丢弃AACDEC.C中的错误.分配”. 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代码,但找不到问题.任何帮助将不胜感激!
您必须在调用avcodec_open2之前为AVCodecContext设置一些其他设置.
我通常设置这些必需的设置(以’k’平均预定义的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
很抱歉,我编写了必须设置为Audio 编码的参数.
对于音频解码,通常足以设置avCtx->channels,ctx->sample_rate或set 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;
}
}
以上所述是小编给大家介绍的在安卓上用ffmpeg将AAC解码为PCM,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/26317.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态