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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "AnotherPacketSource" 19 20 #include "AnotherPacketSource.h" 21 22 #include <media/stagefright/foundation/ABuffer.h> 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/foundation/AMessage.h> 25 #include <media/stagefright/foundation/AString.h> 26 #include <media/stagefright/foundation/hexdump.h> 27 #include <media/stagefright/MediaBuffer.h> 28 #include <media/stagefright/MediaDefs.h> 29 #include <media/stagefright/MetaData.h> 30 #include <utils/Vector.h> 31 32 #include <inttypes.h> 33 34 namespace android { 35 36 const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs 37 38 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta) 39 : mIsAudio(false), 40 mIsVideo(false), 41 mFormat(NULL), 42 mLastQueuedTimeUs(0), 43 mEOSResult(OK), 44 mLatestEnqueuedMeta(NULL), 45 mLatestDequeuedMeta(NULL), 46 mQueuedDiscontinuityCount(0) { 47 setFormat(meta); 48 } 49 50 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) { 51 CHECK(mFormat == NULL); 52 53 mIsAudio = false; 54 mIsVideo = false; 55 56 if (meta == NULL) { 57 return; 58 } 59 60 mFormat = meta; 61 const char *mime; 62 CHECK(meta->findCString(kKeyMIMEType, &mime)); 63 64 if (!strncasecmp("audio/", mime, 6)) { 65 mIsAudio = true; 66 } else if (!strncasecmp("video/", mime, 6)) { 67 mIsVideo = true; 68 } else { 69 CHECK(!strncasecmp("text/", mime, 5)); 70 } 71 } 72 73 AnotherPacketSource::~AnotherPacketSource() { 74 } 75 76 status_t AnotherPacketSource::start(MetaData * /* params */) { 77 return OK; 78 } 79 80 status_t AnotherPacketSource::stop() { 81 return OK; 82 } 83 84 sp<MetaData> AnotherPacketSource::getFormat() { 85 Mutex::Autolock autoLock(mLock); 86 if (mFormat != NULL) { 87 return mFormat; 88 } 89 90 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 91 while (it != mBuffers.end()) { 92 sp<ABuffer> buffer = *it; 93 int32_t discontinuity; 94 if (buffer->meta()->findInt32("discontinuity", &discontinuity)) { 95 break; 96 } 97 98 sp<RefBase> object; 99 if (buffer->meta()->findObject("format", &object)) { 100 return mFormat = static_cast<MetaData*>(object.get()); 101 } 102 103 ++it; 104 } 105 return NULL; 106 } 107 108 status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) { 109 buffer->clear(); 110 111 Mutex::Autolock autoLock(mLock); 112 while (mEOSResult == OK && mBuffers.empty()) { 113 mCondition.wait(mLock); 114 } 115 116 if (!mBuffers.empty()) { 117 *buffer = *mBuffers.begin(); 118 mBuffers.erase(mBuffers.begin()); 119 120 int32_t discontinuity; 121 if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) { 122 if (wasFormatChange(discontinuity)) { 123 mFormat.clear(); 124 } 125 126 --mQueuedDiscontinuityCount; 127 return INFO_DISCONTINUITY; 128 } 129 130 mLatestDequeuedMeta = (*buffer)->meta()->dup(); 131 132 sp<RefBase> object; 133 if ((*buffer)->meta()->findObject("format", &object)) { 134 mFormat = static_cast<MetaData*>(object.get()); 135 } 136 137 return OK; 138 } 139 140 return mEOSResult; 141 } 142 143 status_t AnotherPacketSource::read( 144 MediaBuffer **out, const ReadOptions *) { 145 *out = NULL; 146 147 Mutex::Autolock autoLock(mLock); 148 while (mEOSResult == OK && mBuffers.empty()) { 149 mCondition.wait(mLock); 150 } 151 152 if (!mBuffers.empty()) { 153 154 const sp<ABuffer> buffer = *mBuffers.begin(); 155 mBuffers.erase(mBuffers.begin()); 156 mLatestDequeuedMeta = buffer->meta()->dup(); 157 158 int32_t discontinuity; 159 if (buffer->meta()->findInt32("discontinuity", &discontinuity)) { 160 if (wasFormatChange(discontinuity)) { 161 mFormat.clear(); 162 } 163 164 return INFO_DISCONTINUITY; 165 } 166 167 sp<RefBase> object; 168 if (buffer->meta()->findObject("format", &object)) { 169 mFormat = static_cast<MetaData*>(object.get()); 170 } 171 172 int64_t timeUs; 173 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 174 175 MediaBuffer *mediaBuffer = new MediaBuffer(buffer); 176 177 mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); 178 179 *out = mediaBuffer; 180 return OK; 181 } 182 183 return mEOSResult; 184 } 185 186 bool AnotherPacketSource::wasFormatChange( 187 int32_t discontinuityType) const { 188 if (mIsAudio) { 189 return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0; 190 } 191 192 if (mIsVideo) { 193 return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0; 194 } 195 196 return false; 197 } 198 199 void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) { 200 int32_t damaged; 201 if (buffer->meta()->findInt32("damaged", &damaged) && damaged) { 202 // LOG(VERBOSE) << "discarding damaged AU"; 203 return; 204 } 205 206 int64_t lastQueuedTimeUs; 207 CHECK(buffer->meta()->findInt64("timeUs", &lastQueuedTimeUs)); 208 mLastQueuedTimeUs = lastQueuedTimeUs; 209 ALOGV("queueAccessUnit timeUs=%" PRIi64 " us (%.2f secs)", mLastQueuedTimeUs, mLastQueuedTimeUs / 1E6); 210 211 Mutex::Autolock autoLock(mLock); 212 mBuffers.push_back(buffer); 213 mCondition.signal(); 214 215 int32_t discontinuity; 216 if (buffer->meta()->findInt32("discontinuity", &discontinuity)) { 217 ++mQueuedDiscontinuityCount; 218 } 219 220 if (mLatestEnqueuedMeta == NULL) { 221 mLatestEnqueuedMeta = buffer->meta()->dup(); 222 } else { 223 int64_t latestTimeUs = 0; 224 int64_t frameDeltaUs = 0; 225 CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs)); 226 if (lastQueuedTimeUs > latestTimeUs) { 227 mLatestEnqueuedMeta = buffer->meta()->dup(); 228 frameDeltaUs = lastQueuedTimeUs - latestTimeUs; 229 mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs); 230 } else if (!mLatestEnqueuedMeta->findInt64("durationUs", &frameDeltaUs)) { 231 // For B frames 232 frameDeltaUs = latestTimeUs - lastQueuedTimeUs; 233 mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs); 234 } 235 } 236 } 237 238 void AnotherPacketSource::clear() { 239 Mutex::Autolock autoLock(mLock); 240 241 mBuffers.clear(); 242 mEOSResult = OK; 243 mQueuedDiscontinuityCount = 0; 244 245 mFormat = NULL; 246 mLatestEnqueuedMeta = NULL; 247 } 248 249 void AnotherPacketSource::queueDiscontinuity( 250 ATSParser::DiscontinuityType type, 251 const sp<AMessage> &extra, 252 bool discard) { 253 Mutex::Autolock autoLock(mLock); 254 255 if (discard) { 256 // Leave only discontinuities in the queue. 257 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 258 while (it != mBuffers.end()) { 259 sp<ABuffer> oldBuffer = *it; 260 261 int32_t oldDiscontinuityType; 262 if (!oldBuffer->meta()->findInt32( 263 "discontinuity", &oldDiscontinuityType)) { 264 it = mBuffers.erase(it); 265 continue; 266 } 267 268 ++it; 269 } 270 } 271 272 mEOSResult = OK; 273 mLastQueuedTimeUs = 0; 274 mLatestEnqueuedMeta = NULL; 275 276 if (type == ATSParser::DISCONTINUITY_NONE) { 277 return; 278 } 279 280 ++mQueuedDiscontinuityCount; 281 sp<ABuffer> buffer = new ABuffer(0); 282 buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type)); 283 buffer->meta()->setMessage("extra", extra); 284 285 mBuffers.push_back(buffer); 286 mCondition.signal(); 287 } 288 289 void AnotherPacketSource::signalEOS(status_t result) { 290 CHECK(result != OK); 291 292 Mutex::Autolock autoLock(mLock); 293 mEOSResult = result; 294 mCondition.signal(); 295 } 296 297 bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) { 298 Mutex::Autolock autoLock(mLock); 299 if (!mBuffers.empty()) { 300 return true; 301 } 302 303 *finalResult = mEOSResult; 304 return false; 305 } 306 307 int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) { 308 Mutex::Autolock autoLock(mLock); 309 return getBufferedDurationUs_l(finalResult); 310 } 311 312 int64_t AnotherPacketSource::getBufferedDurationUs_l(status_t *finalResult) { 313 *finalResult = mEOSResult; 314 315 if (mBuffers.empty()) { 316 return 0; 317 } 318 319 int64_t time1 = -1; 320 int64_t time2 = -1; 321 int64_t durationUs = 0; 322 323 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 324 while (it != mBuffers.end()) { 325 const sp<ABuffer> &buffer = *it; 326 327 int64_t timeUs; 328 if (buffer->meta()->findInt64("timeUs", &timeUs)) { 329 if (time1 < 0 || timeUs < time1) { 330 time1 = timeUs; 331 } 332 333 if (time2 < 0 || timeUs > time2) { 334 time2 = timeUs; 335 } 336 } else { 337 // This is a discontinuity, reset everything. 338 durationUs += time2 - time1; 339 time1 = time2 = -1; 340 } 341 342 ++it; 343 } 344 345 return durationUs + (time2 - time1); 346 } 347 348 // A cheaper but less precise version of getBufferedDurationUs that we would like to use in 349 // LiveSession::dequeueAccessUnit to trigger downwards adaptation. 350 int64_t AnotherPacketSource::getEstimatedDurationUs() { 351 Mutex::Autolock autoLock(mLock); 352 if (mBuffers.empty()) { 353 return 0; 354 } 355 356 if (mQueuedDiscontinuityCount > 0) { 357 status_t finalResult; 358 return getBufferedDurationUs_l(&finalResult); 359 } 360 361 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 362 sp<ABuffer> buffer = *it; 363 364 int64_t startTimeUs; 365 buffer->meta()->findInt64("timeUs", &startTimeUs); 366 if (startTimeUs < 0) { 367 return 0; 368 } 369 370 it = mBuffers.end(); 371 --it; 372 buffer = *it; 373 374 int64_t endTimeUs; 375 buffer->meta()->findInt64("timeUs", &endTimeUs); 376 if (endTimeUs < 0) { 377 return 0; 378 } 379 380 int64_t diffUs; 381 if (endTimeUs > startTimeUs) { 382 diffUs = endTimeUs - startTimeUs; 383 } else { 384 diffUs = startTimeUs - endTimeUs; 385 } 386 return diffUs; 387 } 388 389 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) { 390 *timeUs = 0; 391 392 Mutex::Autolock autoLock(mLock); 393 394 if (mBuffers.empty()) { 395 return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK; 396 } 397 398 sp<ABuffer> buffer = *mBuffers.begin(); 399 CHECK(buffer->meta()->findInt64("timeUs", timeUs)); 400 401 return OK; 402 } 403 404 bool AnotherPacketSource::isFinished(int64_t duration) const { 405 if (duration > 0) { 406 int64_t diff = duration - mLastQueuedTimeUs; 407 if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) { 408 ALOGV("Detecting EOS due to near end"); 409 return true; 410 } 411 } 412 return (mEOSResult != OK); 413 } 414 415 sp<AMessage> AnotherPacketSource::getLatestEnqueuedMeta() { 416 Mutex::Autolock autoLock(mLock); 417 return mLatestEnqueuedMeta; 418 } 419 420 sp<AMessage> AnotherPacketSource::getLatestDequeuedMeta() { 421 Mutex::Autolock autoLock(mLock); 422 return mLatestDequeuedMeta; 423 } 424 425 } // namespace android 426