Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e5be7f0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "MediaPlayer2: add native DataSourceDesc."

parents df9e45cc c2636035
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -254,6 +254,7 @@ cc_library {

    srcs: [
        "BufferingSettings.cpp",
        "DataSourceDesc.cpp",
        "IDataSource.cpp",
        "IMediaExtractor.cpp",
        "IMediaExtractorService.cpp",
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "DataSourceDesc"

#include <media/DataSource.h>
#include <media/DataSourceDesc.h>
#include <media/MediaHTTPService.h>

namespace android {

static const int64_t kLongMax = 0x7ffffffffffffffL;

DataSourceDesc::DataSourceDesc()
    : mType(TYPE_NONE),
      mFDOffset(0),
      mFDLength(kLongMax),
      mId(0),
      mStartPositionMs(0),
      mEndPositionMs(0) {
}

}  // namespace android
+34 −145
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#include <utils/Vector.h>

#include <media/AudioPolicyHelper.h>
#include <media/DataSourceDesc.h>
#include <media/MediaHTTPService.h>
#include <media/MediaPlayer2EngineClient.h>
#include <media/MediaPlayer2Interface.h>
@@ -247,13 +248,6 @@ extern ALooperRoster gLooperRoster;

MediaPlayer2Manager gMediaPlayer2Manager;

static bool checkPermission(const char* permissionString) {
    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
    bool ok = checkCallingPermission(String16(permissionString));
    if (!ok) ALOGE("Request requires %s", permissionString);
    return ok;
}

// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
/* static */ int MediaPlayer2Manager::AudioOutput::mMinBufferCount = 4;
/* static */ bool MediaPlayer2Manager::AudioOutput::mIsOnEmulator = false;
@@ -284,6 +278,10 @@ sp<MediaPlayer2Engine> MediaPlayer2Manager::create(
    sp<Client> c = new Client(
            mPid, connId, client, audioSessionId, mUid);

    if (!c->init()) {
        return NULL;
    }

    ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, mPid, mUid);

    wp<Client> w = c;
@@ -514,6 +512,25 @@ MediaPlayer2Manager::Client::Client(
#endif
}

bool MediaPlayer2Manager::Client::init() {
    sp<MediaPlayer2Interface> p = new NuPlayer2Driver(mPid);
    status_t init_result = p->initCheck();
    if (init_result != NO_ERROR) {
        ALOGE("Failed to create player object, initCheck failed(%d)", init_result);
        return false;
    }

    p->setNotifyCallback(this, notify);
    p->setUID(mUid);
    mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
    mAudioOutput = new AudioOutput(mAudioSessionId, mUid,
            mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
    p->setAudioSink(mAudioOutput);

    mPlayer = p;
    return true;
}

MediaPlayer2Manager::Client::~Client()
{
    ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
@@ -560,26 +577,6 @@ void MediaPlayer2Manager::Client::disconnect()
    IPCThreadState::self()->flushCommands();
}

sp<MediaPlayer2Interface> MediaPlayer2Manager::Client::createPlayer() {
    sp<MediaPlayer2Interface> p = getPlayer();
    if (p == NULL) {
        p = new NuPlayer2Driver(mPid);
        status_t init_result = p->initCheck();
        if (init_result == NO_ERROR) {
            p->setNotifyCallback(this, notify);
        } else {
            ALOGE("Failed to create player, initCheck failed(res = %d)", init_result);
            p.clear();
        }
    }

    if (p != NULL) {
        p->setUID(mUid);
    }

    return p;
}

void MediaPlayer2Manager::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
        audio_io_handle_t audioIo,
        audio_port_handle_t deviceId) {
@@ -591,30 +588,20 @@ void MediaPlayer2Manager::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdat
    }
}

sp<MediaPlayer2Interface> MediaPlayer2Manager::Client::setDataSource_pre() {
    sp<MediaPlayer2Interface> p = createPlayer();
status_t MediaPlayer2Manager::Client::setDataSource(
        const sp<DataSourceDesc> &dsd) {
    sp<MediaPlayer2Interface> p = getPlayer();
    if (p == NULL) {
        return p;
        return NO_INIT;
    }

    Mutex::Autolock lock(mLock);

    mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);

    mAudioOutput = new AudioOutput(mAudioSessionId, mUid,
            mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
    p->setAudioSink(mAudioOutput);

    return p;
    if (dsd == NULL) {
        return BAD_VALUE;
    }

status_t MediaPlayer2Manager::Client::setDataSource_post(
        const sp<MediaPlayer2Interface>& p,
        status_t status)
{
    ALOGV(" setDataSource");
    status_t status = p->setDataSource(dsd);
    if (status != OK) {
        ALOGE("  error: %d", status);
        ALOGE("setDataSource error: %d", status);
        return status;
    }

@@ -626,102 +613,9 @@ status_t MediaPlayer2Manager::Client::setDataSource_post(
        }
    }

    if (status == OK) {
        Mutex::Autolock lock(mLock);
        mPlayer = p;
    }
    return status;
}

status_t MediaPlayer2Manager::Client::setDataSource(
        const sp<MediaHTTPService> &httpService,
        const char *url,
        const KeyedVector<String8, String8> *headers)
{
    ALOGV("setDataSource(%s)", url);
    if (url == NULL)
        return UNKNOWN_ERROR;

    if ((strncmp(url, "http://", 7) == 0) ||
        (strncmp(url, "https://", 8) == 0) ||
        (strncmp(url, "rtsp://", 7) == 0)) {
        if (!checkPermission("android.permission.INTERNET")) {
            return PERMISSION_DENIED;
        }
    }

    if (strncmp(url, "content://", 10) == 0) {
        ALOGE("setDataSource: content scheme is not supported here");
        mStatus = UNKNOWN_ERROR;
        return mStatus;
    } else {
        sp<MediaPlayer2Interface> p = setDataSource_pre();
        if (p == NULL) {
            return NO_INIT;
        }

        return mStatus =
                setDataSource_post(
                p, p->setDataSource(httpService, url, headers));
    }
}

status_t MediaPlayer2Manager::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
    ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
    struct stat sb;
    int ret = fstat(fd, &sb);
    if (ret != 0) {
        ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
        return UNKNOWN_ERROR;
    }

    ALOGV("st_dev  = %llu", static_cast<unsigned long long>(sb.st_dev));
    ALOGV("st_mode = %u", sb.st_mode);
    ALOGV("st_uid  = %lu", static_cast<unsigned long>(sb.st_uid));
    ALOGV("st_gid  = %lu", static_cast<unsigned long>(sb.st_gid));
    ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));

    if (offset >= sb.st_size) {
        ALOGE("offset error");
        return UNKNOWN_ERROR;
    }
    if (offset + length > sb.st_size) {
        length = sb.st_size - offset;
        ALOGV("calculated length = %lld", (long long)length);
    }

    sp<MediaPlayer2Interface> p = setDataSource_pre();
    if (p == NULL) {
        return NO_INIT;
    }

    // now set data source
    return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
}

status_t MediaPlayer2Manager::Client::setDataSource(
        const sp<IStreamSource> &source) {
    sp<MediaPlayer2Interface> p = setDataSource_pre();
    if (p == NULL) {
        return NO_INIT;
    }

    // now set data source
    return mStatus = setDataSource_post(p, p->setDataSource(source));
}

status_t MediaPlayer2Manager::Client::setDataSource(
        const sp<DataSource> &source) {
    sp<MediaPlayer2Interface> p = setDataSource_pre();
    if (p == NULL) {
        return NO_INIT;
    }
    // now set data source
    return mStatus = setDataSource_post(p, p->setDataSource(source));
}

void MediaPlayer2Manager::Client::disconnectNativeWindow_l() {
    if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
        status_t err = native_window_api_disconnect(
@@ -1187,13 +1081,8 @@ status_t MediaPlayer2Manager::Client::setRetransmitEndpoint(
        ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
    }

    sp<MediaPlayer2Interface> p = getPlayer();

    // Right now, the only valid time to set a retransmit endpoint is before
    // player selection has been made (since the presence or absence of a
    // retransmit endpoint is going to determine which player is selected during
    // setDataSource).
    if (p != 0) return INVALID_OPERATION;
    // setDataSource.

    if (NULL != endpoint) {
        Mutex::Autolock lock(mLock);
+2 −16
Original line number Diff line number Diff line
@@ -287,22 +287,7 @@ private:
                                        const sp<media::VolumeShaper::Operation>& operation) override;
        virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;

        sp<MediaPlayer2Interface>    createPlayer();

        virtual status_t        setDataSource(
                        const sp<MediaHTTPService> &httpService,
                        const char *url,
                        const KeyedVector<String8, String8> *headers);

        virtual status_t        setDataSource(int fd, int64_t offset, int64_t length);

        virtual status_t        setDataSource(const sp<IStreamSource> &source);
        virtual status_t        setDataSource(const sp<DataSource> &source);


        sp<MediaPlayer2Interface>    setDataSource_pre();
        status_t                setDataSource_post(const sp<MediaPlayer2Interface>& p,
                                                   status_t status);
        virtual status_t        setDataSource(const sp<DataSourceDesc> &dsd);

        static  void            notify(const wp<MediaPlayer2Engine> &listener, int msg,
                                       int ext1, int ext2, const Parcel *obj);
@@ -343,6 +328,7 @@ private:
                                       uid_t uid);
                                Client();
        virtual                 ~Client();
        bool init();

                void            deletePlayer();

+68 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_DATASOURCEDESC_H
#define ANDROID_DATASOURCEDESC_H

#include <media/stagefright/foundation/ABase.h>
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
#include <utils/String8.h>

namespace android {

class DataSource;
struct MediaHTTPService;

// A binder interface for implementing a stagefright DataSource remotely.
struct DataSourceDesc : public RefBase {
public:
    enum {
        /* No data source has been set yet */
        TYPE_NONE     = 0,
        /* data source is type of MediaDataSource */
        TYPE_CALLBACK = 1,
        /* data source is type of FileDescriptor */
        TYPE_FD       = 2,
        /* data source is type of Url */
        TYPE_URL      = 3,
    };

    DataSourceDesc();

    int mType;

    sp<MediaHTTPService> mHttpService;
    String8 mUrl;
    KeyedVector<String8, String8> mHeaders;

    int mFD;
    int64_t mFDOffset;
    int64_t mFDLength;

    sp<DataSource> mCallbackSource;

    int64_t mId;
    int64_t mStartPositionMs;
    int64_t mEndPositionMs;

private:
    DISALLOW_EVIL_CONSTRUCTORS(DataSourceDesc);
};

}; // namespace android

#endif // ANDROID_DATASOURCEDESC_H
Loading