void WebMediaSessionManager::clientStateDidChange(WebMediaSessionManagerClient& client, uint64_t contextId, MediaProducer::MediaStateFlags newFlags) { size_t index = find(&client, contextId); ASSERT(index != notFound); if (index == notFound) return; auto& changedClientState = m_clientState[index]; MediaProducer::MediaStateFlags oldFlags = changedClientState->flags; if (newFlags == oldFlags) return; LOG(Media, "WebMediaSessionManager::clientStateDidChange(%p + %llu) - new flags = %s, old flags = %s", &client, contextId, mediaProducerStateString(newFlags).utf8().data(), mediaProducerStateString(oldFlags).utf8().data()); changedClientState->flags = newFlags; if (!flagsAreSet(oldFlags, MediaProducer::RequiresPlaybackTargetMonitoring) && flagsAreSet(newFlags, MediaProducer::RequiresPlaybackTargetMonitoring)) scheduleDelayedTask(TargetMonitoringConfigurationTask); MediaProducer::MediaStateFlags playingToTargetFlags = MediaProducer::IsPlayingToExternalDevice | MediaProducer::IsPlayingVideo; if ((oldFlags & playingToTargetFlags) != (newFlags & playingToTargetFlags)) { if (flagsAreSet(oldFlags, MediaProducer::IsPlayingVideo) && !flagsAreSet(newFlags, MediaProducer::IsPlayingVideo) && flagsAreSet(newFlags, MediaProducer::DidPlayToEnd)) changedClientState->playedToEnd = true; scheduleDelayedTask(WatchdogTimerConfigurationTask); } if (!m_playbackTarget || !m_playbackTarget->hasActiveRoute() || !flagsAreSet(newFlags, MediaProducer::ExternalDeviceAutoPlayCandidate)) return; // Do not interrupt another element already playing to a device. for (auto& state : m_clientState) { if (state == changedClientState) continue; if (flagsAreSet(state->flags, MediaProducer::IsPlayingToExternalDevice) && flagsAreSet(state->flags, MediaProducer::IsPlayingVideo)) return; } // Do not take begin playing to the device unless playback has just started. if (!flagsAreSet(newFlags, MediaProducer::IsPlayingVideo) || flagsAreSet(oldFlags, MediaProducer::IsPlayingVideo)) return; for (auto& state : m_clientState) { if (state == changedClientState) continue; state->client.setShouldPlayToPlaybackTarget(state->contextId, false); } changedClientState->client.setShouldPlayToPlaybackTarget(changedClientState->contextId, true); if (index && m_clientState.size() > 1) std::swap(m_clientState.at(index), m_clientState.at(0)); }
void TaskScheduler::rescheduleDelayedTask(TaskToken &task, int64_t microseconds, TaskFunc *proc, void *clientData) { unscheduleDelayedTask(task); task = scheduleDelayedTask(microseconds, proc, clientData); }
void WebMediaSessionManager::removeAllPlaybackTargetPickerClients(WebMediaSessionManagerClient& client) { LOG(Media, "WebMediaSessionManager::removeAllPlaybackTargetPickerClients(%p)", &client); for (size_t i = m_clientState.size(); i > 0; --i) { if (&m_clientState[i - 1]->client == &client) m_clientState.remove(i - 1); } scheduleDelayedTask(TargetMonitoringConfigurationTask | TargetClientsConfigurationTask); }
void WebMediaSessionManager::removePlaybackTargetPickerClient(WebMediaSessionManagerClient& client, uint64_t contextId) { size_t index = find(&client, contextId); ASSERT(index != notFound); if (index == notFound) return; LOG(Media, "WebMediaSessionManager::removePlaybackTargetPickerClient(%p + %llu)", &client, contextId); m_clientState.remove(index); scheduleDelayedTask(TargetMonitoringConfigurationTask | TargetClientsConfigurationTask); }
void WebMediaSessionManager::clientStateDidChange(WebMediaSessionManagerClient& client, uint64_t contextId, MediaProducer::MediaStateFlags newFlags) { size_t index = find(&client, contextId); ASSERT(index != notFound); if (index == notFound) return; auto& changedClientState = m_clientState[index]; MediaProducer::MediaStateFlags oldFlags = changedClientState->flags; LOG(Media, "WebMediaSessionManager::clientStateDidChange(%p + %llu) - new flags = %s, old flags = %s", &client, contextId, mediaProducerStateString(newFlags).utf8().data(), mediaProducerStateString(oldFlags).utf8().data()); if (newFlags == oldFlags) return; changedClientState->flags = newFlags; if (!flagsAreSet(oldFlags, MediaProducer::RequiresPlaybackTargetMonitoring) && flagsAreSet(newFlags, MediaProducer::RequiresPlaybackTargetMonitoring)) scheduleDelayedTask(TargetMonitoringConfigurationTask); if (!m_playbackTarget || !m_playbackTarget->hasActiveRoute()) return; if (!flagsAreSet(newFlags, MediaProducer::ExternalDeviceAutoPlayCandidate) || !flagsAreSet(newFlags, MediaProducer::IsPlayingVideo)) return; // Do not interrupt another element already playing to a device. bool anotherClientHasActiveTarget = false; for (auto& state : m_clientState) { if (state == changedClientState) continue; if (flagsAreSet(state->flags, MediaProducer::IsPlayingToExternalDevice)) { if (flagsAreSet(state->flags, MediaProducer::IsPlayingVideo)) return; anotherClientHasActiveTarget = true; } } // Do not take the target if another client has it and the client reporting a state change is not playing. if (anotherClientHasActiveTarget && !flagsAreSet(newFlags, MediaProducer::IsPlayingVideo)) return; for (auto& state : m_clientState) { if (state == changedClientState) continue; state->client.setShouldPlayToPlaybackTarget(state->contextId, false); } changedClientState->client.setShouldPlayToPlaybackTarget(changedClientState->contextId, true); if (index && m_clientState.size() > 1) std::swap(m_clientState.at(index), m_clientState.at(0)); }
uint64_t WebMediaSessionManager::addPlaybackTargetPickerClient(WebMediaSessionManagerClient& client, uint64_t contextId) { size_t index = find(&client, contextId); ASSERT(index == notFound); if (index != notFound) return 0; LOG(Media, "WebMediaSessionManager::addPlaybackTargetPickerClient(%p + %llu)", &client, contextId); m_clientState.append(std::make_unique<ClientState>(client, contextId)); if (m_externalOutputDeviceAvailable || m_playbackTarget) scheduleDelayedTask(InitialConfigurationTask | TargetClientsConfigurationTask); return contextId; }
extern "C" int imp_startStream(void * p, unsigned clientSessionId, void* streamToken, TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData, unsigned short * rtpSeqNum, unsigned * rtpTimestamp) { Amino * psmss = (Amino *)p; if(psmss->fd != NULL) return -1; int curFlags = fcntl(psmss->ftcpSocketNum, F_GETFL, 0); curFlags &= ~O_NONBLOCK; fcntl(psmss->ftcpSocketNum, F_SETFL, curFlags); psmss->fd = nkn_vfs_fopen(psmss->fFileName, "rb"); if(!psmss->fd) return -1; printf("Amino::startStream\n"); psmss->ftaskToken = scheduleDelayedTask(2000, (TaskFunc*)sendNext, p); return 0; }
static void sendNext(void* firstArg) { Amino * p = (Amino *)firstArg; char buf[4096]; int xlen = 7*188; int ret; struct sockaddr_in si_other; int slen = sizeof(struct sockaddr_in); //printf("Amino::sendNext\n"); if(nkn_vfs_feof(p->fd)) { nkn_vfs_fclose(p->fd); p->fd = NULL; return; } ret = nkn_vfs_fread(buf, 1, xlen, p->fd); if(ret != xlen) { printf("nkn_vfs_fread: return len = %d, expect len = %d\n", ret, xlen); nkn_vfs_fclose(p->fd); p->fd = NULL; return; } memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = p->remote_port; si_other.sin_addr.s_addr = p->remote_ip; ret = sendto(p->udpsocket, buf, xlen, 0, (struct sockaddr *)&si_other, slen); updateRTSPCounters(ret); if(ret == -1) { printf("sendto returns %d, errno=%d\n", ret, errno); } p->ftaskToken = scheduleDelayedTask(2000, (TaskFunc*)sendNext, firstArg); }
void BasicTaskScheduler::schedulerTickTask() { scheduleDelayedTask(fMaxSchedulerGranularity, schedulerTickTask, this); }
void WebMediaSessionManager::setPlaybackTarget(Ref<MediaPlaybackTarget>&& target) { m_playbackTarget = WTF::move(target); scheduleDelayedTask(TargetClientsConfigurationTask); }