Android 使用ffmpeg api转换音频文件。avcodec_encode_AUDIO 2崩溃
从这些例子中,我得到了这段代码的基本思想。 但是我不确定我遗漏了什么,比如muxing.c demuxing.c和decoding_encoding.c 它们都使用不同的方法 将音频文件转换为其他文件的过程大致如下: 输入文件-解复用->音频流-读取->输入包-解码2帧-> 框架 -encode2packets->outPackets-write->audiostream-mux->outputfile 然而,我在Dembing.c中发现了以下评论: /*写入第一个平面的原始音频数据样本。这很有效Android 使用ffmpeg api转换音频文件。avcodec_encode_AUDIO 2崩溃,android,audio,android-ndk,ffmpeg,Android,Audio,Android Ndk,Ffmpeg,从这些例子中,我得到了这段代码的基本思想。 但是我不确定我遗漏了什么,比如muxing.c demuxing.c和decoding_encoding.c 它们都使用不同的方法 将音频文件转换为其他文件的过程大致如下: 输入文件-解复用->音频流-读取->输入包-解码2帧-> 框架 -encode2packets->outPackets-write->audiostream-mux->outputfile 然而,我在Dembing.c中发现了以下评论: /*写入第一个平面的原始音频数据样本。这很有
*适用于压缩格式(例如AV_样本_FMT_S16)。然而,
*大多数音频解码器输出平面音频,使用单独的
*每个频道的音频样本平面(例如AV_SAMPLE_FMT_S16P)。
*换句话说,此代码将只写入第一个音频通道
*在这些情况下。
*您应该使用libswresample或libavfilter来转换帧
*压缩数据*/ 我的问题是:
int Java_com_fscz_ffmpeg_Audio_convert(JNIEnv * env, jobject this, jstring jformat, jstring jcodec, jstring jsource, jstring jdest) {
jboolean isCopy;
jclass configClass = (*env)->FindClass(env, "com.fscz.ffmpeg.Config");
jfieldID fid = (*env)->GetStaticFieldID(env, configClass, "ffmpeg_logging", "I");
logging = (*env)->GetStaticIntField(env, configClass, fid);
/// open input
const char* sourceFile = (*env)->GetStringUTFChars(env, jsource, &isCopy);
AVFormatContext* pInputCtx;
AVStream* pInputStream;
open_input(sourceFile, &pInputCtx, &pInputStream);
// open output
const char* destFile = (*env)->GetStringUTFChars(env, jdest, &isCopy);
const char* cformat = (*env)->GetStringUTFChars(env, jformat, &isCopy);
const char* ccodec = (*env)->GetStringUTFChars(env, jcodec, &isCopy);
AVFormatContext* pOutputCtx;
AVOutputFormat* pOutputFmt;
AVStream* pOutputStream;
open_output(cformat, ccodec, destFile, &pOutputCtx, &pOutputFmt, &pOutputStream);
/// decode/encode
error = avformat_write_header(pOutputCtx, NULL);
DIE_IF_LESS_ZERO(error, "error writing output stream header to file: %s, error: %s", destFile, e2s(error));
AVFrame* frame = avcodec_alloc_frame();
DIE_IF_UNDEFINED(frame, "Could not allocate audio frame");
frame->pts = 0;
LOGI("allocate packet");
AVPacket pktIn;
AVPacket pktOut;
LOGI("done");
int got_frame, got_packet, len, frame_count = 0;
int64_t processed_time = 0, duration = pInputStream->duration;
while (av_read_frame(pInputCtx, &pktIn) >= 0) {
do {
len = avcodec_decode_audio4(pInputStream->codec, frame, &got_frame, &pktIn);
DIE_IF_LESS_ZERO(len, "Error decoding frame: %s", e2s(len));
if (len < 0) break;
len = FFMIN(len, pktIn.size);
size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format);
LOGI("audio_frame n:%d nb_samples:%d pts:%s\n", frame_count++, frame->nb_samples, av_ts2timestr(frame->pts, &(pInputStream->codec->time_base)));
if (got_frame) {
do {
av_init_packet(&pktOut);
pktOut.data = NULL;
pktOut.size = 0;
LOGI("encode frame");
DIE_IF_UNDEFINED(pOutputStream->codec, "no output codec");
DIE_IF_UNDEFINED(frame->nb_samples, "no nb samples");
DIE_IF_UNDEFINED(pOutputStream->codec->internal, "no internal");
LOGI("tests done");
len = avcodec_encode_audio2(pOutputStream->codec, &pktOut, frame, &got_packet);
LOGI("encode done");
DIE_IF_LESS_ZERO(len, "Error (re)encoding frame: %s", e2s(len));
} while (!got_packet);
// write packet;
LOGI("write packet");
/* Write the compressed frame to the media file. */
error = av_interleaved_write_frame(pOutputCtx, &pktOut);
DIE_IF_LESS_ZERO(error, "Error while writing audio frame: %s", e2s(error));
av_free_packet(&pktOut);
}
pktIn.data += len;
pktIn.size -= len;
} while (pktIn.size > 0);
av_free_packet(&pktIn);
}
LOGI("write trailer");
av_write_trailer(pOutputCtx);
LOGI("end");
/// close resources
avcodec_free_frame(&frame);
avcodec_close(pInputStream->codec);
av_free(pInputStream->codec);
avcodec_close(pOutputStream->codec);
av_free(pOutputStream->codec);
avformat_close_input(&pInputCtx);
avformat_free_context(pOutputCtx);
return 0;
}
int Java_com_fscz_ffmpeg_Audio_convert(JNIEnv*env,jobject this,jstring jformat,jstring jcodec,jstring jsource,jstring jdest){
jboolean-isCopy;
jclass configClass=(*env)->FindClass(env,“com.fscz.ffmpeg.Config”);
jfieldID fid=(*env)->GetStaticFieldID(env,configClass,“ffmpeg_日志记录”,“I”);
日志=(*env)->GetStaticIntField(env、configClass、fid);
///开放输入
const char*sourceFile=(*env)->GetStringUTFChars(env、jsource和isCopy);
AVFormatContext*pInputCtx;
AVStream*pInputStream;
打开\u输入(源文件,&pInputCtx,&pInputStream);
//开放输出
const char*destFile=(*env)->GetStringUTFChars(env、jdest和isCopy);
const char*cformat=(*env)->GetStringUTFChars(env、jformat和isCopy);
const char*ccodec=(*env)->GetStringUTFChars(env、jcodec和isCopy);
AVFormatContext*pOutputCtx;
AVOutputFormat*pOutputFmt;
AVStream*pOutputStream;
打开输出(cformat、ccodec、destFile和pOutputCtx、pOutputFmt和pOutputStream);
///解码/编码
错误=avformat\u write\u头(pOutputCtx,NULL);
DIE_IF_LESS_ZERO(错误,“将输出流头写入文件%s时出错,错误:%s”,destFile,e2s(错误));
AVFrame*frame=avcodec_alloc_frame();
如果未定义(帧,“无法分配音频帧”);
帧->pts=0;
LOGI(“分配数据包”);
avpktin;
avp-pktOut;
物流(“完成”);
int got_frame,got_packet,len,frame_count=0;
int64\u t processed\u time=0,duration=pInputStream->duration;
而(av读取帧(pInputCtx和pktIn)>=0){
做{
len=avcodec\u decode\u audio4(pInputStream->codec,frame,&got\u frame,&pktIn);
如果小于零(len,“错误解码帧:%s”,e2s(len));
如果(len<0)中断;
len=FFMIN(len,pktIn.size);
size\u t unpudded\u linesize=frame->nb\u samples*av\u get\u bytes\u per\u sample(frame->format);
LOGI(“音频帧n:%d个nb\u样本:%d个pts:%s\n”,帧计数++,帧->nb\u样本,av\u ts2timestr(帧->pts,&(pInputStream->编解码器->时基));
如果(得到了框架){
做{
av_初始_数据包(&pktOut);
pktOut.data=NULL;
pktOut.size=0;
LOGI(“编码帧”);
DIE_IF_未定义(PoutpStream->编解码器,“无输出编解码器”);
如果未定义模具(框架->nb样本,“无nb样本”);
如果未定义(pOutputStream->codec->internal,“无内部”);
LOGI(“测试完成”);
len=avcodec\u encode\u audio2(pOutputStream->codec和pktOut、frame和got\u数据包);
LOGI(“编码完成”);
如果小于零(len,“错误(重新)编码帧:%s”,e2s(len));
}而(!得到了_包);
//写包;
LOGI(“写入数据包”);
/*将压缩帧写入媒体文件*/
错误=av交叉写入帧(pOutputCtx和pktOut);
如果小于零(错误,“写入音频帧时出错:%s”,e2s(错误));
av_免费_包(&pktOut);
}
pktIn.data+=len;
pktIn.size-=len;
}而(pktIn.size>0);
av免费数据包(pktIn);
}
LOGI(“写预告片”);
av_写入_预告片(pOutputCtx);
物流(“结束”);
///密切资源
avcodec_free_帧(&frame);
avcodec_关闭(pInputStream->codec);
av_免费(pInputStream->codec);
avcodec_close(pOutputStream->codec);
av_免费(PoutpStream->codec);
avformat_close_输入(&pInputCtx);
avformat_free_context(pOutputCtx);
返回0;
}
与此同时,我发现了这一点,并编写了一个Android库项目来实现这一点
(用于音频文件)
有关详细信息,请参阅文件/jni/audiodecoder.c这是压缩v的过程吗