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