blob: 450fae548e8b88e82a935cd992b0abf00d3bcead [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
109void NuPlayer::GenericSource::start() {
110 ALOGI("start");
111
112 if (mAudioTrack.mSource != NULL) {
113 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
114
115 mAudioTrack.mPackets =
116 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
117
118 readBuffer(true /* audio */);
119 }
120
121 if (mVideoTrack.mSource != NULL) {
122 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
123
124 mVideoTrack.mPackets =
125 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
126
127 readBuffer(false /* audio */);
128 }
129}
130
131status_t NuPlayer::GenericSource::feedMoreTSData() {
132 return OK;
133}
134
Andreas Huber84066782011-08-16 09:34:26 -0700135sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700136 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
137
138 if (source == NULL) {
139 return NULL;
140 }
141
142 return source->getFormat();
143}
144
145status_t NuPlayer::GenericSource::dequeueAccessUnit(
146 bool audio, sp<ABuffer> *accessUnit) {
147 Track *track = audio ? &mAudioTrack : &mVideoTrack;
148
149 if (track->mSource == NULL) {
150 return -EWOULDBLOCK;
151 }
152
153 status_t finalResult;
154 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
155 return finalResult == OK ? -EWOULDBLOCK : finalResult;
156 }
157
158 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
159
160 readBuffer(audio, -1ll);
161
162 return result;
163}
164
165status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
166 *durationUs = mDurationUs;
167 return OK;
168}
169
170status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
171 if (mVideoTrack.mSource != NULL) {
172 int64_t actualTimeUs;
173 readBuffer(false /* audio */, seekTimeUs, &actualTimeUs);
174
175 seekTimeUs = actualTimeUs;
176 }
177
178 if (mAudioTrack.mSource != NULL) {
179 readBuffer(true /* audio */, seekTimeUs);
180 }
181
182 return OK;
183}
184
185void NuPlayer::GenericSource::readBuffer(
186 bool audio, int64_t seekTimeUs, int64_t *actualTimeUs) {
187 Track *track = audio ? &mAudioTrack : &mVideoTrack;
188 CHECK(track->mSource != NULL);
189
190 if (actualTimeUs) {
191 *actualTimeUs = seekTimeUs;
192 }
193
194 MediaSource::ReadOptions options;
195
196 bool seeking = false;
197
198 if (seekTimeUs >= 0) {
199 options.setSeekTo(seekTimeUs);
200 seeking = true;
201 }
202
203 for (;;) {
204 MediaBuffer *mbuf;
205 status_t err = track->mSource->read(&mbuf, &options);
206
207 options.clearSeekTo();
208
209 if (err == OK) {
210 size_t outLength = mbuf->range_length();
211
212 if (audio && mAudioIsVorbis) {
213 outLength += sizeof(int32_t);
214 }
215
216 sp<ABuffer> buffer = new ABuffer(outLength);
217
218 memcpy(buffer->data(),
219 (const uint8_t *)mbuf->data() + mbuf->range_offset(),
220 mbuf->range_length());
221
222 if (audio && mAudioIsVorbis) {
223 int32_t numPageSamples;
224 if (!mbuf->meta_data()->findInt32(
225 kKeyValidSamples, &numPageSamples)) {
226 numPageSamples = -1;
227 }
228
229 memcpy(buffer->data() + mbuf->range_length(),
230 &numPageSamples,
231 sizeof(numPageSamples));
232 }
233
234 int64_t timeUs;
235 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
236
237 buffer->meta()->setInt64("timeUs", timeUs);
238
239 if (actualTimeUs) {
240 *actualTimeUs = timeUs;
241 }
242
243 mbuf->release();
244 mbuf = NULL;
245
246 if (seeking) {
247 track->mPackets->queueDiscontinuity(
248 ATSParser::DISCONTINUITY_SEEK, NULL);
249 }
250
251 track->mPackets->queueAccessUnit(buffer);
252 break;
253 } else if (err == INFO_FORMAT_CHANGED) {
254#if 0
255 track->mPackets->queueDiscontinuity(
256 ATSParser::DISCONTINUITY_FORMATCHANGE, NULL);
257#endif
258 } else {
259 track->mPackets->signalEOS(err);
260 break;
261 }
262 }
263}
264
Andreas Huberb7c8e912012-11-27 15:02:53 -0800265uint32_t NuPlayer::GenericSource::flags() const {
266 return FLAG_SEEKABLE;
Andreas Huberafed0e12011-09-20 15:39:58 -0700267}
268
269} // namespace android