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

Commit d6afead9 authored by Amy's avatar Amy Committed by Amy Zhang
Browse files

Copy filtered av data to ion buffer to test on cuttlefish

Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 150952766
Change-Id: If007f9c021102dc95be8e9dc70be70d3945192a9
parent 0df912df
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ cc_defaults {
        "libfmq",
        "libfmq",
        "libhidlbase",
        "libhidlbase",
        "libhidlmemory",
        "libhidlmemory",
        "libion",
        "liblog",
        "liblog",
        "libstagefright_foundation",
        "libstagefright_foundation",
        "libutils",
        "libutils",
+147 −19
Original line number Original line Diff line number Diff line
@@ -60,6 +60,8 @@ Return<Result> Filter::setDataSource(const sp<IFilter>& filter) {
Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) {
Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) {
    ALOGV("%s", __FUNCTION__);
    ALOGV("%s", __FUNCTION__);


    mIsUsingFMQ = true;

    _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc());
    _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc());
    return Void();
    return Void();
}
}
@@ -120,9 +122,13 @@ Return<Result> Filter::flush() {
    return Result::SUCCESS;
    return Result::SUCCESS;
}
}


Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t /*avDataId*/) {
Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t avDataId) {
    ALOGV("%s", __FUNCTION__);
    ALOGV("%s", __FUNCTION__);
    if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) {
        return Result::INVALID_ARGUMENT;
    }


    ::close(mDataId2Avfd[avDataId]);
    return Result::SUCCESS;
    return Result::SUCCESS;
}
}


@@ -174,14 +180,21 @@ void Filter::filterThreadLoop() {
    // Event Callback without waiting for the DATA_CONSUMED to init the process.
    // Event Callback without waiting for the DATA_CONSUMED to init the process.
    while (mFilterThreadRunning) {
    while (mFilterThreadRunning) {
        if (mFilterEvent.events.size() == 0) {
        if (mFilterEvent.events.size() == 0) {
            if (DEBUG_FILTER) {
                ALOGD("[Filter] wait for filter data output.");
                ALOGD("[Filter] wait for filter data output.");
            }
            usleep(1000 * 1000);
            usleep(1000 * 1000);
            continue;
            continue;
        }
        }
        // After successfully write, send a callback and wait for the read to be done
        // After successfully write, send a callback and wait for the read to be done
        mCallback->onFilterEvent(mFilterEvent);
        mCallback->onFilterEvent(mFilterEvent);
        freeAvHandle();
        mFilterEvent.events.resize(0);
        mFilterEvent.events.resize(0);
        mFilterStatus = DemuxFilterStatus::DATA_READY;
        mFilterStatus = DemuxFilterStatus::DATA_READY;
        if (mCallback == nullptr) {
            ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId);
            break;
        }
        mCallback->onFilterStatus(mFilterStatus);
        mCallback->onFilterStatus(mFilterStatus);
        break;
        break;
    }
    }
@@ -191,7 +204,7 @@ void Filter::filterThreadLoop() {
        // We do not wait for the last round of written data to be read to finish the thread
        // We do not wait for the last round of written data to be read to finish the thread
        // because the VTS can verify the reading itself.
        // because the VTS can verify the reading itself.
        for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
        for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
            while (mFilterThreadRunning) {
            while (mFilterThreadRunning && mIsUsingFMQ) {
                status_t status = mFilterEventFlag->wait(
                status_t status = mFilterEventFlag->wait(
                        static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
                        static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
                        WAIT_TIMEOUT, true /* retry on spurious wake */);
                        WAIT_TIMEOUT, true /* retry on spurious wake */);
@@ -202,11 +215,6 @@ void Filter::filterThreadLoop() {
                break;
                break;
            }
            }


            if (mCallback == nullptr) {
                ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId);
                break;
            }

            maySendFilterStatusCallback();
            maySendFilterStatusCallback();


            while (mFilterThreadRunning) {
            while (mFilterThreadRunning) {
@@ -232,7 +240,22 @@ void Filter::filterThreadLoop() {
    ALOGD("[Filter] filter thread ended.");
    ALOGD("[Filter] filter thread ended.");
}
}


void Filter::freeAvHandle() {
    if (mType.mainType != DemuxFilterMainType::TS ||
        (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO &&
         mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO)) {
        return;
    }
    for (int i = 0; i < mFilterEvent.events.size(); i++) {
        ::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]);
        native_handle_close(mFilterEvent.events[i].media().avMemory.getNativeHandle());
    }
}

void Filter::maySendFilterStatusCallback() {
void Filter::maySendFilterStatusCallback() {
    if (!mIsUsingFMQ) {
        return;
    }
    std::lock_guard<std::mutex> lock(mFilterStatusLock);
    std::lock_guard<std::mutex> lock(mFilterStatusLock);
    int availableToRead = mFilterMQ->availableToRead();
    int availableToRead = mFilterMQ->availableToRead();
    int availableToWrite = mFilterMQ->availableToWrite();
    int availableToWrite = mFilterMQ->availableToWrite();
@@ -409,19 +432,88 @@ Result Filter::startTsFilterHandler() {
}
}


Result Filter::startMediaFilterHandler() {
Result Filter::startMediaFilterHandler() {
    std::lock_guard<std::mutex> lock(mFilterEventLock);
    if (mFilterOutput.empty()) {
        return Result::SUCCESS;
    }

    for (int i = 0; i < mFilterOutput.size(); i += 188) {
        if (mPesSizeLeft == 0) {
            uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
                              mFilterOutput[i + 6];
            if (DEBUG_FILTER) {
                ALOGD("[Filter] prefix %d", prefix);
            }
            if (prefix == 0x000001) {
                // TODO handle mulptiple Pes filters
                mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9];
                mPesSizeLeft += 6;
                if (DEBUG_FILTER) {
                    ALOGD("[Filter] pes data length %d", mPesSizeLeft);
                }
            } else {
                continue;
            }
        }

        int endPoint = min(184, mPesSizeLeft);
        // append data and check size
        vector<uint8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
        vector<uint8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint;
        mPesOutput.insert(mPesOutput.end(), first, last);
        // size does not match then continue
        mPesSizeLeft -= endPoint;
        if (DEBUG_FILTER) {
            ALOGD("[Filter] pes data left %d", mPesSizeLeft);
        }
        if (mPesSizeLeft > 0 || mAvBufferCopyCount++ < 10) {
            continue;
        }

        int av_fd = createAvIonFd(mPesOutput.size());
        if (av_fd == -1) {
            return Result::UNKNOWN_ERROR;
        }
        // copy the filtered data to the buffer
        uint8_t* avBuffer = getIonBuffer(av_fd, mPesOutput.size());
        if (avBuffer == NULL) {
            return Result::UNKNOWN_ERROR;
        }
        memcpy(avBuffer, mPesOutput.data(), mPesOutput.size() * sizeof(uint8_t));

        native_handle_t* nativeHandle = createNativeHandle(av_fd);
        if (nativeHandle == NULL) {
            return Result::UNKNOWN_ERROR;
        }
        hidl_handle handle;
        handle.setTo(nativeHandle, /*shouldOwn=*/true);

        // Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
        uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
        mDataId2Avfd[dataId] = dup(av_fd);

        // Create mediaEvent and send callback
        DemuxFilterMediaEvent mediaEvent;
        DemuxFilterMediaEvent mediaEvent;
        mediaEvent = {
        mediaEvent = {
            // temp dump meta data
                .avMemory = std::move(handle),
            .pts = 0,
                .dataLength = static_cast<uint32_t>(mPesOutput.size()),
            .dataLength = 530,
                .avDataId = dataId,
            .avMemory = nullptr,
            .isSecureMemory = false,
        };
        };
    mFilterEvent.events.resize(1);
        int size = mFilterEvent.events.size();
    mFilterEvent.events[0].media(mediaEvent);
        mFilterEvent.events.resize(size + 1);
        mFilterEvent.events[size].media(mediaEvent);

        // Clear and log
        mPesOutput.clear();
        mAvBufferCopyCount = 0;
        ::close(av_fd);
        if (DEBUG_FILTER) {
            ALOGD("[Filter] assembled av data length %d", mediaEvent.dataLength);
        }
    }


    mFilterOutput.clear();
    mFilterOutput.clear();
    // TODO handle write FQM for media stream

    return Result::SUCCESS;
    return Result::SUCCESS;
}
}


@@ -493,6 +585,42 @@ void Filter::detachFilterFromRecord() {
    mDvr = nullptr;
    mDvr = nullptr;
}
}


int Filter::createAvIonFd(int size) {
    // Create an ion fd and allocate an av fd mapped to a buffer to it.
    int ion_fd = ion_open();
    if (ion_fd == -1) {
        ALOGE("[Filter] Failed to open ion fd %d", errno);
        return -1;
    }
    int av_fd = -1;
    ion_alloc_fd(dup(ion_fd), size, 0 /*align*/, ION_HEAP_SYSTEM_MASK, 0 /*flags*/, &av_fd);
    if (av_fd == -1) {
        ALOGE("[Filter] Failed to create av fd %d", errno);
        return -1;
    }
    return av_fd;
}

uint8_t* Filter::getIonBuffer(int fd, int size) {
    uint8_t* avBuf = static_cast<uint8_t*>(
            mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 /*offset*/));
    if (avBuf == MAP_FAILED) {
        ALOGE("[Filter] fail to allocate buffer %d", errno);
        return NULL;
    }
    return avBuf;
}

native_handle_t* Filter::createNativeHandle(int fd) {
    // Create a native handle to pass the av fd via the callback event.
    native_handle_t* nativeHandle = native_handle_create(/*numFd*/ 1, 0);
    if (nativeHandle == NULL) {
        ALOGE("[Filter] Failed to create native_handle %d", errno);
        return NULL;
    }
    nativeHandle->data[0] = dup(fd);
    return nativeHandle;
}
}  // namespace implementation
}  // namespace implementation
}  // namespace V1_0
}  // namespace V1_0
}  // namespace tuner
}  // namespace tuner
+12 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@


#include <android/hardware/tv/tuner/1.0/IFilter.h>
#include <android/hardware/tv/tuner/1.0/IFilter.h>
#include <fmq/MessageQueue.h>
#include <fmq/MessageQueue.h>
#include <ion/ion.h>
#include <math.h>
#include <math.h>
#include <set>
#include <set>
#include "Demux.h"
#include "Demux.h"
@@ -87,6 +88,7 @@ class Filter : public IFilter {
    Result startRecordFilterHandler();
    Result startRecordFilterHandler();
    void attachFilterToRecord(const sp<Dvr> dvr);
    void attachFilterToRecord(const sp<Dvr> dvr);
    void detachFilterFromRecord();
    void detachFilterFromRecord();
    void freeAvHandle();


  private:
  private:
    // Tuner service
    // Tuner service
@@ -109,6 +111,7 @@ class Filter : public IFilter {
    vector<uint8_t> mFilterOutput;
    vector<uint8_t> mFilterOutput;
    vector<uint8_t> mRecordFilterOutput;
    vector<uint8_t> mRecordFilterOutput;
    unique_ptr<FilterMQ> mFilterMQ;
    unique_ptr<FilterMQ> mFilterMQ;
    bool mIsUsingFMQ = false;
    EventFlag* mFilterEventFlag;
    EventFlag* mFilterEventFlag;
    DemuxFilterEvent mFilterEvent;
    DemuxFilterEvent mFilterEvent;


@@ -160,6 +163,10 @@ class Filter : public IFilter {
    static void* __threadLoopFilter(void* user);
    static void* __threadLoopFilter(void* user);
    void filterThreadLoop();
    void filterThreadLoop();


    int createAvIonFd(int size);
    uint8_t* getIonBuffer(int fd, int size);
    native_handle_t* createNativeHandle(int fd);

    /**
    /**
     * Lock to protect writes to the FMQs
     * Lock to protect writes to the FMQs
     */
     */
@@ -181,6 +188,11 @@ class Filter : public IFilter {
    // TODO handle mulptiple Pes filters
    // TODO handle mulptiple Pes filters
    int mPesSizeLeft = 0;
    int mPesSizeLeft = 0;
    vector<uint8_t> mPesOutput;
    vector<uint8_t> mPesOutput;

    // A map from data id to ion handle
    std::map<uint64_t, int> mDataId2Avfd;
    uint64_t mLastUsedDataId = 1;
    int mAvBufferCopyCount = 0;
};
};


}  // namespace implementation
}  // namespace implementation
+1 −4
Original line number Original line Diff line number Diff line
@@ -63,9 +63,6 @@ Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
        return Result::INVALID_STATE;
        return Result::INVALID_STATE;
    }
    }


    // TODO dynamically allocate file to the source file
    mSourceStreamFile = FRONTEND_STREAM_FILE;

    mCallback->onEvent(FrontendEventType::LOCKED);
    mCallback->onEvent(FrontendEventType::LOCKED);
    return Result::SUCCESS;
    return Result::SUCCESS;
}
}
@@ -180,7 +177,7 @@ FrontendId Frontend::getFrontendId() {
}
}


string Frontend::getSourceFile() {
string Frontend::getSourceFile() {
    return mSourceStreamFile;
    return FRONTEND_STREAM_FILE;
}
}


}  // namespace implementation
}  // namespace implementation
+0 −1
Original line number Original line Diff line number Diff line
@@ -76,7 +76,6 @@ class Frontend : public IFrontend {
    FrontendId mId = 0;
    FrontendId mId = 0;


    const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts";
    const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts";
    string mSourceStreamFile;
    std::ifstream mFrontendData;
    std::ifstream mFrontendData;
};
};


Loading