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

Commit d3d9263c authored by Andreas Huber's avatar Andreas Huber
Browse files

Get rid of TunnelRenderer

Change-Id: I40dc00e2e689d7a6b8717ce524016c2948229807
parent 6bb4d7f0
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@ LOCAL_SRC_FILES:= \
        rtp/RTPReceiver.cpp             \
        rtp/RTPSender.cpp               \
        sink/DirectRenderer.cpp         \
        sink/TunnelRenderer.cpp         \
        sink/WifiDisplaySink.cpp        \
        SNTPClient.cpp                  \
        TimeSyncer.cpp                  \
+0 −290
Original line number Diff line number Diff line
/*
 * Copyright 2012, 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 "TunnelRenderer"
#include <utils/Log.h>

#include "TunnelRenderer.h"

#include "ATSParser.h"

#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <gui/SurfaceComposerClient.h>
#include <media/IMediaPlayerService.h>
#include <media/IStreamSource.h>
#include <media/mediaplayer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <ui/DisplayInfo.h>

namespace android {

struct TunnelRenderer::PlayerClient : public BnMediaPlayerClient {
    PlayerClient() {}

    virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) {
        ALOGI("notify %d, %d, %d", msg, ext1, ext2);
    }

protected:
    virtual ~PlayerClient() {}

private:
    DISALLOW_EVIL_CONSTRUCTORS(PlayerClient);
};

struct TunnelRenderer::StreamSource : public BnStreamSource {
    StreamSource(TunnelRenderer *owner);

    virtual void setListener(const sp<IStreamListener> &listener);
    virtual void setBuffers(const Vector<sp<IMemory> > &buffers);

    virtual void onBufferAvailable(size_t index);

    virtual uint32_t flags() const;

    void doSomeWork();

    void setTimeOffset(int64_t offset);

protected:
    virtual ~StreamSource();

private:
    mutable Mutex mLock;

    TunnelRenderer *mOwner;

    sp<IStreamListener> mListener;

    Vector<sp<IMemory> > mBuffers;
    List<size_t> mIndicesAvailable;

    size_t mNumDeqeued;

    int64_t mTimeOffsetUs;
    bool mTimeOffsetChanged;

    DISALLOW_EVIL_CONSTRUCTORS(StreamSource);
};

////////////////////////////////////////////////////////////////////////////////

TunnelRenderer::StreamSource::StreamSource(TunnelRenderer *owner)
    : mOwner(owner),
      mNumDeqeued(0),
      mTimeOffsetUs(0ll),
      mTimeOffsetChanged(false) {
}

TunnelRenderer::StreamSource::~StreamSource() {
}

void TunnelRenderer::StreamSource::setListener(
        const sp<IStreamListener> &listener) {
    mListener = listener;
}

void TunnelRenderer::StreamSource::setBuffers(
        const Vector<sp<IMemory> > &buffers) {
    mBuffers = buffers;
}

void TunnelRenderer::StreamSource::onBufferAvailable(size_t index) {
    CHECK_LT(index, mBuffers.size());

    {
        Mutex::Autolock autoLock(mLock);
        mIndicesAvailable.push_back(index);
    }

    doSomeWork();
}

uint32_t TunnelRenderer::StreamSource::flags() const {
    return kFlagAlignedVideoData | kFlagIsRealTimeData;
}

void TunnelRenderer::StreamSource::doSomeWork() {
    Mutex::Autolock autoLock(mLock);

    while (!mIndicesAvailable.empty()) {
        sp<ABuffer> srcBuffer = mOwner->dequeueBuffer();
        if (srcBuffer == NULL) {
            break;
        }

        ++mNumDeqeued;

        if (mTimeOffsetChanged) {
            sp<AMessage> extra = new AMessage;

            extra->setInt32(
                    IStreamListener::kKeyDiscontinuityMask,
                    ATSParser::DISCONTINUITY_TIME_OFFSET);

            extra->setInt64("offset", mTimeOffsetUs);

            mListener->issueCommand(
                    IStreamListener::DISCONTINUITY,
                    false /* synchronous */,
                    extra);

            mTimeOffsetChanged = false;
        }

        ALOGV("dequeue TS packet of size %d", srcBuffer->size());

        size_t index = *mIndicesAvailable.begin();
        mIndicesAvailable.erase(mIndicesAvailable.begin());

        sp<IMemory> mem = mBuffers.itemAt(index);
        CHECK_LE(srcBuffer->size(), mem->size());
        CHECK_EQ((srcBuffer->size() % 188), 0u);

        memcpy(mem->pointer(), srcBuffer->data(), srcBuffer->size());
        mListener->queueBuffer(index, srcBuffer->size());
    }
}

void TunnelRenderer::StreamSource::setTimeOffset(int64_t offset) {
    Mutex::Autolock autoLock(mLock);

    if (offset != mTimeOffsetUs) {
        mTimeOffsetUs = offset;
        mTimeOffsetChanged = true;
    }
}

////////////////////////////////////////////////////////////////////////////////

TunnelRenderer::TunnelRenderer(
        const sp<IGraphicBufferProducer> &bufferProducer)
    : mSurfaceTex(bufferProducer),
      mStartup(true) {
    mStreamSource = new StreamSource(this);
}

TunnelRenderer::~TunnelRenderer() {
    destroyPlayer();
}

void TunnelRenderer::setTimeOffset(int64_t offset) {
    mStreamSource->setTimeOffset(offset);
}

void TunnelRenderer::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        default:
            TRESPASS();
    }
}

void TunnelRenderer::initPlayer() {
    if (mSurfaceTex == NULL) {
        mComposerClient = new SurfaceComposerClient;
        CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);

        DisplayInfo info;
        SurfaceComposerClient::getDisplayInfo(0, &info);
        ssize_t displayWidth = info.w;
        ssize_t displayHeight = info.h;

        mSurfaceControl =
            mComposerClient->createSurface(
                    String8("A Surface"),
                    displayWidth,
                    displayHeight,
                    PIXEL_FORMAT_RGB_565,
                    0);

        CHECK(mSurfaceControl != NULL);
        CHECK(mSurfaceControl->isValid());

        SurfaceComposerClient::openGlobalTransaction();
        CHECK_EQ(mSurfaceControl->setLayer(INT_MAX), (status_t)OK);
        CHECK_EQ(mSurfaceControl->show(), (status_t)OK);
        SurfaceComposerClient::closeGlobalTransaction();

        mSurface = mSurfaceControl->getSurface();
        CHECK(mSurface != NULL);
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.player"));
    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
    CHECK(service.get() != NULL);

    mPlayerClient = new PlayerClient;

    mPlayer = service->create(mPlayerClient, 0);
    CHECK(mPlayer != NULL);
    CHECK_EQ(mPlayer->setDataSource(mStreamSource), (status_t)OK);

    mPlayer->setVideoSurfaceTexture(
            mSurfaceTex != NULL ? mSurfaceTex : mSurface->getIGraphicBufferProducer());

    mPlayer->start();
}

void TunnelRenderer::destroyPlayer() {
    mStreamSource.clear();

    mPlayer->setVideoSurfaceTexture(NULL);

    mPlayer->stop();
    mPlayer.clear();

    if (mSurfaceTex == NULL) {
        mSurface.clear();
        mSurfaceControl.clear();

        mComposerClient->dispose();
        mComposerClient.clear();
    }
}

void TunnelRenderer::queueBuffer(const sp<ABuffer> &buffer) {
    {
        Mutex::Autolock autoLock(mLock);
        mBuffers.push_back(buffer);
    }

    if (mStartup) {
        initPlayer();
        mStartup = false;
    }

    mStreamSource->doSomeWork();
}

sp<ABuffer> TunnelRenderer::dequeueBuffer() {
    Mutex::Autolock autoLock(mLock);
    if (mBuffers.empty()) {
        return NULL;
    }

    sp<ABuffer> buf = *mBuffers.begin();
    mBuffers.erase(mBuffers.begin());

    return buf;
}

}  // namespace android
+0 −78
Original line number Diff line number Diff line
/*
 * Copyright 2012, 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 TUNNEL_RENDERER_H_

#define TUNNEL_RENDERER_H_

#include <gui/Surface.h>
#include <media/stagefright/foundation/AHandler.h>

namespace android {

struct ABuffer;
struct SurfaceComposerClient;
struct SurfaceControl;
struct Surface;
struct IMediaPlayer;
struct IStreamListener;

// This class reassembles incoming RTP packets into the correct order
// and sends the resulting transport stream to a mediaplayer instance
// for playback.
struct TunnelRenderer : public AHandler {
    TunnelRenderer(const sp<IGraphicBufferProducer> &bufferProducer);

    void queueBuffer(const sp<ABuffer> &buffer);
    sp<ABuffer> dequeueBuffer();

    void setTimeOffset(int64_t offset);

    int64_t getAvgLatenessUs() {
        return 0ll;
    }

protected:
    virtual void onMessageReceived(const sp<AMessage> &msg);
    virtual ~TunnelRenderer();

private:
    struct PlayerClient;
    struct StreamSource;

    mutable Mutex mLock;

    sp<IGraphicBufferProducer> mSurfaceTex;

    bool mStartup;
    List<sp<ABuffer> > mBuffers;

    sp<SurfaceComposerClient> mComposerClient;
    sp<SurfaceControl> mSurfaceControl;
    sp<Surface> mSurface;
    sp<PlayerClient> mPlayerClient;
    sp<IMediaPlayer> mPlayer;
    sp<StreamSource> mStreamSource;

    void initPlayer();
    void destroyPlayer();

    DISALLOW_EVIL_CONSTRUCTORS(TunnelRenderer);
};

}  // namespace android

#endif  // TUNNEL_RENDERER_H_