AnotherPacketSource.cpp revision f0d689934e70d3e5b3784265e890377db04c7c1d
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Copyright (C) 2010 The Android Open Source Project 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * you may not use this file except in compliance with the License. 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * You may obtain a copy of the License at 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS, 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * See the License for the specific language governing permissions and 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * limitations under the License. 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//#define LOG_NDEBUG 0 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define LOG_TAG "AnotherPacketSource" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "AnotherPacketSource.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/foundation/ABuffer.h> 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/foundation/ADebug.h> 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/foundation/AMessage.h> 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/foundation/AString.h> 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/foundation/hexdump.h> 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/MediaBuffer.h> 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/MediaDefs.h> 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <media/stagefright/MetaData.h> 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utils/Vector.h> 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <inttypes.h> 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace android { 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : mIsAudio(false), 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mIsVideo(false), 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mFormat(NULL), 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mLastQueuedTimeUs(0), 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mEOSResult(OK), 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mLatestEnqueuedMeta(NULL), 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mLatestDequeuedMeta(NULL), 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mQueuedDiscontinuityCount(0) { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) setFormat(meta); 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AnotherPacketSource::setFormat(const sp<MetaData> &meta) { 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK(mFormat == NULL); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mIsAudio = false; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mIsVideo = false; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (meta == NULL) { 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 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 73AnotherPacketSource::~AnotherPacketSource() { 74} 75 76status_t AnotherPacketSource::start(MetaData * /* params */) { 77 return OK; 78} 79 80status_t AnotherPacketSource::stop() { 81 return OK; 82} 83 84sp<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 108status_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 143status_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 186bool 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 199void 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(); 222 } else { 223 int64_t latestTimeUs = 0; 224 CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs)); 225 if (lastQueuedTimeUs > latestTimeUs) { 226 mLatestEnqueuedMeta = buffer->meta(); 227 } 228 } 229} 230 231void AnotherPacketSource::clear() { 232 Mutex::Autolock autoLock(mLock); 233 234 mBuffers.clear(); 235 mEOSResult = OK; 236 mQueuedDiscontinuityCount = 0; 237 238 mFormat = NULL; 239 mLatestEnqueuedMeta = NULL; 240} 241 242void AnotherPacketSource::queueDiscontinuity( 243 ATSParser::DiscontinuityType type, 244 const sp<AMessage> &extra, 245 bool discard) { 246 Mutex::Autolock autoLock(mLock); 247 248 if (discard) { 249 // Leave only discontinuities in the queue. 250 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 251 while (it != mBuffers.end()) { 252 sp<ABuffer> oldBuffer = *it; 253 254 int32_t oldDiscontinuityType; 255 if (!oldBuffer->meta()->findInt32( 256 "discontinuity", &oldDiscontinuityType)) { 257 it = mBuffers.erase(it); 258 continue; 259 } 260 261 ++it; 262 } 263 } 264 265 mEOSResult = OK; 266 mLastQueuedTimeUs = 0; 267 mLatestEnqueuedMeta = NULL; 268 269 if (type == ATSParser::DISCONTINUITY_NONE) { 270 return; 271 } 272 273 ++mQueuedDiscontinuityCount; 274 sp<ABuffer> buffer = new ABuffer(0); 275 buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type)); 276 buffer->meta()->setMessage("extra", extra); 277 278 mBuffers.push_back(buffer); 279 mCondition.signal(); 280} 281 282void AnotherPacketSource::signalEOS(status_t result) { 283 CHECK(result != OK); 284 285 Mutex::Autolock autoLock(mLock); 286 mEOSResult = result; 287 mCondition.signal(); 288} 289 290bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) { 291 Mutex::Autolock autoLock(mLock); 292 if (!mBuffers.empty()) { 293 return true; 294 } 295 296 *finalResult = mEOSResult; 297 return false; 298} 299 300int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) { 301 Mutex::Autolock autoLock(mLock); 302 return getBufferedDurationUs_l(finalResult); 303} 304 305int64_t AnotherPacketSource::getBufferedDurationUs_l(status_t *finalResult) { 306 *finalResult = mEOSResult; 307 308 if (mBuffers.empty()) { 309 return 0; 310 } 311 312 int64_t time1 = -1; 313 int64_t time2 = -1; 314 int64_t durationUs = 0; 315 316 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 317 while (it != mBuffers.end()) { 318 const sp<ABuffer> &buffer = *it; 319 320 int64_t timeUs; 321 if (buffer->meta()->findInt64("timeUs", &timeUs)) { 322 if (time1 < 0 || timeUs < time1) { 323 time1 = timeUs; 324 } 325 326 if (time2 < 0 || timeUs > time2) { 327 time2 = timeUs; 328 } 329 } else { 330 // This is a discontinuity, reset everything. 331 durationUs += time2 - time1; 332 time1 = time2 = -1; 333 } 334 335 ++it; 336 } 337 338 return durationUs + (time2 - time1); 339} 340 341// A cheaper but less precise version of getBufferedDurationUs that we would like to use in 342// LiveSession::dequeueAccessUnit to trigger downwards adaptation. 343int64_t AnotherPacketSource::getEstimatedDurationUs() { 344 Mutex::Autolock autoLock(mLock); 345 if (mBuffers.empty()) { 346 return 0; 347 } 348 349 if (mQueuedDiscontinuityCount > 0) { 350 status_t finalResult; 351 return getBufferedDurationUs_l(&finalResult); 352 } 353 354 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 355 sp<ABuffer> buffer = *it; 356 357 int64_t startTimeUs; 358 buffer->meta()->findInt64("timeUs", &startTimeUs); 359 if (startTimeUs < 0) { 360 return 0; 361 } 362 363 it = mBuffers.end(); 364 --it; 365 buffer = *it; 366 367 int64_t endTimeUs; 368 buffer->meta()->findInt64("timeUs", &endTimeUs); 369 if (endTimeUs < 0) { 370 return 0; 371 } 372 373 int64_t diffUs; 374 if (endTimeUs > startTimeUs) { 375 diffUs = endTimeUs - startTimeUs; 376 } else { 377 diffUs = startTimeUs - endTimeUs; 378 } 379 return diffUs; 380} 381 382status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) { 383 *timeUs = 0; 384 385 Mutex::Autolock autoLock(mLock); 386 387 if (mBuffers.empty()) { 388 return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK; 389 } 390 391 sp<ABuffer> buffer = *mBuffers.begin(); 392 CHECK(buffer->meta()->findInt64("timeUs", timeUs)); 393 394 return OK; 395} 396 397bool AnotherPacketSource::isFinished(int64_t duration) const { 398 if (duration > 0) { 399 int64_t diff = duration - mLastQueuedTimeUs; 400 if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) { 401 ALOGV("Detecting EOS due to near end"); 402 return true; 403 } 404 } 405 return (mEOSResult != OK); 406} 407 408sp<AMessage> AnotherPacketSource::getLatestEnqueuedMeta() { 409 Mutex::Autolock autoLock(mLock); 410 return mLatestEnqueuedMeta; 411} 412 413sp<AMessage> AnotherPacketSource::getLatestDequeuedMeta() { 414 Mutex::Autolock autoLock(mLock); 415 return mLatestDequeuedMeta; 416} 417 418} // namespace android 419