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