ffmpeg在mac下编译安装与在mac下音频采集

swift语法

//
//  main.swift
//  first_swift
//
//  Created by lichao on 2020/1/29.
//  Copyright © 2020年 lichao. All rights reserved.
//

import Foundation

/*
 swift语言的特点:没有main函数,入口是main.swift
 
1. var 变量  let 常量
 var a = 10
 var b:Int =20
 
2. 可以不写分号
 
3. switch 没有break关键字,case执行后结束 不会连在一起
 
4 循环 for while  for in list
 
5 函数 func
 
 
 */

let a = 555
var b = 456

if a < 500 {
    print("the a is less than 500")
}else {
    print("the a is more than 500")
}

switch a {
case 123:
    print("the value is 123")
case 456:
    print("the value is 456")
default:
    print("the value is ", a)
}

var list = [1,2,3,4,5,6]

for i in list {
    print(i)
}


// 连续数组 0-100
for i in 0..<100 {
    print("for==", i)
}

var loop = 0
while loop < 100 {
    print("loop=", loop)
    loop = loop + 1
}

func myfunc(a : Int)->Int{
    var b: Int = 0
    b = a + 10
    return b
}

var aa = 20
print("Hello, World!", a, b, myfunc(a: aa))

创建Mac App

 

随后点击创建,选择保存项目的路径即可。产生的文件:

AppDelegate.swift  一般不做逻辑操作

ViewController.swift  做主要的工作 在viewDidLoad中做窗口的初始化

Assets.xcassets 资源 如AppIcon

Main.storyboard 可以使用拖拽方式实现布局

Info.plist 项目基本信息

 

打开一个窗口

        窗口与view的关系:窗口并不是显示在屏幕上的窗口,是描述的信息(title 大小 最小化最大化等),并不会真正的显示出来;view将窗口显示出来:将窗口的信息交给view,view根据信息显示出来窗口

        设置View大小:self.view.setFrameSize  (self 代表this)

        显示控件:self.view.addSubView

import Cocoa

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        
        //设置窗口大小
        self.view.setFrameSize(NSSize(width:320,height:240));
        
        //添加控件
        let btn = NSButton.init(title: "button", target: nil, action: nil);
        
        btn.title = "hello";//
        btn.frame = NSRect(x:100,y:100,width: 80,height: 50);//显示位置 mac app 原点在左下角不是在左上角
        btn.setButtonType(.pushOnPushOff);
        
        //设置控件回调函数callback func:注意:回调函数前要加 @objc 
        btn.target = self;
        btn.action = #selector(myfunc);
        
        //添加子控件
        self.view.addSubview(btn);
        
        
    }
    
    @objc
    func myfunc(){
        print("hello world");
        testc_show();
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }


}

        

 

Swift调用C函数

         ffmepg 是用C语言实现的。

         1.编写C函数

         2. 在桥接头文件中引入C头文件

        3. 在swift中直接调用C函数

       

 

next 在弹出的对话框中选择create Bridging Header 即创建桥接头文件

创建出的三个文件:

在桥接头文件中引入c的头文件,即可使用c文件中定义的接口

如定义以下接口:

使用接口:

引入ffmpeg

ffmpeg在mac下安装:

brew方式安装:

源码方式安装(选择):

1.下载源码:

git clone https://git.ffmpeg.org/ffmpeg.git

2.编译

首先进入代码文件夹:执行
./configure --prefix=/Users/jiweili/Project/ffmpeg/mac_build --enable-debug=3 --enable-static --enable-nonfree --enable-libmp3lame  --disable-shared
其中:
--prefix=/Users/jiweili/Project/ffmpeg/mac_build 是安装位置
--enable-debug=3 调试级别 方便调试代码
--enable-static 生成静态库
--disable-shared 不生成动态库
 --enable-nonfree --enable-libmp3lame   生成mp3编码库

然后执行: -j 指定并发编译的cpu个数
make -j 4
最后
make install

添加ffmpeg

 

需要将ffmpeg静态库需要的其他库页添加,否则必报错。

关闭沙箱:

 

打开音频设备

int open_device(){
    
    AVFormatContext* fmt_ctx=NULL;
    int ret;
    char errors[1024];
    
    //[[video device]:[audio device]]   : 代表可以选
    char devicename[] = ":0";//第一个音频设备
    
    //1 注册设备
    avdevice_register_all();
    
    //2 获取格式
    AVInputFormat * input_format = av_find_input_format("avfoundation");
    if (NULL == input_format)
    {
        printf("av_find_input_format fail\n");
        return -1;
    }
    
    //打开设备 url可以是本地地址或网络地址
    ret = avformat_open_input(&fmt_ctx, devicename,input_format, NULL);
    if (ret)
    {
        av_strerror(ret, errors, 1024);
        printf("avformat_open_input fail,[%d]%s",ret,errors);
        return -1;
    }
    
    
    
    return 0;
}

从音频设备中读取音频数据

/**
 * 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.
 *
 * If pkt->buf is NULL, then the packet is valid until the next
 * av_read_frame() or until avformat_close_input(). Otherwise the packet
 * is valid indefinitely. In both cases 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
 */
int av_read_frame(AVFormatContext *s, AVPacket *pkt);

 

/**
 * Initialize optional fields of a packet with default values.
 *
 * Note, this does not touch the data and size members, which have to be
 * initialized separately.
 *
 * @param pkt packet
 */
void av_init_packet(AVPacket *pkt);

/**
 * Wipe the packet.
 *
 * Unreference the buffer referenced by the packet and reset the
 * remaining packet fields to their default values.
 *
 * @param pkt The packet to be unreferenced.
 */
void av_packet_unref(AVPacket *pkt);

/**
 * Allocate an AVPacket and set its fields to default values.  The resulting
 * struct must be freed using av_packet_free().
 *
 * @return An AVPacket filled with default values or NULL on failure.
 *
 * @note this only allocates the AVPacket itself, not the data buffers. Those
 * must be allocated through other means such as av_new_packet.
 *
 * @see av_new_packet
 */
AVPacket *av_packet_alloc(void);


/**
 * Free the packet, if the packet is reference counted, it will be
 * unreferenced first.
 *
 * @param pkt packet to be freed. The pointer will be set to NULL.
 * @note passing NULL is a no-op.
 */
void av_packet_free(AVPacket **pkt);

对于av_packet_alloc 做了两个操作,首先分配一个AVPacket的内存,然后调用av_init_packet对这块内存初始化


AVPacket *av_packet_alloc(void)
{
    AVPacket *pkt = av_mallocz(sizeof(AVPacket));
    if (!pkt)
        return pkt;

    av_packet_unref(pkt);

    return pkt;
}

void av_packet_unref(AVPacket *pkt)
{
    av_packet_free_side_data(pkt);
    av_buffer_unref(&pkt->buf);
    av_init_packet(pkt);
    pkt->data = NULL;
    pkt->size = 0;
}



void av_init_packet(AVPacket *pkt)
{
    pkt->pts                  = AV_NOPTS_VALUE;
    pkt->dts                  = AV_NOPTS_VALUE;
    pkt->pos                  = -1;
    pkt->duration             = 0;
#if FF_API_CONVERGENCE_DURATION
FF_DISABLE_DEPRECATION_WARNINGS
    pkt->convergence_duration = 0;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
    pkt->flags                = 0;
    pkt->stream_index         = 0;
    pkt->buf                  = NULL;
    pkt->side_data            = NULL;
    pkt->side_data_elems      = 0;
}


void av_packet_free(AVPacket **pkt)
{
    if (!pkt || !*pkt)
        return;

    av_packet_unref(*pkt);
    av_freep(pkt);
}

录制音频

 ./ffplay  -ar 44100 -ac 2 -f f32le /Users/jiweili/Desktop/macapp/macapp/audio.pcm 播发音频

通过界面控制录制

 

git仓库:

git@github.com:Paul199406/rec_recording.git

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值