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

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

Various improvements to the wifi display implementation.

Using a MediaPuller now, audio and video on their separate threads.
No more flushing the RTP stream on audio tracks, since it wastes too much
of a full size UDP packet.

Change-Id: I53346b4aea739c3142da13bd179428503a3c98b0
parent 8a9e791c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ RemoteDisplay::RemoteDisplay(
    : mLooper(new ALooper),
      mNetSession(new ANetworkSession),
      mSource(new WifiDisplaySource(mNetSession, client)) {
    mLooper->setName("wfd_looper");
    mLooper->registerHandler(mSource);

    mNetSession->start();
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ LOCAL_SRC_FILES:= \
        sink/TunnelRenderer.cpp         \
        sink/WifiDisplaySink.cpp        \
        source/Converter.cpp            \
        source/MediaPuller.cpp          \
        source/PlaybackSession.cpp      \
        source/RepeaterSource.cpp       \
        source/Serializer.cpp           \
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ status_t Converter::initEncoder() {
    if (isAudio) {
        mOutputFormat->setInt32("bitrate", 64000);      // 64 kBit/sec
    } else {
        mOutputFormat->setInt32("bitrate", 5000000);    // 5Mbit/sec
        mOutputFormat->setInt32("bitrate", 10000000);    // 10Mbit/sec
        mOutputFormat->setInt32("frame-rate", 60);
        mOutputFormat->setInt32("i-frame-interval", 3);  // Iframes every 3 secs
    }
+152 −0
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 "MediaPuller"
#include <utils/Log.h>

#include "MediaPuller.h"

#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>

namespace android {

MediaPuller::MediaPuller(
        const sp<MediaSource> &source, const sp<AMessage> &notify)
    : mSource(source),
      mNotify(notify),
      mPullGeneration(0) {
}

MediaPuller::~MediaPuller() {
}

status_t MediaPuller::postSynchronouslyAndReturnError(
        const sp<AMessage> &msg) {
    sp<AMessage> response;
    status_t err = msg->postAndAwaitResponse(&response);

    if (err != OK) {
        return err;
    }

    if (!response->findInt32("err", &err)) {
        err = OK;
    }

    return err;
}

status_t MediaPuller::start() {
    return postSynchronouslyAndReturnError(new AMessage(kWhatStart, id()));
}

status_t MediaPuller::stop() {
    return postSynchronouslyAndReturnError(new AMessage(kWhatStop, id()));
}

void MediaPuller::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatStart:
        case kWhatStop:
        {
            status_t err;

            if (msg->what() == kWhatStart) {
                err = mSource->start();

                if (err == OK) {
                    schedulePull();
                }
            } else {
                err = mSource->stop();
                ++mPullGeneration;
            }

            sp<AMessage> response = new AMessage;
            response->setInt32("err", err);

            uint32_t replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            response->postReply(replyID);
            break;
        }

        case kWhatPull:
        {
            int32_t generation;
            CHECK(msg->findInt32("generation", &generation));

            if (generation != mPullGeneration) {
                break;
            }

            MediaBuffer *mbuf;
            status_t err = mSource->read(&mbuf);

            if (err != OK) {
                if (err == ERROR_END_OF_STREAM) {
                    ALOGI("stream ended.");
                } else {
                    ALOGE("error %d reading stream.", err);
                }

                sp<AMessage> notify = mNotify->dup();
                notify->setInt32("what", kWhatEOS);
                notify->post();
            } else {
                int64_t timeUs;
                CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));

                sp<ABuffer> accessUnit = new ABuffer(mbuf->range_length());

                memcpy(accessUnit->data(),
                       (const uint8_t *)mbuf->data() + mbuf->range_offset(),
                       mbuf->range_length());

                accessUnit->meta()->setInt64("timeUs", timeUs);
                accessUnit->meta()->setPointer("mediaBuffer", mbuf);

                sp<AMessage> notify = mNotify->dup();

                notify->setInt32("what", kWhatAccessUnit);
                notify->setBuffer("accessUnit", accessUnit);
                notify->post();

                schedulePull();
            }
            break;
        }

        default:
            TRESPASS();
    }
}

void MediaPuller::schedulePull() {
    sp<AMessage> msg = new AMessage(kWhatPull, id());
    msg->setInt32("generation", mPullGeneration);
    msg->post();
}

}  // namespace android
+61 −0
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 MEDIA_PULLER_H_

#define MEDIA_PULLER_H_

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

namespace android {

struct MediaSource;

struct MediaPuller : public AHandler {
    enum {
        kWhatEOS,
        kWhatAccessUnit
    };

    MediaPuller(const sp<MediaSource> &source, const sp<AMessage> &notify);

    status_t start();
    status_t stop();

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

private:
    enum {
        kWhatStart,
        kWhatStop,
        kWhatPull,
    };

    sp<MediaSource> mSource;
    sp<AMessage> mNotify;
    int32_t mPullGeneration;

    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
    void schedulePull();

    DISALLOW_EVIL_CONSTRUCTORS(MediaPuller);
};

}  // namespace android

#endif  // MEDIA_PULLER_H_
Loading