Audio 如何使用FFmpeg将ADPCM转换为PCM?

Audio 如何使用FFmpeg将ADPCM转换为PCM?,audio,android-ndk,ffmpeg,pcm,Audio,Android Ndk,Ffmpeg,Pcm,我有一个视频源,它使用ADPCM编解码器向我发送音频。但是,android仅支持PCM格式。如何将ADPCM音频馈送转换为PCM音频馈送 对此的答案可能与对的答案类似 我已成功使用以下代码解码帧: int len = avcodec_decode_audio4(pAudioCodecCtx, pAudioFrame, &frameFinished, &packet); 这里的秘诀是使用反向编码功能吗 以下是迄今为止我的音频解码功能: <!-- language: c --

我有一个视频源,它使用ADPCM编解码器向我发送音频。但是,android仅支持PCM格式。如何将ADPCM音频馈送转换为PCM音频馈送

对此的答案可能与对的答案类似

我已成功使用以下代码解码帧:

int len = avcodec_decode_audio4(pAudioCodecCtx, pAudioFrame, &frameFinished, &packet);
这里的秘诀是使用反向编码功能吗

以下是迄今为止我的音频解码功能:

<!-- language: c -->
if(packet_queue_get(env, javaThread, pAudioPacketQueue, &packet, 1) < 0) {
    LOGE("audio - after get packet failed");
    return;
}
LOGD("Dequeued audio packet");

// calculate frame size
int frameSize;
if (pPcmAudioCodecCtx->frame_size) {
    frameSize = pPcmAudioCodecCtx->frame_size;
} else {
    /* if frame_size is not set, the number of samples must be
     * calculated from the buffer size */
    int64_t nb_samples = (int64_t)AUDIO_PCM_OUTBUFF_SIZE * 8 /
            (av_get_bits_per_sample(pPcmAudioCodecCtx->codec_id) *
                    pPcmAudioCodecCtx->channels);
    frameSize = nb_samples;
}

int pcmBytesPerSample = av_get_bytes_per_sample(pPcmAudioCodecCtx->sample_fmt);
int pcmFrameBytes = frameSize * pcmBytesPerSample * pPcmAudioCodecCtx->channels;

uint8_t *pDataStart = packet.data;
while(packet.size > 0) {
    int len = avcodec_decode_audio4(pAudioCodecCtx, pAudioFrame, &frameFinished, &packet);
    LOGD("Decoded ADPCM frame");

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

    if (frameFinished) {
        // store frame data in FIFO buffer
        uint8_t *inputBuffer = pAudioFrame->data[0];
        int inputBufferSize = pAudioFrame->linesize[0];
        av_fifo_generic_write(fifoBuffer, inputBuffer, inputBufferSize, NULL);
        LOGD("Added ADPCM frame to FIFO buffer");

        // check if fifo buffer has enough data for a PCM frame
        while (av_fifo_size(fifoBuffer) >= pcmFrameBytes) {
            LOGI("PCM frame data in FIFO buffer");

            // read frame's worth of data from FIFO buffer
            av_fifo_generic_read(fifoBuffer, pAudioPcmOutBuffer, pcmFrameBytes, NULL);
            LOGD("Read data from FIFO buffer into pcm frame");


            avcodec_get_frame_defaults(pPcmAudioFrame);
            LOGD("Got frame defaults");

            pPcmAudioFrame->nb_samples = pcmFrameBytes / (pPcmAudioCodecCtx->channels *
                    pcmBytesPerSample);

            avcodec_fill_audio_frame(pPcmAudioFrame, pPcmAudioCodecCtx->channels,
                    pPcmAudioCodecCtx->sample_fmt,
                    pAudioPcmOutBuffer, pcmFrameBytes, 1);
            LOGD("Filled frame audio with data");

            // fill audio play buffer
            int dataSize = pPcmAudioFrame->linesize[0];
            LOGD("Data to output: %d", dataSize);
            jbyteArray audioPlayBuffer = (jbyteArray) env->GetObjectField(ffmpegCtx, env->GetFieldID(cls, "audioPlayBuffer", "[B"));
            jbyte *bytes = env->GetByteArrayElements(audioPlayBuffer, NULL);
            memcpy(bytes, pPcmAudioFrame->data[0], dataSize);
            env->ReleaseByteArrayElements(audioPlayBuffer, bytes, 0);
            LOGD("Copied data into Java array");

            env->CallVoidMethod(player, env->GetMethodID(playerCls, "updateAudio", "(I)V"), dataSize);
        }

if(数据包队列获取(env、javaThread、pAudioPacketQueue和数据包,1)<0){
LOGE(“音频-获取数据包失败后”);
返回;
}
LOGD(“排队音频包”);
//计算帧大小
整数帧大小;
if(PPCMAudioDecctX->帧大小){
frameSize=ppcAudioDecctX->帧大小;
}否则{
/*如果未设置帧大小,则采样数必须为
*根据缓冲区大小计算*/
int64_t nb_samples=(int64_t)音频\u PCM\u突发\u大小*8/
(av_获取每个样本的位(PPCMAudioDecctX->编解码器id)*
PPCMAudiocodecTx->频道);
frameSize=nb_样本;
}
int pcmBytesPerSample=av_get_bytes_per_sample(ppcmaudiodeccctx->sample_fmt);
int pcmFrameBytes=frameSize*pcmBytesPerSample*pPcmAudioCodecCtx->channels;
uint8_t*pDataStart=packet.data;
while(packet.size>0){
int len=avcodec\u decode\u audio4(pAudioCodecCtx、pAudioFrame、frameFinished和packet);
LOGD(“解码的ADPCM帧”);
if(len<0){
LOGE(“解码音频时出错”);
返回;
}
如果(框架完成){
//将帧数据存储在FIFO缓冲区中
uint8_t*inputBuffer=pAudioFrame->data[0];
int inputBufferSize=pAudioFrame->linesize[0];
av_fifo_generic_write(fifoBuffer、inputBuffer、inputBufferSize、NULL);
LOGD(“将ADPCM帧添加到FIFO缓冲区”);
//检查fifo缓冲区是否有足够的数据用于PCM帧
而(av_fifo_大小(fifoBuffer)>=pcmFrameBytes){
LOGI(“FIFO缓冲区中的PCM帧数据”);
//从FIFO缓冲区读取帧值的数据
av_fifo_generic_read(fifoBuffer、pAudioPcmOutBuffer、pcmFrameBytes、NULL);
LOGD(“将数据从FIFO缓冲区读入pcm帧”);
avcodec_get_frame_默认值(pPcmAudioFrame);
LOGD(“获得帧默认值”);
ppcAudioFrame->nb_samples=pcmFrameBytes/(ppcAudioDecctX->通道*
pcmBytesPerSample);
avcodec_fill_audio_frame(pPcmAudioFrame,PPCMaudioDecctX->频道,
PPC音频检测器->样本,
pAudioPcmOutBuffer,pcmFrameBytes,1);
LOGD(“数据填充帧音频”);
//填充音频播放缓冲区
int dataSize=pPcmAudioFrame->linesize[0];
LOGD(“输出数据:%d”,数据大小);
jbyteArray audioPlayBuffer=(jbyteArray)env->GetObjectField(ffmpegCtx,env->GetFieldID(cls,“audioPlayBuffer”,“[B”);
jbyte*bytes=env->GetByteArrayElements(audioPlayBuffer,NULL);
memcpy(字节,pPcmAudioFrame->data[0],数据大小);
env->ReleaseByteArrayElements(音频播放缓冲区,字节,0);
LOGD(“将数据复制到Java数组”);
env->CallVoidMethod(player,env->GetMethodID(playerCls,“updateAudio”,“I)V”),数据大小;
}

您可以在


参见
audio\u encode\u示例
函数。

结果是
audio\u decode\u
函数返回16位PCM格式,我只是不知道如何正确访问它

以下是基于
avcodec\u decode\u audio4
播放音频的包循环中经过修改的代码

int len = avcodec_decode_audio4(pAudioCodecCtx, pAudioFrame, &frameFinished, &packet);

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

if (frameFinished) {
    int planeSize;
    uint8_t *pcmBuffer = pAudioFrame->extended_data[0];
    int dataSize = av_samples_get_buffer_size(&planeSize, pAudioCodecCtx->channels,
                                                       pAudioFrame->nb_samples,
                                                       pAudioCodecCtx->sample_fmt, 1);
    // fill audio play buffer
    jbyteArray audioPlayBuffer = (jbyteArray) env->GetObjectField(ffmpegCtx, env->GetFieldID(cls, "audioPlayBuffer", "[B"));
    jbyte *bytes = env->GetByteArrayElements(audioPlayBuffer, NULL);
    memcpy(bytes, pcmBuffer, dataSize);
    env->ReleaseByteArrayElements(audioPlayBuffer, bytes, 0);
    env->CallVoidMethod(player, env->GetMethodID(playerCls, "updateAudio", "(I)V"), dataSize);
}
int len=avcodec\u decode\u audio4(pAudioCodecCtx、pAudioFrame、frameFinished和packet);
if(len<0){
LOGE(“解码音频时出错”);
返回;
}
如果(框架完成){
平面尺寸;
uint8_t*pcmBuffer=pAudioFrame->extended_data[0];
int dataSize=av_samples_get_buffer_size(&planeSize,pAudioCodecCtx->channels,
pAudioFrame->nb_样品,
pAudioCodecCtx->sample_fmt,1);
//填充音频播放缓冲区
jbyteArray audioPlayBuffer=(jbyteArray)env->GetObjectField(ffmpegCtx,env->GetFieldID(cls,“audioPlayBuffer”,“[B”);
jbyte*bytes=env->GetByteArrayElements(audioPlayBuffer,NULL);
memcpy(字节、pcmBuffer、数据大小);
env->ReleaseByteArrayElements(音频播放缓冲区,字节,0);
env->CallVoidMethod(player,env->GetMethodID(playerCls,“updateAudio”,“I)V”),数据大小;
}

该示例仅显示如何将随机音频编码到数据包中并输出回文件。我遇到的问题是我可以成功解码ADPCM,但我不知道如何将其重新编码到PCM帧以写入Android AudioTrack。您有更具体的示例吗?