blob: b3f224d4494b3027e898d5e34b293f5653804adc [file] [log] [blame]
Andreas Huber5bc087c2010-12-23 10:27:40 -08001/*
2 * Copyright (C) 2010 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
17//#define LOG_NDEBUG 0
18#define LOG_TAG "StreamingSource"
19#include <utils/Log.h>
20
21#include "StreamingSource.h"
22
23#include "ATSParser.h"
24#include "AnotherPacketSource.h"
25#include "NuPlayerStreamListener.h"
26
27#include <media/stagefright/foundation/ABuffer.h>
28#include <media/stagefright/foundation/ADebug.h>
29#include <media/stagefright/foundation/AMessage.h>
30#include <media/stagefright/MediaSource.h>
31#include <media/stagefright/MetaData.h>
32
33namespace android {
34
Andreas Huberb5f25f02013-02-05 10:14:26 -080035NuPlayer::StreamingSource::StreamingSource(
36 const sp<AMessage> &notify,
37 const sp<IStreamSource> &source)
38 : Source(notify),
39 mSource(source),
Chong Zhang180d1b92014-12-02 18:35:35 -080040 mFinalResult(OK),
41 mBuffering(false) {
Andreas Huber5bc087c2010-12-23 10:27:40 -080042}
43
44NuPlayer::StreamingSource::~StreamingSource() {
Chong Zhang180d1b92014-12-02 18:35:35 -080045 if (mLooper != NULL) {
46 mLooper->unregisterHandler(id());
47 mLooper->stop();
48 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080049}
50
Andreas Huber9575c962013-02-05 13:59:56 -080051void NuPlayer::StreamingSource::prepareAsync() {
Chong Zhang180d1b92014-12-02 18:35:35 -080052 if (mLooper == NULL) {
53 mLooper = new ALooper;
54 mLooper->setName("streaming");
55 mLooper->start();
56
57 mLooper->registerHandler(this);
58 }
59
Chong Zhangced1c2f2014-08-08 15:22:35 -070060 notifyVideoSizeChanged();
Andreas Huber9575c962013-02-05 13:59:56 -080061 notifyFlagsChanged(0);
62 notifyPrepared();
63}
64
Andreas Huber5bc087c2010-12-23 10:27:40 -080065void NuPlayer::StreamingSource::start() {
66 mStreamListener = new NuPlayerStreamListener(mSource, 0);
Andreas Huber87f2a552012-08-31 13:55:24 -070067
68 uint32_t sourceFlags = mSource->flags();
69
70 uint32_t parserFlags = ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE;
71 if (sourceFlags & IStreamSource::kFlagAlignedVideoData) {
72 parserFlags |= ATSParser::ALIGNED_VIDEO_DATA;
73 }
74
75 mTSParser = new ATSParser(parserFlags);
Andreas Huber5bc087c2010-12-23 10:27:40 -080076
77 mStreamListener->start();
Chong Zhang180d1b92014-12-02 18:35:35 -080078
79 postReadBuffer();
Andreas Huber5bc087c2010-12-23 10:27:40 -080080}
81
Andreas Hubereac68ba2011-09-27 12:12:25 -070082status_t NuPlayer::StreamingSource::feedMoreTSData() {
Chong Zhang180d1b92014-12-02 18:35:35 -080083 return postReadBuffer();
84}
Andreas Huber5bc087c2010-12-23 10:27:40 -080085
Chong Zhang180d1b92014-12-02 18:35:35 -080086void NuPlayer::StreamingSource::onReadBuffer() {
Andreas Huber078cfcf2011-09-15 12:25:04 -070087 for (int32_t i = 0; i < 50; ++i) {
Andreas Huber5bc087c2010-12-23 10:27:40 -080088 char buffer[188];
Andreas Huber32f3cef2011-03-02 15:34:46 -080089 sp<AMessage> extra;
90 ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
Andreas Huber5bc087c2010-12-23 10:27:40 -080091
92 if (n == 0) {
Steve Blockdf64d152012-01-04 20:05:49 +000093 ALOGI("input data EOS reached.");
Andreas Huber5bc087c2010-12-23 10:27:40 -080094 mTSParser->signalEOS(ERROR_END_OF_STREAM);
Chong Zhang180d1b92014-12-02 18:35:35 -080095 setError(ERROR_END_OF_STREAM);
Andreas Huber5bc087c2010-12-23 10:27:40 -080096 break;
97 } else if (n == INFO_DISCONTINUITY) {
Wei Jiafef808d2014-10-31 17:57:05 -070098 int32_t type = ATSParser::DISCONTINUITY_TIME;
Andreas Huber42e549e2011-07-13 09:36:11 -070099
Andreas Huberbfcc8d82011-11-29 11:57:35 -0800100 int32_t mask;
Andreas Huber42e549e2011-07-13 09:36:11 -0700101 if (extra != NULL
102 && extra->findInt32(
Andreas Huberbfcc8d82011-11-29 11:57:35 -0800103 IStreamListener::kKeyDiscontinuityMask, &mask)) {
104 if (mask == 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000105 ALOGE("Client specified an illegal discontinuity type.");
Chong Zhang180d1b92014-12-02 18:35:35 -0800106 setError(ERROR_UNSUPPORTED);
107 break;
Andreas Huberbfcc8d82011-11-29 11:57:35 -0800108 }
109
110 type = mask;
Andreas Huber42e549e2011-07-13 09:36:11 -0700111 }
112
Andreas Huberbfcc8d82011-11-29 11:57:35 -0800113 mTSParser->signalDiscontinuity(
114 (ATSParser::DiscontinuityType)type, extra);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800115 } else if (n < 0) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800116 break;
117 } else {
118 if (buffer[0] == 0x00) {
119 // XXX legacy
Andreas Huberb7c8e912012-11-27 15:02:53 -0800120
121 if (extra == NULL) {
122 extra = new AMessage;
123 }
124
125 uint8_t type = buffer[1];
126
127 if (type & 2) {
128 int64_t mediaTimeUs;
129 memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs));
130
131 extra->setInt64(IStreamListener::kKeyMediaTimeUs, mediaTimeUs);
132 }
133
Andreas Huber5bc087c2010-12-23 10:27:40 -0800134 mTSParser->signalDiscontinuity(
Andreas Huberb7c8e912012-11-27 15:02:53 -0800135 ((type & 1) == 0)
Wei Jiafef808d2014-10-31 17:57:05 -0700136 ? ATSParser::DISCONTINUITY_TIME
Andreas Huber32f3cef2011-03-02 15:34:46 -0800137 : ATSParser::DISCONTINUITY_FORMATCHANGE,
138 extra);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800139 } else {
Andreas Huber06528d72011-08-31 16:29:05 -0700140 status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
141
142 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000143 ALOGE("TS Parser returned error %d", err);
Andreas Huber06528d72011-08-31 16:29:05 -0700144
145 mTSParser->signalEOS(err);
Chong Zhang180d1b92014-12-02 18:35:35 -0800146 setError(err);
Andreas Huber06528d72011-08-31 16:29:05 -0700147 break;
148 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800149 }
150 }
151 }
Chong Zhang180d1b92014-12-02 18:35:35 -0800152}
Andreas Huber5bc087c2010-12-23 10:27:40 -0800153
Chong Zhang180d1b92014-12-02 18:35:35 -0800154status_t NuPlayer::StreamingSource::postReadBuffer() {
155 {
156 Mutex::Autolock _l(mBufferingLock);
157 if (mFinalResult != OK) {
158 return mFinalResult;
159 }
160 if (mBuffering) {
161 return OK;
162 }
163 mBuffering = true;
164 }
165
166 (new AMessage(kWhatReadBuffer, id()))->post();
Andreas Hubereac68ba2011-09-27 12:12:25 -0700167 return OK;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800168}
169
Chong Zhang180d1b92014-12-02 18:35:35 -0800170bool NuPlayer::StreamingSource::haveSufficientDataOnAllTracks() {
171 // We're going to buffer at least 2 secs worth data on all tracks before
172 // starting playback (both at startup and after a seek).
173
174 static const int64_t kMinDurationUs = 2000000ll;
175
176 sp<AnotherPacketSource> audioTrack = getSource(true /*audio*/);
177 sp<AnotherPacketSource> videoTrack = getSource(false /*audio*/);
178
179 status_t err;
180 int64_t durationUs;
181 if (audioTrack != NULL
182 && (durationUs = audioTrack->getBufferedDurationUs(&err))
183 < kMinDurationUs
184 && err == OK) {
185 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
186 durationUs / 1E6);
187 return false;
188 }
189
190 if (videoTrack != NULL
191 && (durationUs = videoTrack->getBufferedDurationUs(&err))
192 < kMinDurationUs
193 && err == OK) {
194 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
195 durationUs / 1E6);
196 return false;
197 }
198
199 return true;
200}
201
202void NuPlayer::StreamingSource::setError(status_t err) {
203 Mutex::Autolock _l(mBufferingLock);
204 mFinalResult = err;
205}
206
207sp<AnotherPacketSource> NuPlayer::StreamingSource::getSource(bool audio) {
Wei Jiaab05b4c2014-12-02 09:41:21 -0800208 if (mTSParser == NULL) {
209 return NULL;
210 }
211
Chong Zhang180d1b92014-12-02 18:35:35 -0800212 sp<MediaSource> source = mTSParser->getSource(
213 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800214
Chong Zhang180d1b92014-12-02 18:35:35 -0800215 return static_cast<AnotherPacketSource *>(source.get());
216}
217
218sp<MetaData> NuPlayer::StreamingSource::getFormatMeta(bool audio) {
219 sp<AnotherPacketSource> source = getSource(audio);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800220
221 if (source == NULL) {
222 return NULL;
223 }
224
225 return source->getFormat();
226}
227
228status_t NuPlayer::StreamingSource::dequeueAccessUnit(
229 bool audio, sp<ABuffer> *accessUnit) {
Chong Zhang180d1b92014-12-02 18:35:35 -0800230 sp<AnotherPacketSource> source = getSource(audio);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800231
232 if (source == NULL) {
233 return -EWOULDBLOCK;
234 }
235
Chong Zhang180d1b92014-12-02 18:35:35 -0800236 if (!haveSufficientDataOnAllTracks()) {
237 postReadBuffer();
238 }
239
Andreas Huber5bc087c2010-12-23 10:27:40 -0800240 status_t finalResult;
241 if (!source->hasBufferAvailable(&finalResult)) {
242 return finalResult == OK ? -EWOULDBLOCK : finalResult;
243 }
244
Andreas Huber87f2a552012-08-31 13:55:24 -0700245 status_t err = source->dequeueAccessUnit(accessUnit);
246
247#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
248 if (err == OK) {
249 int64_t timeUs;
250 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
251 ALOGV("dequeueAccessUnit timeUs=%lld us", timeUs);
252 }
253#endif
254
255 return err;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800256}
257
Andreas Huberd5e56232013-03-12 11:01:43 -0700258bool NuPlayer::StreamingSource::isRealTime() const {
259 return mSource->flags() & IStreamSource::kFlagIsRealTimeData;
260}
261
Chong Zhang180d1b92014-12-02 18:35:35 -0800262void NuPlayer::StreamingSource::onMessageReceived(
263 const sp<AMessage> &msg) {
264 switch (msg->what()) {
265 case kWhatReadBuffer:
266 {
267 onReadBuffer();
268
269 {
270 Mutex::Autolock _l(mBufferingLock);
271 mBuffering = false;
272 }
273 break;
274 }
275 default:
276 {
277 TRESPASS();
278 }
279 }
280}
281
282
Andreas Huber5bc087c2010-12-23 10:27:40 -0800283} // namespace android
284