RTSPSource.cpp revision cfaeeec0900014d97e15829e0fa52f865ee4c786
1ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe/* 2ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe * Copyright (C) 2010 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4f29ed28c7b878ef28058bc730715d0d32445bc57John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy * you may not use this file except in compliance with the License. 61f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett * You may obtain a copy of the License at 71f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett * 8e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy * http://www.apache.org/licenses/LICENSE-2.0 9e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy * 10e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 15dccca44ffda4836b56a21da95a046c9708ffd49csergeyv */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 171f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett//#define LOG_NDEBUG 0 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "RTSPSource" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 203d528c403c8945cc326bb656ff0c2e11373401daRaph Levien 216ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "RTSPSource.h" 22bad99183916ba2bac6659efc8a28273e344ba511sergeyv 233d528c403c8945cc326bb656ff0c2e11373401daRaph Levien#include "AnotherPacketSource.h" 243d528c403c8945cc326bb656ff0c2e11373401daRaph Levien#include "MyHandler.h" 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/MediaDefs.h> 271abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik#include <media/stagefright/MetaData.h> 281abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik 291abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craiknamespace android { 301abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik 311abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris CraikNuPlayer::RTSPSource::RTSPSource( 321abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik const char *url, 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const KeyedVector<String8, String8> *headers, 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool uidValid, 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uid_t uid) 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : mURL(url), 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUIDValid(uidValid), 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUID(uid), 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlags(0), 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState(DISCONNECTED), 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFinalResult(OK), 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisconnectReplyID(0), 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStartingUp(true), 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSeekGeneration(0) { 458451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes if (headers) { 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mExtraHeaders = *headers; 478451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t index = 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log")); 508451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= 0) { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlags |= kFlagIncognito; 538451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 54c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck mExtraHeaders.removeItemsAt(index); 55f29ed28c7b878ef28058bc730715d0d32445bc57John Reck } 56ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck } 57ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck} 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 598451b25a4422656bbd6657a5855e69c0f4d53c74Elliott HughesNuPlayer::RTSPSource::~RTSPSource() { 604c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed if (mLooper != NULL) { 614c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed mLooper->stop(); 624c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed } 634c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed} 641103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed 651103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reedvoid NuPlayer::RTSPSource::start() { 661103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed if (mLooper == NULL) { 671103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed mLooper = new ALooper; 681103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed mLooper->setName("rtsp"); 691103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed mLooper->start(); 701103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed 711103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed mReflector = new AHandlerReflector<RTSPSource>(this); 7242a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed mLooper->registerHandler(mReflector); 7342a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7542a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed CHECK(mHandler == NULL); 768451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 77f29ed28c7b878ef28058bc730715d0d32445bc57John Reck sp<AMessage> notify = new AMessage(kWhatNotify, mReflector->id()); 78f29ed28c7b878ef28058bc730715d0d32445bc57John Reck 79f29ed28c7b878ef28058bc730715d0d32445bc57John Reck mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID); 80e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy mLooper->registerHandler(mHandler); 81f29ed28c7b878ef28058bc730715d0d32445bc57John Reck 82f29ed28c7b878ef28058bc730715d0d32445bc57John Reck CHECK_EQ(mState, (int)DISCONNECTED); 83f29ed28c7b878ef28058bc730715d0d32445bc57John Reck mState = CONNECTING; 848451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 858790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III mHandler->connect(); 868790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III} 878790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III 88f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid NuPlayer::RTSPSource::stop() { 891abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik sp<AMessage> msg = new AMessage(kWhatDisconnect, mReflector->id()); 909f58361e98be7386a4eadd3aa254e9b7d09d0a3bChris Craik 919f58361e98be7386a4eadd3aa254e9b7d09d0a3bChris Craik sp<AMessage> dummy; 929f58361e98be7386a4eadd3aa254e9b7d09d0a3bChris Craik msg->postAndAwaitResponse(&dummy); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 951f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettstatus_t NuPlayer::RTSPSource::feedMoreTSData() { 96f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wen return mFinalResult; 97f29ed28c7b878ef28058bc730715d0d32445bc57John Reck} 981abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik 99e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroysp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) { 10039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews sp<AnotherPacketSource> source = getSource(audio); 10139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews 10239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews if (source == NULL) { 10339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews return NULL; 104a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown } 10539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews 1063d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger return source->getFormat(); 1073d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger} 1083d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger 1093d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenbergerbool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() { 1103d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger // We're going to buffer at least 2 secs worth data on all tracks before 1113d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger // starting playback (both at startup and after a seek). 1123d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger 1133d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger static const int64_t kMinDurationUs = 2000000ll; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t err; 11657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III int64_t durationUs; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioTrack != NULL 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (durationUs = mAudioTrack->getBufferedDurationUs(&err)) 1191abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik < kMinDurationUs 12057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III && err == OK) { 121e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)", 122e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy durationUs / 1E6); 123e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy return false; 124e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy } 125e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy 126e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy if (mVideoTrack != NULL 127e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy && (durationUs = mVideoTrack->getBufferedDurationUs(&err)) 1281f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett < kMinDurationUs 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && err == OK) { 13012d81c49a015ed8d5ef7af2d854eee1e80472219Carl Shapiro ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)", 131f29ed28c7b878ef28058bc730715d0d32445bc57John Reck durationUs / 1E6); 1328451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes return false; 133f29ed28c7b878ef28058bc730715d0d32445bc57John Reck } 134afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy 135f29ed28c7b878ef28058bc730715d0d32445bc57John Reck return true; 136f29ed28c7b878ef28058bc730715d0d32445bc57John Reck} 137afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy 138f29ed28c7b878ef28058bc730715d0d32445bc57John Reckstatus_t NuPlayer::RTSPSource::dequeueAccessUnit( 139f29ed28c7b878ef28058bc730715d0d32445bc57John Reck bool audio, sp<ABuffer> *accessUnit) { 140f29ed28c7b878ef28058bc730715d0d32445bc57John Reck if (mStartingUp) { 141afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy if (!haveSufficientDataOnAllTracks()) { 142afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy return -EWOULDBLOCK; 143e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy } 1441f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1451f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett mStartingUp = false; 1461f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett } 1471f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1481f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett sp<AnotherPacketSource> source = getSource(audio); 1491f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (source == NULL) { 151f29ed28c7b878ef28058bc730715d0d32445bc57John Reck return -EWOULDBLOCK; 152f29ed28c7b878ef28058bc730715d0d32445bc57John Reck } 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t finalResult; 1551f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett if (!source->hasBufferAvailable(&finalResult)) { 1561f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return finalResult == OK ? -EWOULDBLOCK : finalResult; 1571f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett } 1581f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1591f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return source->dequeueAccessUnit(accessUnit); 1601f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett} 1611f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1621f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettsp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) { 1631f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett if (mTSParser != NULL) { 1641f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett sp<MediaSource> source = mTSParser->getSource( 1651f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett audio ? ATSParser::AUDIO : ATSParser::VIDEO); 1661f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1671f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return static_cast<AnotherPacketSource *>(source.get()); 1681f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett } 1691f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1701f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return audio ? mAudioTrack : mVideoTrack; 1711f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett} 1721f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1731f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettstatus_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) { 1741f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett *durationUs = 0ll; 1751f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1761f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett int64_t audioDurationUs; 1771f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett if (mAudioTrack != NULL 1781f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett && mAudioTrack->getFormat()->findInt64( 1791f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett kKeyDuration, &audioDurationUs) 1801f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett && audioDurationUs > *durationUs) { 1811f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett *durationUs = audioDurationUs; 1821f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett } 1831f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1841f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett int64_t videoDurationUs; 1851f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett if (mVideoTrack != NULL 1861f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett && mVideoTrack->getFormat()->findInt64( 1871f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett kKeyDuration, &videoDurationUs) 1881f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett && videoDurationUs > *durationUs) { 1891f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett *durationUs = videoDurationUs; 1901f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett } 1911f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1921f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return OK; 1931f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett} 1941f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 1951f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettstatus_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) { 1961f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id()); 1971f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett msg->setInt32("generation", ++mSeekGeneration); 1981f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett msg->setInt64("timeUs", seekTimeUs); 1991f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett msg->post(200000ll); 2001f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 2011f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return OK; 2021f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett} 2031f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 2041f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettvoid NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) { 2051f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett if (mState != CONNECTED) { 2061f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return; 2071f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett } 2081f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 2091f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett mState = SEEKING; 2101f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett mHandler->seek(seekTimeUs); 2111f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett} 2121f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett 2131f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettbool NuPlayer::RTSPSource::isSeekable() { 2141f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett return true; 2151f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett} 216721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews 217721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrewsvoid NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) { 218721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews if (msg->what() == kWhatDisconnect) { 219721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews uint32_t replyID; 220721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews CHECK(msg->senderAwaitsResponse(&replyID)); 221721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews 222721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews mDisconnectReplyID = replyID; 223721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews finishDisconnectIfPossible(); 224721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews return; 225721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews } else if (msg->what() == kWhatPerformSeek) { 226721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews int32_t generation; 227721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews CHECK(msg->findInt32("generation", &generation)); 228721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews 229721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews if (generation != mSeekGeneration) { 230721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews // obsolete. 231721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews return; 232721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews } 233c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed 234c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed int64_t seekTimeUs; 235c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed CHECK(msg->findInt64("timeUs", &seekTimeUs)); 236c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed 237c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed performSeek(seekTimeUs); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 240c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed 241c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed CHECK_EQ(msg->what(), (int)kWhatNotify); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2438451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes int32_t what; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CHECK(msg->findInt32("what", &what)); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2468451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes switch (what) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MyHandler::kWhatConnected: 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onConnected(); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MyHandler::kWhatDisconnected: 252c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed onDisconnected(msg); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MyHandler::kWhatSeekDone: 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = CONNECTED; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStartingUp = true; 2598451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes break; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2628451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes case MyHandler::kWhatAccessUnit: 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t trackIndex; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CHECK(msg->findSize("trackIndex", &trackIndex)); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTSParser == NULL) { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CHECK_LT(trackIndex, mTracks.size()); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CHECK_EQ(trackIndex, 0u); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 272c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed 273c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed sp<ABuffer> accessUnit; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CHECK(msg->findBuffer("accessUnit", &accessUnit)); 2758451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t damaged; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (accessUnit->meta()->findInt32("damaged", &damaged) 2788451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes && damaged) { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGI("dropping damaged access unit."); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTSParser != NULL) { 284c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed size_t offset = 0; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t err = OK; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (offset + 188 <= accessUnit->size()) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = mTSParser->feedTSPacket( 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project accessUnit->data() + offset, 188); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != OK) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2918451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset += 188; 2948451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < accessUnit->size()) { 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = ERROR_MALFORMED; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != OK) { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<AnotherPacketSource> source = getSource(false /* audio */); 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (source != NULL) { 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project source->signalEOS(err); 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project source = getSource(true /* audio */); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (source != NULL) { 308f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wen source->signalEOS(err); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TrackInfo *info = &mTracks.editItemAt(trackIndex); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 316ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe sp<AnotherPacketSource> source = info->mSource; 317 if (source != NULL) { 318 uint32_t rtpTime; 319 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)); 320 321 if (!info->mNPTMappingValid) { 322 // This is a live stream, we didn't receive any normal 323 // playtime mapping. We won't map to npt time. 324 source->queueAccessUnit(accessUnit); 325 break; 326 } 327 328 int64_t nptUs = 329 ((double)rtpTime - (double)info->mRTPTime) 330 / info->mTimeScale 331 * 1000000ll 332 + info->mNormalPlaytimeUs; 333 334 accessUnit->meta()->setInt64("timeUs", nptUs); 335 336 source->queueAccessUnit(accessUnit); 337 } 338 break; 339 } 340 341 case MyHandler::kWhatEOS: 342 { 343 int32_t finalResult; 344 CHECK(msg->findInt32("finalResult", &finalResult)); 345 CHECK_NE(finalResult, (status_t)OK); 346 347 if (mTSParser != NULL) { 348 sp<AnotherPacketSource> source = getSource(false /* audio */); 349 if (source != NULL) { 350 source->signalEOS(finalResult); 351 } 352 353 source = getSource(true /* audio */); 354 if (source != NULL) { 355 source->signalEOS(finalResult); 356 } 357 358 return; 359 } 360 361 size_t trackIndex; 362 CHECK(msg->findSize("trackIndex", &trackIndex)); 363 CHECK_LT(trackIndex, mTracks.size()); 364 365 TrackInfo *info = &mTracks.editItemAt(trackIndex); 366 sp<AnotherPacketSource> source = info->mSource; 367 if (source != NULL) { 368 source->signalEOS(finalResult); 369 } 370 371 break; 372 } 373 374 case MyHandler::kWhatSeekDiscontinuity: 375 { 376 size_t trackIndex; 377 CHECK(msg->findSize("trackIndex", &trackIndex)); 378 CHECK_LT(trackIndex, mTracks.size()); 379 380 TrackInfo *info = &mTracks.editItemAt(trackIndex); 381 sp<AnotherPacketSource> source = info->mSource; 382 if (source != NULL) { 383 source->queueDiscontinuity(ATSParser::DISCONTINUITY_SEEK, NULL); 384 } 385 386 break; 387 } 388 389 case MyHandler::kWhatNormalPlayTimeMapping: 390 { 391 size_t trackIndex; 392 CHECK(msg->findSize("trackIndex", &trackIndex)); 393 CHECK_LT(trackIndex, mTracks.size()); 394 395 uint32_t rtpTime; 396 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime)); 397 398 int64_t nptUs; 399 CHECK(msg->findInt64("nptUs", &nptUs)); 400 401 TrackInfo *info = &mTracks.editItemAt(trackIndex); 402 info->mRTPTime = rtpTime; 403 info->mNormalPlaytimeUs = nptUs; 404 info->mNPTMappingValid = true; 405 break; 406 } 407 408 default: 409 TRESPASS(); 410 } 411} 412 413void NuPlayer::RTSPSource::onConnected() { 414 CHECK(mAudioTrack == NULL); 415 CHECK(mVideoTrack == NULL); 416 417 size_t numTracks = mHandler->countTracks(); 418 for (size_t i = 0; i < numTracks; ++i) { 419 int32_t timeScale; 420 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale); 421 422 const char *mime; 423 CHECK(format->findCString(kKeyMIMEType, &mime)); 424 425 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) { 426 // Very special case for MPEG2 Transport Streams. 427 CHECK_EQ(numTracks, 1u); 428 429 mTSParser = new ATSParser; 430 return; 431 } 432 433 bool isAudio = !strncasecmp(mime, "audio/", 6); 434 bool isVideo = !strncasecmp(mime, "video/", 6); 435 436 TrackInfo info; 437 info.mTimeScale = timeScale; 438 info.mRTPTime = 0; 439 info.mNormalPlaytimeUs = 0ll; 440 info.mNPTMappingValid = false; 441 442 if ((isAudio && mAudioTrack == NULL) 443 || (isVideo && mVideoTrack == NULL)) { 444 sp<AnotherPacketSource> source = new AnotherPacketSource(format); 445 446 if (isAudio) { 447 mAudioTrack = source; 448 } else { 449 mVideoTrack = source; 450 } 451 452 info.mSource = source; 453 } 454 455 mTracks.push(info); 456 } 457 458 mState = CONNECTED; 459} 460 461void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) { 462 status_t err; 463 CHECK(msg->findInt32("result", &err)); 464 CHECK_NE(err, (status_t)OK); 465 466 mLooper->unregisterHandler(mHandler->id()); 467 mHandler.clear(); 468 469 mState = DISCONNECTED; 470 mFinalResult = err; 471 472 if (mDisconnectReplyID != 0) { 473 finishDisconnectIfPossible(); 474 } 475} 476 477void NuPlayer::RTSPSource::finishDisconnectIfPossible() { 478 if (mState != DISCONNECTED) { 479 mHandler->disconnect(); 480 return; 481 } 482 483 (new AMessage)->postReply(mDisconnectReplyID); 484 mDisconnectReplyID = 0; 485} 486 487} // namespace android 488