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