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 namespace android { 30 31 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta) 32 : mIsAudio(false), 33 mFormat(meta), 34 mEOSResult(OK) { 35 const char *mime; 36 CHECK(meta->findCString(kKeyMIMEType, &mime)); 37 38 if (!strncasecmp("audio/", mime, 6)) { 39 mIsAudio = true; 40 } else { 41 CHECK(!strncasecmp("video/", mime, 6)); 42 } 43 } 44 45 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) { 46 CHECK(mFormat == NULL); 47 mFormat = meta; 48 } 49 50 AnotherPacketSource::~AnotherPacketSource() { 51 } 52 53 status_t AnotherPacketSource::start(MetaData *params) { 54 return OK; 55 } 56 57 status_t AnotherPacketSource::stop() { 58 return OK; 59 } 60 61 sp<MetaData> AnotherPacketSource::getFormat() { 62 return mFormat; 63 } 64 65 status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) { 66 buffer->clear(); 67 68 Mutex::Autolock autoLock(mLock); 69 while (mEOSResult == OK && mBuffers.empty()) { 70 mCondition.wait(mLock); 71 } 72 73 if (!mBuffers.empty()) { 74 *buffer = *mBuffers.begin(); 75 mBuffers.erase(mBuffers.begin()); 76 77 int32_t discontinuity; 78 if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) { 79 if (wasFormatChange(discontinuity)) { 80 mFormat.clear(); 81 } 82 83 return INFO_DISCONTINUITY; 84 } 85 86 return OK; 87 } 88 89 return mEOSResult; 90 } 91 92 status_t AnotherPacketSource::read( 93 MediaBuffer **out, const ReadOptions *) { 94 *out = NULL; 95 96 Mutex::Autolock autoLock(mLock); 97 while (mEOSResult == OK && mBuffers.empty()) { 98 mCondition.wait(mLock); 99 } 100 101 if (!mBuffers.empty()) { 102 const sp<ABuffer> buffer = *mBuffers.begin(); 103 mBuffers.erase(mBuffers.begin()); 104 105 int32_t discontinuity; 106 if (buffer->meta()->findInt32("discontinuity", &discontinuity)) { 107 if (wasFormatChange(discontinuity)) { 108 mFormat.clear(); 109 } 110 111 return INFO_DISCONTINUITY; 112 } else { 113 int64_t timeUs; 114 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 115 116 MediaBuffer *mediaBuffer = new MediaBuffer(buffer); 117 118 mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); 119 120 *out = mediaBuffer; 121 return OK; 122 } 123 } 124 125 return mEOSResult; 126 } 127 128 bool AnotherPacketSource::wasFormatChange( 129 int32_t discontinuityType) const { 130 if (mIsAudio) { 131 return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0; 132 } 133 134 return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0; 135 } 136 137 void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) { 138 int32_t damaged; 139 if (buffer->meta()->findInt32("damaged", &damaged) && damaged) { 140 // LOG(VERBOSE) << "discarding damaged AU"; 141 return; 142 } 143 144 int64_t timeUs; 145 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 146 LOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", timeUs, timeUs / 1E6); 147 148 Mutex::Autolock autoLock(mLock); 149 mBuffers.push_back(buffer); 150 mCondition.signal(); 151 } 152 153 void AnotherPacketSource::queueDiscontinuity( 154 ATSParser::DiscontinuityType type, 155 const sp<AMessage> &extra) { 156 Mutex::Autolock autoLock(mLock); 157 158 // Leave only discontinuities in the queue. 159 List<sp<ABuffer> >::iterator it = mBuffers.begin(); 160 while (it != mBuffers.end()) { 161 sp<ABuffer> oldBuffer = *it; 162 163 int32_t oldDiscontinuityType; 164 if (!oldBuffer->meta()->findInt32( 165 "discontinuity", &oldDiscontinuityType)) { 166 it = mBuffers.erase(it); 167 continue; 168 } 169 170 ++it; 171 } 172 173 mEOSResult = OK; 174 175 sp<ABuffer> buffer = new ABuffer(0); 176 buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type)); 177 buffer->meta()->setMessage("extra", extra); 178 179 mBuffers.push_back(buffer); 180 mCondition.signal(); 181 } 182 183 void AnotherPacketSource::signalEOS(status_t result) { 184 CHECK(result != OK); 185 186 Mutex::Autolock autoLock(mLock); 187 mEOSResult = result; 188 mCondition.signal(); 189 } 190 191 bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) { 192 Mutex::Autolock autoLock(mLock); 193 if (!mBuffers.empty()) { 194 return true; 195 } 196 197 *finalResult = mEOSResult; 198 return false; 199 } 200 201 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) { 202 *timeUs = 0; 203 204 Mutex::Autolock autoLock(mLock); 205 206 if (mBuffers.empty()) { 207 return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK; 208 } 209 210 sp<ABuffer> buffer = *mBuffers.begin(); 211 CHECK(buffer->meta()->findInt64("timeUs", timeUs)); 212 213 return OK; 214 } 215 216 } // namespace android 217