GenericSource.cpp revision dd235727a1b4e283deeb581559f99c2c8889da07
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 : Source(notify), 40 mDurationUs(0ll), 41 mAudioIsVorbis(false) { 42 DataSource::RegisterDefaultSniffers(); 43 44 sp<DataSource> dataSource = 45 DataSource::CreateFromURI(httpService, url, headers); 46 CHECK(dataSource != NULL); 47 48 initFromDataSource(dataSource); 49} 50 51NuPlayer::GenericSource::GenericSource( 52 const sp<AMessage> ¬ify, 53 int fd, int64_t offset, int64_t length) 54 : Source(notify), 55 mDurationUs(0ll), 56 mAudioIsVorbis(false) { 57 DataSource::RegisterDefaultSniffers(); 58 59 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length); 60 61 initFromDataSource(dataSource); 62} 63 64void NuPlayer::GenericSource::initFromDataSource( 65 const sp<DataSource> &dataSource) { 66 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 67 68 CHECK(extractor != NULL); 69 70 sp<MetaData> fileMeta = extractor->getMetaData(); 71 if (fileMeta != NULL) { 72 int64_t duration; 73 if (fileMeta->findInt64(kKeyDuration, &duration)) { 74 mDurationUs = duration; 75 } 76 } 77 78 for (size_t i = 0; i < extractor->countTracks(); ++i) { 79 sp<MetaData> meta = extractor->getTrackMetaData(i); 80 81 const char *mime; 82 CHECK(meta->findCString(kKeyMIMEType, &mime)); 83 84 sp<MediaSource> track = extractor->getTrack(i); 85 86 if (!strncasecmp(mime, "audio/", 6)) { 87 if (mAudioTrack.mSource == NULL) { 88 mAudioTrack.mIndex = i; 89 mAudioTrack.mSource = track; 90 91 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 92 mAudioIsVorbis = true; 93 } else { 94 mAudioIsVorbis = false; 95 } 96 } 97 } else if (!strncasecmp(mime, "video/", 6)) { 98 if (mVideoTrack.mSource == NULL) { 99 mVideoTrack.mIndex = i; 100 mVideoTrack.mSource = track; 101 } 102 } 103 104 if (track != NULL) { 105 mSources.push(track); 106 int64_t durationUs; 107 if (meta->findInt64(kKeyDuration, &durationUs)) { 108 if (durationUs > mDurationUs) { 109 mDurationUs = durationUs; 110 } 111 } 112 } 113 } 114} 115 116NuPlayer::GenericSource::~GenericSource() { 117} 118 119void NuPlayer::GenericSource::prepareAsync() { 120 if (mVideoTrack.mSource != NULL) { 121 sp<MetaData> meta = mVideoTrack.mSource->getFormat(); 122 123 int32_t width, height; 124 CHECK(meta->findInt32(kKeyWidth, &width)); 125 CHECK(meta->findInt32(kKeyHeight, &height)); 126 127 notifyVideoSizeChanged(width, height); 128 } 129 130 notifyFlagsChanged( 131 FLAG_CAN_PAUSE 132 | FLAG_CAN_SEEK_BACKWARD 133 | FLAG_CAN_SEEK_FORWARD 134 | FLAG_CAN_SEEK); 135 136 notifyPrepared(); 137} 138 139void NuPlayer::GenericSource::start() { 140 ALOGI("start"); 141 142 if (mAudioTrack.mSource != NULL) { 143 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK); 144 145 mAudioTrack.mPackets = 146 new AnotherPacketSource(mAudioTrack.mSource->getFormat()); 147 148 readBuffer(true /* audio */); 149 } 150 151 if (mVideoTrack.mSource != NULL) { 152 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK); 153 154 mVideoTrack.mPackets = 155 new AnotherPacketSource(mVideoTrack.mSource->getFormat()); 156 157 readBuffer(false /* audio */); 158 } 159} 160 161status_t NuPlayer::GenericSource::feedMoreTSData() { 162 return OK; 163} 164 165sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) { 166 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; 167 168 if (source == NULL) { 169 return NULL; 170 } 171 172 return source->getFormat(); 173} 174 175status_t NuPlayer::GenericSource::dequeueAccessUnit( 176 bool audio, sp<ABuffer> *accessUnit) { 177 Track *track = audio ? &mAudioTrack : &mVideoTrack; 178 179 if (track->mSource == NULL) { 180 return -EWOULDBLOCK; 181 } 182 183 status_t finalResult; 184 if (!track->mPackets->hasBufferAvailable(&finalResult)) { 185 return finalResult == OK ? -EWOULDBLOCK : finalResult; 186 } 187 188 status_t result = track->mPackets->dequeueAccessUnit(accessUnit); 189 190 readBuffer(audio, -1ll); 191 192 return result; 193} 194 195status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) { 196 *durationUs = mDurationUs; 197 return OK; 198} 199 200size_t NuPlayer::GenericSource::getTrackCount() const { 201 return mSources.size(); 202} 203 204sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const { 205 size_t trackCount = mSources.size(); 206 if (trackIndex >= trackCount) { 207 return NULL; 208 } 209 210 sp<AMessage> format = new AMessage(); 211 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat(); 212 213 const char *mime; 214 CHECK(meta->findCString(kKeyMIMEType, &mime)); 215 216 int32_t trackType; 217 if (!strncasecmp(mime, "video/", 6)) { 218 trackType = MEDIA_TRACK_TYPE_VIDEO; 219 } else if (!strncasecmp(mime, "audio/", 6)) { 220 trackType = MEDIA_TRACK_TYPE_AUDIO; 221 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 222 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT; 223 } else { 224 trackType = MEDIA_TRACK_TYPE_UNKNOWN; 225 } 226 format->setInt32("type", trackType); 227 228 const char *lang; 229 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 230 lang = "und"; 231 } 232 format->setString("language", lang); 233 234 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 235 format->setString("mime", mime); 236 237 int32_t isAutoselect = 1, isDefault = 0, isForced = 0; 238 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect); 239 meta->findInt32(kKeyTrackIsDefault, &isDefault); 240 meta->findInt32(kKeyTrackIsForced, &isForced); 241 242 format->setInt32("auto", !!isAutoselect); 243 format->setInt32("default", !!isDefault); 244 format->setInt32("forced", !!isForced); 245 } 246 247 return format; 248} 249 250status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) { 251 if (mVideoTrack.mSource != NULL) { 252 int64_t actualTimeUs; 253 readBuffer(false /* audio */, seekTimeUs, &actualTimeUs); 254 255 seekTimeUs = actualTimeUs; 256 } 257 258 if (mAudioTrack.mSource != NULL) { 259 readBuffer(true /* audio */, seekTimeUs); 260 } 261 262 return OK; 263} 264 265void NuPlayer::GenericSource::readBuffer( 266 bool audio, int64_t seekTimeUs, int64_t *actualTimeUs) { 267 Track *track = audio ? &mAudioTrack : &mVideoTrack; 268 CHECK(track->mSource != NULL); 269 270 if (actualTimeUs) { 271 *actualTimeUs = seekTimeUs; 272 } 273 274 MediaSource::ReadOptions options; 275 276 bool seeking = false; 277 278 if (seekTimeUs >= 0) { 279 options.setSeekTo(seekTimeUs); 280 seeking = true; 281 } 282 283 for (;;) { 284 MediaBuffer *mbuf; 285 status_t err = track->mSource->read(&mbuf, &options); 286 287 options.clearSeekTo(); 288 289 if (err == OK) { 290 size_t outLength = mbuf->range_length(); 291 292 if (audio && mAudioIsVorbis) { 293 outLength += sizeof(int32_t); 294 } 295 296 sp<ABuffer> buffer = new ABuffer(outLength); 297 298 memcpy(buffer->data(), 299 (const uint8_t *)mbuf->data() + mbuf->range_offset(), 300 mbuf->range_length()); 301 302 if (audio && mAudioIsVorbis) { 303 int32_t numPageSamples; 304 if (!mbuf->meta_data()->findInt32( 305 kKeyValidSamples, &numPageSamples)) { 306 numPageSamples = -1; 307 } 308 309 memcpy(buffer->data() + mbuf->range_length(), 310 &numPageSamples, 311 sizeof(numPageSamples)); 312 } 313 314 int64_t timeUs; 315 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 316 317 buffer->meta()->setInt64("timeUs", timeUs); 318 319 if (actualTimeUs) { 320 *actualTimeUs = timeUs; 321 } 322 323 mbuf->release(); 324 mbuf = NULL; 325 326 if (seeking) { 327 track->mPackets->queueDiscontinuity( 328 ATSParser::DISCONTINUITY_SEEK, 329 NULL, 330 true /* discard */); 331 } 332 333 track->mPackets->queueAccessUnit(buffer); 334 break; 335 } else if (err == INFO_FORMAT_CHANGED) { 336#if 0 337 track->mPackets->queueDiscontinuity( 338 ATSParser::DISCONTINUITY_FORMATCHANGE, 339 NULL, 340 false /* discard */); 341#endif 342 } else { 343 track->mPackets->signalEOS(err); 344 break; 345 } 346 } 347} 348 349} // namespace android 350