1 /* 2 * Copyright (C) 2010 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 "AnotherPacketSource.h" 18 19 #include <media/stagefright/foundation/ABuffer.h> 20 #include <media/stagefright/foundation/ADebug.h> 21 #include <media/stagefright/foundation/AMessage.h> 22 #include <media/stagefright/foundation/AString.h> 23 #include <media/stagefright/foundation/hexdump.h> 24 #include <media/stagefright/MediaBuffer.h> 25 #include <media/stagefright/MediaDefs.h> 26 #include <media/stagefright/MetaData.h> 27 #include <utils/Vector.h> 28 29 namespace android { 30 31 const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs 32 33 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta) 34 : mIsAudio(false), 35 mFormat(NULL), 36 mLastQueuedTimeUs(0), 37 mEOSResult(OK), 38 mLatestEnqueuedMeta(NULL) { 39 setFormat(meta); 40 } 41 42 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) { 43 CHECK(mFormat == NULL); 44 45 mIsAudio = false; 46 47 if (meta == NULL) { 48 return; 49 } 50 51 mFormat = meta; 52 const char *mime; 53 CHECK(meta->findCString(kKeyMIMEType, &mime)); 54 55 if (!strncasecmp("audio/", mime, 6)) { 56 mIsAudio = true; 57 } else { 58 CHECK(!strncasecmp("video/", mime, 6)); 59 } 60 } 61 62 AnotherPacketSource::~AnotherPacketSource() { 63 } 64 65 status_t AnotherPacketSource::start(MetaData *params) { 66 return OK; 67 } 68 69 status_t AnotherPacketSource::stop() { 70 return OK; 71 } 72 73 sp<MetaData> AnotherPacketSource::getFormat() { 74 Mutex::Autolock autoLock(mLock); 75 if (mFormat != NULL) { 76 return mFormat; 77 } 78 79 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 80 while (it != mBuffers.end()) { 81 sp<ABuffer> buffer = *it; 82 int32_t discontinuity; 83 if (buffer->meta()->findInt32("discontinuity", &discontinuity)) { 84 break; 85 } 86 87 sp<RefBase> object; 88 if (buffer->meta()->findObject("format", &object)) { 89 return static_cast<MetaData*>(object.get()); 90 } 91 92 ++it; 93 } 94 return NULL; 95 } 96 97 status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) { 98 buffer->clear(); 99 100 Mutex::Autolock autoLock(mLock); 101 while (mEOSResult == OK && mBuffers.empty()) { 102 mCondition.wait(mLock); 103 } 104 105 if (!mBuffers.empty()) { 106 *buffer = *mBuffers.begin(); 107 mBuffers.erase(mBuffers.begin()); 108 109 int32_t discontinuity; 110 if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) { 111 if (wasFormatChange(discontinuity)) { 112 mFormat.clear(); 113 } 114 115 return INFO_DISCONTINUITY; 116 } 117 118 sp<RefBase> object; 119 if ((*buffer)->meta()->findObject("format", &object)) { 120 mFormat = static_cast<MetaData*>(object.get()); 121 } 122 123 return OK; 124 } 125 126 return mEOSResult; 127 } 128 129 status_t AnotherPacketSource::read( 130 MediaBuffer **out, const ReadOptions *) { 131 *out = NULL; 132 133 Mutex::Autolock autoLock(mLock); 134 while (mEOSResult == OK && mBuffers.empty()) { 135 mCondition.wait(mLock); 136 } 137 138 if (!mBuffers.empty()) { 139 const sp<ABuffer> buffer = *mBuffers.begin(); 140 mBuffers.erase(mBuffers.begin()); 141 142 int32_t discontinuity; 143 if (buffer->meta()->findInt32("discontinuity", &discontinuity)) { 144 if (wasFormatChange(discontinuity)) { 145 mFormat.clear(); 146 } 147 148 return INFO_DISCONTINUITY; 149 } 150 151 sp<RefBase> object; 152 if (buffer->meta()->findObject("format", &object)) { 153 mFormat = static_cast<MetaData*>(object.get()); 154 } 155 156 int64_t timeUs; 157 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 158 159 MediaBuffer *mediaBuffer = new MediaBuffer(buffer); 160 161 mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); 162 163 *out = mediaBuffer; 164 return OK; 165 } 166 167 return mEOSResult; 168 } 169 170 bool AnotherPacketSource::wasFormatChange( 171 int32_t discontinuityType) const { 172 if (mIsAudio) { 173 return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0; 174 } 175 176 return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0; 177 } 178 179 void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) { 180 int32_t damaged; 181 if (buffer->meta()->findInt32("damaged", &damaged) && damaged) { 182 // LOG(VERBOSE) << "discarding damaged AU"; 183 return; 184 } 185 186 int64_t lastQueuedTimeUs; 187 CHECK(buffer->meta()->findInt64("timeUs", &lastQueuedTimeUs)); 188 mLastQueuedTimeUs = lastQueuedTimeUs; 189 ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", mLastQueuedTimeUs, mLastQueuedTimeUs / 1E6); 190 191 Mutex::Autolock autoLock(mLock); 192 mBuffers.push_back(buffer); 193 mCondition.signal(); 194 195 if (!mLatestEnqueuedMeta.get()) { 196 mLatestEnqueuedMeta = buffer->meta(); 197 } else { 198 int64_t latestTimeUs = 0; 199 CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs)); 200 if (lastQueuedTimeUs > latestTimeUs) { 201 mLatestEnqueuedMeta = buffer->meta(); 202 } 203 } 204 } 205 206 void AnotherPacketSource::clear() { 207 Mutex::Autolock autoLock(mLock); 208 209 mBuffers.clear(); 210 mEOSResult = OK; 211 212 mFormat = NULL; 213 mLatestEnqueuedMeta = NULL; 214 } 215 216 void AnotherPacketSource::queueDiscontinuity( 217 ATSParser::DiscontinuityType type, 218 const sp<AMessage> &extra) { 219 Mutex::Autolock autoLock(mLock); 220 221 // Leave only discontinuities in the queue. 222 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 223 while (it != mBuffers.end()) { 224 sp<ABuffer> oldBuffer = *it; 225 226 int32_t oldDiscontinuityType; 227 if (!oldBuffer->meta()->findInt32( 228 "discontinuity", &oldDiscontinuityType)) { 229 it = mBuffers.erase(it); 230 continue; 231 } 232 233 ++it; 234 } 235 236 mEOSResult = OK; 237 mLastQueuedTimeUs = 0; 238 mLatestEnqueuedMeta = NULL; 239 240 sp<ABuffer> buffer = new ABuffer(0); 241 buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type)); 242 buffer->meta()->setMessage("extra", extra); 243 244 mBuffers.push_back(buffer); 245 mCondition.signal(); 246 } 247 248 void AnotherPacketSource::signalEOS(status_t result) { 249 CHECK(result != OK); 250 251 Mutex::Autolock autoLock(mLock); 252 mEOSResult = result; 253 mCondition.signal(); 254 } 255 256 bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) { 257 Mutex::Autolock autoLock(mLock); 258 if (!mBuffers.empty()) { 259 return true; 260 } 261 262 *finalResult = mEOSResult; 263 return false; 264 } 265 266 int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) { 267 Mutex::Autolock autoLock(mLock); 268 269 *finalResult = mEOSResult; 270 271 if (mBuffers.empty()) { 272 return 0; 273 } 274 275 int64_t time1 = -1; 276 int64_t time2 = -1; 277 278 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 279 while (it != mBuffers.end()) { 280 const sp<ABuffer> &buffer = *it; 281 282 int64_t timeUs; 283 if (buffer->meta()->findInt64("timeUs", &timeUs)) { 284 if (time1 < 0) { 285 time1 = timeUs; 286 } 287 288 time2 = timeUs; 289 } else { 290 // This is a discontinuity, reset everything. 291 time1 = time2 = -1; 292 } 293 294 ++it; 295 } 296 297 return time2 - time1; 298 } 299 300 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) { 301 *timeUs = 0; 302 303 Mutex::Autolock autoLock(mLock); 304 305 if (mBuffers.empty()) { 306 return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK; 307 } 308 309 sp<ABuffer> buffer = *mBuffers.begin(); 310 CHECK(buffer->meta()->findInt64("timeUs", timeUs)); 311 312 return OK; 313 } 314 315 bool AnotherPacketSource::isFinished(int64_t duration) const { 316 if (duration > 0) { 317 int64_t diff = duration - mLastQueuedTimeUs; 318 if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) { 319 ALOGV("Detecting EOS due to near end"); 320 return true; 321 } 322 } 323 return (mEOSResult != OK); 324 } 325 326 sp<AMessage> AnotherPacketSource::getLatestMeta() { 327 Mutex::Autolock autoLock(mLock); 328 return mLatestEnqueuedMeta; 329 } 330 331 } // namespace android 332