140 lines
5.2 KiB
C++
140 lines
5.2 KiB
C++
/*
|
|
* Copyright (C) 2014-2025 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* All information contained herein is Amlogic confidential.
|
|
*
|
|
* This software is provided to you pursuant to Software License Agreement
|
|
* (SLA) with Amlogic Inc ("Amlogic"). This software may be used
|
|
* only in accordance with the terms of this agreement.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification is strictly prohibited without prior written permission from
|
|
* Amlogic.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <mutex>
|
|
#include <thread>
|
|
// maybe we can use std::chrono::steady_clock
|
|
// how to program it with longlong time?
|
|
#include <utils/Looper.h>
|
|
#include <utils/Mutex.h>
|
|
#include <utils/Timers.h>
|
|
|
|
#include "Parser.h"
|
|
#include "Render.h"
|
|
#include "ai_translation/SubtitleAiTranslation.h"
|
|
|
|
using android::Looper;
|
|
using android::Message;
|
|
using android::Mutex;
|
|
using android::sp;
|
|
|
|
class Presentation : public ParserSubdataNotifier,
|
|
public SubtitleAiTranslation::ISubtitleAiTranslationObserver {
|
|
public:
|
|
explicit Presentation(bool registeredOnDataCB);
|
|
virtual ~Presentation();
|
|
|
|
bool notifyStartTimeStamp(int64_t startpts);
|
|
bool syncCurrentPresentTime(int64_t pts);
|
|
|
|
bool startPresent(std::shared_ptr<Parser> parser);
|
|
bool stopPresent();
|
|
bool resetForSeek();
|
|
bool combineSamePtsSubtitle(std::shared_ptr<AML_SPUVAR> spu1, std::shared_ptr<AML_SPUVAR> spu2);
|
|
bool show();
|
|
bool hide();
|
|
|
|
virtual void notifySubdataAdded();
|
|
|
|
void dump(int fd, const char* prefix);
|
|
|
|
// This is the trigger of Ai translation
|
|
bool setSubTranslationLanguage(const std::string& srcLang, const std::string& dstLang);
|
|
|
|
// ISubtitleAiTranslationObserver
|
|
void onReceiveTranslatedText(const std::shared_ptr<AML_SPUVAR>& item) override;
|
|
void onError(const std::string& reason) override;
|
|
|
|
private:
|
|
class MessageProcess : public android::MessageHandler {
|
|
public:
|
|
static const int MSG_PTS_TIME_UPDATED = 0xBB10100;
|
|
static const int MSG_PTS_TIME_CHECK_SPU = 0xBB10101;
|
|
static const int MSG_RESET_MESSAGE_QUEUE = 0xCB10100;
|
|
|
|
MessageProcess(Presentation* present, bool isExtSub);
|
|
virtual ~MessageProcess();
|
|
void looperLoop();
|
|
void join();
|
|
bool notifyMessage(int what);
|
|
|
|
private:
|
|
std::shared_ptr<std::thread> mLooperThread;
|
|
Presentation* mPresent; // this use shared_ptr, decouple with sp raw pointer here
|
|
bool mIsExtSub;
|
|
bool mRequestThreadExit;
|
|
void handleMessage(const Message& message);
|
|
void handleExtSub(const Message& message);
|
|
void handleStreamSub(const Message& message);
|
|
std::shared_ptr<AML_SPUVAR> mLastShowingSpu;
|
|
sp<Looper> mLooper;
|
|
};
|
|
|
|
int64_t mCurrentPresentRelativeTime = 0;
|
|
int64_t mStartPresentMonoTimeNs = 0;
|
|
int64_t mOrigStartTimeModifier = 0;
|
|
int64_t mStartTimeModifier = 0;
|
|
bool mRegisteredOnDataCB = false;
|
|
|
|
std::shared_ptr<Parser> mParser;
|
|
std::shared_ptr<Render> mRender;
|
|
|
|
// for present subtitle.
|
|
std::list<std::shared_ptr<AML_SPUVAR>> mEmittedShowingSpu;
|
|
std::list<std::shared_ptr<AML_SPUVAR>> mEmittedFaddingSpu;
|
|
|
|
/* this use android sp, so de-couple with shared_ptr */
|
|
sp<MessageProcess> mMsgProcess;
|
|
|
|
// since mMsgProcess is a pointer here
|
|
// we need a mutex to protect it
|
|
std::mutex mMutex;
|
|
|
|
std::unique_ptr<SubtitleAiTranslation> mAiTranslation;
|
|
std::mutex mRenderMutex;
|
|
void send2RenderDisplay(std::shared_ptr<AML_SPUVAR> spu);
|
|
void showSubtitleItem(const std::shared_ptr<AML_SPUVAR>& spu, int type);
|
|
void hideSubtitleItem(const std::shared_ptr<AML_SPUVAR>& spu);
|
|
void removeSubtitleItem(const std::shared_ptr<AML_SPUVAR>& spu);
|
|
void resetSubtitleItem();
|
|
|
|
// There is a latency delay between media sync and display as the MEMC feature in T5M,
|
|
// the actual delay time is calculated in display module, the latency delay is around:
|
|
// actual_delay = actual_delay + frc_delay (frc_delay = 3.5 * vpp_vsync)
|
|
// This function is to get the frc_delay minisecond from /dev/frc, which is used to adjust the
|
|
// subtitle presentation time.
|
|
// FRC = Frequency Rate Convert
|
|
// MEMC = Motion Estimation and Motion Compensation
|
|
int mLatestFrcTimeMs = 0;
|
|
// FRC latency time will be stable and fixed in 1 second after playback.
|
|
bool mIsFrcDelayTimeDoubleConfirmed = false;
|
|
uint64_t mFrcUpdateClock = 0;
|
|
void adjustStartTimeByFrcIfNeed();
|
|
int getFrcDelayTimeMs();
|
|
};
|