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 "IStreamSource" 19 #include <utils/Log.h> 20 21 #include <media/IStreamSource.h> 22 #include <media/stagefright/foundation/AMessage.h> 23 24 #include <binder/IMemory.h> 25 #include <binder/Parcel.h> 26 27 namespace android { 28 29 // static 30 const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS"; 31 32 // static 33 const char *const IStreamListener::kKeyDiscontinuityMask = "discontinuity-mask"; 34 35 // static 36 const char *const IStreamListener::kKeyMediaTimeUs = "media-time-us"; 37 38 // static 39 const char *const IStreamListener::kKeyRecentMediaTimeUs = "recent-media-time-us"; 40 41 enum { 42 // IStreamSource 43 SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION, 44 SET_BUFFERS, 45 ON_BUFFER_AVAILABLE, 46 FLAGS, 47 48 // IStreamListener 49 QUEUE_BUFFER, 50 ISSUE_COMMAND, 51 }; 52 53 struct BpStreamSource : public BpInterface<IStreamSource> { 54 BpStreamSource(const sp<IBinder> &impl) 55 : BpInterface<IStreamSource>(impl) { 56 } 57 58 virtual void setListener(const sp<IStreamListener> &listener) { 59 Parcel data, reply; 60 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 61 data.writeStrongBinder(IInterface::asBinder(listener)); 62 remote()->transact(SET_LISTENER, data, &reply); 63 } 64 65 virtual void setBuffers(const Vector<sp<IMemory> > &buffers) { 66 Parcel data, reply; 67 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 68 data.writeInt64(static_cast<int64_t>(buffers.size())); 69 for (size_t i = 0; i < buffers.size(); ++i) { 70 data.writeStrongBinder(IInterface::asBinder(buffers.itemAt(i))); 71 } 72 remote()->transact(SET_BUFFERS, data, &reply); 73 } 74 75 virtual void onBufferAvailable(size_t index) { 76 Parcel data, reply; 77 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 78 data.writeInt64(static_cast<int64_t>(index)); 79 remote()->transact( 80 ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); 81 } 82 83 virtual uint32_t flags() const { 84 Parcel data, reply; 85 data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); 86 remote()->transact(FLAGS, data, &reply); 87 88 return reply.readInt32(); 89 } 90 }; 91 92 IMPLEMENT_META_INTERFACE(StreamSource, "android.hardware.IStreamSource"); 93 94 status_t BnStreamSource::onTransact( 95 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 96 switch (code) { 97 case SET_LISTENER: 98 { 99 CHECK_INTERFACE(IStreamSource, data, reply); 100 setListener( 101 interface_cast<IStreamListener>(data.readStrongBinder())); 102 break; 103 } 104 105 case SET_BUFFERS: 106 { 107 CHECK_INTERFACE(IStreamSource, data, reply); 108 size_t n = static_cast<size_t>(data.readInt64()); 109 Vector<sp<IMemory> > buffers; 110 for (size_t i = 0; i < n; ++i) { 111 sp<IMemory> mem = 112 interface_cast<IMemory>(data.readStrongBinder()); 113 114 if (mem != NULL) { 115 buffers.push(mem); 116 } else if (data.dataAvail() == 0) { 117 break; 118 } 119 } 120 setBuffers(buffers); 121 break; 122 } 123 124 case ON_BUFFER_AVAILABLE: 125 { 126 CHECK_INTERFACE(IStreamSource, data, reply); 127 onBufferAvailable(static_cast<size_t>(data.readInt64())); 128 break; 129 } 130 131 case FLAGS: 132 { 133 CHECK_INTERFACE(IStreamSource, data, reply); 134 reply->writeInt32(this->flags()); 135 break; 136 } 137 138 default: 139 return BBinder::onTransact(code, data, reply, flags); 140 } 141 142 return OK; 143 } 144 145 //////////////////////////////////////////////////////////////////////////////// 146 147 struct BpStreamListener : public BpInterface<IStreamListener> { 148 BpStreamListener(const sp<IBinder> &impl) 149 : BpInterface<IStreamListener>(impl) { 150 } 151 152 virtual void queueBuffer(size_t index, size_t size) { 153 Parcel data, reply; 154 data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); 155 data.writeInt64(static_cast<int64_t>(index)); 156 data.writeInt64(static_cast<int64_t>(size)); 157 158 remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); 159 } 160 161 virtual void issueCommand( 162 Command cmd, bool synchronous, const sp<AMessage> &msg) { 163 Parcel data, reply; 164 data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); 165 data.writeInt32(static_cast<int32_t>(cmd)); 166 data.writeInt32(static_cast<int32_t>(synchronous)); 167 168 if (msg != NULL) { 169 data.writeInt32(1); 170 msg->writeToParcel(&data); 171 } else { 172 data.writeInt32(0); 173 } 174 175 remote()->transact(ISSUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY); 176 } 177 }; 178 179 IMPLEMENT_META_INTERFACE(StreamListener, "android.hardware.IStreamListener"); 180 181 status_t BnStreamListener::onTransact( 182 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 183 switch (code) { 184 case QUEUE_BUFFER: 185 { 186 CHECK_INTERFACE(IStreamListener, data, reply); 187 size_t index = static_cast<size_t>(data.readInt64()); 188 size_t size = static_cast<size_t>(data.readInt64()); 189 190 queueBuffer(index, size); 191 break; 192 } 193 194 case ISSUE_COMMAND: 195 { 196 CHECK_INTERFACE(IStreamListener, data, reply); 197 Command cmd = static_cast<Command>(data.readInt32()); 198 199 bool synchronous = static_cast<bool>(data.readInt32()); 200 201 sp<AMessage> msg; 202 203 if (data.readInt32()) { 204 msg = AMessage::FromParcel(data); 205 } 206 207 issueCommand(cmd, synchronous, msg); 208 break; 209 } 210 211 default: 212 return BBinder::onTransact(code, data, reply, flags); 213 } 214 215 return OK; 216 } 217 218 } // namespace android 219