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