/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include VideoStreamGraphRtpRx::VideoStreamGraphRtpRx(BaseSessionCallback* callback, int localFd) : VideoStreamGraph(callback, localFd) { mSurface = nullptr; } VideoStreamGraphRtpRx::~VideoStreamGraphRtpRx() {} ImsMediaResult VideoStreamGraphRtpRx::create(RtpConfig* config) { IMLOGI1("[create] state[%d]", mGraphState); if (config == nullptr) { return RESULT_INVALID_PARAM; } mConfig = new VideoConfig(reinterpret_cast(config)); char localIp[MAX_IP_LEN]; uint32_t localPort = 0; ImsMediaNetworkUtil::getLocalIpPortFromSocket(mLocalFd, localIp, MAX_IP_LEN, localPort); RtpAddress localAddress(localIp, localPort); BaseNode* pNodeSocketReader = new SocketReaderNode(mCallback); pNodeSocketReader->SetMediaType(IMS_MEDIA_VIDEO); (static_cast(pNodeSocketReader))->SetLocalFd(mLocalFd); (static_cast(pNodeSocketReader))->SetLocalAddress(localAddress); (static_cast(pNodeSocketReader))->SetProtocolType(kProtocolRtp); pNodeSocketReader->SetConfig(config); AddNode(pNodeSocketReader); BaseNode* pNodeRtpDecoder = new RtpDecoderNode(mCallback); pNodeRtpDecoder->SetMediaType(IMS_MEDIA_VIDEO); pNodeRtpDecoder->SetConfig(mConfig); (static_cast(pNodeRtpDecoder))->SetLocalAddress(localAddress); AddNode(pNodeRtpDecoder); pNodeSocketReader->ConnectRearNode(pNodeRtpDecoder); BaseNode* pNodeRtpPayloadDecoder = new VideoRtpPayloadDecoderNode(mCallback); pNodeRtpPayloadDecoder->SetMediaType(IMS_MEDIA_VIDEO); pNodeRtpPayloadDecoder->SetConfig(mConfig); AddNode(pNodeRtpPayloadDecoder); pNodeRtpDecoder->ConnectRearNode(pNodeRtpPayloadDecoder); BaseNode* pNodeRenderer = new IVideoRendererNode(mCallback); pNodeRenderer->SetMediaType(IMS_MEDIA_VIDEO); pNodeRenderer->SetConfig(mConfig); AddNode(pNodeRenderer); pNodeRtpPayloadDecoder->ConnectRearNode(pNodeRenderer); setState(StreamState::kStreamStateCreated); return RESULT_SUCCESS; } ImsMediaResult VideoStreamGraphRtpRx::update(RtpConfig* config) { IMLOGI1("[update] state[%d]", mGraphState); if (config == nullptr) { return RESULT_INVALID_PARAM; } VideoConfig* pConfig = reinterpret_cast(config); if (*reinterpret_cast(mConfig) == *pConfig) { IMLOGI0("[update] no update"); return RESULT_SUCCESS; } if (mGraphState == kStreamStateWaitSurface) { setState(StreamState::kStreamStateCreated); } if (mConfig != nullptr) { delete mConfig; mConfig = nullptr; } mConfig = new VideoConfig(pConfig); if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW || mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY || mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_INACTIVE) { IMLOGI0("[update] pause RX"); return stop(); } ImsMediaResult ret = RESULT_NOT_READY; if (mGraphState == kStreamStateRunning) { mScheduler->Stop(); for (auto& node : mListNodeStarted) { if (node != nullptr) { IMLOGD1("[update] update node[%s]", node->GetNodeName()); ret = node->UpdateConfig(mConfig); if (ret != RESULT_SUCCESS) { IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret); } } } mScheduler->Start(); } else if (mGraphState == kStreamStateCreated) { for (auto& node : mListNodeToStart) { if (node != nullptr) { IMLOGD1("[update] update node[%s]", node->GetNodeName()); ret = node->UpdateConfig(mConfig); if (ret != RESULT_SUCCESS) { IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret); } } } } if (mGraphState == kStreamStateCreated && (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY || pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE)) { IMLOGI0("[update] resume RX"); return start(); } return ret; } ImsMediaResult VideoStreamGraphRtpRx::start() { IMLOGI1("[start] state[%d]", mGraphState); if (mConfig == nullptr) { return RESULT_INVALID_PARAM; } VideoConfig* pConfig = reinterpret_cast(mConfig); if (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW || pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY || mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_INACTIVE) { IMLOGI1("[start] direction[%d] no need to start", pConfig->getMediaDirection()); return RESULT_SUCCESS; } if (mSurface == nullptr) { IMLOGI2("[start] direction[%d], mode[%d], surface is not ready, wait", pConfig->getMediaDirection(), pConfig->getVideoMode()); setState(StreamState::kStreamStateWaitSurface); return RESULT_SUCCESS; } ImsMediaResult result = startNodes(); if (result != RESULT_SUCCESS) { setState(StreamState::kStreamStateCreated); mCallback->SendEvent(kImsMediaEventNotifyError, result, kStreamModeRtpRx); return result; } setState(StreamState::kStreamStateRunning); return RESULT_SUCCESS; } bool VideoStreamGraphRtpRx::setMediaQualityThreshold(MediaQualityThreshold* threshold) { if (threshold != nullptr) { BaseNode* node = findNode(kNodeIdRtpDecoder); if (node != nullptr) { RtpDecoderNode* decoder = reinterpret_cast(node); decoder->SetInactivityTimerSec(threshold->getRtpInactivityTimerMillis().empty() ? 0 : threshold->getRtpInactivityTimerMillis().front() / 1000); return true; } node = findNode(kNodeIdVideoRenderer); if (node != nullptr) { IVideoRendererNode* decoder = reinterpret_cast(node); decoder->SetPacketLossParam(threshold->getRtpPacketLossDurationMillis(), threshold->getRtpPacketLossRate().empty() ? 0 : threshold->getRtpPacketLossRate().front()); return true; } } return false; } void VideoStreamGraphRtpRx::setSurface(ANativeWindow* surface) { IMLOGD0("[setSurface]"); if (surface != nullptr) { mSurface = surface; BaseNode* node = findNode(kNodeIdVideoRenderer); if (node != nullptr) { IVideoRendererNode* renderer = reinterpret_cast(node); renderer->UpdateSurface(surface); if (getState() == StreamState::kStreamStateWaitSurface) { setState(StreamState::kStreamStateCreated); start(); } } } } bool VideoStreamGraphRtpRx::OnEvent(int32_t type, uint64_t param1, uint64_t param2) { IMLOGI3("[OnEvent] type[%d], param1[%d], param2[%d]", type, param1, param2); switch (type) { case kRequestRoundTripTimeDelayUpdate: { BaseNode* node = findNode(kNodeIdVideoRenderer); if (node != nullptr) { IVideoRendererNode* pNode = reinterpret_cast(node); pNode->UpdateRoundTripTimeDelay(param1); return true; } } break; default: break; } return false; }