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> {
BpStreamSourceandroid::BpStreamSource54     BpStreamSource(const sp<IBinder> &impl)
55         : BpInterface<IStreamSource>(impl) {
56     }
57 
setListenerandroid::BpStreamSource58     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 
setBuffersandroid::BpStreamSource65     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 
onBufferAvailableandroid::BpStreamSource75     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 
flagsandroid::BpStreamSource83     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 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)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> {
BpStreamListenerandroid::BpStreamListener148     BpStreamListener(const sp<IBinder> &impl)
149         : BpInterface<IStreamListener>(impl) {
150     }
151 
queueBufferandroid::BpStreamListener152     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 
issueCommandandroid::BpStreamListener161     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 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)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