1 /* 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 32 namespace android { 33 34 NuPlayer::GenericSource::GenericSource( 35 const sp<AMessage> ¬ify, 36 const char *url, 37 const KeyedVector<String8, String8> *headers, 38 bool uidValid, 39 uid_t uid) 40 : Source(notify), 41 mDurationUs(0ll), 42 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 52 NuPlayer::GenericSource::GenericSource( 53 const sp<AMessage> ¬ify, 54 int fd, int64_t offset, int64_t length) 55 : Source(notify), 56 mDurationUs(0ll), 57 mAudioIsVorbis(false) { 58 DataSource::RegisterDefaultSniffers(); 59 60 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length); 61 62 initFromDataSource(dataSource); 63 } 64 65 void 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 106 NuPlayer::GenericSource::~GenericSource() { 107 } 108 109 void 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 129 void 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 151 status_t NuPlayer::GenericSource::feedMoreTSData() { 152 return OK; 153 } 154 155 sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) { 156 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; 157 158 if (source == NULL) { 159 return NULL; 160 } 161 162 return source->getFormat(); 163 } 164 165 status_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 185 status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) { 186 *durationUs = mDurationUs; 187 return OK; 188 } 189 190 status_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 205 void 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 285 } // namespace android 286