1/*
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "IMediaExtractorService"
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22#include <stdint.h>
23#include <sys/types.h>
24#include <binder/Parcel.h>
25#include <media/IMediaExtractorService.h>
26#include <media/stagefright/MediaExtractor.h>
27
28namespace android {
29
30enum {
31    MAKE_EXTRACTOR = IBinder::FIRST_CALL_TRANSACTION,
32    MAKE_IDATA_SOURCE_FD,
33};
34
35class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
36{
37public:
38    explicit BpMediaExtractorService(const sp<IBinder>& impl)
39        : BpInterface<IMediaExtractorService>(impl)
40    {
41    }
42
43    virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) {
44        Parcel data, reply;
45        data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
46        data.writeStrongBinder(IInterface::asBinder(source));
47        if (mime != NULL) {
48            data.writeCString(mime);
49        }
50        status_t ret = remote()->transact(MAKE_EXTRACTOR, data, &reply);
51        if (ret == NO_ERROR) {
52            return interface_cast<IMediaExtractor>(reply.readStrongBinder());
53        }
54        return NULL;
55    }
56
57    virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length)
58    {
59        Parcel data, reply;
60        data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
61        data.writeFileDescriptor(fd);
62        data.writeInt64(offset);
63        data.writeInt64(length);
64        status_t ret = remote()->transact(MAKE_IDATA_SOURCE_FD, data, &reply);
65        ALOGV("fd:%d offset:%lld length:%lld ret:%d",
66                fd, (long long)offset, (long long)length, ret);
67        if (ret == NO_ERROR) {
68            return interface_cast<IDataSource>(reply.readStrongBinder());
69        }
70        return nullptr;
71    }
72};
73
74IMPLEMENT_META_INTERFACE(MediaExtractorService, "android.media.IMediaExtractorService");
75
76// ----------------------------------------------------------------------
77
78status_t BnMediaExtractorService::onTransact(
79    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
80{
81    switch (code) {
82
83        case MAKE_EXTRACTOR: {
84            CHECK_INTERFACE(IMediaExtractorService, data, reply);
85            sp<IBinder> b;
86            status_t ret = data.readStrongBinder(&b);
87            if (ret != NO_ERROR || b == NULL) {
88                ALOGE("Error reading source from parcel");
89                return ret;
90            }
91            // If we make an extractor through Binder, enabled shared memory
92            // for MediaBuffers for this process.
93            MediaBuffer::useSharedMemory();
94            sp<IDataSource> source = interface_cast<IDataSource>(b);
95            const char *mime = data.readCString();
96            sp<IMediaExtractor> ex = makeExtractor(source, mime);
97            reply->writeStrongBinder(IInterface::asBinder(ex));
98            return NO_ERROR;
99        }
100
101        case MAKE_IDATA_SOURCE_FD: {
102            CHECK_INTERFACE(IMediaExtractorService, data, reply);
103            const int fd = dup(data.readFileDescriptor()); // -1 fd checked in makeIDataSource
104            const int64_t offset = data.readInt64();
105            const int64_t length = data.readInt64();
106            ALOGV("fd %d  offset%lld  length:%lld", fd, (long long)offset, (long long)length);
107            sp<IDataSource> source = makeIDataSource(fd, offset, length);
108            reply->writeStrongBinder(IInterface::asBinder(source));
109            // The FileSource closes the descriptor, so if it is not created
110            // we need to close the descriptor explicitly.
111            if (source.get() == nullptr && fd != -1) {
112                close(fd);
113            }
114            return NO_ERROR;
115        }
116
117        default:
118            return BBinder::onTransact(code, data, reply, flags);
119    }
120}
121
122// ----------------------------------------------------------------------------
123
124} // namespace android
125