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