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