void RTMPPublisher::InitializeBuffer() { bool bFirstAudio = true; for (UINT i=0; i<bufferedPackets.Num(); i++) { TimedPacket &packet = bufferedPackets[i]; //first, get the audio time offset from the first audio packet if (packet.type == PacketType_Audio) { if (bFirstAudio) { audioTimeOffset = packet.timestamp; OSDebugOut(TEXT("Set audio offset: %d\n"), audioTimeOffset); bFirstAudio = false; } DWORD newTimestamp = packet.timestamp-audioTimeOffset; UINT newIndex = FindClosestBufferIndex(newTimestamp); if (newIndex < i) { bufferedPackets.MoveItem(i, newIndex); bufferedPackets[newIndex].timestamp = newTimestamp; } else { bufferedPackets[i].timestamp = newTimestamp; } } } }
void RTMPPublisher::SendPacket(BYTE *data, UINT size, DWORD timestamp, PacketType type) { //OSDebugOut (TEXT("SendPacket (%08x)\n"), quickHash(data,size)); if(!bConnected && !bConnecting && !bStopping) { hConnectionThread = OSCreateThread((XTHREAD)CreateConnectionThread, this); bConnecting = true; } if (bFirstKeyframe) { if (!bConnected || type != PacketType_VideoHighest) return; firstTimestamp = timestamp; bFirstKeyframe = false; } if (bufferedPackets.Num() == MAX_BUFFERED_PACKETS) { if (!bBufferFull) { InitializeBuffer(); bBufferFull = true; } TimedPacket packet; mcpy(&packet, &bufferedPackets[0], sizeof(TimedPacket)); bufferedPackets.Remove(0); SendPacketForReal(packet.data.Array(), packet.data.Num(), packet.timestamp, packet.type); } timestamp -= firstTimestamp; TimedPacket *packet; if (type == PacketType_Audio) { UINT newID; timestamp -= audioTimeOffset; newID = FindClosestBufferIndex(timestamp); packet = bufferedPackets.InsertNew(newID); } else { packet = bufferedPackets.CreateNew(); } packet->data.CopyArray(data, size); packet->timestamp = timestamp; packet->type = type; /*for (UINT i=0; i<bufferedPackets.Num(); i++) { if (bufferedPackets[i].data.Array() == 0) nop(); }*/ }
void RTMPPublisher::SendPacket(BYTE *data, UINT size, DWORD timestamp, PacketType type) { if(!bConnected && !bConnecting && !bStopping) { hConnectionThread = OSCreateThread((XTHREAD)CreateConnectionThread, this); bConnecting = true; } if (bFastInitialKeyframe) { if (!bConnected) { //while not connected, keep at most one keyframe buffered if (type != PacketType_VideoHighest) return; bufferedPackets.Clear(); } if (bConnected && bFirstKeyframe) { bFirstKeyframe = false; firstTimestamp = timestamp; //send out our buffered keyframe immediately, unless this packet happens to also be a keyframe if (type != PacketType_VideoHighest && bufferedPackets.Num() == 1) { TimedPacket packet; mcpy(&packet, &bufferedPackets[0], sizeof(TimedPacket)); bufferedPackets.Remove(0); packet.timestamp = 0; SendPacketForReal(packet.data.Array(), packet.data.Num(), packet.timestamp, packet.type); } else bufferedPackets.Clear(); } } else { if (bFirstKeyframe) { if (!bConnected || type != PacketType_VideoHighest) return; firstTimestamp = timestamp; bFirstKeyframe = false; } } //OSDebugOut (TEXT("%u: SendPacket (%d bytes - %08x @ %u)\n"), OSGetTime(), size, quickHash(data,size), timestamp); if (bufferedPackets.Num() == MAX_BUFFERED_PACKETS) { if (!bBufferFull) { InitializeBuffer(); bBufferFull = true; } TimedPacket packet; mcpy(&packet, &bufferedPackets[0], sizeof(TimedPacket)); bufferedPackets.Remove(0); SendPacketForReal(packet.data.Array(), packet.data.Num(), packet.timestamp, packet.type); } timestamp -= firstTimestamp; TimedPacket *packet; if (type == PacketType_Audio) { UINT newID; timestamp -= audioTimeOffset; newID = FindClosestBufferIndex(timestamp); packet = bufferedPackets.InsertNew(newID); } else { packet = bufferedPackets.CreateNew(); } packet->data.CopyArray(data, size); packet->timestamp = timestamp; packet->type = type; /*for (UINT i=0; i<bufferedPackets.Num(); i++) { if (bufferedPackets[i].data.Array() == 0) nop(); }*/ }