- 注册所有组件 av_register_all()
- 创建封装格式上下文 avformat_alloc_context() 返回一个AVFormatContext
- 初始化输入输出上下文(打开输出文件) avio_open(),可以输出到本地或者网络地址等等
- 创建媒体流 avformat_new_stream()
- 初始化编码器上下文以及设置参数 AVCodecContext
- 查找编码器 avcodec_find_encoder_by_name()
- 打开编码器 avcodec_open2()
- 写入头文件 avformat_write_header();
- 打开本地需要转换的文件 fopen(inFile, “rb”)
- 初始化 AVframe,AVPacket
- 开始转换 avcodec_send_frame() avcodec_receive_packet()
- 开始写入本地 av_write_frame()
- 写入文件尾 av_write_trailer()
AVCodec *avAudioCodec; //编码器对象 AVCodecContext *avAudioContext; //编码器上下文 AVframe *audioframe; //储存原始PCM数据AVframe AVPacket *audioPacket; //储存编码后AAC数据AVPacket AVStream *audioStream; //流通道对象 int audioPts = 0; //pts AVFormatContext *formatContext; //封装格式上下文对象 int audioBufferSize; //缓冲区大小 uint8_t *outBuffer; //缓冲区buffer FILE *in_file; //本地音频文件初始化
int AudioVideoEncode::audioEncoderInit(JNIEnv *env) { //输出文件(AAC)路径 const char *outFile = "/sdcard/aaa/gjk.aac"; //原始文件(PCM)路径 const char *inFile = "/sdcard/aaa/PCM/pcm.pcm"; //注册组件 av_register_all(); //初始化封装格式上下文 formatContext = avformat_alloc_context(); //指定封装类型 formatContext->oformat = av_guess_format(NULL, outFile, NULL);//得到输出格式 //打开输出文件 if (avio_open(&formatContext->pb, outFile, AVIO_FLAG_READ_WRITE) < 0) return -1; //创建媒体流 audioStream = avformat_new_stream(formatContext, 0); if (audioStream == NULL) return -1; //获取编码器上下文 avAudioContext = audioStream->codec; //设置编码器上下文参数 avAudioContext->codec_id = formatContext->oformat->audio_codec;//设置id avAudioContext->codec_type = AVMEDIA_TYPE_AUDIO;//设置类型为音频 avAudioContext->sample_fmt = AV_SAMPLE_FMT_S16;//设置格式为16bit avAudioContext->sample_rate = 8000;//设置采样率 avAudioContext->channel_layout = AV_CH_LAYOUT_MONO;//设置通道类型和下面通道数量对应 avAudioContext->channels = 1;//单通道 avAudioContext->bit_rate = 128000;//码率 //查找编码器 avAudioCodec = avcodec_find_encoder_by_name("libfdk_aac"); if (avAudioCodec == NULL) return -1; //打开编码器 int ret = avcodec_open2(avAudioContext, avAudioCodec, NULL); if (ret < 0) return -1; //写入头文件 avformat_write_header(formatContext, NULL); //初始化编码前(原始数据)数据储存结构体,也就是创建数据缓冲区 audioframe = av_frame_alloc(); //设置参数 audioframe->nb_samples = avAudioContext->frame_size; audioframe->format = avAudioContext->sample_fmt; //打开音频输入文件 in_file = fopen(inFile, "rb"); if (in_file == NULL) return -1; //获取缓冲区大小 audioBufferSize = av_samples_get_buffer_size(NULL, avAudioContext->channels, avAudioContext->frame_size, avAudioContext->sample_fmt, 1); //创建缓冲区 outBuffer = (uint8_t *) av_malloc(audioBufferSize); avcodec_fill_audio_frame(audioframe, avAudioContext->channels, avAudioContext->sample_fmt, (const uint8_t *) outBuffer, audioBufferSize, 1); //初始化编码后数据储存结构体 audioPacket = (AVPacket *) av_malloc(audioBufferSize); audioPts = 0;//pts return 0; }开始编码
void AudioVideoEncode::audioEncoder(JNIEnv *env, jobject obj, jbyte *byte, int byteLength) { int ret; memcpy(audioframe->data[0], buf, byteLength); audioframe->pts = audioPts; audioPts++; ret = avcodec_send_frame(avAudioContext, audioframe); if (ret < 0) return; ret = avcodec_receive_packet(avAudioContext, audioPacket); if (ret < 0) return; audioPacket->stream_index = audioStream->index; ret = av_write_frame(formatContext, audioPacket); if (ret < 0) return; LOGE("音频编码写入成功"); av_packet_unref(audioPacket); }写入文件尾
//这里是把麦克风实时采集到文件写入本地,所以在实时采集数据结束以后调用这个方法, //要不然写入本地文件大小是0kb,有一些文件不用这个这一块不太了解 av_write_trailer(formatContext);
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)