AnotherPacketSource.cpp revision b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81
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 Mutex::Autolock autoLock(mLock); 222 223 // Leave only discontinuities in the queue. 224 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 225 while (it != mBuffers.end()) { 226 sp<ABuffer> oldBuffer = *it; 227 228 int32_t oldDiscontinuityType; 229 if (!oldBuffer->meta()->findInt32( 230 "discontinuity", &oldDiscontinuityType)) { 231 it = mBuffers.erase(it); 232 continue; 233 } 234 235 ++it; 236 } 237 238 mEOSResult = OK; 239 mLastQueuedTimeUs = 0; 240 mLatestEnqueuedMeta = NULL; 241 242 sp<ABuffer> buffer = new ABuffer(0); 243 buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type)); 244 buffer->meta()->setMessage("extra", extra); 245 246 mBuffers.push_back(buffer); 247 mCondition.signal(); 248} 249 250void AnotherPacketSource::signalEOS(status_t result) { 251 CHECK(result != OK); 252 253 Mutex::Autolock autoLock(mLock); 254 mEOSResult = result; 255 mCondition.signal(); 256} 257 258bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) { 259 Mutex::Autolock autoLock(mLock); 260 if (!mBuffers.empty()) { 261 return true; 262 } 263 264 *finalResult = mEOSResult; 265 return false; 266} 267 268int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) { 269 Mutex::Autolock autoLock(mLock); 270 271 *finalResult = mEOSResult; 272 273 if (mBuffers.empty()) { 274 return 0; 275 } 276 277 int64_t time1 = -1; 278 int64_t time2 = -1; 279 280 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 281 while (it != mBuffers.end()) { 282 const sp<ABuffer> &buffer = *it; 283 284 int64_t timeUs; 285 if (buffer->meta()->findInt64("timeUs", &timeUs)) { 286 if (time1 < 0) { 287 time1 = timeUs; 288 } 289 290 time2 = timeUs; 291 } else { 292 // This is a discontinuity, reset everything. 293 time1 = time2 = -1; 294 } 295 296 ++it; 297 } 298 299 return time2 - time1; 300} 301 302status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) { 303 *timeUs = 0; 304 305 Mutex::Autolock autoLock(mLock); 306 307 if (mBuffers.empty()) { 308 return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK; 309 } 310 311 sp<ABuffer> buffer = *mBuffers.begin(); 312 CHECK(buffer->meta()->findInt64("timeUs", timeUs)); 313 314 return OK; 315} 316 317bool AnotherPacketSource::isFinished(int64_t duration) const { 318 if (duration > 0) { 319 int64_t diff = duration - mLastQueuedTimeUs; 320 if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) { 321 ALOGV("Detecting EOS due to near end"); 322 return true; 323 } 324 } 325 return (mEOSResult != OK); 326} 327 328sp<AMessage> AnotherPacketSource::getLatestMeta() { 329 Mutex::Autolock autoLock(mLock); 330 return mLatestEnqueuedMeta; 331} 332 333} // namespace android 334