Files
2026-08-24 10:03:24 +08:00

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();
};