nonocast / me

记录和分享技术的博客
http://nonocast.cn
MIT License
20 stars 0 forks source link

Swift & C (Part 1: RTMP Routine) #282

Open nonocast opened 2 years ago

nonocast commented 2 years ago

hello world

先起一个linux c的项目, foo.c

int biubiubiu() { return 666; }

Makefile

libfoo.a: foo.o
    libtool -static -o $@ $^

foo.o: foo.c
    clang -c -arch arm64 -arch x86_64 -o $@ $<

然后Xcode新建一个SwiftUI或Swift CommandLine都行,打开后在Target/General/Frameworks and Libraries中添加libfoo.a, 几点说明:

第二步,在项目中添加一个C File, 此时Xcode会提示你添加一个Bridge文件,选同意,同意后保留Bridge删除刚才的C文件。Bridge就是用来告诉swiftc libfoo.a的definitions,所以可以选择3种方式:

最后,在swift中可以直接调用:

app.swift

func main() {
  print(biubiubiu()) // 666
}

main()

RTMP_LibVersion


func main() {
  let version = RTMP_LibVersion();
  let versionString = String(format:"0x%08x", version); // RTMP_LibVersion: 0x00020300
  print("RTMP_LibVersion: \(versionString)");
  RTMP_LogSetLevel(RTMP_LOGALL)
}

main()

RTMP main routine

import Foundation

func main() {
  RTMP_LogSetLevel(RTMP_LOGDEBUG)

  // Show librtmp version
  let version = RTMP_LibVersion();
  let versionString = String(format:"0x%08x", version); // RTMP_LibVersion: 0x00020300
  print("RTMP_LibVersion: \(versionString)");

  // C: RTMP rtmp
  var rtmp = RTMP()
  RTMP_Init(&rtmp)

  // C: char *url = "rtmp://shgbit.xyz/app/1"
  // C: RTMP_SetupURL(&rtmp, url)
  // RTMP_SetupURL(UnsafeMutablePointer<RTMP>! , _ url: UnsafeMutalbePointer<CChar>!)
  let url = "rtmp://shgbit.xyz/app/1"
  _ = url.withCString { ptr in
    RTMP_SetupURL(&rtmp, UnsafeMutablePointer<CChar>(mutating: ptr))
  }

  // C: RTMP_EnableWrite(&rtmp)
  RTMP_EnableWrite(&rtmp)

  // C: RTMP_Connect(&rtmp, NULL)
  RTMP_Connect(&rtmp, nil)

  // C: RTMP_ConnectStream(&rtmp, NULL)
  RTMP_ConnectStream(&rtmp, 0)

  // C: RTMP_Close(&rtmp)
  RTMP_Close(&rtmp)
}

main()

运行后输出:

RTMP_LibVersion: 0x00020300
DEBUG: Parsing...
DEBUG: Parsed protocol: 0
DEBUG: Parsed host    : shgbit.xyz
DEBUG: Parsed app     : app
DEBUG: RTMP_Connect1, ... connected, handshaking
DEBUG: HandShake: Type Answer   : 03
DEBUG: HandShake: Server Uptime : 1653333607
DEBUG: HandShake: FMS Version   : -14.92.-63.-82
DEBUG: RTMP_Connect1, handshaked
DEBUG: Invoking connect
DEBUG: HandleServerBW: server BW = 2500000
DEBUG: HandleClientBW: client BW = 2500000 2
DEBUG: HandleChangeChunkSize, received: chunk size change to 60000
DEBUG: RTMP_ClientPacket, received: invoke 510 bytes
DEBUG: (object begin)
DEBUG: (object begin)
DEBUG: Property: <Name:             fmsVer, STRING: FMS/3,5,3,888>
DEBUG: Property: <Name:       capabilities, NUMBER: 127.00>
DEBUG: Property: <Name:               mode, NUMBER: 1.00>
DEBUG: (object end)
DEBUG: (object begin)
DEBUG: Property: <Name:              level, STRING: status>
DEBUG: Property: <Name:               code, STRING: NetConnection.Connect.Success>
DEBUG: Property: <Name:        description, STRING: Connection succeeded>
DEBUG: Property: <Name:     objectEncoding, NUMBER: 0.00>
DEBUG: Property: <Name:               data, ECMA_ARRAY>
DEBUG: (object begin)
DEBUG: Property: <Name:            version, STRING: 3,5,3,888>
DEBUG: Property: <Name:            srs_sig, STRING: SRS>
DEBUG: Property: <Name:         srs_server, STRING: SRS/4.0.251(Leo)>
DEBUG: Property: <Name:        srs_license, STRING: MIT>
DEBUG: Property: <Name:            srs_url, STRING: https://github.com/ossrs/srs>
DEBUG: Property: <Name:        srs_version, STRING: 4.0.251>
DEBUG: Property: <Name:        srs_authors, STRING: https://github.com/ossrs/srs/blob/4.0release/trunk/AUTHORS.txt>
DEBUG: Property: <Name:      srs_server_ip, STRING: 172.18.0.2>
DEBUG: Property: <Name:            srs_pid, NUMBER: 1.00>
DEBUG: Property: <Name:             srs_id, STRING: c9615dg9>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <connect>
DEBUG: Invoking releaseStream
DEBUG: Invoking FCPublish
DEBUG: Invoking createStream
DEBUG: RTMP_ClientPacket, received: invoke 21 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <onBWDone>
DEBUG: Invoking _checkbw
DEBUG: RTMP_ClientPacket, received: invoke 21 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: Property: NULL
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result id 2.000000 without matching request
DEBUG: RTMP_ClientPacket, received: invoke 21 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: Property: NULL
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result id 3.000000 without matching request
DEBUG: RTMP_ClientPacket, received: invoke 29 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <createStream>
DEBUG: Invoking publish
DEBUG: RTMP_ClientPacket, received: invoke 102 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object begin)
DEBUG: Property: <Name:               code, STRING: NetStream.Publish.Start>
DEBUG: Property: <Name:        description, STRING: Started publishing stream.>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <onFCPublish>
DEBUG: RTMP_ClientPacket, received: invoke 136 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object begin)
DEBUG: Property: <Name:              level, STRING: status>
DEBUG: Property: <Name:               code, STRING: NetStream.Publish.Start>
DEBUG: Property: <Name:        description, STRING: Started publishing stream.>
DEBUG: Property: <Name:           clientid, STRING: ASAICiss>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <onStatus>
DEBUG: HandleInvoke, onStatus: NetStream.Publish.Start
DEBUG: Invoking FCUnpublish
DEBUG: Invoking deleteStream

AMF

func amf() {
  var data: Array<CChar> = Array(repeating: 0x00, count: 256)
  let _ = data.withUnsafeMutableBufferPointer { ptr in
    var enc: UnsafeMutablePointer<CChar>
    let end = ptr.baseAddress?.advanced(by: ptr.count)
    enc = AMF_EncodeBoolean(ptr.baseAddress, end, 1)
    enc = AMF_EncodeInt32(enc, end, 7)

    "nonocast".withCString { cstr in
      var val = AVal(av_val: UnsafeMutablePointer<CChar>(mutating: cstr), av_len: Int32(strlen(cstr)))
      enc = AMF_EncodeString(enc, end, &val)
    }

    let offset = enc - ptr.baseAddress!
    RTMP_LogHexString(Int32(RTMP_LOGDEBUG.rawValue), ptr.baseAddress, UInt(offset))
  }
}

输出结果如下:

DEBUG:   0000:  01 01 00 00 00 07 02 00  08 6e 6f 6e 6f 63 61 73   .........nonocas  
DEBUG:   0010:  74 

参考阅读