#include "libavutil/avutil.h"
#include "libavformat/avformat.h"
int main(int argc, char const *argv[])
{
av_log_set_level(AV_LOG_DEBUG);
if (argc < 3)
{
av_log(NULL, AV_LOG_ERROR, "Usage:%s infile outfile\n", argv[0]);
return -1;
}
const char *infileName = argv[1];
const char *outfileName = argv[2];
//提取acc数据流程
AVFormatContext *inFormatCtx = NULL;
//1.打开媒体文件
int ret = avformat_open_input(&inFormatCtx, infileName, NULL, NULL);
if (ret != 0)
{
av_log(NULL, AV_LOG_ERROR, "open input file format failed: %s\n", av_err2str(ret));
return -1;
}
//2.获取码流信息
ret = avformat_find_stream_info(inFormatCtx, NULL);
if (ret < 0)
{
av_log(NULL, AV_LOG_ERROR, "find stream info failed: %s\n", av_err2str(ret));
avformat_close_input(&inFormatCtx);
return -1;
}
//3.获取音频流
int audioIndex = av_find_best_stream(inFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if (audioIndex < 0)
{
av_log(NULL, AV_LOG_ERROR, "find best stream failed, index is: %d\n", audioIndex);
avformat_close_input(&inFormatCtx);
return -1;
}
av_log(NULL, AV_LOG_INFO, "the audio index is %d\n", audioIndex);
//4.初始化packett
AVPacket packet;
av_init_packet(&packet);
FILE *dest_fp = fopen(outfileName, "wb");
if (dest_fp == NULL)
{
av_log(NULL, AV_LOG_ERROR, "open %s file failed\n", outfileName);
avformat_close_input(&inFormatCtx);
return -1;
}
//5.读取packet数据
while (av_read_frame(inFormatCtx, &packet) == 0)
{
if (packet.stream_index == audioIndex)
{
ret = fwrite(packet.data, 1, packet.size, dest_fp);
if (ret != packet.size)
{
av_log(NULL, AV_LOG_ERROR, "write file failed\n");
fclose(dest_fp);
avformat_close_input(&inFormatCtx);
return -1;
}
}
//6.释放packet资源
av_packet_unref(&packet);
}
if (inFormatCtx)
{
//7.关闭媒体文件
avformat_close_input(&inFormatCtx);
}
if (dest_fp)
{
fclose(dest_fp);
}
return 0;
}
但是播放out.aac会失败,需要补充头信息:
关于ADIF vs ADTS:
ADIF: 音视频数据交换格式。解码必须在明确定义的开始处进行。常用在磁盘文件中。
ADTS: 音视频数据传输流。是一个有同步字的比特流,解码可以在这个流中任何位置开始。
#include "libavutil/avutil.h"
#include "libavformat/avformat.h"
const int sampleFrequencyTable[] = {
96000,
88200,
64000,
48000,
44100,
32000,
24000,
22050,
16000,
12000,
11025,
8000,
7350
};
//获取音频数据传输流的头
int getADTSHeader(char *adtsHeader, int packetSize, int profile, int sampleRate, int channels)
{
int sampleFrequencyIndex = 3; //48000
int adtsLength = packetSize + 7;
for (int i = 0; i < sizeof(sampleFrequencyTable) / sizeof(sampleFrequencyTable[0]); i++)
{
if (sampleRate == sampleFrequencyTable[i])
{
sampleFrequencyIndex = i;
break;
}
}
adtsHeader[0] = 0xff; //syncwork:0xfff
adtsHeader[1] = 0xf0; //syncwork:0xfff
adtsHeader[1] |= (0 << 3); //MPEG Version:0 for MPEG-4, 1 for MPEG-2
adtsHeader[1] |= (0 << 1); //Layer:0
adtsHeader[1] |= 1; //protection absent:1
adtsHeader[2] = (profile << 6); //profile:profile
adtsHeader[2] |= (sampleFrequencyIndex & 0x0f) << 2; //sampling frequency index: sampling_frequency_index
adtsHeader[2] |= (0 << 1); //private bit : 0
adtsHeader[2] |= (channels & 0x04) >> 2; //channel configuration: channels
adtsHeader[3] = (channels & 0x03) << 6; //channel configuration: channels
adtsHeader[3] |= (0 << 5);
adtsHeader[3] |= (0 << 4);
adtsHeader[3] |= (0 << 3);
adtsHeader[3] |= (0 << 2);
adtsHeader[3] |= ((adtsLength & 0x1800) >> 11);
adtsHeader[4] = (uint8_t)((adtsLength & 0x7f8) >> 3); //frame length: value
adtsHeader[5] = (uint8_t)((adtsLength & 0x7) >> 5); //frame length: value
adtsHeader[5] |= 0x1f; //buffer fullness: 0x7ff
adtsHeader[6] = 0xfc; //buffer fullness: 0x7ff
return 0;
}
int main(int argc, char const *argv[])
{
av_log_set_level(AV_LOG_DEBUG);
if (argc < 3)
{
av_log(NULL, AV_LOG_ERROR, "Usage:%s infile outfile\n", argv[0]);
return -1;
}
const char *infileName = argv[1];
const char *outfileName = argv[2];
//提取acc数据流程
AVFormatContext *inFormatCtx = NULL;
//1.打开媒体文件
int ret = avformat_open_input(&inFormatCtx, infileName, NULL, NULL);
if (ret != 0)
{
av_log(NULL, AV_LOG_ERROR, "open input file format failed: %s\n", av_err2str(ret));
return -1;
}
//2.获取码流信息
ret = avformat_find_stream_info(inFormatCtx, NULL);
if (ret < 0)
{
av_log(NULL, AV_LOG_ERROR, "find stream info failed: %s\n", av_err2str(ret));
avformat_close_input(&inFormatCtx);
return -1;
}
//3.获取音频流
int audioIndex = av_find_best_stream(inFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if (audioIndex < 0)
{
av_log(NULL, AV_LOG_ERROR, "find best stream failed, index is: %d\n", audioIndex);
avformat_close_input(&inFormatCtx);
return -1;
}
av_log(NULL, AV_LOG_INFO, "the audio index is %d\n", audioIndex);
//4.初始化packett
AVPacket packet;
av_init_packet(&packet);
FILE *dest_fp = fopen(outfileName, "wb");
if (dest_fp == NULL)
{
av_log(NULL, AV_LOG_ERROR, "open %s file failed\n", outfileName);
avformat_close_input(&inFormatCtx);
return -1;
}
//5.读取packet数据
while (av_read_frame(inFormatCtx, &packet) == 0)
{
if (packet.stream_index == audioIndex)
{
char adtsHeader[7] = {0};
getADTSHeader(adtsHeader, packet.size, inFormatCtx->streams[audioIndex]->codecpar->profile,
inFormatCtx->streams[audioIndex]->codecpar->sample_rate,
inFormatCtx->streams[audioIndex]->codecpar->channels);
ret = fwrite(adtsHeader, 1, sizeof(adtsHeader), dest_fp);
if (ret != sizeof(adtsHeader))
{
av_log(NULL, AV_LOG_ERROR, "write adtsHeader failed\n");
fclose(dest_fp);
avformat_close_input(&inFormatCtx);
return -1;
}
ret = fwrite(packet.data, 1, packet.size, dest_fp);
if (ret != packet.size)
{
av_log(NULL, AV_LOG_ERROR, "write file failed\n");
fclose(dest_fp);
avformat_close_input(&inFormatCtx);
return -1;
}
}
//6.释放packet资源
av_packet_unref(&packet);
}
if (inFormatCtx)
{
//7.关闭媒体文件
avformat_close_input(&inFormatCtx);
}
if (dest_fp)
{
fclose(dest_fp);
}
return 0;
}
Makefile:
TARGET=demoBin
SRC=demuxing_audio.c
CC=gcc
CFLAGS=-I../include
LDFLAGS=-L../lib/
LDFLAGS+= \
-lavutil \
-lavformat \
-lavcodec \
all:$(TARGET)
$(TARGET):$(SRC)
$(CC) $(SRC) $(CFLAGS) $(LDFLAGS) -o $(TARGET)
clean:
rm $(TARGET) -rf
① make
② ./demoBin ../../sourceVideo/out.mp4 out.aac
③ ffplay out.aac:
扫描二维码关注公众号,回复:
14639498 查看本文章