NuPlayerStreamListener.cpp revision 5bc087c573c70c84c6a39946457590b42d392a33
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(void *data, size_t size) { 96 CHECK_GT(size, 0u); 97 98 Mutex::Autolock autoLock(mLock); 99 100 if (mEOS) { 101 return 0; 102 } 103 104 if (mQueue.empty()) { 105 mSendDataNotification = true; 106 107 return -EWOULDBLOCK; 108 } 109 110 QueueEntry *entry = &*mQueue.begin(); 111 112 if (entry->mIsCommand) { 113 switch (entry->mCommand) { 114 case EOS: 115 { 116 mQueue.erase(mQueue.begin()); 117 entry = NULL; 118 119 mEOS = true; 120 return 0; 121 } 122 123 case DISCONTINUITY: 124 { 125 mQueue.erase(mQueue.begin()); 126 entry = NULL; 127 128 return INFO_DISCONTINUITY; 129 } 130 131 default: 132 TRESPASS(); 133 break; 134 } 135 } 136 137 size_t copy = entry->mSize; 138 if (copy > size) { 139 copy = size; 140 } 141 142 memcpy(data, 143 (const uint8_t *)mBuffers.editItemAt(entry->mIndex)->pointer() 144 + entry->mOffset, 145 copy); 146 147 entry->mOffset += copy; 148 entry->mSize -= copy; 149 150 if (entry->mSize == 0) { 151 mSource->onBufferAvailable(entry->mIndex); 152 mQueue.erase(mQueue.begin()); 153 entry = NULL; 154 } 155 156 return copy; 157} 158 159} // namespace android 160