blob: 92642a8e2fbebfe9199c6876840ffe1c674a6060 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
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