ARTPSession.cpp revision 39ddf8e0f18766f7ba1e3246b774aa6ebd93eea8
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 1739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ARTPSession.h" 1839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 1939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 2039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ADebug.h> 2139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/AMessage.h> 2239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/hexdump.h> 2339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 2439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <ctype.h> 2539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <arpa/inet.h> 2639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <sys/socket.h> 2739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 2839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "APacketSource.h" 2939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ARTPConnection.h" 3039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ASessionDescription.h" 3139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubernamespace android { 3339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberARTPSession::ARTPSession() 3539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber : mInitCheck(NO_INIT) { 3639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 3739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatus_t ARTPSession::setup(const sp<ASessionDescription> &desc) { 3939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_EQ(mInitCheck, (status_t)NO_INIT); 4039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 4139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mDesc = desc; 4239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 4339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mRTPConn = new ARTPConnection; 4439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber looper()->registerHandler(mRTPConn); 4539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 4639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber for (size_t i = 1; i < mDesc->countTracks(); ++i) { 4739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber AString connection; 4839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!mDesc->findAttribute(i, "c=", &connection)) { 4939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber // No per-stream connection information, try global fallback. 5039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!mDesc->findAttribute(0, "c=", &connection)) { 5139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(ERROR) << "Unable to find connection attribtue."; 5239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 5339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 5439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 5539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!(connection == "IN IP4 127.0.0.1")) { 5639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(ERROR) << "We only support localhost connections for now."; 5739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 5839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 5939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 6039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber unsigned port; 6139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (!validateMediaFormat(i, &port) || (port & 1) != 0) { 6239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(ERROR) << "Invalid media format."; 6339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 6439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 6539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 6639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<APacketSource> source = new APacketSource(mDesc, i); 6739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (source->initCheck() != OK) { 6839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(ERROR) << "Unsupported format."; 6939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mInitCheck; 7039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 7139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 7239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int rtpSocket = MakeUDPSocket(port); 7339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int rtcpSocket = MakeUDPSocket(port + 1); 7439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 7539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mTracks.push(TrackInfo()); 7639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 7739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mRTPSocket = rtpSocket; 7839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mRTCPSocket = rtcpSocket; 7939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 8039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<AMessage> notify = new AMessage(kWhatAccessUnitComplete, id()); 8139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber notify->setSize("track-index", mTracks.size() - 1); 8239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 8339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mRTPConn->addStream(rtpSocket, rtcpSocket, mDesc, i, notify); 8439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 8539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource = source; 8639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 8739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 8839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mInitCheck = OK; 8939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 9039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return OK; 9139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 9239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 9339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber// static 9439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberint ARTPSession::MakeUDPSocket(unsigned port) { 9539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int s = socket(AF_INET, SOCK_DGRAM, 0); 9639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_GE(s, 0); 9739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 9839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber struct sockaddr_in addr; 9939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); 10039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber addr.sin_family = AF_INET; 10139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber addr.sin_addr.s_addr = INADDR_ANY; 10239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber addr.sin_port = htons(port); 10339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 10439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_EQ(0, bind(s, (const struct sockaddr *)&addr, sizeof(addr))); 10539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 10639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return s; 10739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 10839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 10939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberARTPSession::~ARTPSession() { 11039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 11139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 11239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 11339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource->signalEOS(UNKNOWN_ERROR); 11439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 11539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber close(info->mRTPSocket); 11639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber close(info->mRTCPSocket); 11739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 11839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 11939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 12039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPSession::onMessageReceived(const sp<AMessage> &msg) { 12139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber switch (msg->what()) { 12239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber case kWhatAccessUnitComplete: 12339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber { 12439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber size_t trackIndex; 12539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 12639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 12739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int32_t eos; 12839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (msg->findInt32("eos", &eos) && eos) { 12939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 13039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 13139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber break; 13239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 13339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 13439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<RefBase> obj; 13539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(msg->findObject("access-unit", &obj)); 13639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 13739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); 13839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 13939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber uint64_t ntpTime; 14039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(accessUnit->meta()->findInt64( 14139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber "ntp-time", (int64_t *)&ntpTime)); 14239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 14339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 14439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 14539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber printf("access unit complete size=%d\tntp-time=0x%016llx\n", 14639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber accessUnit->size(), ntpTime); 14739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#else 14839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(INFO) << "access unit complete, " 14939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber << "size=" << accessUnit->size() << ", " 15039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber << "ntp-time=" << ntpTime; 15139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber hexdump(accessUnit->data(), accessUnit->size()); 15239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 15339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 15439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 15539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 15639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_GE(accessUnit->size(), 5u); 15739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(!memcmp("\x00\x00\x00\x01", accessUnit->data(), 4)); 15839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber unsigned x = accessUnit->data()[4]; 15939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 16039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(INFO) << "access unit complete: " 16139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber << StringPrintf("nalType=0x%02x, nalRefIdc=0x%02x", 16239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber x & 0x1f, (x & 0x60) >> 5); 16339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 16439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 16539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber accessUnit->meta()->setInt64("ntp-time", ntpTime); 16639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 16739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0 16839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber int32_t damaged; 16939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (accessUnit->meta()->findInt32("damaged", &damaged) 17039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber && damaged != 0) { 17139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(INFO) << "ignoring damaged AU"; 17239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else 17339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif 17439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber { 17539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 17639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource->queueAccessUnit(accessUnit); 17739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 17839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber break; 17939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 18039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 18139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber default: 18239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TRESPASS(); 18339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber break; 18439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 18539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 18639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 18739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberbool ARTPSession::validateMediaFormat(size_t index, unsigned *port) const { 18839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber AString format; 18939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mDesc->getFormat(index, &format); 19039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 19139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ssize_t i = format.find(" "); 19239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (i < 0) { 19339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 19439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 19539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 19639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++i; 19739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber size_t j = i; 19839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber while (isdigit(format.c_str()[j])) { 19939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++j; 20039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 20139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (format.c_str()[j] != ' ') { 20239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 20339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 20439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 20539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber AString portString(format, i, j - i); 20639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 20739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber char *end; 20839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber unsigned long x = strtoul(portString.c_str(), &end, 10); 20939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (end == portString.c_str() || *end != '\0') { 21039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 21139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 21239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 21339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (x == 0 || x > 65535) { 21439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return false; 21539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 21639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 21739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber *port = x; 21839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 21939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return true; 22039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 22139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 22239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubersize_t ARTPSession::countTracks() { 22339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mTracks.size(); 22439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 22539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 22639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubersp<MediaSource> ARTPSession::trackAt(size_t index) { 22739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_LT(index, mTracks.size()); 22839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mTracks.editItemAt(index).mPacketSource; 22939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 23039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 23139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} // namespace android 232