当前位置: 首页 > news >正文

ffmpeg解复用aac

[[AAC ADTS格式分析]]
目标:从 MP4 格式的视频格式中抽取 aac 音频单独保存。

采样率

null
根据采样率和对应编号整理为一个数组:

int samplingFrequency[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,
};

组织 ADTS 头

null
null

void encode_adts_header(char* buf, const int data_length, int profile, int samplerate, int channels) {int sampling_frequency_index = 3;  // 默认48000频率int adtsLen = data_length + 7; // 包长+头长=总长int frequencies_size = sizeof(samplingFrequency) / sizeof(samplingFrequency[0]);int i = 0;// 匹配采样评率for (i = 0; i < frequencies_size; i++) {if (samplingFrequency[i] == samplerate) {sampling_frequency_index = i;break;}}if (i >= frequencies_size) {printf("unsupport samplerate: %d\n", samplerate);return -1;}buf[0] = 0xFF; // syncword 高8位buf[1] = 0xF0; // syncword 第8位buf[1] |= (0 << 3); // ID 0表示MPEG-4 buf[1] |= (0 << 2); // layer 00buf[1] |= (0 << 1); buf[1] |= 1; // protection_absent 1 表示没有校验buf[2] = (profile << 6); // profile 支持哪个级别的AACbuf[2] |= (sampling_frequency_index & 0x0F) << 2; // 采样频率buf[2] |= (0 << 1); // private 0buf[2] |= (channels & 0x04) >> 2; // channels 声道 高1位buf[3] = (channels & 0x03) << 6; // channels 声道 低2位buf[3] |= (0 << 5);buf[3] |= (0 << 4);buf[3] |= (0 << 3);buf[3] |= (0 << 2);buf[3] |= (adtsLen & 0x1800) >> 11; // 包长高2位buf[4] = (uint8_t)((adtsLen & 0x7F8) >> 3); // 包长3-10位buf[5] = (uint8_t)((adtsLen & 0x7) << 5); // 包长最后三位// 0x7FF 可变码流buf[5] |= 0x1F;buf[6] = 0xFC;return 0;
}

读取 packet

// 运行带两个参数 分别时候输入文件和输出文件
if (argc < 3) {return -1;}const char* in_filepath = argv[1];const char* out_filepath = argv[2];int errbuf[1024] = {0};FILE* acc_fp = NULL;int ret = -1;AVFormatContext* ifmt_ctx = NULL; // 解码器上下文AVPacket pkt;av_log_set_level(AV_LOG_DEBUG); // 设置日志级别acc_fp = fopen(out_filepath, "wb"); // 打开文件准备写入if (!acc_fp) {av_log(NULL, AV_LOG_ERROR, "Open out_file error\n");return ret;}ret = avformat_open_input(&ifmt_ctx, in_filepath, NULL, NULL); // 输入源if (ret < 0) {av_strerror(ret, errbuf, 1024);av_log(NULL, AV_LOG_ERROR, "Could not open source file: %s, %d(%s)", in_filepath, ret, errbuf);return ret;}ret = avformat_find_stream_info(ifmt_ctx, NULL);if (ret < 0) {av_strerror(ret, errbuf, 1024);av_log(NULL, AV_LOG_ERROR, "Find stream error: %d(%s)\n", ret, errbuf);return ret;}av_dump_format(ifmt_ctx, NULL, in_filepath, NULL); // dump文件到上下文// pkt = av_packet_alloc();av_init_packet(&pkt);// 找到音频流int audio_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);if(audio_index < 0){av_log(NULL, AV_LOG_DEBUG, "Could not find %s stream in input file %s\n",av_get_media_type_string(AVMEDIA_TYPE_AUDIO),in_filepath);return AVERROR(EINVAL);}// 判断音频流是不是aacif (ifmt_ctx->streams[audio_index]->codecpar->codec_id != AV_CODEC_ID_AAC) {printf("The media file no contain AAC stream, it's codec_id is %d\n", ifmt_ctx->streams[audio_index]->codecpar->codec_id);goto failed;}

写入文件

while (av_read_frame(ifmt_ctx, &pkt) >= 0) {/* code */if (pkt.stream_index == audio_index) {char adts_header_buf[7] = {0};// adts_headerencode_adts_header(adts_header_buf, pkt.size,ifmt_ctx->streams[audio_index]->codecpar->profile,ifmt_ctx->streams[audio_index]->codecpar->sample_rate,ifmt_ctx->streams[audio_index]->codecpar->channels);fwrite(adts_header_buf, 1, 7, acc_fp);int len = fwrite(pkt.data, 1, pkt.size, acc_fp);if (len != pkt.size) {av_log(NULL, AV_LOG_DEBUG, "warning, length of writed data isn't equal\n");}}av_packet_unref(&pkt);}

完整代码

#include <stdio.h>
#include <libavformat/avformat.h>int samplingFrequency[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,
};void encode_adts_header(char* buf, const int data_length, int profile, int samplerate, int channels) {int sampling_frequency_index = 3;int adtsLen = data_length + 7;int frequencies_size = sizeof(samplingFrequency) / sizeof(samplingFrequency[0]);int i = 0;for (i = 0; i < frequencies_size; i++) {if (samplingFrequency[i] == samplerate) {sampling_frequency_index = i;break;}}if (i >= frequencies_size) {printf("unsupport samplerate: %d\n", samplerate);return -1;}buf[0] = 0xFF;buf[1] = 0xF0;buf[1] |= (0 << 3);buf[1] |= (0 << 2);buf[1] |= (0 << 1);buf[1] |= 1;buf[2] = (profile << 6);buf[2] |= (sampling_frequency_index & 0x0F) << 2;buf[2] |= (0 << 1);buf[2] |= (channels & 0x04) >> 2;buf[3] = (channels & 0x03) << 6;buf[3] |= (0 << 5);buf[3] |= (0 << 4);buf[3] |= (0 << 3);buf[3] |= (0 << 2);buf[3] |= (adtsLen & 0x1800) >> 11;buf[4] = (uint8_t)((adtsLen & 0x7F8) >> 3);buf[5] = (uint8_t)((adtsLen & 0x7) << 5);buf[5] |= 0x1F;buf[6] = 0xFC;return 0;
}int main(int argc, char* argv[]) {if (argc < 3) {return -1;}const char* in_filepath = argv[1];const char* out_filepath = argv[2];int errbuf[1024] = {0};FILE* acc_fp = NULL;int ret = -1;AVFormatContext* ifmt_ctx = NULL;AVPacket pkt;av_log_set_level(AV_LOG_DEBUG);acc_fp = fopen(out_filepath, "wb");if (!acc_fp) {av_log(NULL, AV_LOG_ERROR, "Open out_file error\n");return ret;}ret = avformat_open_input(&ifmt_ctx, in_filepath, NULL, NULL);if (ret < 0) {av_strerror(ret, errbuf, 1024);av_log(NULL, AV_LOG_ERROR, "Could not open source file: %s, %d(%s)", in_filepath, ret, errbuf);return ret;}ret = avformat_find_stream_info(ifmt_ctx, NULL);if (ret < 0) {av_strerror(ret, errbuf, 1024);av_log(NULL, AV_LOG_ERROR, "Find stream error: %d(%s)\n", ret, errbuf);return ret;}av_dump_format(ifmt_ctx, NULL, in_filepath, NULL);// pkt = av_packet_alloc();av_init_packet(&pkt);int audio_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);if(audio_index < 0){av_log(NULL, AV_LOG_DEBUG, "Could not find %s stream in input file %s\n",av_get_media_type_string(AVMEDIA_TYPE_AUDIO),in_filepath);return AVERROR(EINVAL);}if (ifmt_ctx->streams[audio_index]->codecpar->codec_id != AV_CODEC_ID_AAC) {printf("The media file no contain AAC stream, it's codec_id is %d\n", ifmt_ctx->streams[audio_index]->codecpar->codec_id);goto failed;}while (av_read_frame(ifmt_ctx, &pkt) >= 0) {/* code */if (pkt.stream_index == audio_index) {char adts_header_buf[7] = {0};// adts_headerencode_adts_header(adts_header_buf, pkt.size,ifmt_ctx->streams[audio_index]->codecpar->profile,ifmt_ctx->streams[audio_index]->codecpar->sample_rate,ifmt_ctx->streams[audio_index]->codecpar->channels);fwrite(adts_header_buf, 1, 7, acc_fp);int len = fwrite(pkt.data, 1, pkt.size, acc_fp);if (len != pkt.size) {av_log(NULL, AV_LOG_DEBUG, "warning, length of writed data isn't equal\n");}}av_packet_unref(&pkt);}failed:if (ifmt_ctx) {avformat_close_input(&ifmt_ctx);}if (acc_fp) {fclose(acc_fp);}
}

参考资料:https://github.com/0voice


文章转载自:

http://6D0bfuh9.tqxtx.cn
http://hbGzqcdC.tqxtx.cn
http://cS1zDn04.tqxtx.cn
http://7bJvWNxd.tqxtx.cn
http://3iVLSgK4.tqxtx.cn
http://94v6zmWO.tqxtx.cn
http://YGoLcBwb.tqxtx.cn
http://e2U0BqxQ.tqxtx.cn
http://CXQlRH67.tqxtx.cn
http://olufMSSs.tqxtx.cn
http://rFIJ0IXW.tqxtx.cn
http://XRPqKC2t.tqxtx.cn
http://LU3VCjhf.tqxtx.cn
http://i97DndKp.tqxtx.cn
http://uefqUd7y.tqxtx.cn
http://0NUImilr.tqxtx.cn
http://JNEFFBvF.tqxtx.cn
http://OkbnJFsM.tqxtx.cn
http://FrmP8EXz.tqxtx.cn
http://C8Z4xBlD.tqxtx.cn
http://zyxUv6LK.tqxtx.cn
http://HvDV3YrD.tqxtx.cn
http://dXoZ5VAF.tqxtx.cn
http://4BJtlZza.tqxtx.cn
http://RZalkhPw.tqxtx.cn
http://edL06lKE.tqxtx.cn
http://7k3aQcqW.tqxtx.cn
http://fyst4aJp.tqxtx.cn
http://G2qGnxJB.tqxtx.cn
http://dtqTFIvh.tqxtx.cn
http://www.dtcms.com/a/388056.html

相关文章:

  • 数据结构--3:LinkedList与链表
  • linx 系统 ffmpeg 推流 rtsp
  • 防水淹厂房监测报警系统的设计原则及主要构成
  • RFID技术赋能工业教学设备教学应用经典!
  • Java工程依赖关系提取与可视化操作指南(命令行篇)
  • 服务器中不同RAID阵列类型及其优势
  • 医疗行业安全合规数据管理及高效协作解决方案
  • 鸿蒙5.0应用开发——V2装饰器@Event的使用
  • logstash同步mysql流水表到es
  • Ground Control-卫星通信 (SATCOM) 和基于蜂窝的无人机和机器人物联网解决方案
  • 计算机视觉技术深度解析:从图像处理到深度学习的完整实战指南
  • 互联网大厂Java面试:从Spring Boot到微服务的实战考验
  • k8s NodePort 30000 - 32767 被用完后该如何处理
  • 高级系统架构师笔记——软件工程基础知识(2)RAD/敏捷模型/CMM/CBSE
  • 【C++】C++类和对象—(中)
  • React 记忆缓存使用
  • 图观 流渲染场景服务编辑器
  • WALL-OSS——点燃QwenVL 2.5在具身空间中的潜力:VL FFN可预测子任务及离散动作token,Action FNN则预测连续动作
  • 设备中断绑定于香港服务器高性能容器的优化方法
  • 物理服务器具体是指哪些
  • Hive内部表外部表分区分桶数据类型
  • THREE练习写了几个简单小游戏的总结
  • Flume与Sqoop核心知识点总结:Hadoop生态的数据传输双引擎
  • 微服务spring cloud alibabab 启动报错: No spring.config.import set
  • 开心实习之第n天
  • 【系列文章】Linux系统中断的应用04-共享工作队列实验
  • Java的jdk21与 Go语言对比
  • 告别 MaaS 模型选型困难:AI Ping 为大模型服务选型提供精准性能评测排行榜
  • 41.OpenCV入门:计算机视觉的瑞士军刀
  • 初识golang