139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber/* 239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * Copyright (C) 2010 The Android Open Source Project 339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * 439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * you may not use this file except in compliance with the License. 639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * You may obtain a copy of the License at 739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * 839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * 1039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * Unless required by applicable law or agreed to in writing, software 1139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * See the License for the specific language governing permissions and 1439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * limitations under the License. 1539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber */ 1639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 176e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber//#define LOG_NDEBUG 0 186e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "ARTPSession" 196e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h> 206e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber 2139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ARTPSession.h" 2239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 2339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 2439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ADebug.h> 2539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/AMessage.h> 2639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/hexdump.h> 2739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 2839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <ctype.h> 2939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <arpa/inet.h> 3039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <sys/socket.h> 3139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "APacketSource.h" 3339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ARTPConnection.h" 3439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ASessionDescription.h" 3539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubernamespace android { 3739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberARTPSession::ARTPSession() 3939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber : mInitCheck(NO_INIT) { 4039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 4139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 4239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatus_t ARTPSession::setup(const sp<ASessionDescription> &desc) { 4339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_EQ(mInitCheck, (status_t)NO_INIT); 4439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 4539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mDesc = desc; 4639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 47100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mRTPConn = new ARTPConnection(ARTPConnection::kRegularlyRequestFIR); 48f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas Huber 4939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber looper()->registerHandler(mRTPConn); 5039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 5139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber for (size_t i = 1; i < mDesc->countTracks(); ++i) { 5239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber AString connection; 5339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!mDesc->findAttribute(i, "c=", &connection)) { 5439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber // No per-stream connection information, try global fallback. 5539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!mDesc->findAttribute(0, "c=", &connection)) { 5629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unable to find connection attribute."); 5739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 5839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 5939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 6039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!(connection == "IN IP4 127.0.0.1")) { 6129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("We only support localhost connections for now."); 6239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 6339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 6439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 6539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber unsigned port; 6639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!validateMediaFormat(i, &port) || (port & 1) != 0) { 6729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Invalid media format."); 6839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 6939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 7039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 7139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<APacketSource> source = new APacketSource(mDesc, i); 7239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (source->initCheck() != OK) { 7329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unsupported format."); 7439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 7539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 7639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 7739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int rtpSocket = MakeUDPSocket(port); 7839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int rtcpSocket = MakeUDPSocket(port + 1); 7939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 8039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mTracks.push(TrackInfo()); 8139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 8239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mRTPSocket = rtpSocket; 8339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mRTCPSocket = rtcpSocket; 8439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 8539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<AMessage> notify = new AMessage(kWhatAccessUnitComplete, id()); 8639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber notify->setSize("track-index", mTracks.size() - 1); 8739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 880792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mRTPConn->addStream( 890792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber rtpSocket, rtcpSocket, mDesc, i, notify, false /* injected */); 9039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 9139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource = source; 9239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 9339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 9439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mInitCheck = OK; 9539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 9639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return OK; 9739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 9839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 9939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber// static 10039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberint ARTPSession::MakeUDPSocket(unsigned port) { 10139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int s = socket(AF_INET, SOCK_DGRAM, 0); 10239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_GE(s, 0); 10339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 10439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber struct sockaddr_in addr; 10539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); 10639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber addr.sin_family = AF_INET; 10739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber addr.sin_addr.s_addr = INADDR_ANY; 10839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber addr.sin_port = htons(port); 10939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 11039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_EQ(0, bind(s, (const struct sockaddr *)&addr, sizeof(addr))); 11139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 11239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return s; 11339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 11439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 11539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberARTPSession::~ARTPSession() { 11639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 11739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 11839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 11939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource->signalEOS(UNKNOWN_ERROR); 12039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 12139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber close(info->mRTPSocket); 12239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber close(info->mRTCPSocket); 12339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 12439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 12539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 12639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPSession::onMessageReceived(const sp<AMessage> &msg) { 12739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber switch (msg->what()) { 12839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber case kWhatAccessUnitComplete: 12939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber { 130389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber int32_t firstRTCP; 131389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber if (msg->findInt32("first-rtcp", &firstRTCP)) { 132389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber // There won't be an access unit here, it's just a notification 133389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber // that the data communication worked since we got the first 134389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber // rtcp packet. 135389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber break; 136389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber } 137389636ce967af15e72817e2133907a2cb2efd1aeAndreas Huber 13839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber size_t trackIndex; 13939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 14039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 14139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int32_t eos; 14239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (msg->findInt32("eos", &eos) && eos) { 14339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 14439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 14539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber break; 14639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 14739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 1482d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber sp<ABuffer> accessUnit; 1492d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber CHECK(msg->findBuffer("access-unit", &accessUnit)); 15039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 15139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber uint64_t ntpTime; 15239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(accessUnit->meta()->findInt64( 15339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber "ntp-time", (int64_t *)&ntpTime)); 15439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 15539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 15639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 15739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber printf("access unit complete size=%d\tntp-time=0x%016llx\n", 15839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber accessUnit->size(), ntpTime); 15939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#else 160df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("access unit complete, size=%d, ntp-time=%llu", 1616e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber accessUnit->size(), ntpTime); 16239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber hexdump(accessUnit->data(), accessUnit->size()); 16339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 16439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 16539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 16639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 16739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_GE(accessUnit->size(), 5u); 16839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(!memcmp("\x00\x00\x00\x01", accessUnit->data(), 4)); 16939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber unsigned x = accessUnit->data()[4]; 17039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 171df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("access unit complete: nalType=0x%02x, nalRefIdc=0x%02x", 1726e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber x & 0x1f, (x & 0x60) >> 5); 17339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 17439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 17539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber accessUnit->meta()->setInt64("ntp-time", ntpTime); 176b186054757f4743eb9a6d6e81d262b9c7b36bec7Andreas Huber accessUnit->meta()->setInt64("timeUs", 0); 17739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 17839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 17939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int32_t damaged; 18039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (accessUnit->meta()->findInt32("damaged", &damaged) 18139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber && damaged != 0) { 182df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("ignoring damaged AU"); 18339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else 18439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 18539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber { 18639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 18739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource->queueAccessUnit(accessUnit); 18839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 18939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber break; 19039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 19139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 19239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber default: 19339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TRESPASS(); 19439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber break; 19539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 19639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 19739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 19839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberbool ARTPSession::validateMediaFormat(size_t index, unsigned *port) const { 19939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber AString format; 20039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mDesc->getFormat(index, &format); 20139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 20239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ssize_t i = format.find(" "); 20339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (i < 0) { 20439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 20539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 20639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 20739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++i; 20839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber size_t j = i; 20939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber while (isdigit(format.c_str()[j])) { 21039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++j; 21139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 21239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (format.c_str()[j] != ' ') { 21339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 21439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 21539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 21639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber AString portString(format, i, j - i); 21739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 21839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber char *end; 21939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber unsigned long x = strtoul(portString.c_str(), &end, 10); 22039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (end == portString.c_str() || *end != '\0') { 22139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 22239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 22339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 22439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (x == 0 || x > 65535) { 22539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 22639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 22739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 22839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber *port = x; 22939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 23039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return true; 23139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 23239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 23339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubersize_t ARTPSession::countTracks() { 23439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mTracks.size(); 23539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 23639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 23739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubersp<MediaSource> ARTPSession::trackAt(size_t index) { 23839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_LT(index, mTracks.size()); 23939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mTracks.editItemAt(index).mPacketSource; 24039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 24139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 24239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} // namespace android 243