diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index 104ddbd5..aeaafe1e 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -405,7 +405,7 @@ func (s *session) Write(data []byte) (int, error) { return len(data), nil } -func rtmpIsConnected(r *C.RTMP) int { +func C_RTMP_IsConnected(r *C.RTMP) int32 { if r.m_sb.sb_socket != -1 { return 1 } @@ -1289,11 +1289,9 @@ func rtmpConnectStream(r *C.RTMP, seekTime int32) int { return int(r.m_bPlaying) } -// TODO: finish porting this -/* func rtmpReadPacket(r *C.RTMP, packet *C.RTMPPacket) int32 { var hbuf [RTMP_MAX_HEADER_SIZE]uint8 - memset((*byte)(hbuf), RTMP_MAX_HEADER_SIZE) + memset((*byte)(&hbuf[0]), 0, RTMP_MAX_HEADER_SIZE) var header *byte header = (*byte)(unsafe.Pointer(&hbuf[0])) var nSize, hSize, nToRead, nChunk int32 @@ -1305,8 +1303,8 @@ func rtmpReadPacket(r *C.RTMP, packet *C.RTMPPacket) int32 { return 0 } - packet.m_headerType = C.int((hbuf[0] & 0xc0) >> 6) - packet.m_Channel = C.int(hbuf[0] & 0x3f) + packet.m_headerType = C.uint8_t((hbuf[0] & 0xc0) >> 6) + packet.m_nChannel = C.int(hbuf[0] & 0x3f) header = (*byte)(incBytePtr(unsafe.Pointer(header), 1)) switch { @@ -1316,85 +1314,96 @@ func rtmpReadPacket(r *C.RTMP, packet *C.RTMPPacket) int32 { return 0 } - packet.m_nChannel = hbuf[1] + packet.m_nChannel = C.int(hbuf[1]) packet.m_nChannel += 64 header = (*byte)(incBytePtr(unsafe.Pointer(header), 1)) case packet.m_nChannel == 1: var tmp int32 - if readN(r, (*byte)(&hubf[1]), 2) != 2 { + if readN(r, (*byte)(&hbuf[1]), 2) != 2 { log.Println("rtmpReadPacket: failed to read RTMP packet 3rd byte") return 0 } - tmp = (hbuf[2] << 8) + hbuf[1] + tmp = int32((hbuf[2] << 8) + hbuf[1]) packet.m_nChannel = C.int(tmp + 64) header = (*byte)(incBytePtr(unsafe.Pointer(header), 2)) } - nSize = packetSize[packet.m_headerType] + nSize = int32(packetSize[packet.m_headerType]) if packet.m_nChannel >= r.m_channelsAllocatedIn { - var n int32 = packet.m_nChannel + 10 - timestamp := (*int32)(C.realloc(r.m_channelTimestamp, unsafe.Sizeof(n)*n)) - var packets **C.RTMPPacket = (**C.RTMPPacket)(C.realloc(r.m_vecChannelsIn, unsafe.Sizeof(*packets)*n)) + var n int32 = int32(packet.m_nChannel + 10) + timestamp := (*int32)(C.realloc(unsafe.Pointer(r.m_channelTimestamp), + C.size_t(int32(unsafe.Sizeof(n))*n))) + var packetPtr *C.RTMPPacket + packets := (**C.RTMPPacket)(C.realloc(unsafe.Pointer(r.m_vecChannelsIn), + C.size_t(int32(unsafe.Sizeof(packetPtr))*n))) if timestamp == nil { - C.free(r.m_channelTimestamp) + C.free(unsafe.Pointer(r.m_channelTimestamp)) } if packets == nil { - C.free(r.m_vecChannelsIn) + C.free(unsafe.Pointer(r.m_vecChannelsIn)) } - r.m_channelTimestamp = timestamp + r.m_channelTimestamp = (*C.int)(timestamp) r.m_vecChannelsIn = packets if timestamp == nil || packets == nil { - r.m_channelsAllocatedInt = 0 + r.m_channelsAllocatedIn = 0 return 0 } - memset(r.m_channelTimestamp+r.m_channelsAllocatedInt, 0, int32Size*(n- - r.m_channelsAllocatedIn)) - memset(incPtr(unsafe.Pointer(r.m_vecChannelsIn), int(uintptr(unsafe.Pointer( - r.m_channelsAllocatedIn))), unsafe.Sizeof(*r.m_vecChannelsIn)), 0, - unsafe.Sizeof(*packets)*(n-r.m_channelsAllocatedIn)) - r.m_channelsAllocatedIn = n + memset((*byte)(incPtr(unsafe.Pointer(r.m_channelTimestamp), + int(r.m_channelsAllocatedIn), int(unsafe.Sizeof(*r.m_channelTimestamp)))), + 0, int(int32Size*int32((n-int32(r.m_channelsAllocatedIn))))) + memset((*byte)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), int( + r.m_channelsAllocatedIn), int(unsafe.Sizeof(*r.m_vecChannelsIn)))), 0, + int(int32(unsafe.Sizeof(*packets))*(n-int32(r.m_channelsAllocatedIn)))) + r.m_channelsAllocatedIn = C.int(n) } switch { case nSize == RTMP_LARGE_HEADER_SIZE: packet.m_hasAbsTimestamp = 1 case nSize < RTMP_LARGE_HEADER_SIZE: - if r.m_vecChannelsIn[packet.m_nChannel] != nil { + var tmpPacketPtr *C.RTMPPacket + if *(**C.RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), + int(packet.m_nChannel), int(unsafe.Sizeof(tmpPacketPtr)))) != nil { + var tmpPacket C.RTMPPacket memmove(unsafe.Pointer(packet), unsafe.Pointer( - r.m_vecChannelsIn[packet.m_nChannel]), unsafe.Sizeof(**packets)) + *(**C.RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), + int(packet.m_nChannel), int(unsafe.Sizeof(tmpPacketPtr))))), + unsafe.Sizeof(tmpPacket)) } } nSize-- - if nSize > 0 && readN(r, header, nSize) != nSize { + if nSize > 0 && readN(r, header, int(nSize)) != int(nSize) { log.Println("rtmpReadPacket: failed to read rtmp packet header.") return 0 } - hSize = nSize + decBytePtr(unsafe.Pointer(header), int(uintptr( - unsafe.Pointer(&hbuf[0])))) + hSize = int32(uintptr(incBytePtr(decBytePtr(unsafe.Pointer(header), int(uintptr( + unsafe.Pointer(&hbuf[0])))), int(nSize)))) if nSize >= 3 { - packet.m_nTimeStamp = amfDecodeInt24(header) + packet.m_nTimeStamp = C.uint32_t(amfDecodeInt24(header)) if nSize >= 6 { - packet.m_nBodySize = amfDecodeInt24((*byte)(incBytePtr(unsafe.Pointer(header), 3))) + packet.m_nBodySize = C.uint32_t(amfDecodeInt24((*byte)(incBytePtr( + unsafe.Pointer(header), 3)))) packet.m_nBytesRead = 0 if nSize > 6 { - packet.m_packetType = C.char(*indxBytePtr(unsafe.Pointer(header), 6)) + packet.m_packetType = C.uint8_t(*indxBytePtr(unsafe.Pointer(header), 6)) if nSize == 11 { // TODO: port this - packet.m_nInfoField2 = C.DecodeInt32LE((*C.char)(incBytePtr(unsafe.Pointer(header), 7))) + packet.m_nInfoField2 = C.int32_t(C.DecodeInt32LE((*C.char)(incBytePtr( + unsafe.Pointer(header), 7)))) } } } @@ -1405,12 +1414,13 @@ func rtmpReadPacket(r *C.RTMP, packet *C.RTMPPacket) int32 { } if extendedTimestamp != 0 { - if readN(r, (*byte)(incBytePtr(unsafe.Pointer(header), nSize)), 4) != 4 { + if readN(r, (*byte)(incBytePtr(unsafe.Pointer(header), int(nSize))), 4) != 4 { log.Println("RTMPRead_Packet: Failed to read extended timestamp") return 0 } // TODO: port this - packet.m_nTimeStamp = amfDecodeInt32((*C.char)(incBytePtr(unsafe.Pointer(header), nSize))) + packet.m_nTimeStamp = C.uint32_t(C.AMF_DecodeInt32((*C.char)(incBytePtr( + unsafe.Pointer(header), int(nSize))))) hSize += 4 } @@ -1421,9 +1431,72 @@ func rtmpReadPacket(r *C.RTMP, packet *C.RTMPPacket) int32 { return 0 } didAlloc = TRUE + packet.m_headerType = C.uint8_t((hbuf[0] & 0xc0) >> 6) } + + nToRead = int32(packet.m_nBodySize - packet.m_nBytesRead) + nChunk = int32(r.m_inChunkSize) + + if nToRead < nChunk { + nChunk = nToRead + } + + if packet.m_chunk != nil { + packet.m_chunk.c_headerSize = C.int(hSize) + memmove(unsafe.Pointer(&packet.m_chunk.c_header[0]), unsafe.Pointer(&hbuf[0]), + uintptr(hSize)) + packet.m_chunk.c_chunk = (*C.char)(incBytePtr(unsafe.Pointer(packet.m_body), + int(packet.m_nBytesRead))) + packet.m_chunk.c_chunkSize = C.int(nChunk) + } + + if readN(r, (*byte)(incBytePtr(unsafe.Pointer(packet.m_body), int(packet.m_nBytesRead))), + int(nChunk)) != int(nChunk) { + log.Println("rtmpReadPacket: failed to read RTMP packet body") + return FALSE + } + + packet.m_nBytesRead += C.uint32_t(nChunk) + + var tmpPktPtr *C.RTMPPacket + // keep the packet as ref for other packets on this channel + if *(**C.RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), + int(packet.m_nChannel), int(unsafe.Sizeof(tmpPktPtr)))) == nil { + var tmpPkt C.RTMPPacket + *(**C.RTMPPacket)(incPtr(unsafe.Pointer(r.m_vecChannelsIn), int(packet.m_nChannel), + int(unsafe.Sizeof(tmpPktPtr)))) = (*C.RTMPPacket)(C.malloc(C.size_t(unsafe.Sizeof(tmpPkt)))) + } + memmove(unsafe.Pointer(*(**C.RTMPPacket)(incPtr(unsafe.Pointer( + r.m_vecChannelsIn), int(packet.m_nChannel), int(unsafe.Sizeof(tmpPktPtr))))), + unsafe.Pointer(packet), unsafe.Sizeof(tmpPkt)) + + if extendedTimestamp != 0 { + (*(**C.RTMPPacket)(incPtr(unsafe.Pointer( + r.m_vecChannelsIn), int(packet.m_nChannel), + int(unsafe.Sizeof(tmpPktPtr))))).m_nTimeStamp = 0xffffff + } + + // TODO: port this + if C.RTMPPacket_IsRead(packet) != 0 { + if !packet.m_hasAbsTimestamp { + // timestamps seem to always be relative + packet.m_nTimeStamp += r.m_channelTimestamp[packet.m_nChannel] + } + r.m_channelTimestamp[packet.m_nChannel] = packet.m_nTimeStamp + + /* reset the data from the stored packet. we keep the header since we may + use it later if a new packet for this channel + arrives and requests to re-use some info (small packet header) */ + r.m_vecChannelsIn[packet.m_nChannel].m_body = NULL + r.m_vecChannelsIn[packet.m_nChannel].m_nBytesRead = 0 + /* can only be false if we reuse header */ + r.m_vecChannelsIn[packet.m_nChannel].m_hasAbsTimestamp = FALSE + } else { + packet.m_body = nil /* so it won't be erased on free */ + } + + return TRUE } -*/ func rtmpPacketIsReady(p *C.RTMPPacket) int { if p.m_nBytesRead == p.m_nBodySize {