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

Commit ba21a7f8 authored by shubang's avatar shubang
Browse files

Read data from file for DVR

Test: make; acoud create;
Change-Id: Ie8dcda51f4c5d0319d2b308a4e9c4652d1c4133d
parent 3c5d179a
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import java.io.FileDescriptor;
import java.util.List;

/**
@@ -708,6 +709,9 @@ public final class Tuner implements AutoCloseable {
        private native int nativeStopDvr();
        private native int nativeFlushDvr();
        private native int nativeClose();
        private native void nativeSetFileDescriptor(FileDescriptor fd);
        private native int nativeRead(int size);
        private native int nativeRead(byte[] bytes, int offset, int size);

        private Dvr() {}

@@ -780,6 +784,31 @@ public final class Tuner implements AutoCloseable {
        public int close() {
            return nativeClose();
        }

        /**
         * Sets file descriptor to read/write data.
         */
        public void setFileDescriptor(FileDescriptor fd) {
            nativeSetFileDescriptor(fd);
        }

        /**
         * Reads data from the file for DVR playback.
         */
        public int read(int size) {
            return nativeRead(size);
        }

        /**
         * Reads data from the buffer for DVR playback.
         */
        public int read(@NonNull byte[] bytes, int offset, int size) {
            if (size + offset > bytes.length) {
                throw new ArrayIndexOutOfBoundsException(
                        "Array length=" + bytes.length + ", offset=" + offset + ", size=" + size);
            }
            return nativeRead(bytes, offset, size);
        }
    }

    private Dvr openDvr(int type, int bufferSize) {
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ cc_library_shared {
        "libfmq",
        "libhidlbase",
        "liblog",
        "libnativehelper",
        "libutils",
    ],

+92 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/JNIHelp.h>

#pragma GCC diagnostic ignored "-Wunused-function"

@@ -92,7 +93,7 @@ Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus /*status*/) {
}

void DvrCallback::setDvr(const jobject dvr) {
    ALOGD("FilterCallback::setDvr");
    ALOGD("DvrCallback::setDvr");
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    mDvr = env->NewWeakGlobalRef(dvr);
}
@@ -101,6 +102,18 @@ void DvrCallback::setDvr(const jobject dvr) {

Dvr::Dvr(sp<IDvr> sp, jweak obj) : mDvrSp(sp), mDvrObj(obj) {}

Dvr::~Dvr() {
    EventFlag::deleteEventFlag(&mDvrMQEventFlag);
}

int Dvr::close() {
    Result r = mDvrSp->close();
    if (r == Result::SUCCESS) {
        EventFlag::deleteEventFlag(&mDvrMQEventFlag);
    }
    return (int)r;
}

sp<IDvr> Dvr::getIDvr() {
    return mDvrSp;
}
@@ -864,12 +877,28 @@ static int android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobjec
}

static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
    sp<Dvr> dvrSp = getDvr(env, dvr);
    sp<IDvr> iDvrSp = dvrSp->getIDvr();
    if (dvrSp == NULL) {
        ALOGD("Failed to configure dvr: dvr not found");
        return (int)Result::INVALID_STATE;
    }
    Result result = dvrSp->configure(getDvrSettings(env, settings));
    Result result = iDvrSp->configure(getDvrSettings(env, settings));
    MQDescriptorSync<uint8_t> dvrMQDesc;
    if (result == Result::SUCCESS) {
        Result getQueueDescResult = Result::UNKNOWN_ERROR;
        iDvrSp->getQueueDesc(
                [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
                    dvrMQDesc = desc;
                    getQueueDescResult = r;
                    ALOGD("getDvrQueueDesc");
                });
        if (getQueueDescResult == Result::SUCCESS) {
            dvrSp->mDvrMQ = std::make_unique<DvrMQ>(dvrMQDesc, true);
            EventFlag::createEventFlag(
                    dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
        }
    }
    return (int)result;
}

@@ -927,6 +956,62 @@ static int android_media_tv_Tuner_close_lnb(JNIEnv*, jobject) {
    return 0;
}

static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jobject jfd) {
    sp<Dvr> dvrSp = getDvr(env, dvr);
    if (dvrSp == NULL) {
        ALOGD("Failed to set FD for dvr: dvr not found");
    }
    dvrSp->mFd = jniGetFDFromFileDescriptor(env, jfd);
    ALOGD("set fd = %d", dvrSp->mFd);
}

static int android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jint size) {
    sp<Dvr> dvrSp = getDvr(env, dvr);
    if (dvrSp == NULL) {
        ALOGD("Failed to read dvr: dvr not found");
    }

    int available = dvrSp->mDvrMQ->availableToWrite();
    int write = std::min(size, available);

    DvrMQ::MemTransaction tx;
    int ret = 0;
    if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
        auto first = tx.getFirstRegion();
        auto data = first.getAddress();
        int length = first.getLength();
        int firstToWrite = std::min(length, write);
        ret = read(dvrSp->mFd, data, firstToWrite);
        if (ret < firstToWrite) {
            ALOGW("[DVR] file to MQ, first region: %d bytes to write, but %d bytes written",
                    firstToWrite, ret);
        } else if (firstToWrite < write) {
            ALOGD("[DVR] write second region: %d bytes written, %d bytes in total", ret, write);
            auto second = tx.getSecondRegion();
            data = second.getAddress();
            length = second.getLength();
            int secondToWrite = std::min(length, write - firstToWrite);
            ret += read(dvrSp->mFd, data, secondToWrite);
        }
        ALOGD("[DVR] file to MQ: %d bytes need to be written, %d bytes written", write, ret);
        if (!dvrSp->mDvrMQ->commitWrite(ret)) {
            ALOGE("[DVR] Error: failed to commit write!");
        }

    } else {
        ALOGE("dvrMq.beginWrite failed");
    }
    return ret;
}

static int android_media_tv_Tuner_read_dvr_to_array(
        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */,
        jint /* size */) {
    //TODO: impl
    return 0;
}


static const JNINativeMethod gTunerMethods[] = {
    { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
    { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
@@ -989,6 +1074,10 @@ static const JNINativeMethod gDvrMethods[] = {
    { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
    { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
    { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
    { "nativeSetFileDescriptor", "(Ljava/io/FileDescriptor;)V",
            (void *)android_media_tv_Tuner_dvr_set_fd },
    { "nativeRead", "(I)I", (void *)android_media_tv_Tuner_read_dvr },
    { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_dvr_to_array },
};

static const JNINativeMethod gLnbMethods[] = {
+9 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <fmq/MessageQueue.h>
#include <fstream>
#include <string>
#include <unordered_map>
#include <utils/RefBase.h>

@@ -58,6 +60,7 @@ using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
using ::android::hardware::tv::tuner::V1_0::RecordStatus;

using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
using DvrMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;

namespace android {

@@ -80,9 +83,15 @@ private:

struct Dvr : public RefBase {
    Dvr(sp<IDvr> sp, jweak obj);
    ~Dvr();
    int close();
    sp<IDvr> getIDvr();
    sp<IDvr> mDvrSp;
    jweak mDvrObj;
    std::unique_ptr<DvrMQ> mDvrMQ;
    EventFlag* mDvrMQEventFlag;
    std::string mFilePath;
    int mFd;
};

struct FilterCallback : public IFilterCallback {