300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 使用FFmpeg实现抽取多媒体文件的音频并按照AAC格式进行保存--附源码

使用FFmpeg实现抽取多媒体文件的音频并按照AAC格式进行保存--附源码

时间:2021-03-25 08:27:57

相关推荐

使用FFmpeg实现抽取多媒体文件的音频并按照AAC格式进行保存--附源码

抽取音频文件

注册log与编解码器

av_log_set_level(AV_LOG_INFO);

av_register_all();

打开多媒体文件

打开多媒体文件,并读取头部信息

/*** Open an input stream and read the header. The codecs are not opened.* The stream must be closed with avformat_close_input().** @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).* May be a pointer to NULL, in which case an AVFormatContext is allocated by this* function and written into ps.* Note that a user-supplied AVFormatContext will be freed on failure.* @param url URL of the stream to open.* @param fmt If non-NULL, this parameter forces a specific input format.* Otherwise the format is autodetected.* @param options A dictionary filled with AVFormatContext and demuxer-private options.* On return this parameter will be destroyed and replaced with a dict containing* options that were not found. May be NULL.** @return 0 on success, a negative AVERROR on failure.** @note If you want to use custom IO, preallocate the format context and set its pb field.*/int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);

/*Open an input stream and read the header*/int ret = avformat_open_input(&fmt_ctx, "/work/test/test.mp4", NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "can't open file.\n");return -1;}

打开一个文件用于写入音频文件

char *pDst = NULL;pDst = "test.aac";// write audio data to AAC fileFILE *dst_fd = fopen(pDst, "wb");if (dst_fd == NULL) {av_log(NULL, AV_LOG_ERROR, "open dst_fd failed.\n");avformat_close_input(&fmt_ctx);return -1;}

输出多媒体信息

输出多媒体信息就是讲多媒体的信息以及metadata信息打印出来

/** Print detailed information about the input or output format**/av_dump_format(fmt_ctx, 0, "/work/test/test.mp4", 0);

确保输入的多媒体文件中有帧信息

// 2. get stream/*Read packets of a media file to get stream information.*/ret = avformat_find_stream_info(fmt_ctx, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "failed to find stream information.");avformat_close_input(&fmt_ctx);fclose(dst_fd);return -1;}

提取音频信息

提取音频信息,并按照AAC格式将音频信息写入文件

AVPacket pkt;/*Initialize optional fields of a packet with default values.*/av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;// 循环将音频信息写入AAC文件int len = -1;/*保存原始数据,播放时需要添加AAC的音频格式说明的头*/while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == audio_index) {/*每帧开头都要写*/char adts_header_buf[7];// 为每帧音频添加AAC头部信息adts_header(adts_header_buf, pkt.size);fwrite(adts_header_buf, 1, 7, dst_fd);len = fwrite(pkt.data, 1, pkt.size, dst_fd);cout << pkt.size << endl;if (len != pkt.size) {av_log(NULL, AV_LOG_ERROR, "waning, length is not equl size of pkt.\n");return -1;}}/*Wipe the packet.*/av_packet_unref(&pkt);}

// 添加ADTS头部信息void adts_header(char *szAdtsHeader, int dataLen) {int audio_object_type = 2;int sampling_frequency_index = 7;int channel_config = 2;int adtsLen = dataLen + 7;szAdtsHeader[0] = 0xff; //syncword:0xfff高8bitsszAdtsHeader[1] = 0xf0; //syncword:0xfff低4bitsszAdtsHeader[1] |= (0 << 3); //MPEG Version:0 for MPEG-4,1 for MPEG-2 1bitszAdtsHeader[1] |= (0 << 1); //Layer:0 2bitsszAdtsHeader[1] |= 1; //protection absent:1 1bitszAdtsHeader[2] =(audio_object_type - 1) << 6; //profile:audio_object_type - 1 2bitsszAdtsHeader[2] |=(sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index 4bitsszAdtsHeader[2] |= (0 << 1); //private bit:0 1bitszAdtsHeader[2] |=(channel_config & 0x04) >> 2; //channel configuration:channel_config高1bitszAdtsHeader[3] = (channel_config & 0x03) << 6;//channel configuration:channel_config低2bitsszAdtsHeader[3] |= (0 << 5); //original:0 1bitszAdtsHeader[3] |= (0 << 4); //home:01bitszAdtsHeader[3] |= (0 << 3); //copyright id bit:0 1bitszAdtsHeader[3] |= (0 << 2); //copyright id start:0 1bitszAdtsHeader[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bitsszAdtsHeader[4] = (uint8_t) ((adtsLen & 0x7f8) >> 3);//frame length:value 中间8bitsszAdtsHeader[5] = (uint8_t) ((adtsLen & 0x7) << 5); //frame length:value 低3bitsszAdtsHeader[5] |= 0x1f; //buffer fullness:0x7ff 高5bitsszAdtsHeader[6] = 0xfc;}

AAC结构说明参考

[AAC说明可以参考]: /leixiaohua1020/article/details/50535042

结束释放资源

音频写好之后,释放掉申请的资源

/*Close an opened input AVFormatContext*/avformat_close_input(&fmt_ctx);if (dst_fd != NULL)fclose(dst_fd);

完整代码

//// Created by andrew on /11/1.//#include <iostream>using namespace std;extern "C" {#include <libavutil/log.h>#include <libavformat/avformat.h>}void adts_header(char *szAdtsHeader, int dataLen) {int audio_object_type = 2;int sampling_frequency_index = 7;int channel_config = 2;int adtsLen = dataLen + 7;szAdtsHeader[0] = 0xff; //syncword:0xfff高8bitsszAdtsHeader[1] = 0xf0; //syncword:0xfff低4bitsszAdtsHeader[1] |= (0 << 3); //MPEG Version:0 for MPEG-4,1 for MPEG-2 1bitszAdtsHeader[1] |= (0 << 1); //Layer:0 2bitsszAdtsHeader[1] |= 1; //protection absent:1 1bitszAdtsHeader[2] =(audio_object_type - 1) << 6; //profile:audio_object_type - 1 2bitsszAdtsHeader[2] |=(sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index 4bitsszAdtsHeader[2] |= (0 << 1); //private bit:0 1bitszAdtsHeader[2] |=(channel_config & 0x04) >> 2; //channel configuration:channel_config高1bitszAdtsHeader[3] = (channel_config & 0x03) << 6;//channel configuration:channel_config低2bitsszAdtsHeader[3] |= (0 << 5); //original:0 1bitszAdtsHeader[3] |= (0 << 4); //home:01bitszAdtsHeader[3] |= (0 << 3); //copyright id bit:0 1bitszAdtsHeader[3] |= (0 << 2); //copyright id start:0 1bitszAdtsHeader[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bitsszAdtsHeader[4] = (uint8_t) ((adtsLen & 0x7f8) >> 3);//frame length:value 中间8bitsszAdtsHeader[5] = (uint8_t) ((adtsLen & 0x7) << 5); //frame length:value 低3bitsszAdtsHeader[5] |= 0x1f; //buffer fullness:0x7ff 高5bitsszAdtsHeader[6] = 0xfc;}/** 从多媒体文件中抽取媒体信息* */int main(int argc, char *argv[]) {AVFormatContext *fmt_ctx = NULL;av_log_set_level(AV_LOG_INFO);/*所有进行操作前,先执行以下,否则需要自己制定类型*/av_register_all();// 1. 读取多媒体文件char *pSrc = NULL;char *pDst = NULL;pSrc = (char *) "/work/test/test.mp4";pDst = "test.aac";/*Open an input stream and read the header*/int ret = avformat_open_input(&fmt_ctx, "/work/test/test.mp4", NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "can't open file.\n");return -1;}// write audio data to AAC fileFILE *dst_fd = fopen(pDst, "wb");if (dst_fd == NULL) {av_log(NULL, AV_LOG_ERROR, "open dst_fd failed.\n");avformat_close_input(&fmt_ctx);return -1;}// 2. get stream/*Read packets of a media file to get stream information.*/ret = avformat_find_stream_info(fmt_ctx, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "failed to find stream information.");avformat_close_input(&fmt_ctx);fclose(dst_fd);return -1;}/** Print detailed information about the input or output format* */av_dump_format(fmt_ctx, 0, "/work/test/test.mp4", 0);int audio_index = -1;audio_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);if (audio_index < 0) {av_log(NULL, AV_LOG_ERROR, "ret = %d\n", ret);avformat_close_input(&fmt_ctx);fclose(dst_fd);return -1;}AVPacket pkt;/*Initialize optional fields of a packet with default values.*/av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;int len = -1;/*保存原始数据,播放时需要添加AAC的音频格式说明的头*/while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == audio_index) {/*每帧开头都要写*/char adts_header_buf[7];adts_header(adts_header_buf, pkt.size);fwrite(adts_header_buf, 1, 7, dst_fd);len = fwrite(pkt.data, 1, pkt.size, dst_fd);cout << pkt.size << endl;if (len != pkt.size) {av_log(NULL, AV_LOG_ERROR, "waning, length is not equl size of pkt.\n");return -1;}}/*Wipe the packet.*/av_packet_unref(&pkt);}/*Close an opened input AVFormatContext*/avformat_close_input(&fmt_ctx);if (dst_fd != NULL)fclose(dst_fd);return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。