blob: b04e7a66f46f012244a031d4928a9105156cf420 [file] [log] [blame]
Andreas Huberafed0e12011-09-20 15:39:58 -07001/*
2 * Copyright (C) 2012 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#include "GenericSource.h"
18
19#include "AnotherPacketSource.h"
20
21#include <media/stagefright/foundation/ABuffer.h>
22#include <media/stagefright/foundation/ADebug.h>
23#include <media/stagefright/foundation/AMessage.h>
24#include <media/stagefright/DataSource.h>
25#include <media/stagefright/FileSource.h>
26#include <media/stagefright/MediaBuffer.h>
27#include <media/stagefright/MediaDefs.h>
28#include <media/stagefright/MediaExtractor.h>
29#include <media/stagefright/MediaSource.h>
30#include <media/stagefright/MetaData.h>
31
32namespace android {
33
34NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080035 const sp<AMessage> &notify,
Andreas Huberafed0e12011-09-20 15:39:58 -070036 const char *url,
37 const KeyedVector<String8, String8> *headers,
38 bool uidValid,
39 uid_t uid)
Andreas Huberb5f25f02013-02-05 10:14:26 -080040 : Source(notify),
41 mDurationUs(0ll),
Andreas Huberafed0e12011-09-20 15:39:58 -070042 mAudioIsVorbis(false) {
43 DataSource::RegisterDefaultSniffers();
44
45 sp<DataSource> dataSource =
46 DataSource::CreateFromURI(url, headers);
47 CHECK(dataSource != NULL);
48
49 initFromDataSource(dataSource);
50}
51
52NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080053 const sp<AMessage> &notify,
Andreas Huberafed0e12011-09-20 15:39:58 -070054 int fd, int64_t offset, int64_t length)
Andreas Huberb5f25f02013-02-05 10:14:26 -080055 : Source(notify),
56 mDurationUs(0ll),
Andreas Huberafed0e12011-09-20 15:39:58 -070057 mAudioIsVorbis(false) {
58 DataSource::RegisterDefaultSniffers();
59
60 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
61
62 initFromDataSource(dataSource);
63}
64
65void NuPlayer::GenericSource::initFromDataSource(
66 const sp<DataSource> &dataSource) {
67 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
68
69 CHECK(extractor != NULL);
70
71 for (size_t i = 0; i < extractor->countTracks(); ++i) {
72 sp<MetaData> meta = extractor->getTrackMetaData(i);
73
74 const char *mime;
75 CHECK(meta->findCString(kKeyMIMEType, &mime));
76
77 sp<MediaSource> track;
78
79 if (!strncasecmp(mime, "audio/", 6)) {
80 if (mAudioTrack.mSource == NULL) {
81 mAudioTrack.mSource = track = extractor->getTrack(i);
82
83 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
84 mAudioIsVorbis = true;
85 } else {
86 mAudioIsVorbis = false;
87 }
88 }
89 } else if (!strncasecmp(mime, "video/", 6)) {
90 if (mVideoTrack.mSource == NULL) {
91 mVideoTrack.mSource = track = extractor->getTrack(i);
92 }
93 }
94
95 if (track != NULL) {
96 int64_t durationUs;
97 if (meta->findInt64(kKeyDuration, &durationUs)) {
98 if (durationUs > mDurationUs) {
99 mDurationUs = durationUs;
100 }
101 }
102 }
103 }
104}
105
106NuPlayer::GenericSource::~GenericSource() {
107}
108
Andreas Huber9575c962013-02-05 13:59:56 -0800109void NuPlayer::GenericSource::prepareAsync() {
110 if (mVideoTrack.mSource != NULL) {
111 sp<MetaData> meta = mVideoTrack.mSource->getFormat();
112
113 int32_t width, height;
114 CHECK(meta->findInt32(kKeyWidth, &width));
115 CHECK(meta->findInt32(kKeyHeight, &height));
116
117 notifyVideoSizeChanged(width, height);
118 }
119
120 notifyFlagsChanged(
121 FLAG_CAN_PAUSE
122 | FLAG_CAN_SEEK_BACKWARD
123 | FLAG_CAN_SEEK_FORWARD
124 | FLAG_CAN_SEEK);
125
126 notifyPrepared();
127}
128
Andreas Huberafed0e12011-09-20 15:39:58 -0700129void NuPlayer::GenericSource::start() {
130 ALOGI("start");
131
132 if (mAudioTrack.mSource != NULL) {
133 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
134
135 mAudioTrack.mPackets =
136 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
137
138 readBuffer(true /* audio */);
139 }
140
141 if (mVideoTrack.mSource != NULL) {
142 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
143
144 mVideoTrack.mPackets =
145 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
146
147 readBuffer(false /* audio */);
148 }
149}
150
151status_t NuPlayer::GenericSource::feedMoreTSData() {
152 return OK;
153}
154
Andreas Huber84066782011-08-16 09:34:26 -0700155sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700156 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
157
158 if (source == NULL) {
159 return NULL;
160 }
161
162 return source->getFormat();
163}
164
165status_t NuPlayer::GenericSource::dequeueAccessUnit(
166 bool audio, sp<ABuffer> *accessUnit) {
167 Track *track = audio ? &mAudioTrack : &mVideoTrack;
168
169 if (track->mSource == NULL) {
170 return -EWOULDBLOCK;
171 }
172
173 status_t finalResult;
174 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
175 return finalResult == OK ? -EWOULDBLOCK : finalResult;
176 }
177
178 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
179
180 readBuffer(audio, -1ll);
181
182 return result;
183}
184
185status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
186 *durationUs = mDurationUs;
187 return OK;
188}
189
190status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
191 if (mVideoTrack.mSource != NULL) {
192 int64_t actualTimeUs;
193 readBuffer(false /* audio */, seekTimeUs, &actualTimeUs);
194
195 seekTimeUs = actualTimeUs;
196 }
197
198 if (mAudioTrack.mSource != NULL) {
199 readBuffer(true /* audio */, seekTimeUs);
200 }
201
202 return OK;
203}
204
205void NuPlayer::GenericSource::readBuffer(
206 bool audio, int64_t seekTimeUs, int64_t *actualTimeUs) {
207 Track *track = audio ? &mAudioTrack : &mVideoTrack;
208 CHECK(track->mSource != NULL);
209
210 if (actualTimeUs) {
211 *actualTimeUs = seekTimeUs;
212 }
213
214 MediaSource::ReadOptions options;
215
216 bool seeking = false;
217
218 if (seekTimeUs >= 0) {
219 options.setSeekTo(seekTimeUs);
220 seeking = true;
221 }
222
223 for (;;) {
224 MediaBuffer *mbuf;
225 status_t err = track->mSource->read(&mbuf, &options);
226
227 options.clearSeekTo();
228
229 if (err == OK) {
230 size_t outLength = mbuf->range_length();
231
232 if (audio && mAudioIsVorbis) {
233 outLength += sizeof(int32_t);
234 }
235
236 sp<ABuffer> buffer = new ABuffer(outLength);
237
238 memcpy(buffer->data(),
239 (const uint8_t *)mbuf->data() + mbuf->range_offset(),
240 mbuf->range_length());
241
242 if (audio && mAudioIsVorbis) {
243 int32_t numPageSamples;
244 if (!mbuf->meta_data()->findInt32(
245 kKeyValidSamples, &numPageSamples)) {
246 numPageSamples = -1;
247 }
248
249 memcpy(buffer->data() + mbuf->range_length(),
250 &numPageSamples,
251 sizeof(numPageSamples));
252 }
253
254 int64_t timeUs;
255 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
256
257 buffer->meta()->setInt64("timeUs", timeUs);
258
259 if (actualTimeUs) {
260 *actualTimeUs = timeUs;
261 }
262
263 mbuf->release();
264 mbuf = NULL;
265
266 if (seeking) {
267 track->mPackets->queueDiscontinuity(
268 ATSParser::DISCONTINUITY_SEEK, NULL);
269 }
270
271 track->mPackets->queueAccessUnit(buffer);
272 break;
273 } else if (err == INFO_FORMAT_CHANGED) {
274#if 0
275 track->mPackets->queueDiscontinuity(
276 ATSParser::DISCONTINUITY_FORMATCHANGE, NULL);
277#endif
278 } else {
279 track->mPackets->signalEOS(err);
280 break;
281 }
282 }
283}
284
Andreas Huberafed0e12011-09-20 15:39:58 -0700285} // namespace android