NuPlayerStreamListener.cpp revision f933441648ef6a71dee783d733aac17b9508b452
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 "NuPlayerStreamListener"
19#include <utils/Log.h>
20
21#include "NuPlayerStreamListener.h"
22
23#include <binder/MemoryDealer.h>
24#include <media/stagefright/foundation/ADebug.h>
25
26namespace android {
27
28NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener(
29        const sp<IStreamSource> &source,
30        ALooper::handler_id id)
31    : mSource(source),
32      mTargetID(id),
33      mEOS(false),
34      mSendDataNotification(true) {
35    mSource->setListener(this);
36
37    mMemoryDealer = new MemoryDealer(kNumBuffers * kBufferSize);
38    for (size_t i = 0; i < kNumBuffers; ++i) {
39        sp<IMemory> mem = mMemoryDealer->allocate(kBufferSize);
40        CHECK(mem != NULL);
41
42        mBuffers.push(mem);
43    }
44    mSource->setBuffers(mBuffers);
45}
46
47void NuPlayer::NuPlayerStreamListener::start() {
48    for (size_t i = 0; i < kNumBuffers; ++i) {
49        mSource->onBufferAvailable(i);
50    }
51}
52
53void NuPlayer::NuPlayerStreamListener::queueBuffer(size_t index, size_t size) {
54    QueueEntry entry;
55    entry.mIsCommand = false;
56    entry.mIndex = index;
57    entry.mSize = size;
58    entry.mOffset = 0;
59
60    Mutex::Autolock autoLock(mLock);
61    mQueue.push_back(entry);
62
63    if (mSendDataNotification) {
64        mSendDataNotification = false;
65        (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
66    }
67}
68
69void NuPlayer::NuPlayerStreamListener::issueCommand(
70        Command cmd, bool synchronous, const sp<AMessage> &extra) {
71    CHECK(!synchronous);
72
73    QueueEntry entry;
74    entry.mIsCommand = true;
75    entry.mCommand = cmd;
76    entry.mExtra = extra;
77
78    Mutex::Autolock autoLock(mLock);
79    mQueue.push_back(entry);
80
81    if (mSendDataNotification) {
82        mSendDataNotification = false;
83        (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
84    }
85}
86
87ssize_t NuPlayer::NuPlayerStreamListener::read(void *data, size_t size) {
88    CHECK_GT(size, 0u);
89
90    Mutex::Autolock autoLock(mLock);
91
92    if (mEOS) {
93        return 0;
94    }
95
96    if (mQueue.empty()) {
97        mSendDataNotification = true;
98
99        return -EWOULDBLOCK;
100    }
101
102    QueueEntry *entry = &*mQueue.begin();
103
104    if (entry->mIsCommand) {
105        switch (entry->mCommand) {
106            case EOS:
107            {
108                mQueue.erase(mQueue.begin());
109                entry = NULL;
110
111                mEOS = true;
112                return 0;
113            }
114
115            case DISCONTINUITY:
116            {
117                mQueue.erase(mQueue.begin());
118                entry = NULL;
119
120                return INFO_DISCONTINUITY;
121            }
122
123            default:
124                TRESPASS();
125                break;
126        }
127    }
128
129    size_t copy = entry->mSize;
130    if (copy > size) {
131        copy = size;
132    }
133
134    memcpy(data,
135           (const uint8_t *)mBuffers.editItemAt(entry->mIndex)->pointer()
136            + entry->mOffset,
137           copy);
138
139    entry->mOffset += copy;
140    entry->mSize -= copy;
141
142    if (entry->mSize == 0) {
143        mSource->onBufferAvailable(entry->mIndex);
144        mQueue.erase(mQueue.begin());
145        entry = NULL;
146    }
147
148    return copy;
149}
150
151}  // namespace android
152