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