RTSPSource2.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. /*
  2. * Copyright 2017 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. //#define LOG_NDEBUG 0
  17. #define LOG_TAG "RTSPSource2"
  18. #include <utils/Log.h>
  19. #include "RTSPSource2.h"
  20. #include "AnotherPacketSource.h"
  21. #include "MyHandler.h"
  22. #include "SDPLoader.h"
  23. #include <media/MediaHTTPService.h>
  24. #include <media/stagefright/MediaDefs.h>
  25. #include <media/stagefright/MetaData.h>
  26. namespace android {
  27. const int64_t kNearEOSTimeoutUs = 2000000LL; // 2 secs
  28. // Default Buffer Underflow/Prepare/StartServer/Overflow Marks
  29. static const int kUnderflowMarkMs = 1000; // 1 second
  30. static const int kPrepareMarkMs = 3000; // 3 seconds
  31. //static const int kStartServerMarkMs = 5000;
  32. static const int kOverflowMarkMs = 10000; // 10 seconds
  33. NuPlayer2::RTSPSource2::RTSPSource2(
  34. const sp<AMessage> &notify,
  35. const sp<MediaHTTPService> &httpService,
  36. const char *url,
  37. const KeyedVector<String8, String8> *headers,
  38. uid_t uid,
  39. bool isSDP)
  40. : Source(notify),
  41. mHTTPService(httpService),
  42. mURL(url),
  43. mUID(uid),
  44. mFlags(0),
  45. mIsSDP(isSDP),
  46. mState(DISCONNECTED),
  47. mFinalResult(OK),
  48. mDisconnectReplyID(0),
  49. mBuffering(false),
  50. mInPreparationPhase(true),
  51. mEOSPending(false),
  52. mSeekGeneration(0),
  53. mEOSTimeoutAudio(0),
  54. mEOSTimeoutVideo(0) {
  55. mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
  56. mBufferingSettings.mResumePlaybackMarkMs = kOverflowMarkMs;
  57. if (headers) {
  58. mExtraHeaders = *headers;
  59. ssize_t index =
  60. mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
  61. if (index >= 0) {
  62. mFlags |= kFlagIncognito;
  63. mExtraHeaders.removeItemsAt(index);
  64. }
  65. }
  66. }
  67. NuPlayer2::RTSPSource2::~RTSPSource2() {
  68. if (mLooper != NULL) {
  69. mLooper->unregisterHandler(id());
  70. mLooper->stop();
  71. }
  72. }
  73. status_t NuPlayer2::RTSPSource2::getBufferingSettings(
  74. BufferingSettings* buffering /* nonnull */) {
  75. Mutex::Autolock _l(mBufferingSettingsLock);
  76. *buffering = mBufferingSettings;
  77. return OK;
  78. }
  79. status_t NuPlayer2::RTSPSource2::setBufferingSettings(const BufferingSettings& buffering) {
  80. Mutex::Autolock _l(mBufferingSettingsLock);
  81. mBufferingSettings = buffering;
  82. return OK;
  83. }
  84. // TODO: fetch data starting from |startTimeUs|
  85. void NuPlayer2::RTSPSource2::prepareAsync(int64_t /* startTimeUs */) {
  86. if (mIsSDP && mHTTPService == NULL) {
  87. notifyPrepared(BAD_VALUE);
  88. return;
  89. }
  90. if (mLooper == NULL) {
  91. mLooper = new ALooper;
  92. mLooper->setName("rtsp2");
  93. mLooper->start();
  94. mLooper->registerHandler(this);
  95. }
  96. CHECK(mHandler == NULL);
  97. CHECK(mSDPLoader == NULL);
  98. sp<AMessage> notify = new AMessage(kWhatNotify, this);
  99. CHECK_EQ(mState, (int)DISCONNECTED);
  100. mState = CONNECTING;
  101. if (mIsSDP) {
  102. mSDPLoader = new SDPLoader(notify,
  103. (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
  104. mHTTPService);
  105. mSDPLoader->load(
  106. mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
  107. } else {
  108. mHandler = new MyHandler(mURL.c_str(), notify, true /* uidValid */, mUID);
  109. mLooper->registerHandler(mHandler);
  110. mHandler->connect();
  111. }
  112. startBufferingIfNecessary();
  113. }
  114. void NuPlayer2::RTSPSource2::start() {
  115. }
  116. void NuPlayer2::RTSPSource2::stop() {
  117. if (mLooper == NULL) {
  118. return;
  119. }
  120. sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
  121. sp<AMessage> dummy;
  122. msg->postAndAwaitResponse(&dummy);
  123. }
  124. status_t NuPlayer2::RTSPSource2::feedMoreTSData() {
  125. Mutex::Autolock _l(mBufferingLock);
  126. return mFinalResult;
  127. }
  128. sp<MetaData> NuPlayer2::RTSPSource2::getFormatMeta(bool audio) {
  129. sp<AnotherPacketSource> source = getSource(audio);
  130. if (source == NULL) {
  131. return NULL;
  132. }
  133. return source->getFormat();
  134. }
  135. bool NuPlayer2::RTSPSource2::haveSufficientDataOnAllTracks() {
  136. // We're going to buffer at least 2 secs worth data on all tracks before
  137. // starting playback (both at startup and after a seek).
  138. static const int64_t kMinDurationUs = 2000000LL;
  139. int64_t mediaDurationUs = 0;
  140. getDuration(&mediaDurationUs);
  141. if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
  142. || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
  143. return true;
  144. }
  145. status_t err;
  146. int64_t durationUs;
  147. if (mAudioTrack != NULL
  148. && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
  149. < kMinDurationUs
  150. && err == OK) {
  151. ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
  152. durationUs / 1E6);
  153. return false;
  154. }
  155. if (mVideoTrack != NULL
  156. && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
  157. < kMinDurationUs
  158. && err == OK) {
  159. ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
  160. durationUs / 1E6);
  161. return false;
  162. }
  163. return true;
  164. }
  165. status_t NuPlayer2::RTSPSource2::dequeueAccessUnit(
  166. bool audio, sp<ABuffer> *accessUnit) {
  167. if (!stopBufferingIfNecessary()) {
  168. return -EWOULDBLOCK;
  169. }
  170. sp<AnotherPacketSource> source = getSource(audio);
  171. if (source == NULL) {
  172. return -EWOULDBLOCK;
  173. }
  174. status_t finalResult;
  175. if (!source->hasBufferAvailable(&finalResult)) {
  176. if (finalResult == OK) {
  177. // If other source already signaled EOS, this source should also return EOS
  178. if (sourceReachedEOS(!audio)) {
  179. return ERROR_END_OF_STREAM;
  180. }
  181. // If this source has detected near end, give it some time to retrieve more
  182. // data before returning EOS
  183. int64_t mediaDurationUs = 0;
  184. getDuration(&mediaDurationUs);
  185. if (source->isFinished(mediaDurationUs)) {
  186. int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
  187. if (eosTimeout == 0) {
  188. setEOSTimeout(audio, ALooper::GetNowUs());
  189. } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
  190. setEOSTimeout(audio, 0);
  191. return ERROR_END_OF_STREAM;
  192. }
  193. return -EWOULDBLOCK;
  194. }
  195. if (!sourceNearEOS(!audio)) {
  196. // We should not enter buffering mode
  197. // if any of the sources already have detected EOS.
  198. startBufferingIfNecessary();
  199. }
  200. return -EWOULDBLOCK;
  201. }
  202. return finalResult;
  203. }
  204. setEOSTimeout(audio, 0);
  205. return source->dequeueAccessUnit(accessUnit);
  206. }
  207. sp<AnotherPacketSource> NuPlayer2::RTSPSource2::getSource(bool audio) {
  208. if (mTSParser != NULL) {
  209. sp<MediaSource> source = mTSParser->getSource(
  210. audio ? ATSParser::AUDIO : ATSParser::VIDEO);
  211. return static_cast<AnotherPacketSource *>(source.get());
  212. }
  213. return audio ? mAudioTrack : mVideoTrack;
  214. }
  215. void NuPlayer2::RTSPSource2::setEOSTimeout(bool audio, int64_t timeout) {
  216. if (audio) {
  217. mEOSTimeoutAudio = timeout;
  218. } else {
  219. mEOSTimeoutVideo = timeout;
  220. }
  221. }
  222. status_t NuPlayer2::RTSPSource2::getDuration(int64_t *durationUs) {
  223. *durationUs = -1LL;
  224. int64_t audioDurationUs;
  225. if (mAudioTrack != NULL
  226. && mAudioTrack->getFormat()->findInt64(
  227. kKeyDuration, &audioDurationUs)
  228. && audioDurationUs > *durationUs) {
  229. *durationUs = audioDurationUs;
  230. }
  231. int64_t videoDurationUs;
  232. if (mVideoTrack != NULL
  233. && mVideoTrack->getFormat()->findInt64(
  234. kKeyDuration, &videoDurationUs)
  235. && videoDurationUs > *durationUs) {
  236. *durationUs = videoDurationUs;
  237. }
  238. return OK;
  239. }
  240. status_t NuPlayer2::RTSPSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
  241. sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
  242. msg->setInt32("generation", ++mSeekGeneration);
  243. msg->setInt64("timeUs", seekTimeUs);
  244. msg->setInt32("mode", mode);
  245. sp<AMessage> response;
  246. status_t err = msg->postAndAwaitResponse(&response);
  247. if (err == OK && response != NULL) {
  248. CHECK(response->findInt32("err", &err));
  249. }
  250. return err;
  251. }
  252. void NuPlayer2::RTSPSource2::performSeek(int64_t seekTimeUs) {
  253. if (mState != CONNECTED) {
  254. finishSeek(INVALID_OPERATION);
  255. return;
  256. }
  257. mState = SEEKING;
  258. mHandler->seek(seekTimeUs);
  259. mEOSPending = false;
  260. }
  261. void NuPlayer2::RTSPSource2::schedulePollBuffering() {
  262. sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
  263. msg->post(1000000LL); // 1 second intervals
  264. }
  265. void NuPlayer2::RTSPSource2::checkBuffering(
  266. bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
  267. size_t numTracks = mTracks.size();
  268. size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
  269. preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
  270. size_t count = numTracks;
  271. for (size_t i = 0; i < count; ++i) {
  272. status_t finalResult;
  273. TrackInfo *info = &mTracks.editItemAt(i);
  274. sp<AnotherPacketSource> src = info->mSource;
  275. if (src == NULL) {
  276. --numTracks;
  277. continue;
  278. }
  279. int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
  280. int64_t initialMarkUs;
  281. int64_t maxRebufferingMarkUs;
  282. {
  283. Mutex::Autolock _l(mBufferingSettingsLock);
  284. initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000LL;
  285. // TODO: maxRebufferingMarkUs could be larger than
  286. // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
  287. maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000LL;
  288. }
  289. // isFinished when duration is 0 checks for EOS result only
  290. if (bufferedDurationUs > initialMarkUs
  291. || src->isFinished(/* duration */ 0)) {
  292. ++preparedCount;
  293. }
  294. if (src->isFinished(/* duration */ 0)) {
  295. ++overflowCount;
  296. ++finishedCount;
  297. } else {
  298. // TODO: redefine kUnderflowMarkMs to a fair value,
  299. if (bufferedDurationUs < kUnderflowMarkMs * 1000) {
  300. ++underflowCount;
  301. }
  302. if (bufferedDurationUs > maxRebufferingMarkUs) {
  303. ++overflowCount;
  304. }
  305. int64_t startServerMarkUs =
  306. (kUnderflowMarkMs * 1000LL + maxRebufferingMarkUs) / 2;
  307. if (bufferedDurationUs < startServerMarkUs) {
  308. ++startCount;
  309. }
  310. }
  311. }
  312. *prepared = (preparedCount == numTracks);
  313. *underflow = (underflowCount > 0);
  314. *overflow = (overflowCount == numTracks);
  315. *startServer = (startCount > 0);
  316. *finished = (finishedCount > 0);
  317. }
  318. void NuPlayer2::RTSPSource2::onPollBuffering() {
  319. bool prepared, underflow, overflow, startServer, finished;
  320. checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
  321. if (prepared && mInPreparationPhase) {
  322. mInPreparationPhase = false;
  323. notifyPrepared();
  324. }
  325. if (!mInPreparationPhase && underflow) {
  326. startBufferingIfNecessary();
  327. }
  328. if (haveSufficientDataOnAllTracks()) {
  329. stopBufferingIfNecessary();
  330. }
  331. if (overflow && mHandler != NULL) {
  332. mHandler->pause();
  333. }
  334. if (startServer && mHandler != NULL) {
  335. mHandler->resume();
  336. }
  337. if (finished && mHandler != NULL) {
  338. mHandler->cancelAccessUnitTimeoutCheck();
  339. }
  340. schedulePollBuffering();
  341. }
  342. void NuPlayer2::RTSPSource2::signalSourceEOS(status_t result) {
  343. const bool audio = true;
  344. const bool video = false;
  345. sp<AnotherPacketSource> source = getSource(audio);
  346. if (source != NULL) {
  347. source->signalEOS(result);
  348. }
  349. source = getSource(video);
  350. if (source != NULL) {
  351. source->signalEOS(result);
  352. }
  353. }
  354. bool NuPlayer2::RTSPSource2::sourceReachedEOS(bool audio) {
  355. sp<AnotherPacketSource> source = getSource(audio);
  356. status_t finalResult;
  357. return (source != NULL &&
  358. !source->hasBufferAvailable(&finalResult) &&
  359. finalResult == ERROR_END_OF_STREAM);
  360. }
  361. bool NuPlayer2::RTSPSource2::sourceNearEOS(bool audio) {
  362. sp<AnotherPacketSource> source = getSource(audio);
  363. int64_t mediaDurationUs = 0;
  364. getDuration(&mediaDurationUs);
  365. return (source != NULL && source->isFinished(mediaDurationUs));
  366. }
  367. void NuPlayer2::RTSPSource2::onSignalEOS(const sp<AMessage> &msg) {
  368. int32_t generation;
  369. CHECK(msg->findInt32("generation", &generation));
  370. if (generation != mSeekGeneration) {
  371. return;
  372. }
  373. if (mEOSPending) {
  374. signalSourceEOS(ERROR_END_OF_STREAM);
  375. mEOSPending = false;
  376. }
  377. }
  378. void NuPlayer2::RTSPSource2::postSourceEOSIfNecessary() {
  379. const bool audio = true;
  380. const bool video = false;
  381. // If a source has detected near end, give it some time to retrieve more
  382. // data before signaling EOS
  383. if (sourceNearEOS(audio) || sourceNearEOS(video)) {
  384. if (!mEOSPending) {
  385. sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
  386. msg->setInt32("generation", mSeekGeneration);
  387. msg->post(kNearEOSTimeoutUs);
  388. mEOSPending = true;
  389. }
  390. }
  391. }
  392. void NuPlayer2::RTSPSource2::onMessageReceived(const sp<AMessage> &msg) {
  393. if (msg->what() == kWhatDisconnect) {
  394. sp<AReplyToken> replyID;
  395. CHECK(msg->senderAwaitsResponse(&replyID));
  396. mDisconnectReplyID = replyID;
  397. finishDisconnectIfPossible();
  398. return;
  399. } else if (msg->what() == kWhatPerformSeek) {
  400. int32_t generation;
  401. CHECK(msg->findInt32("generation", &generation));
  402. CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
  403. if (generation != mSeekGeneration) {
  404. // obsolete.
  405. finishSeek(OK);
  406. return;
  407. }
  408. int64_t seekTimeUs;
  409. int32_t mode;
  410. CHECK(msg->findInt64("timeUs", &seekTimeUs));
  411. CHECK(msg->findInt32("mode", &mode));
  412. // TODO: add "mode" to performSeek.
  413. performSeek(seekTimeUs/*, (MediaPlayer2SeekMode)mode */);
  414. return;
  415. } else if (msg->what() == kWhatPollBuffering) {
  416. onPollBuffering();
  417. return;
  418. } else if (msg->what() == kWhatSignalEOS) {
  419. onSignalEOS(msg);
  420. return;
  421. }
  422. CHECK_EQ(msg->what(), kWhatNotify);
  423. int32_t what;
  424. CHECK(msg->findInt32("what", &what));
  425. switch (what) {
  426. case MyHandler::kWhatConnected:
  427. {
  428. onConnected();
  429. notifyVideoSizeChanged();
  430. uint32_t flags = 0;
  431. if (mHandler->isSeekable()) {
  432. flags = FLAG_CAN_PAUSE
  433. | FLAG_CAN_SEEK
  434. | FLAG_CAN_SEEK_BACKWARD
  435. | FLAG_CAN_SEEK_FORWARD;
  436. }
  437. notifyFlagsChanged(flags);
  438. schedulePollBuffering();
  439. break;
  440. }
  441. case MyHandler::kWhatDisconnected:
  442. {
  443. onDisconnected(msg);
  444. break;
  445. }
  446. case MyHandler::kWhatSeekDone:
  447. {
  448. mState = CONNECTED;
  449. // Unblock seekTo here in case we attempted to seek in a live stream
  450. finishSeek(OK);
  451. break;
  452. }
  453. case MyHandler::kWhatSeekPaused:
  454. {
  455. sp<AnotherPacketSource> source = getSource(true /* audio */);
  456. if (source != NULL) {
  457. source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
  458. /* extra */ NULL,
  459. /* discard */ true);
  460. }
  461. source = getSource(false /* video */);
  462. if (source != NULL) {
  463. source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
  464. /* extra */ NULL,
  465. /* discard */ true);
  466. };
  467. status_t err = OK;
  468. msg->findInt32("err", &err);
  469. if (err == OK) {
  470. int64_t timeUs;
  471. CHECK(msg->findInt64("time", &timeUs));
  472. mHandler->continueSeekAfterPause(timeUs);
  473. } else {
  474. finishSeek(err);
  475. }
  476. break;
  477. }
  478. case MyHandler::kWhatAccessUnit:
  479. {
  480. size_t trackIndex;
  481. CHECK(msg->findSize("trackIndex", &trackIndex));
  482. if (mTSParser == NULL) {
  483. CHECK_LT(trackIndex, mTracks.size());
  484. } else {
  485. CHECK_EQ(trackIndex, 0u);
  486. }
  487. sp<ABuffer> accessUnit;
  488. CHECK(msg->findBuffer("accessUnit", &accessUnit));
  489. int32_t damaged;
  490. if (accessUnit->meta()->findInt32("damaged", &damaged)
  491. && damaged) {
  492. ALOGI("dropping damaged access unit.");
  493. break;
  494. }
  495. if (mTSParser != NULL) {
  496. size_t offset = 0;
  497. status_t err = OK;
  498. while (offset + 188 <= accessUnit->size()) {
  499. err = mTSParser->feedTSPacket(
  500. accessUnit->data() + offset, 188);
  501. if (err != OK) {
  502. break;
  503. }
  504. offset += 188;
  505. }
  506. if (offset < accessUnit->size()) {
  507. err = ERROR_MALFORMED;
  508. }
  509. if (err != OK) {
  510. signalSourceEOS(err);
  511. }
  512. postSourceEOSIfNecessary();
  513. break;
  514. }
  515. TrackInfo *info = &mTracks.editItemAt(trackIndex);
  516. sp<AnotherPacketSource> source = info->mSource;
  517. if (source != NULL) {
  518. uint32_t rtpTime;
  519. CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
  520. if (!info->mNPTMappingValid) {
  521. // This is a live stream, we didn't receive any normal
  522. // playtime mapping. We won't map to npt time.
  523. source->queueAccessUnit(accessUnit);
  524. break;
  525. }
  526. int64_t nptUs =
  527. ((double)rtpTime - (double)info->mRTPTime)
  528. / info->mTimeScale
  529. * 1000000LL
  530. + info->mNormalPlaytimeUs;
  531. accessUnit->meta()->setInt64("timeUs", nptUs);
  532. source->queueAccessUnit(accessUnit);
  533. }
  534. postSourceEOSIfNecessary();
  535. break;
  536. }
  537. case MyHandler::kWhatEOS:
  538. {
  539. int32_t finalResult;
  540. CHECK(msg->findInt32("finalResult", &finalResult));
  541. CHECK_NE(finalResult, (status_t)OK);
  542. if (mTSParser != NULL) {
  543. signalSourceEOS(finalResult);
  544. }
  545. size_t trackIndex;
  546. CHECK(msg->findSize("trackIndex", &trackIndex));
  547. CHECK_LT(trackIndex, mTracks.size());
  548. TrackInfo *info = &mTracks.editItemAt(trackIndex);
  549. sp<AnotherPacketSource> source = info->mSource;
  550. if (source != NULL) {
  551. source->signalEOS(finalResult);
  552. }
  553. break;
  554. }
  555. case MyHandler::kWhatSeekDiscontinuity:
  556. {
  557. size_t trackIndex;
  558. CHECK(msg->findSize("trackIndex", &trackIndex));
  559. CHECK_LT(trackIndex, mTracks.size());
  560. TrackInfo *info = &mTracks.editItemAt(trackIndex);
  561. sp<AnotherPacketSource> source = info->mSource;
  562. if (source != NULL) {
  563. source->queueDiscontinuity(
  564. ATSParser::DISCONTINUITY_TIME,
  565. NULL,
  566. true /* discard */);
  567. }
  568. break;
  569. }
  570. case MyHandler::kWhatNormalPlayTimeMapping:
  571. {
  572. size_t trackIndex;
  573. CHECK(msg->findSize("trackIndex", &trackIndex));
  574. CHECK_LT(trackIndex, mTracks.size());
  575. uint32_t rtpTime;
  576. CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
  577. int64_t nptUs;
  578. CHECK(msg->findInt64("nptUs", &nptUs));
  579. TrackInfo *info = &mTracks.editItemAt(trackIndex);
  580. info->mRTPTime = rtpTime;
  581. info->mNormalPlaytimeUs = nptUs;
  582. info->mNPTMappingValid = true;
  583. break;
  584. }
  585. case SDPLoader::kWhatSDPLoaded:
  586. {
  587. onSDPLoaded(msg);
  588. break;
  589. }
  590. default:
  591. TRESPASS();
  592. }
  593. }
  594. void NuPlayer2::RTSPSource2::onConnected() {
  595. CHECK(mAudioTrack == NULL);
  596. CHECK(mVideoTrack == NULL);
  597. size_t numTracks = mHandler->countTracks();
  598. for (size_t i = 0; i < numTracks; ++i) {
  599. int32_t timeScale;
  600. sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
  601. const char *mime;
  602. CHECK(format->findCString(kKeyMIMEType, &mime));
  603. if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
  604. // Very special case for MPEG2 Transport Streams.
  605. CHECK_EQ(numTracks, 1u);
  606. mTSParser = new ATSParser;
  607. return;
  608. }
  609. bool isAudio = !strncasecmp(mime, "audio/", 6);
  610. bool isVideo = !strncasecmp(mime, "video/", 6);
  611. TrackInfo info;
  612. info.mTimeScale = timeScale;
  613. info.mRTPTime = 0;
  614. info.mNormalPlaytimeUs = 0LL;
  615. info.mNPTMappingValid = false;
  616. if ((isAudio && mAudioTrack == NULL)
  617. || (isVideo && mVideoTrack == NULL)) {
  618. sp<AnotherPacketSource> source = new AnotherPacketSource(format);
  619. if (isAudio) {
  620. mAudioTrack = source;
  621. } else {
  622. mVideoTrack = source;
  623. }
  624. info.mSource = source;
  625. }
  626. mTracks.push(info);
  627. }
  628. mState = CONNECTED;
  629. }
  630. void NuPlayer2::RTSPSource2::onSDPLoaded(const sp<AMessage> &msg) {
  631. status_t err;
  632. CHECK(msg->findInt32("result", &err));
  633. mSDPLoader.clear();
  634. if (mDisconnectReplyID != 0) {
  635. err = UNKNOWN_ERROR;
  636. }
  637. if (err == OK) {
  638. sp<ASessionDescription> desc;
  639. sp<RefBase> obj;
  640. CHECK(msg->findObject("description", &obj));
  641. desc = static_cast<ASessionDescription *>(obj.get());
  642. AString rtspUri;
  643. if (!desc->findAttribute(0, "a=control", &rtspUri)) {
  644. ALOGE("Unable to find url in SDP");
  645. err = UNKNOWN_ERROR;
  646. } else {
  647. sp<AMessage> notify = new AMessage(kWhatNotify, this);
  648. mHandler = new MyHandler(rtspUri.c_str(), notify, true /* uidValid */, mUID);
  649. mLooper->registerHandler(mHandler);
  650. mHandler->loadSDP(desc);
  651. }
  652. }
  653. if (err != OK) {
  654. if (mState == CONNECTING) {
  655. // We're still in the preparation phase, signal that it
  656. // failed.
  657. notifyPrepared(err);
  658. }
  659. mState = DISCONNECTED;
  660. setError(err);
  661. if (mDisconnectReplyID != 0) {
  662. finishDisconnectIfPossible();
  663. }
  664. }
  665. }
  666. void NuPlayer2::RTSPSource2::onDisconnected(const sp<AMessage> &msg) {
  667. if (mState == DISCONNECTED) {
  668. return;
  669. }
  670. status_t err;
  671. CHECK(msg->findInt32("result", &err));
  672. CHECK_NE(err, (status_t)OK);
  673. mLooper->unregisterHandler(mHandler->id());
  674. mHandler.clear();
  675. if (mState == CONNECTING) {
  676. // We're still in the preparation phase, signal that it
  677. // failed.
  678. notifyPrepared(err);
  679. }
  680. mState = DISCONNECTED;
  681. setError(err);
  682. if (mDisconnectReplyID != 0) {
  683. finishDisconnectIfPossible();
  684. }
  685. }
  686. void NuPlayer2::RTSPSource2::finishDisconnectIfPossible() {
  687. if (mState != DISCONNECTED) {
  688. if (mHandler != NULL) {
  689. mHandler->disconnect();
  690. } else if (mSDPLoader != NULL) {
  691. mSDPLoader->cancel();
  692. }
  693. return;
  694. }
  695. (new AMessage)->postReply(mDisconnectReplyID);
  696. mDisconnectReplyID = 0;
  697. }
  698. void NuPlayer2::RTSPSource2::setError(status_t err) {
  699. Mutex::Autolock _l(mBufferingLock);
  700. mFinalResult = err;
  701. }
  702. void NuPlayer2::RTSPSource2::startBufferingIfNecessary() {
  703. Mutex::Autolock _l(mBufferingLock);
  704. if (!mBuffering) {
  705. mBuffering = true;
  706. sp<AMessage> notify = dupNotify();
  707. notify->setInt32("what", kWhatPauseOnBufferingStart);
  708. notify->post();
  709. }
  710. }
  711. bool NuPlayer2::RTSPSource2::stopBufferingIfNecessary() {
  712. Mutex::Autolock _l(mBufferingLock);
  713. if (mBuffering) {
  714. if (!haveSufficientDataOnAllTracks()) {
  715. return false;
  716. }
  717. mBuffering = false;
  718. sp<AMessage> notify = dupNotify();
  719. notify->setInt32("what", kWhatResumeOnBufferingEnd);
  720. notify->post();
  721. }
  722. return true;
  723. }
  724. void NuPlayer2::RTSPSource2::finishSeek(status_t err) {
  725. if (mSeekReplyID == NULL) {
  726. return;
  727. }
  728. sp<AMessage> seekReply = new AMessage;
  729. seekReply->setInt32("err", err);
  730. seekReply->postReply(mSeekReplyID);
  731. mSeekReplyID = NULL;
  732. }
  733. } // namespace android