两种方法实现抽取一个视频文件中音频流(基于ffmpeg)

使用到的ffmpeg API
av_log_set_level()
设置日志打印的标准, 高于这个标准的将不会打印

av_log()
打印ffmpeg中的日志,当做printf用

av_dump_format()
打印流的各种信息

av_register_all()
初始化所有组件

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)

打开一个文件并解析,传入文件地址,输入文件的上下文会保存在 ps
主要是完成了对输入的AVFormatContext中的AVInputFormat的初始化,对AVIOContext打开输入控制,以及创建AVStream。

avformat_close_input()
传入上下文,关闭文件

av_find_best_stream()
输入流的上下文和要找的流的类型,返回最好流的索引

av_init_packet()
初始化一个包,保存了解复用(demuxer)之后,解码(decode)之前的数据(仍然是压缩后的数据)和关于这些数据的一些附加的信息

av_read_frame()
返回流的下一帧,当不再需要数据包时,必须使用av_packet_unref释放该数据包,当到文件结尾时返回负数

av_packet_unref()
取消引用数据包引用的缓冲区,并将剩余的数据包字段重置为其默认值。

avformat_alloc_context()
用来申请AVFormatContext类型变量空间并初始化默认参数,返回AVFormatContext类型上下文

av_guess_format()
根据输入的文件名生成最适合的输出容器,也可以指定文件类型,返回容器的上下文

avformat_new_stream()
创建流通道,返回AVStream
首先调用av_mallocz()为AVStream分配内存。
接着给新分配的AVStream的各个字段赋上默认值。
然后调用了另一个函数avcodec_alloc_context3()初始化AVStream中的AVCodecContext。

avcodec_parameters_copy()
拷贝avstream中的codecpar的信息,这里将输入流的参数信息拷贝到输出流中

*int av_strerror(int errnum, char errbuf, size_t errbuf_size)
errnum指错误码,errbuf返回错误的buf,错误buf的size,给错误信息赋值,为打印做准备

avformat_write_header
写输出文件流的头

av_rescale_q_rnd
计算 “a * b / c” 的值并分五种方式来取整.

av_rescale_q
av_rescale_q_rnd的特殊情况

av_interleaved_write_frame
此函数将根据需要在内部缓冲数据包,以确保输出文件中的数据包按照增加dts的顺序正确地交织在一起

av_write_trailer
将流尾随写入输出媒体文件并释放文件私有数据。只能在成功调用avformat_write_header后调用。

avio_open
创建并初始化一个AVIOContext,用于访问由url指示的资源。

avio_close
关闭

使用到的ffmpeg的数据结构

AVFormatContext(统领全局,主要存储视音频封装格式中包含的信息)

  |------AVInputFormat(存储输入视音频使用的封装格式)

     |------AVOutputFormat(存储输出音视频使用的封装格式)

     |------AVIOContext(处在协议层)

     |              |---------URLContext(存储视音频使用的协议的类型以及状态)

     |                                   |--------- URLProtocol(存储输入视音频使用的封装格式)

     |------AVStream(存储一个视频/音频流的相关数据)

                      |---------AVCondecContext(存储该视频/音频流使用解码方式的相关数据)

                                               |---------AVCodec(视频/音频对应的解码器)

AVOutputFormat

对流(Stream)的封装和抽象,描述了视频、音频等流的编码格式等基本流信息。此外也是音频、视频、字母数据流的重要载体。

AVStream
存储每一个视频/音频流信息的结构体
AVCodecContext *codec        // 已过时,使用另一个 codecpar 结构体代替。
AVRational time_base         // 时间基数。
int64_t duration            // 总时长。流的总时长,该参数不可靠。
AVRational avg_frame_rate       // 帧率。
AVCodecParameters *codecpar;     // 包含音视频参数的结构体。很重要,可以用来获取音视频参数中的宽度、高度、采样率、编码格式等信息。

AVPacket
保存了解复用(demuxer)之后,解码(decode)之前的数据(仍然是压缩后的数据)和关于这些数据的一些附加的信息
关于数据的属性有以下字段:

pts: (int64_t)显示时间,结合AVStream->time_base转换成时间戳

dts: (int64_t)解码时间,结合AVStream->time_base转换成时间戳

size: (int)data的大小

stream_index: (int)packet在stream的index位置

flags: (int)标示,结合AV_PKT_FLAG使用,其中最低为1表示该数据是一个关键帧。

#define AV_PKT_FLAG_KEY 0x0001 //关键帧

#define AV_PKT_FLAG_CORRUPT 0x0002 //损坏的数据

#define AV_PKT_FLAG_DISCARD 0x0004 /丢弃的数据

side_data_elems: (int)边缘数据元数个数

duration: (int64_t)数据的时长,以所属媒体流的时间基准为单位,未知则值为默认值0

pos: (int64_t )数据在流媒体中的位置,未知则值为默认值-1

convergence_duration:该字段已deprecated,不在使用

关于数据缓存,AVPacket本身只是个容器,不直接的包含数据,而是通过数据缓存的指针引用数据。AVPacket包含两种数据

uint8_t *data:指向保存压缩数据的指针,这就是AVPacket的实际数据。

AVPacketSideData *side_data:容器提供的一些附加数据

AVBufferRef *buf:用来管理data指针引用的数据缓存,其使用在后面介绍

第一种方式
先取出一个个音频包,然后在每个音频包前边手动的加 ADTS Header写成一个文件。

#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#ifdef __cplusplus
extern "C" {
   
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavutil/log.h>

#ifdef __cplusplus
};
#endif

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                          高8bits
    szAdtsHeader[1] = 0xf0;      //syncword:0xfff                          低4bits
    szAdtsHeader[1] |= (0 << 3); //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit
    szAdtsHeader[1] |= (0 << 1); //Layer:0                                 2bits
    szAdtsHeader[1] |= 1;        //protection absent:1                     1bit

    szAdtsHeader[2] = (audio_object_type - 1) << 6;            //profile:audio_object_type - 1                      2bits
    szAdtsHeader[2] |= (sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index  4bits
    szAdtsHeader[2] 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值