bash
复制代码
#include <stdio.h>
#include "libavutil/log.h"
#include "libavformat/avformat.h"
#define ERROR_STRING_SIZE 1024
#define ADTS_HEADER_LEN 7;
const int sampling_frequencies[] = {
96000,
88200,
64000,
48000,
44100,
32000,
24000,
22050,
16000,
12000,
11025,
8000
};
int adts_header(char * const p_adts_header, const int data_length,
const int profile, const int samplerate,
const int channels)
{
int sampling_frequency_index = 3;
int adtsLen = data_length + 7;
int frequencies_size = sizeof(sampling_frequencies) / sizeof(sampling_frequencies[0]);
for(int i = 0; i < frequencies_size; i++)
{
if(sampling_frequencies[i] == samplerate)
{
sampling_frequency_index = i;
break;
}
}
p_adts_header[0] = 0xff;
p_adts_header[1] = 0xf0;
p_adts_header[1] |= (0 << 3);
p_adts_header[1] |= (0 << 1);
p_adts_header[1] |= 1;
p_adts_header[2] = (profile)<<6;
p_adts_header[2] |= (sampling_frequency_index & 0x0f)<<2;
p_adts_header[2] |= (0 << 1);
p_adts_header[2] |= (channels & 0x04)>>2;
p_adts_header[3] = (channels & 0x03)<<6;
p_adts_header[3] |= (0 << 5);
p_adts_header[3] |= (0 << 4);
p_adts_header[3] |= (0 << 3);
p_adts_header[3] |= (0 << 2);
p_adts_header[3] |= ((adtsLen & 0x1800) >> 11);
p_adts_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3);
p_adts_header[5] = (uint8_t)((adtsLen & 0x7) << 5);
p_adts_header[5] |= 0x1f;
p_adts_header[6] = 0xfc;
return 0;
}
int main(int argc, char **argv)
{
char *in_filename = "/home/yx/media_file/believe.mp4";
char *h264_filename = "/home/yx/media_file/believe.h264";
char *aac_filename = "/home/yx/media_file/believe.aac";
FILE *aac_fd = NULL;
FILE *h264_fd = NULL;
h264_fd = fopen(h264_filename, "wb");
aac_fd = fopen(aac_filename, "wb");
AVFormatContext *ifmt_ctx = NULL;
int video_index = -1;
int audio_index = -1;
AVPacket *pkt = NULL;
ifmt_ctx = avformat_alloc_context();
avformat_open_input(&ifmt_ctx, in_filename, NULL, NULL); // 将媒体流与解复用器相关联
video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); // 查找视频流标签
audio_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); // 查找音频流标签
const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb"); // 查找H264过滤器
AVBSFContext *bsf_ctx = NULL;
av_bsf_alloc(bsfilter, &bsf_ctx);
avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[video_index]->codecpar);
av_bsf_init(bsf_ctx); // 初始化过滤器
pkt = av_packet_alloc();
av_init_packet(pkt);
while (1)
{
if(av_read_frame(ifmt_ctx, pkt) < 0) // 逐个包读取
break;
if(pkt->stream_index == video_index)
{
av_bsf_send_packet(bsf_ctx, pkt); // 视频包就将包发给过滤器
while (1)
{
if(av_bsf_receive_packet(bsf_ctx, pkt) != 0) // 从过滤器接收包
break;
size_t size = fwrite(pkt->data, 1, pkt->size, h264_fd); // 将包写到输出文件
av_packet_unref(pkt);
}
}
else if(pkt->stream_index == audio_index)
{
char adts_header_buf[7] = {0};
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); // 音频包构建ADTS帧头部
fwrite(adts_header_buf, 1, 7, aac_fd); // 将头部写到输出文件
size_t size = fwrite( pkt->data, 1, pkt->size, aac_fd); // 将AAC包写到输出文件
av_packet_unref(pkt); // 引用计数--
}
else
{
av_packet_unref(pkt);
}
}
printf("while finish\n");
printf("Hello World!\n");
return 0;
}