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

Commit 150a516c authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Squashed commit of the following:"

parents cabdae99 bf049b94
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -534,6 +534,16 @@ status_t ATSParser::Stream::parse(
        mBuffer->setRange(0, 0);
        mExpectedContinuityCounter = -1;

#if 0
        // Uncomment this if you'd rather see no corruption whatsoever on
        // screen and suspend updates until we come across another IDR frame.

        if (mStreamType == STREAMTYPE_H264) {
            ALOGI("clearing video queue");
            mQueue->clear(true /* clearFormat */);
        }
#endif

        return OK;
    }

+2 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ LOCAL_SRC_FILES:= \
        ANetworkSession.cpp             \
        Parameters.cpp                  \
        ParsedMessage.cpp               \
        sink/DirectRenderer.cpp         \
        sink/LinearRegression.cpp       \
        sink/RTPSink.cpp                \
        sink/TunnelRenderer.cpp         \
@@ -18,6 +19,7 @@ LOCAL_SRC_FILES:= \
        source/TSPacketizer.cpp         \
        source/WifiDisplaySource.cpp    \
        TimeSeries.cpp                  \
        VideoFormats.cpp                \

LOCAL_C_INCLUDES:= \
        $(TOP)/frameworks/av/media/libstagefright \
+370 −0
Original line number Diff line number Diff line
/*
 * Copyright 2013, 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 "VideoFormats"
#include <utils/Log.h>

#include "VideoFormats.h"

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

namespace android {

VideoFormats::VideoFormats() {
    for (size_t i = 0; i < kNumResolutionTypes; ++i) {
        mResolutionEnabled[i] = 0;
    }

    setNativeResolution(RESOLUTION_CEA, 0);  // default to 640x480 p60
}

void VideoFormats::setNativeResolution(ResolutionType type, size_t index) {
    CHECK_LT(type, kNumResolutionTypes);
    CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL));

    mNativeType = type;
    mNativeIndex = index;

    setResolutionEnabled(type, index);
}

void VideoFormats::getNativeResolution(
        ResolutionType *type, size_t *index) const {
    *type = mNativeType;
    *index = mNativeIndex;
}

void VideoFormats::disableAll() {
    for (size_t i = 0; i < kNumResolutionTypes; ++i) {
        mResolutionEnabled[i] = 0;
    }
}

void VideoFormats::enableAll() {
    for (size_t i = 0; i < kNumResolutionTypes; ++i) {
        mResolutionEnabled[i] = 0xffffffff;
    }
}

void VideoFormats::setResolutionEnabled(
        ResolutionType type, size_t index, bool enabled) {
    CHECK_LT(type, kNumResolutionTypes);
    CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL));

    if (enabled) {
        mResolutionEnabled[type] |= (1ul << index);
    } else {
        mResolutionEnabled[type] &= ~(1ul << index);
    }
}

bool VideoFormats::isResolutionEnabled(
        ResolutionType type, size_t index) const {
    CHECK_LT(type, kNumResolutionTypes);
    CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL));

    return mResolutionEnabled[type] & (1ul << index);
}

// static
bool VideoFormats::GetConfiguration(
        ResolutionType type,
        size_t index,
        size_t *width, size_t *height, size_t *framesPerSecond,
        bool *interlaced) {
    CHECK_LT(type, kNumResolutionTypes);

    if (index >= 32) {
        return false;
    }

    static const struct config_t {
        size_t width, height, framesPerSecond;
        bool interlaced;
    } kConfigs[kNumResolutionTypes][32] = {
        {
            // CEA Resolutions
            { 640, 480, 60, false },
            { 720, 480, 60, false },
            { 720, 480, 60, true },
            { 720, 576, 50, false },
            { 720, 576, 50, true },
            { 1280, 720, 30, false },
            { 1280, 720, 60, false },
            { 1920, 1080, 30, false },
            { 1920, 1080, 60, false },
            { 1920, 1080, 60, true },
            { 1280, 720, 25, false },
            { 1280, 720, 50, false },
            { 1920, 1080, 25, false },
            { 1920, 1080, 50, false },
            { 1920, 1080, 50, true },
            { 1280, 720, 24, false },
            { 1920, 1080, 24, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
        },
        {
            // VESA Resolutions
            { 800, 600, 30, false },
            { 800, 600, 60, false },
            { 1024, 768, 30, false },
            { 1024, 768, 60, false },
            { 1152, 864, 30, false },
            { 1152, 864, 60, false },
            { 1280, 768, 30, false },
            { 1280, 768, 60, false },
            { 1280, 800, 30, false },
            { 1280, 800, 60, false },
            { 1360, 768, 30, false },
            { 1360, 768, 60, false },
            { 1366, 768, 30, false },
            { 1366, 768, 60, false },
            { 1280, 1024, 30, false },
            { 1280, 1024, 60, false },
            { 1400, 1050, 30, false },
            { 1400, 1050, 60, false },
            { 1440, 900, 30, false },
            { 1440, 900, 60, false },
            { 1600, 900, 30, false },
            { 1600, 900, 60, false },
            { 1600, 1200, 30, false },
            { 1600, 1200, 60, false },
            { 1680, 1024, 30, false },
            { 1680, 1024, 60, false },
            { 1680, 1050, 30, false },
            { 1680, 1050, 60, false },
            { 1920, 1200, 30, false },
            { 1920, 1200, 60, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
        },
        {
            // HH Resolutions
            { 800, 480, 30, false },
            { 800, 480, 60, false },
            { 854, 480, 30, false },
            { 854, 480, 60, false },
            { 864, 480, 30, false },
            { 864, 480, 60, false },
            { 640, 360, 30, false },
            { 640, 360, 60, false },
            { 960, 540, 30, false },
            { 960, 540, 60, false },
            { 848, 480, 30, false },
            { 848, 480, 60, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
            { 0, 0, 0, false },
        }
    };

    const config_t *config = &kConfigs[type][index];

    if (config->width == 0) {
        return false;
    }

    if (width) {
        *width = config->width;
    }

    if (height) {
        *height = config->height;
    }

    if (framesPerSecond) {
        *framesPerSecond = config->framesPerSecond;
    }

    if (interlaced) {
        *interlaced = config->interlaced;
    }

    return true;
}

bool VideoFormats::parseFormatSpec(const char *spec) {
    CHECK_EQ(kNumResolutionTypes, 3);

    unsigned native, dummy;

    if (sscanf(
            spec,
            "%02x %02x %02x %02x %08X %08X %08X",
            &native,
            &dummy,
            &dummy,
            &dummy,
            &mResolutionEnabled[0],
            &mResolutionEnabled[1],
            &mResolutionEnabled[2]) != 7) {
        return false;
    }

    mNativeIndex = native >> 3;
    mNativeType = (ResolutionType)(native & 7);

    if (mNativeType >= kNumResolutionTypes) {
        return false;
    }

    return GetConfiguration(mNativeType, mNativeIndex, NULL, NULL, NULL, NULL);
}

AString VideoFormats::getFormatSpec() const {
    CHECK_EQ(kNumResolutionTypes, 3);

    // wfd_video_formats:
    // 1 byte "native"
    // 1 byte "preferred-display-mode-supported" 0 or 1
    // one or more avc codec structures
    //   1 byte profile
    //   1 byte level
    //   4 byte CEA mask
    //   4 byte VESA mask
    //   4 byte HH mask
    //   1 byte latency
    //   2 byte min-slice-slice
    //   2 byte slice-enc-params
    //   1 byte framerate-control-support
    //   max-hres (none or 2 byte)
    //   max-vres (none or 2 byte)

    return StringPrintf(
            "%02x 00 02 02 %08x %08x %08x 00 0000 0000 00 none none",
            (mNativeIndex << 3) | mNativeType,
            mResolutionEnabled[0],
            mResolutionEnabled[1],
            mResolutionEnabled[2]);
}

// static
bool VideoFormats::PickBestFormat(
        const VideoFormats &sinkSupported,
        const VideoFormats &sourceSupported,
        ResolutionType *chosenType,
        size_t *chosenIndex) {
    ResolutionType nativeType;
    size_t nativeIndex;
    sinkSupported.getNativeResolution(&nativeType, &nativeIndex);
    if (sinkSupported.isResolutionEnabled(nativeType, nativeIndex)) {
        if (sourceSupported.isResolutionEnabled(nativeType, nativeIndex)) {
            ALOGI("Choosing sink's native resolution");
            *chosenType = nativeType;
            *chosenIndex = nativeIndex;
            return true;
        }
    } else {
        ALOGW("Sink advertised native resolution that it doesn't "
              "actually support... ignoring");
    }

    sourceSupported.getNativeResolution(&nativeType, &nativeIndex);
    if (sourceSupported.isResolutionEnabled(nativeType, nativeIndex)) {
        if (sinkSupported.isResolutionEnabled(nativeType, nativeIndex)) {
            ALOGI("Choosing source's native resolution");
            *chosenType = nativeType;
            *chosenIndex = nativeIndex;
            return true;
        }
    } else {
        ALOGW("Source advertised native resolution that it doesn't "
              "actually support... ignoring");
    }

    bool first = true;
    uint32_t bestScore = 0;
    size_t bestType = 0;
    size_t bestIndex = 0;
    for (size_t i = 0; i < kNumResolutionTypes; ++i) {
        for (size_t j = 0; j < 32; ++j) {
            size_t width, height, framesPerSecond;
            bool interlaced;
            if (!GetConfiguration(
                        (ResolutionType)i,
                        j,
                        &width, &height, &framesPerSecond, &interlaced)) {
                break;
            }

            if (!sinkSupported.isResolutionEnabled((ResolutionType)i, j)
                    || !sourceSupported.isResolutionEnabled(
                        (ResolutionType)i, j)) {
                continue;
            }

            ALOGV("type %u, index %u, %u x %u %c%u supported",
                  i, j, width, height, interlaced ? 'i' : 'p', framesPerSecond);

            uint32_t score = width * height * framesPerSecond;
            if (!interlaced) {
                score *= 2;
            }

            if (first || score > bestScore) {
                bestScore = score;
                bestType = i;
                bestIndex = j;

                first = false;
            }
        }
    }

    if (first) {
        return false;
    }

    *chosenType = (ResolutionType)bestType;
    *chosenIndex = bestIndex;

    return true;
}

}  // namespace android
+83 −0
Original line number Diff line number Diff line
/*
 * Copyright 2013, 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 VIDEO_FORMATS_H_

#define VIDEO_FORMATS_H_

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

#include <stdint.h>

namespace android {

struct AString;

// This class encapsulates that video resolution capabilities of a wfd source
// or sink as outlined in the wfd specs. Currently three sets of resolutions
// are specified, each of which supports up to 32 resolutions.
// In addition to its capabilities each sink/source also publishes its
// "native" resolution, presumably one that is preferred among all others
// because it wouldn't require any scaling and directly corresponds to the
// display capabilities/pixels.
struct VideoFormats {
    VideoFormats();

    enum ResolutionType {
        RESOLUTION_CEA,
        RESOLUTION_VESA,
        RESOLUTION_HH,
        kNumResolutionTypes,
    };

    void setNativeResolution(ResolutionType type, size_t index);
    void getNativeResolution(ResolutionType *type, size_t *index) const;

    void disableAll();
    void enableAll();

    void setResolutionEnabled(
            ResolutionType type, size_t index, bool enabled = true);

    bool isResolutionEnabled(ResolutionType type, size_t index) const;

    static bool GetConfiguration(
            ResolutionType type, size_t index,
            size_t *width, size_t *height, size_t *framesPerSecond,
            bool *interlaced);

    bool parseFormatSpec(const char *spec);
    AString getFormatSpec() const;

    static bool PickBestFormat(
            const VideoFormats &sinkSupported,
            const VideoFormats &sourceSupported,
            ResolutionType *chosenType,
            size_t *chosenIndex);

private:
    ResolutionType mNativeType;
    size_t mNativeIndex;

    uint32_t mResolutionEnabled[kNumResolutionTypes];

    DISALLOW_EVIL_CONSTRUCTORS(VideoFormats);
};

}  // namespace android

#endif  // VIDEO_FORMATS_H_
+14 −3
Original line number Diff line number Diff line
@@ -21,7 +21,14 @@
#include "RTPSink.h"

#include "ANetworkSession.h"

#if USE_TUNNEL_RENDERER
#include "TunnelRenderer.h"
#define RENDERER_CLASS TunnelRenderer
#else
#include "DirectRenderer.h"
#define RENDERER_CLASS DirectRenderer
#endif

#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -238,9 +245,11 @@ void RTPSink::Source::addReportBlock(

RTPSink::RTPSink(
        const sp<ANetworkSession> &netSession,
        const sp<IGraphicBufferProducer> &bufferProducer)
        const sp<IGraphicBufferProducer> &bufferProducer,
        const sp<AMessage> &notify)
    : mNetSession(netSession),
      mSurfaceTex(bufferProducer),
      mNotify(notify),
      mRTPPort(0),
      mRTPSessionID(0),
      mRTCPSessionID(0),
@@ -470,6 +479,7 @@ status_t RTPSink::parseRTP(const sp<ABuffer> &buffer) {
    uint32_t rtpTime = U32_AT(&data[4]);
    uint16_t seqNo = U16_AT(&data[2]);

#if 0
    int64_t arrivalTimeUs;
    CHECK(buffer->meta()->findInt64("arrivalTimeUs", &arrivalTimeUs));

@@ -500,6 +510,7 @@ status_t RTPSink::parseRTP(const sp<ABuffer> &buffer) {
            ALOGI("packet was %.2f ms late", latenessMs);
        }
    }
#endif

    sp<AMessage> meta = buffer->meta();
    meta->setInt32("ssrc", srcId);
@@ -515,12 +526,12 @@ status_t RTPSink::parseRTP(const sp<ABuffer> &buffer) {
            sp<AMessage> notifyLost = new AMessage(kWhatPacketLost, id());
            notifyLost->setInt32("ssrc", srcId);

            mRenderer = new TunnelRenderer(notifyLost, mSurfaceTex);
            mRenderer = new RENDERER_CLASS(notifyLost, mSurfaceTex);
            looper()->registerHandler(mRenderer);
        }

        sp<AMessage> queueBufferMsg =
            new AMessage(TunnelRenderer::kWhatQueueBuffer, mRenderer->id());
            new AMessage(RENDERER_CLASS::kWhatQueueBuffer, mRenderer->id());

        sp<Source> source = new Source(seqNo, buffer, queueBufferMsg);
        mSources.add(srcId, source);
Loading