FFmpeg4.3 抽取音频数据

环境

FFmpeg4.3 + vs2019

FFmpeg 相关api

avformat_open_input();	// 打开输入文件或者流
avformat_find_stream_info();	// 获取音视频流信息
av_find_best_stream();	// 获取指定流
av_read_frame();	// 读取数据包
av_packet_unref();	// 释放数据资源
avformat_close_input();	//关闭打开的文件或流,释放资源

实例

#include <iostream>
#include <string>
using namespace std;

#ifdef __cplusplus
extern "C"
{
	#include <libavutil/log.h>
	#include <libavformat/avformat.h>
}
#endif

#define ADTS_HEADER_LEN  7;

void adts_header(char* szAdtsHeader, int dataLen) {
	// aac级别,0: AAC Main 1:AAC LC (Low Complexity) 2:AAC SSR (Scalable Sample Rate) 3:AAC LTP (Long Term Prediction)
	int audio_object_type = 2;
	// 采样率下标,下标7表示采样率为22050 
	int sampling_frequency_index = 7;
	// 声道数
	int channel_config = 2;

	// ADTS帧长度,包括ADTS长度和AAC声音数据长度的和。
	int adtsLen = dataLen + 7;

	// syncword,标识一个帧的开始,固定为0xFFF,占12bit(byte0占8位,byte1占前4位)
	szAdtsHeader[0] = 0xff;         //syncword:0xfff                          高8bits
	szAdtsHeader[1] = 0xf0;         //syncword:0xfff                          低4bits

	// ID,MPEG 标示符。0表示MPEG-4,1表示MPEG-2。占1bit(byte1第5位)
	szAdtsHeader[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit

	// layer,固定为0,占2bit(byte1第6、7位)
	szAdtsHeader[1] |= (0 << 1);    //Layer:0                                 2bits 

	// protection_absent,标识是否进行误码校验。0表示有CRC校验,1表示没有CRC校验。占1bit(byte1第8位)
	szAdtsHeader[1] |= 1;           //protection absent:1                     1bit

	// profile,标识使用哪个级别的AAC。1: AAC Main 2:AAC LC 3:AAC SSR 4:AAC LTP。占2bit(byte2第1、2位)
	szAdtsHeader[2] = (audio_object_type - 1) << 6;            //profile:audio_object_type - 1                      2bits

	// sampling_frequency_index,采样率的下标。占4bit(byte2第3、4、5、6位)
	szAdtsHeader[2] |= (sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index  4bits 

	// private_bit,私有位,编码时设置为0,解码时忽略。占1bit(byte2第7位)
	szAdtsHeader[2] |= (0 << 1);                             //private bit:0                                      1bit

	// channel_configuration,声道数。占3bit(byte2第8位和byte3第1、2位)
	szAdtsHeader[2] |= (channel_config & 0x04) >> 2;           //channel configuration:channel_config               高1bit
	szAdtsHeader[3] = (channel_config & 0x03) << 6;     //channel configuration:channel_config      低2bits

	// original_copy,编码时设置为0,解码时忽略。占1bit(byte3第3位)
	szAdtsHeader[3] |= (0 << 5);                      //original:0                               1bit

	// home,编码时设置为0,解码时忽略。占1bit(byte3第4位)
	szAdtsHeader[3] |= (0 << 4);                      //home:0                                   1bit

	// copyrighted_id_bit,编码时设置为0,解码时忽略。占1bit(byte3第5位)
	szAdtsHeader[3] |= (0 << 3);                      //copyright id bit:0                       1bit  

	// copyrighted_id_start,编码时设置为0,解码时忽略。占1bit(byte3第6位)
	szAdtsHeader[3] |= (0 << 2);                      //copyright id start:0                     1bit

	// aac_frame_length,ADTS帧长度,包括ADTS长度和AAC声音数据长度的和。占13bit(byte3第7、8位,byte4全部,byte5第1-3位)
	szAdtsHeader[3] |= ((adtsLen & 0x1800) >> 11);           //frame length:value   高2bits
	szAdtsHeader[4] = (uint8_t)((adtsLen & 0x7f8) >> 3);     //frame length:value    中间8bits
	szAdtsHeader[5] = (uint8_t)((adtsLen & 0x7) << 5);       //frame length:value    低3bits

	// adts_buffer_fullness,固定为0x7FF。表示是码率可变的码流 。占11bit(byte5后5位,byte6前6位)   
	szAdtsHeader[5] |= 0x1f;                                 //buffer fullness:0x7ff 高5bits
	szAdtsHeader[6] = 0xfc;
}

void extractAudio()
{
	av_log_set_level(AV_LOG_INFO);

	string src = "./01.mp4";
	string dst = "test.aac";
	char errors[1024];
	int audio_index;
	FILE* dst_fd = nullptr;
	errno_t err;
	AVFormatContext* fmt_ctx = nullptr;
	AVPacket pkt;

	// 打开输入文件,分配上下文中的资源
	int ret = avformat_open_input(&fmt_ctx, src.c_str(), nullptr, nullptr);
	if (ret < 0) {
		av_log(nullptr, AV_LOG_ERROR, "Open failed!\n");
		return;
	}

	// 获取音视频流信息
	if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
		av_strerror(ret, errors, 1024);
		av_log(NULL, AV_LOG_DEBUG, "failed to find stream information: %s, %d(%s)\n",
			src.c_str(),
			ret,
			errors);
		return;
	}

	// 打印输入文件信息
	av_dump_format(fmt_ctx, 0, src.c_str(), 0);

	err = fopen_s(&dst_fd,dst.c_str(), "wb");
	if (err != 0) {
		av_log(nullptr, AV_LOG_ERROR, "fopen failed!\n");
		avformat_close_input(&fmt_ctx);
		return;
	}

	// 获取到音频流
	audio_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
	if (ret < 0) {
		av_log(nullptr, AV_LOG_ERROR, "Can not find best stream!\n");
		fclose(dst_fd);
		return;
	}

	av_init_packet(&pkt);
	while (av_read_frame(fmt_ctx, &pkt) >= 0) {
		// 寻找音频数据包
		if (pkt.stream_index == audio_index && dst_fd != 0) {
			// 先写音频头部信息
			char adts_header_buf[7];
			adts_header(adts_header_buf, pkt.size);
			size_t len = fwrite(adts_header_buf, 1, 7, dst_fd);
			if (len != 7) {
				av_log(nullptr, AV_LOG_WARNING, "fwrite header failed!\n");
			}
			// 写音频数据信息
			len = fwrite(pkt.data, 1, pkt.size, dst_fd);
			if (len != pkt.size) {
				av_log(nullptr, AV_LOG_WARNING, "fwrite data failed!\n");
			}
		}

		// 对于每次使用后的pkt需要释放,防止内存泄露
		av_packet_unref(&pkt);
	}

	// 关闭打开的文件,释放资源
	avformat_close_input(&fmt_ctx);
	if (dst_fd) {
		fclose(dst_fd);
	}	
}


int main()
{
	extractAudio();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值