void Room::RoomImpl::BroadcastRoomInformation() { Packet packet; packet << static_cast<u8>(IdRoomInformation); packet << room_information.name; packet << room_information.member_slots; packet << room_information.uid; packet << room_information.port; packet << room_information.preferred_game; packet << static_cast<u32>(members.size()); { std::lock_guard<std::mutex> lock(member_mutex); for (const auto& member : members) { packet << member.nickname; packet << member.mac_address; packet << member.game_info.name; packet << member.game_info.id; } } ENetPacket* enet_packet = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_host_broadcast(server, 0, enet_packet); enet_host_flush(server); }
void CAudioPin::JoinAudioBuffers(Packet* pBuffer, CDeMultiplexer* pDemuxer) { if (pBuffer->pmt) { // Currently only uncompressed PCM audio is supported if (pBuffer->pmt->subtype == MEDIASUBTYPE_PCM) { //LogDebug("aud: Joinig Audio Buffers"); WAVEFORMATEXTENSIBLE* wfe = (WAVEFORMATEXTENSIBLE*)pBuffer->pmt->pbFormat; WAVEFORMATEX* wf = (WAVEFORMATEX*)wfe; // Assuming all packets in the stream are the same size int packetSize = pBuffer->GetDataSize(); int maxDurationInBytes = wf->nAvgBytesPerSec / 10; // max 100 ms buffer while (true) { if ((MAX_BUFFER_SIZE - pBuffer->GetDataSize() >= packetSize ) && (maxDurationInBytes >= pBuffer->GetDataSize() + packetSize)) { Packet* buf = pDemuxer->GetAudio(pBuffer->nPlaylist,pBuffer->nClipNumber); if (buf) { byte* data = buf->GetData(); // Skip LPCM header when copying the next buffer pBuffer->SetCount(pBuffer->GetDataSize() + buf->GetDataSize() - LPCM_HEADER_SIZE); memcpy(pBuffer->GetData()+pBuffer->GetDataSize() - (buf->GetDataSize() - LPCM_HEADER_SIZE), &data[LPCM_HEADER_SIZE], buf->GetDataSize() - LPCM_HEADER_SIZE); delete buf; } else { // No new buffer was available in the demuxer break; } } else { // buffer limit reached break; } } } } }
void Room::RoomImpl::SendJoinSuccess(ENetPeer* client, MacAddress mac_address) { Packet packet; packet << static_cast<u8>(IdJoinSuccess); packet << mac_address; ENetPacket* enet_packet = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(client, 0, enet_packet); enet_host_flush(server); }
void Room::RoomImpl::SendWrongPassword(ENetPeer* client) { Packet packet; packet << static_cast<u8>(IdWrongPassword); ENetPacket* enet_packet = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(client, 0, enet_packet); enet_host_flush(server); }
void Room::RoomImpl::SendVersionMismatch(ENetPeer* client) { Packet packet; packet << static_cast<u8>(IdVersionMismatch); packet << network_version; ENetPacket* enet_packet = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(client, 0, enet_packet); enet_host_flush(server); }
//////////////////////////////////////////////////////////// /// Send a packet of data to the host (must be connected first) //////////////////////////////////////////////////////////// Socket::Status SocketTCP::Send(Packet& PacketToSend) { // Let the packet do custom stuff before sending it PacketToSend.OnSend(); // First send the packet size Uint32 PacketSize = htonl(PacketToSend.GetDataSize()); Send(reinterpret_cast<const char*>(&PacketSize), sizeof(PacketSize)); // Send the packet data if (PacketSize > 0) { return Send(PacketToSend.GetData(), PacketToSend.GetDataSize()); } else { return Socket::Done; } }
void Room::RoomImpl::SendModBanListResponse(ENetPeer* client) { Packet packet; packet << static_cast<u8>(IdModBanListResponse); { std::lock_guard lock(ban_list_mutex); packet << username_ban_list; packet << ip_ban_list; } ENetPacket* enet_packet = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(client, 0, enet_packet); enet_host_flush(server); }
// Get a packet from the beginning of the list Packet *CPacketQueue::Get() { CAutoLock cAutoLock(this); if (m_queue.size() == 0) { return NULL; } Packet *pPacket = m_queue.front(); m_queue.pop_front(); if (pPacket) m_dataSize -= pPacket->GetDataSize(); return pPacket; }
void Room::RoomImpl::SendCloseMessage() { Packet packet; packet << static_cast<u8>(IdCloseRoom); std::lock_guard<std::mutex> lock(member_mutex); if (!members.empty()) { ENetPacket* enet_packet = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); for (auto& member : members) { enet_peer_send(member.peer, 0, enet_packet); } } enet_host_flush(server); for (auto& member : members) { enet_peer_disconnect(member.peer, 0); } }
void Room::RoomImpl::SendStatusMessage(StatusMessageTypes type, const std::string& nickname, const std::string& username) { Packet packet; packet << static_cast<u8>(IdStatusMessage); packet << static_cast<u8>(type); packet << nickname; packet << username; std::lock_guard lock(member_mutex); if (!members.empty()) { ENetPacket* enet_packet = enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); for (auto& member : members) { enet_peer_send(member.peer, 0, enet_packet); } } enet_host_flush(server); }
HRESULT CVideoPin::FillBuffer(IMediaSample* pSample) { try { Packet* buffer = NULL; do { if (m_pFilter->IsStopping() || m_demux.IsMediaChanging() || m_bFlushing || !m_bSeekDone || m_demux.m_bRebuildOngoing) { Sleep(1); return ERROR_NO_DATA; } if (m_demux.EndOfFile()) { LogDebug("vid: set EOF"); return S_FALSE; } if (m_demux.m_bVideoClipSeen || m_demux.m_bAudioRequiresRebuild && !m_demux.m_bVideoClipSeen && !m_demux.m_eAudioClipSeen->Check()) { CheckPlaybackState(); return ERROR_NO_DATA; } if (m_pCachedBuffer) { LogDebug("vid: cached fetch %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist); buffer = m_pCachedBuffer; m_pCachedBuffer = NULL; buffer->bDiscontinuity = true; if (m_bProvidePMT) { CMediaType mt(*buffer->pmt); SetMediaType(&mt); pSample->SetMediaType(&mt); m_bProvidePMT = false; } } else buffer = m_demux.GetVideo(); if (!buffer) { if (m_bFirstSample) Sleep(10); else { if (!m_bClipEndingNotified) { // Deliver end of stream notification to flush the video decoder. // This should only happen when the stream enters into paused state LogDebug("vid: FillBuffer - DeliverEndOfStream"); DeliverEndOfStream(); m_bClipEndingNotified = true; } else Sleep(10); return ERROR_NO_DATA; } } else { bool checkPlaybackState = false; { CAutoLock lock(m_section); if (buffer->nNewSegment > 0) { if ((buffer->nNewSegment & NS_NEW_CLIP) == NS_NEW_CLIP) { LogDebug("vid: Playlist changed to %d - nNewSegment: %d offset: %6.3f rtStart: %6.3f rtPlaylistTime: %6.3f", buffer->nPlaylist, buffer->nNewSegment, buffer->rtOffset / 10000000.0, buffer->rtStart / 10000000.0, buffer->rtPlaylistTime / 10000000.0); m_demux.m_bVideoClipSeen = true; m_bInitDuration = true; checkPlaybackState = true; m_bClipEndingNotified = false; if (buffer->bResuming || buffer->nNewSegment & NS_INTERRUPTED) { m_bDoFakeSeek = true; m_rtStreamOffset = buffer->rtPlaylistTime; m_bZeroTimeStream = true; m_demux.m_bAudioResetStreamPosition = true; } else m_rtStreamOffset = 0; // LAV video decoder requires an end of stream notification to be able to provide complete video frames // to downstream filters in a case where we are waiting for the audio pin to see the clip boundary as // we cannot provide yet the next clip's PMT downstream since audio stream could require a rebuild if (m_currentDecoder == CLSID_LAVVideo && (buffer->nNewSegment & NS_NEW_PLAYLIST)) { LogDebug("DeliverEndOFStream LAV Only for audio pin wait (%d,%d)", buffer->nPlaylist, buffer->nClipNumber); DeliverEndOfStream(); } } if ((buffer->nNewSegment & NS_STREAM_RESET) == NS_STREAM_RESET) m_bInitDuration = true; } if (buffer->pmt) { GUID subtype = subtype = buffer->pmt->subtype; if (buffer->pmt->subtype == FOURCCMap('1CVW') && m_VC1Override != GUID_NULL) { buffer->pmt->subtype = m_VC1Override; LogDebug("vid: FillBuffer - force VC-1 GUID"); } if (!CompareMediaTypes(buffer->pmt, &m_mt)) { LogMediaType(buffer->pmt); HRESULT hrAccept = S_FALSE; m_bProvidePMT = true; if (m_pReceiver && CheckVideoFormat(&buffer->pmt->subtype, &m_currentDecoder)) { // Currently no other video decoders than LAV seems to be compatible with // the dynamic format changes if (m_currentDecoder == CLSID_LAVVideo) hrAccept = m_pReceiver->QueryAccept(buffer->pmt); } if (hrAccept != S_OK) { CMediaType mt(*buffer->pmt); SetMediaType(&mt); LogDebug("vid: graph rebuilding required"); m_demux.m_bVideoRequiresRebuild = true; m_bZeroTimeStream = true; checkPlaybackState = true; //LogDebug("DeliverEndOFStream for rebuild (%d,%d)", buffer->nPlaylist, buffer->nClipNumber); //DeliverEndOfStream(); } else { LogDebug("vid: format change accepted"); CMediaType mt(*buffer->pmt); SetMediaType(&mt); pSample->SetMediaType(&mt); buffer->nNewSegment = 0; m_pCachedBuffer = buffer; //if (m_currentDecoder == CLSID_LAVVideo) //{ // LogDebug("DeliverEndOFStream LAV Only (%d,%d)", buffer->nPlaylist, buffer->nClipNumber); // DeliverEndOfStream(); //} return ERROR_NO_DATA; } } // comparemediatypes } } // lock ends m_rtTitleDuration = buffer->rtTitleDuration; if (checkPlaybackState) { buffer->nNewSegment = 0; m_pCachedBuffer = buffer; CheckPlaybackState(); LogDebug("vid: cached push %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist); return ERROR_NO_DATA; } bool hasTimestamp = buffer->rtStart != Packet::INVALID_TIME; REFERENCE_TIME rtCorrectedStartTime = 0; REFERENCE_TIME rtCorrectedStopTime = 0; if (hasTimestamp) { if (m_bZeroTimeStream) { m_rtStreamTimeOffset = buffer->rtStart - buffer->rtClipStartTime; m_bZeroTimeStream = false; } if (m_bDiscontinuity || buffer->bDiscontinuity) { LogDebug("vid: set discontinuity"); pSample->SetDiscontinuity(true); pSample->SetMediaType(buffer->pmt); m_bDiscontinuity = false; } rtCorrectedStartTime = buffer->rtStart - m_rtStreamTimeOffset; rtCorrectedStopTime = buffer->rtStop - m_rtStreamTimeOffset; pSample->SetTime(&rtCorrectedStartTime, &rtCorrectedStopTime); if (m_bInitDuration) { m_pFilter->SetTitleDuration(m_rtTitleDuration); m_pFilter->ResetPlaybackOffset(buffer->rtPlaylistTime - rtCorrectedStartTime); m_bInitDuration = false; } m_pFilter->OnPlaybackPositionChange(); } else // Buffer has no timestamp pSample->SetTime(NULL, NULL); pSample->SetSyncPoint(buffer->bSyncPoint); { CAutoLock lock(&m_csDeliver); if (!m_bFlushing) { BYTE* pSampleBuffer; pSample->SetActualDataLength(buffer->GetDataSize()); pSample->GetPointer(&pSampleBuffer); memcpy(pSampleBuffer, buffer->GetData(), buffer->GetDataSize()); m_bFirstSample = false; #ifdef LOG_VIDEO_PIN_SAMPLES LogDebug("vid: %6.3f corr %6.3f playlist time %6.3f clip: %d playlist: %d size: %d", buffer->rtStart / 10000000.0, rtCorrectedStartTime / 10000000.0, buffer->rtPlaylistTime / 10000000.0, buffer->nClipNumber, buffer->nPlaylist, buffer->GetCount()); #endif } else { LogDebug("vid: dropped sample as flush is active!"); return ERROR_NO_DATA; } } //static int iFrameNumber = 0; //LogMediaSample(pSample, iFrameNumber++); delete buffer; } } while (!buffer); return NOERROR; } catch(...) { LogDebug("vid: FillBuffer exception"); } return S_OK; }