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

Commit b5e3d164 authored by Amy Zhang's avatar Amy Zhang Committed by android-build-merger
Browse files

Merge changes from topic "play"

am: 297193ce

Change-Id: I022154516e912fd25163009b3f5d2f4d1d1c8639
parents ea37be51 297193ce
Loading
Loading
Loading
Loading
+216 −1
Original line number Diff line number Diff line
@@ -180,5 +180,220 @@ interface IDemux {
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    close() generates (Result result);
};

    /**
     * Add output to the demux
     *
     * It is used by the client to record output data from selected filters.
     *
     * @param bufferSize the buffer size of the output to be added. It's used to
     * create a FMQ(Fast Message Queue) to hold data from selected filters.
     * @param cb the callback for the demux to be used to send notifications
     * back to the client.
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         OUT_OF_MEMORY if failed for not enough memory.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    addOutput(uint32_t bufferSize, IDemuxCallback cb) generates (Result result);

    /**
     * Get the descriptor of the output's FMQ
     *
     * It is used by the client to get the descriptor of the output's Fast
     * Message Queue. The data in FMQ is muxed packets output from selected
     * filters. The packet's format is specifed by DemuxDataFormat in
     * DemuxOutputSettings.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         UNKNOWN_ERROR if failed for other reasons.
     * @return queue the descriptor of the output's FMQ
     */
    getOutputQueueDesc() generates (Result result, fmq_sync<uint8_t> queue);

    /**
     * Configure the demux's output.
     *
     * It is used by the client to configure the demux's output for recording.
     *
     * @param settings the settings of the demux's output.
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    configureOutput(DemuxOutputSettings settings) generates (Result result);

    /**
     * Attach one filter to the demux's output.
     *
     * It is used by the client to mux one filter's output to demux's output.
     *
     * @param filterId the ID of the attached filter.
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    attachOutputTsFilter(DemuxFilterId filterId) generates (Result result);

    /**
     * Detach one filter from the demux's output.
     *
     * It is used by the client to remove one filter's output from demux's
     * output.
     *
     * @param filterId the ID of the detached filter.
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    detachOutputTsFilter(DemuxFilterId filterId) generates (Result result);

    /**
     * Start to take data to the demux's output.
     *
     * It is used by the client to ask the output to start to take data from
     * attached filters.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    startOutput() generates (Result result);

    /**
     * Stop to take data to the demux's output.
     *
     * It is used by the client to ask the output to stop to take data from
     * attached filters.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    stopOutput() generates (Result result);

    /**
     * Flush unconsumed data in the demux's output.
     *
     * It is used by the client to ask the demux to flush the data which is
     * already produced but not consumed yet in the demux's output.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    flushOutput() generates (Result result);

    /**
     * Remove the demux's output.
     *
     * It is used by the client to remove the demux's output.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    removeOutput() generates (Result result);

    /**
     * Add input to the demux
     *
     * It is used by the client to add the demux's input for playback content.
     *
     * @param bufferSize the buffer size of the demux's input to be added.
     * It's used to create a FMQ(Fast Message Queue) to hold input data.
     * @param cb the callback for the demux to be used to send notifications
     * back to the client.
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         OUT_OF_MEMORY if failed for not enough memory.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    addInput(uint32_t bufferSize, IDemuxCallback cb) generates (Result result);

    /**
     * Get the descriptor of the input's FMQ
     *
     * It is used by the client to get the descriptor of the input's Fast
     * Message Queue. The data in FMQ is fed by client. Data format is specifed
     * by DemuxDataFormat in DemuxInputSettings.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         UNKNOWN_ERROR if failed for other reasons.
     * @return queue the descriptor of the output's FMQ
     */
    getInputQueueDesc() generates (Result result, fmq_sync<uint8_t> queue);

    /**
     * Configure the demux's input.
     *
     * It is used by the client to configure the demux's input for playback.
     *
     * @param settings the settings of the demux's input.
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    configureInput(DemuxInputSettings settings) generates (Result result);

    /**
     * Start to consume the data from the demux's input.
     *
     * It is used by the client to ask the demux to start to consume data from
     * the demux's input.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    startInput() generates (Result result);

    /**
     * Stop to consume the data from the demux's input.
     *
     * It is used by the client to ask the demux to stop to consume data from
     * the demux's input.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    stopInput() generates (Result result);

    /**
     * Flush unconsumed data in the demux's input.
     *
     * It is used by the client to ask the demux to flush the data which is
     * already produced but not consumed yet in the demux's input.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    flushInput() generates (Result result);

    /**
     * Remove the demux's input.
     *
     * It is used by the client to remove the demux's input.
     *
     * @return result Result status of the operation.
     *         SUCCESS if successful,
     *         INVALID_STATE if failed for wrong state.
     *         UNKNOWN_ERROR if failed for other reasons.
     */
    removeInput() generates (Result result);
};
+14 −0
Original line number Diff line number Diff line
@@ -15,5 +15,19 @@ interface IDemuxCallback {
     * @param status a new status of the demux filter.
     */
    oneway onFilterStatus(DemuxFilterId filterId, DemuxFilterStatus status);

    /**
     * Notify the client a new status of the demux's output.
     *
     * @param status a new status of the demux's output.
     */
    oneway onOutputStatus(DemuxOutputStatus status);

    /**
     * Notify the client a new status of the demux's input.
     *
     * @param status a new status of the demux's input.
     */
    oneway onInputStatus(DemuxInputStatus status);
};
+383 −117

File changed.

Preview size limit exceeded, changes collapsed.

+97 −24
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <android/hardware/tv/tuner/1.0/IDemux.h>
#include <fmq/MessageQueue.h>
#include <set>

using namespace std;

@@ -43,6 +44,8 @@ class Demux : public IDemux {
  public:
    Demux(uint32_t demuxId);

    ~Demux();

    virtual Return<Result> setFrontendDataSource(uint32_t frontendId) override;

    virtual Return<Result> close() override;
@@ -68,8 +71,58 @@ class Demux : public IDemux {

    virtual Return<void> getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) override;

    virtual Return<Result> addInput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) override;

    virtual Return<void> getInputQueueDesc(getInputQueueDesc_cb _hidl_cb) override;

    virtual Return<Result> configureInput(const DemuxInputSettings& settings) override;

    virtual Return<Result> startInput() override;

    virtual Return<Result> stopInput() override;

    virtual Return<Result> flushInput() override;

    virtual Return<Result> removeInput() override;

    virtual Return<Result> addOutput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) override;

    virtual Return<void> getOutputQueueDesc(getOutputQueueDesc_cb _hidl_cb) override;

    virtual Return<Result> configureOutput(const DemuxOutputSettings& settings) override;

    virtual Return<Result> attachOutputTsFilter(uint32_t filterId) override;

    virtual Return<Result> detachOutputTsFilter(uint32_t filterId) override;

    virtual Return<Result> startOutput() override;

    virtual Return<Result> stopOutput() override;

    virtual Return<Result> flushOutput() override;

    virtual Return<Result> removeOutput() override;

  private:
    virtual ~Demux();
    // A struct that passes the arguments to a newly created filter thread
    struct ThreadArgs {
        Demux* user;
        uint32_t filterId;
    };

    /**
     * Filter handlers to handle the data filtering.
     * They are also responsible to write the filtered output into the filter FMQ
     * and update the filterEvent bound with the same filterId.
     */
    Result startSectionFilterHandler(uint32_t filterId, vector<uint8_t> data);
    Result startPesFilterHandler(uint32_t filterId);
    Result startTsFilterHandler();
    Result startMediaFilterHandler(uint32_t filterId);
    Result startRecordFilterHandler(uint32_t filterId);
    Result startPcrFilterHandler();
    Result startFilterLoop(uint32_t filterId);

    /**
     * To create a FilterMQ with the the next available Filter ID.
     * Creating Event Flag at the same time.
@@ -77,60 +130,80 @@ class Demux : public IDemux {
     *
     * Return false is any of the above processes fails.
     */
    bool createAndSaveMQ(uint32_t bufferSize, uint32_t filterId);
    bool createFilterMQ(uint32_t bufferSize, uint32_t filterId);
    bool createMQ(FilterMQ* queue, EventFlag* eventFlag, uint32_t bufferSize);
    void deleteEventFlag();
    bool writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId);
    Result startSectionFilterHandler(DemuxFilterEvent event);
    Result startPesFilterHandler(DemuxFilterEvent& event);
    Result startTsFilterHandler();
    Result startMediaFilterHandler(DemuxFilterEvent& event);
    Result startRecordFilterHandler(DemuxFilterEvent& event);
    Result startPcrFilterHandler();
    bool writeSectionsAndCreateEvent(DemuxFilterEvent& event, uint32_t sectionNum);
    void filterThreadLoop(DemuxFilterEvent* event);
    static void* __threadLoop(void* data);
    bool readDataFromMQ();
    bool writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data);
    /**
     * A dispatcher to read and dispatch input data to all the started filters.
     * Each filter handler handles the data filtering/output writing/filterEvent updating.
     */
    bool filterAndOutputData();
    static void* __threadLoopFilter(void* data);
    static void* __threadLoopInput(void* user);
    void filterThreadLoop(uint32_t filterId);
    void inputThreadLoop();

    uint32_t mDemuxId;
    uint32_t mSourceFrontendId;
    /**
     * Record the last used filer id. Initial value is -1.
     * Record the last used filter id. Initial value is -1.
     * Filter Id starts with 0.
     */
    uint32_t mLastUsedFilterId = -1;
    /**
     * Record all the used filter Ids.
     * Any removed filter id should be removed from this set.
     */
    set<uint32_t> mUsedFilterIds;
    /**
     * Record all the unused filter Ids within mLastUsedFilterId.
     * Removed filter Id should be added into this set.
     * When this set is not empty, ids here should be allocated first
     * and added into usedFilterIds.
     */
    set<uint32_t> mUnusedFilterIds;
    /**
     * A list of created FilterMQ ptrs.
     * The array number is the filter ID.
     */
    vector<unique_ptr<FilterMQ>> mFilterMQs;
    vector<DemuxFilterType> mFilterTypes;
    vector<EventFlag*> mFilterEventFlags;
    vector<DemuxFilterEvent> mFilterEvents;
    unique_ptr<FilterMQ> mInputMQ;
    unique_ptr<FilterMQ> mOutputMQ;
    EventFlag* mInputEventFlag;
    EventFlag* mOutputEventFlag;
    /**
     * Demux callbacks used on filter events or IO buffer status
     */
    vector<sp<IDemuxCallback>> mDemuxCallbacks;
    /**
     * How many times a specific filter has written since started
     */
    vector<uint16_t> mFilterWriteCount;
    pthread_t mThreadId = 0;
    sp<IDemuxCallback> mInputCallback;
    sp<IDemuxCallback> mOutputCallback;
    // Thread handlers
    pthread_t mInputThread;
    pthread_t mOutputThread;
    vector<pthread_t> mFilterThreads;
    /**
     * If a specific filter's writing loop is still running
     */
    vector<bool> mThreadRunning;
    vector<bool> mFilterThreadRunning;
    bool mInputThreadRunning;
    /**
     * Lock to protect writes to the FMQs
     */
    std::mutex mWriteLock;
    /**
     * Lock to protect writes to the filter event
     */
    std::mutex mFilterEventLock;
    /**
     * How many times a filter should write
     * TODO make this dynamic/random/can take as a parameter
     */
    const uint16_t SECTION_WRITE_COUNT = 10;
    // A struct that passes the arguments to a newly created filter thread
    struct ThreadArgs {
        Demux* user;
        DemuxFilterEvent* event;
    };
};

}  // namespace implementation
+96 −0
Original line number Diff line number Diff line
@@ -479,3 +479,99 @@ typedef uint32_t AvSyncHwId;
 *  framework and apps.
 */
typedef vec<uint8_t> TunerKeyToken;

/**
 * A data format in demux's output or input according to ISO/IEC 13818-1.
 */
@export
enum DemuxDataFormat : uint32_t {
    /* Data is Transport Stream. */
    TS,
    /* Data is Packetized Elementary Stream. */
    PES,
    /* Data is Elementary Stream. */
    ES,
};

/**
 * A status of the demux's output.
 */
typedef DemuxFilterStatus DemuxOutputStatus;

/**
 *  The Settings for the demux's output.
 */
struct DemuxOutputSettings {
    /**
     * Register for interested status events so that the HAL can send these
     * status events back to client.
     */
    bitfield<DemuxOutputStatus> statusMask;
    /**
     * Unconsumed data size in bytes in the output. The HAL uses it to trigger
     * DemuxOutputStatus::LOW_WATER.
     */
    uint32_t lowThreshold;
    /**
     * Unconsumed data size in bytes in the output. The HAL uses it to trigger
     * DemuxOutputStatus::High_WATER.
     */
    uint32_t highThreshold;
    /**
     * The data format in the output.
     */
    DemuxDataFormat dataFormat;
    /**
     * The packet size in bytes in the output.
     */
    uint8_t packetSize;
};

/**
 * A status of the demux's input.
 */
@export
enum DemuxInputStatus : uint32_t {
    /**
     * The space of the demux's input is empty.
     */
    SPACE_EMPTY        = 1 << 0,
    /**
     * The spece of the demux's input is almost empty.
     */
    SPACE_ALMOST_EMPTY = 1 << 1,
    /**
     * The space of the demux's input is almost full.
     */
    SPACE_ALMOST_FULL  = 1 << 2,
    /**
     * The space of the demux's input is full.
     */
    SPACE_FULL         = 1 << 3,
};

struct DemuxInputSettings {
    /**
     * Register for interested status events so that the HAL can send these
     * status events back to client.
     */
    bitfield<DemuxInputStatus> statusMask;
    /**
     * Unused space size in bytes in the input. The HAL uses it to trigger
     * DemuxInputStatus::SPACE_ALMOST_EMPTY.
     */
    uint32_t lowThreshold;
    /**
     * Unused space size in bytes in the input. The HAL uses it to trigger
     * DemuxInputStatus::SPACE_ALMOST_FULL.
     */
    uint32_t highThreshold;
    /**
     * The data format in the input.
     */
    DemuxDataFormat dataFormat;
    /**
     * The packet size in bytes in the input.
     */
    uint8_t packetSize;
};
Loading