日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

音频采集

發布時間:2023/12/31 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 音频采集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天我們來談論下如何在進行音頻采集。

系統多種多樣?電腦上的系統有mac,windows,linux。手機系統有android,ios等。如果我們使用每種系統的音視頻函數進行采集,成本會很大。ffmpeg已經為我們封裝了相應的api。

今天我們講一下,音頻的采集流程和相應的api。最后我們通過一個例子來實現音頻的采集。

音頻采集的流程簡單來說如下圖

用ffmepg描述上面的流程

可以下面流程圖描述

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

ffmpeg流程講解

1、要想對設備操作我們就要對設備進行注冊

/*** Initialize libavdevice and register all the input and output devices.*/ void avdevice_register_all(void);

2、設置采集方式

/*** Find AVInputFormat based on the short name of the input format.*/ ff_const59 AVInputFormat *av_find_input_format(const char *short_name);

av_find_input_format?傳入的參數avfoundataion/dshow/alsa

avfoundataion mac

dshow? windows

alsa? linux

AVInputFormat是ffmpeg的解復用器對象,

一種文件格式對應一個AVInputFormat結構,在程序運行時候有多個實例。

next變量用于把支持的所有輸入文件容器格式連接成鏈表,便于遍歷查找。

priv_data_size標識具體的文件容器格式對應的Context大小。

我們看下AVInputFormat?的結構體都有什么內容

typedef struct AVInputFormat {/*格式的短名稱*/const char *name;/*格式的長名稱*/const char *long_name;/*** Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,* AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,* AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.*/int flags;/*定義了擴展,如果不進行格式探測通常不用擴展*/const char *extensions;/*codec 的tag*/const struct AVCodecTag * const *codec_tag;/*AvClass 用戶內部的context*/const AVClass *priv_class; ///< AVClass for the private context/*** Comma-separated list of mime types.* It is used check for matching mime types while probing.* @see av_probe_input_format2*//*mime類型,當probing的時候需檢測是否是需要的mime類型*/const char *mime_type;/****************************************************************** No fields below this line are part of the public API. They* may not be used outside of libavformat and can be changed and* removed at will.* New public fields should be added right above.******************************************************************//*用于把支持的所有輸入文件容器格式連接成鏈表*/ #if FF_API_NEXTff_const59 struct AVInputFormat *next; #endif/*** 原始解封裝存儲的id*/int raw_codec_id;/*** 格式文件的大小*/int priv_data_size;/*** 判斷給定的文件是否有機會被解析為這種格式。* 提供的緩沖區保證為AVPROBE_PADDING_SIZE字節大小,因此除非您需要更多,否則不必檢查該緩沖區。.*/int (*read_probe)(const AVProbeData *);/**讀取格式頭并初始化AVFormatContext結構。 如果正確,則返回0。 應該調用“ avformat_new_stream”來創建新的流。*/int (*read_header)(struct AVFormatContext *);/*讀取一個包,并放在pkt當中。pts和flags常常被設置。加入當前flag = AVFMTCTX_NOHEADER,就會調用avformat_new_stream,這個方法必須在可見線程調用0為成功,<0錯誤調用后,不管成功與否,必須釋放AVPacket*/int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);/*關閉流。AVFormatContext和AVStreams沒有被釋放*/int (*read_close)(struct AVFormatContext *);/*讀取給定的時間錯*/int (*read_seek)(struct AVFormatContext *,int stream_index, int64_t timestamp, int flags);/*** Get the next timestamp in stream[stream_index].time_base units.* @return the timestamp or AV_NOPTS_VALUE if an error occurred*//*讀取stream[stream_index]中的下一個時間戳, 如果錯誤發生返回AV_NOPTS_VALUE*/int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,int64_t *pos, int64_t pos_limit);/*恢復播放,只在RTSP格式下有意義*/int (*read_play)(struct AVFormatContext *);/*暫停播放,只在RTSP格式下有意義*/int (*read_pause)(struct AVFormatContext *);/*快進快退到指定時間戳*/int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);/*返回設備列表及其屬性*/int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);/*初始化設備能力子模塊*/int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);/*釋放設備能力子模塊*/int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); } AVInputFormat;

3、打開設備

/*** 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);

4、從音頻設備獲取數據放在AVPacket

/*** Return the next frame of a stream.* This function returns what is stored in the file, and does not validate* that what is there are valid frames for the decoder. It will split what is* stored in the file into frames and return one for each call. It will not* omit invalid data between valid frames so as to give the decoder the maximum* information possible for decoding.** On success, the returned packet is reference-counted (pkt->buf is set) and* valid indefinitely. The packet must be freed with av_packet_unref() when* it is no longer needed. For video, the packet contains exactly one frame.* For audio, it contains an integer number of frames if each frame has* a known fixed size (e.g. PCM or ADPCM data). If the audio frames have* a variable size (e.g. MPEG audio), then it contains one frame.** pkt->pts, pkt->dts and pkt->duration are always set to correct* values in AVStream.time_base units (and guessed if the format cannot* provide them). pkt->pts can be AV_NOPTS_VALUE if the video format* has B-frames, so it is better to rely on pkt->dts if you do not* decompress the payload.** @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank* (as if it came from av_packet_alloc()).** @note pkt will be initialized, so it may be uninitialized, but it must not* contain data that needs to be freed.*/ int av_read_frame(AVFormatContext *s, AVPacket *pkt);

5、AVPacket使用完要進行釋放

涉及到四個函數

av_init_packet(<AVPacket *pkt)

av_packet_unref(AVPacket *pkt)

?

av_packet_alloc()

先分配空間,再進行初始化

av_packet_free(AVPacket **pkt)

av_packet_unref再釋放空間

av_init_packet和av_packet_unref是一對

av_packet_alloc和av_packet_free是一對。

要成對出現要不會內存泄漏

6關閉輸入設備

/*** Close an opened input AVFormatContext. Free it and all its contents* and set *s to NULL.*/ void avformat_close_input(AVFormatContext **s);

?

下一篇文章我們來進行下實戰,在mac寫一個demo能夠進行音頻采集。

總結

以上是生活随笔為你收集整理的音频采集的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。