diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 6c992ecb..0f0ed99e 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -153,8 +153,23 @@ func memmove(to, from unsafe.Pointer, n uintptr) { } // av_setDataFrame is a static const global in rtmp.c -var setDataFrame = AVC("@setDataFrame") -var av_connect = AVC("connect") +var ( + setDataFrame = AVC("@setDataFrame") + av_connect = AVC("connect") + av_app = AVC("app") + av_type = AVC("type") + av_nonprivate = AVC("nonprivate") + av_flashVer = AVC("flashVer") + av_swfUrl = AVC("swfUrl") + av_tcUrl = AVC("tcUrl") + av_fpad = AVC("fpad") + av_capabilities = AVC("capabilities") + av_audioCodecs = AVC("audioCodecs") + av_videoCodecs = AVC("videoCodecs") + av_videoFunction = AVC("videoFunction") + av_pageUrl = AVC("av_pageUrl") + av_objectEncoding = AVC("av_objectEncoding") +) var packetSize = [...]int{12, 8, 4, 1} @@ -807,8 +822,140 @@ func sendConnectPacket(r *C.RTMP, cp *C.RTMPPacket) int { enc = (*byte)(unsafe.Pointer(packet.m_body)) enc = afmEncodeString(enc, (*byte)(pend), &av_connect) r.m_numInvokes += 1 - enc = afmEncodeString(unsafe.Pointer(enc), unsafe.Pointer(pend), r.m_numInvokes) - return 1 + // TODO: port this + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNumber((*C.char)(unsafe.Pointer(enc)), + (*C.char)(unsafe.Pointer(pend)), + C.double(r.m_numInvokes)))) + // TODO: port this const + *indxBytePtr(unsafe.Pointer(enc), 0) = C.AMF_OBJECT + + // TODO: port this + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer( + enc)), (*C.char)(unsafe.Pointer(pend)), &av_app, &r.Link.app))) + + if enc == nil { + return 0 + } + if r.Link.protocol&RTMP_FEATURE_WRITE != 0 { + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), + (*C.char)(unsafe.Pointer(pend)), &av_type, &av_nonprivate))) + + if enc == nil { + return 0 + } + } + + if r.Link.flashVer.av_len != 0 { + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), + (*C.char)(unsafe.Pointer(pend)), &av_flashVer, &r.Link.flashVer))) + if enc == nil { + return 0 + } + } + if r.Link.swfUrl.av_len != 0 { + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), + (*C.char)(unsafe.Pointer(pend)), &av_swfUrl, &r.Link.swfUrl))) + if enc == nil { + return 0 + } + } + + if r.Link.tcUrl.av_len != 0 { + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), + (*C.char)(unsafe.Pointer(pend)), &av_tcUrl, &r.Link.tcUrl))) + if enc == nil { + return 0 + } + } + + if r.Link.protocol&RTMP_FEATURE_WRITE == 0 { + // TODO: port this + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedBoolean((*C.char)( + unsafe.Pointer(enc)), (*C.char)(unsafe.Pointer(pend)), &av_fpad, 0))) + if enc == nil { + return 0 + } + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)( + unsafe.Pointer(enc)), (*C.char)(unsafe.Pointer(pend)), &av_capabilities, + 15.0))) + if enc == nil { + return 0 + } + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( + unsafe.Pointer(pend)), &av_audioCodecs, r.m_fAudioCodecs))) + if enc == nil { + return 0 + } + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( + unsafe.Pointer(pend)), &av_videoCodecs, r.m_fVideoCodecs))) + if enc == nil { + return 0 + } + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( + unsafe.Pointer(pend)), &av_videoFunction, 1.0))) + if enc == nil { + return 0 + } + if r.Link.pageUrl.av_len != 0 { + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedString((*C.char)(unsafe.Pointer(enc)), (*C.char)( + unsafe.Pointer(pend)), &av_pageUrl, &r.Link.pageUrl))) + if enc == nil { + return 0 + } + } + } + + if r.m_fEncoding != 0.0 || r.m_bSendEncoding != 0 { + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeNamedNumber((*C.char)(unsafe.Pointer(enc)), (*C.char)( + unsafe.Pointer(pend)), &av_objectEncoding, r.m_fEncoding))) + if enc == nil { + return 0 + } + } + + if int(uintptr(incBytePtr(unsafe.Pointer(enc), 3))) >= int(uintptr( + unsafe.Pointer(pend))) { + return 0 + } + + *indxBytePtr(unsafe.Pointer(enc), 0) = 0 + enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) + *indxBytePtr(unsafe.Pointer(enc), 0) = 0 + enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) + *indxBytePtr(unsafe.Pointer(enc), 0) = C.AMF_OBJECT_END + enc = (*byte)(incBytePtr(unsafe.Pointer(enc), 1)) + + /* add auth string */ + if r.Link.auth.av_len != 0 { + // TODO: port this + enc = (*byte)(unsafe.Pointer(C.AMF_EncodeBoolean((*C.char)(unsafe.Pointer(enc)), (*C.char)( + unsafe.Pointer(pend)), r.Link.lFlags&RTMP_LF_AUTH))) + if enc == nil { + return 0 + } + enc = afmEncodeString(enc, (*byte)(pend), &r.Link.auth) + if enc == nil { + return 0 + } + } + + if r.Link.extras.o_num != 0 { + for i := 0; i < int(r.Link.extras.o_num); i++ { + enc = (*byte)(unsafe.Pointer(C.AMFProp_Encode((*C.AMFObjectProperty)( + incPtr(unsafe.Pointer(&r.Link.extras.o_props), int(unsafe.Sizeof( + r.Link.extras.o_props)), i)), (*C.char)(unsafe.Pointer(enc)), (*C.char)( + unsafe.Pointer(pend))))) + + if enc == nil { + return 0 + } + } + } + + packet.m_nBodySize = C.uint32_t(int(uintptr(decBytePtr(unsafe.Pointer(enc), int(uintptr( + unsafe.Pointer(packet.m_body))))))) + + return sendPacket(r, &packet, 1) } func rtmpConnectStream(r *C.RTMP, seekTime int32) int {