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