Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 35 additions & 16 deletions AAMP-UVE-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -2716,28 +2716,47 @@ XREReceiver.onEvent("onDecoderAvailable", { decoderHandle: null });

## Inband (CEA608/708) Closed Caption Management (modern UVE/AAMP API)

Configure nativeCCRendering to true to signal use of subtec for caption rendering.
```
player.initConfig( { nativeCCRendering: true } );
Whether AAMP manages CC visibility and styles directly depends on the platform.
On **X1 devices**, CC is owned by **XREReceiver**, which runs independently of AAMP.
`nativeCCRendering` must remain `false` (the default) so AAMP does not interfere with
XREReceiver's trickplay muting, parental control gating, or style management.
On **platforms without XREReceiver**, the app must set `nativeCCRendering: true` to
hand AAMP ownership of the CC lifecycle via `PlayerCCManager`. Apps must refrain from
using AAMP CC APIs when `nativeCCRendering` is set to false.

### Platform Summary

| Device Class | `nativeCCRendering` | `player.setTextStyleOptions` |
|---|---|---|
| X1 (XREReceiver present) | `false` (default — do not set to true) | Do **not** call AAMP CC APIs; XREReceiver owns CC visibility and styling and applies guide-configured styles automatically |
| Non-XRE but pre-ENT-OS | `true` (must be explicitly enabled) | Required to apply caption styling; guide settings are not automatically propagated |
| ENT-OS (with Text Track plugin) | `true` | Not required; Text Track plugin automatically maps guide-configured caption styling |

### Configuration

For non-XRE platforms, opt AAMP into managing CC before calling `load()`:
```js
player.initConfig( { nativeCCRendering: true } );
```
Toggle CC display on or off at runtime:
```
player.setClosedCaptionStatus(true); // show captions (off by default)
player.setClosedCaptionStatus(false); // mute captions
```
Get/Set CC track at runtime:
```
player.getTextTrack(); // returns json object listing track attributes
player.setTextTrack(trackIdentifier);

Get/Set CC style options at runtime
### Runtime CC Control

Toggle CC display on or off:
```js
player.setClosedCaptionStatus(true); // show captions (off by default)
player.setClosedCaptionStatus(false); // hide captions
```
player.getTextStyleOptions(); // returns JSON object reflecting currently styling options
player.setTextStyleOptions(options); // TODO: include examples known to work with RDK CC Manager and/or subtec

On newer devices there is no need to call setTextStyleOptions, as the Text Track plugin will automatically map guide-configured caption styling.
Get/Set CC track:
```js
player.getTextTrack(); // returns JSON object listing track attributes
player.setTextTrack(trackIdentifier);
```

Get/Set CC style options:
```js
player.getTextStyleOptions(); // returns JSON object reflecting current styling options
player.setTextStyleOptions(options); // set styling options (see setTextStyleOptions API for format)
```

---
Expand Down
13 changes: 12 additions & 1 deletion AampConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,18 @@ typedef enum
eAAMPConfig_BulkTimedMetaReport, /**< Enabled Bulk event reporting for TimedMetadata*/
eAAMPConfig_BulkTimedMetaReportLive, /**< Enabled Bulk TimedMetadata event reporting for live stream */
eAAMPConfig_AvgBWForABR, /**< Enables usage of AverageBandwidth if available for ABR */
eAAMPConfig_NativeCCRendering, /**< If native CC rendering to be supported */
eAAMPConfig_NativeCCRendering, /**< Controls whether AAMP manages CC visibility/styles
directly via PlayerCCManager (true), or defers to an
external CC controller such as XREReceiver (false).
Default: false.
On X1 platforms XREReceiver owns CC; set to false so
AAMP does not interfere with trickplay muting, parental
control gating, or CC track selection.
On platforms without XREReceiver, set to true so AAMP
takes over the full CC lifecycle.
Note: Regardless of this flag, AAMP's CC APIs still
route through PlayerCCManager and apps must refrain from
using them when the flag is set to false.*/
eAAMPConfig_Subtec_subtitle, /**< Enable subtec-based subtitles */
eAAMPConfig_WebVTTNative, /**< Enable subtec-based subtitles */
eAAMPConfig_AsyncTune, /**< To enable Asynchronous tune */
Expand Down
26 changes: 13 additions & 13 deletions AampMPDParseHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* @fn AampMPDParseHelper
* @brief Default Constructor
*/
AampMPDParseHelper::AampMPDParseHelper() : mMPDInstance(NULL),mIsLiveManifest(false),mMinUpdateDurationMs(0),
AampMPDParseHelper::AampMPDParseHelper() : mMPDInstance(NULL),mIsLiveManifest(false),mMinUpdateDurationMs(0),
mIsFogMPD(false),
mAvailabilityStartTime(0.0),mPublishTime(0.0),mSegmentDurationSeconds(0),mTSBDepth(0.0),
mPresentationOffsetDelay(0.0),mMediaPresentationDuration(0),
Expand Down Expand Up @@ -654,7 +654,7 @@ double AampMPDParseHelper::GetPeriodEndTime(int periodIndex, uint64_t mLastPlayl
}

string startTimeStr = period->GetStart();
periodDurationMs = GetPeriodDuration(periodIndex,mLastPlaylistDownloadTimeMs,checkIFrame,IsUninterruptedTSB);
periodDurationMs = GetPeriodDuration(periodIndex,mLastPlaylistDownloadTimeMs,checkIFrame,IsUninterruptedTSB);
if((mMPDInstance->GetAvailabilityStarttime().empty()) && !(mMPDInstance->GetType() == "static"))
{
AAMPLOG_WARN("availabilityStartTime required to calculate period duration not present in MPD");
Expand All @@ -669,18 +669,18 @@ double AampMPDParseHelper::GetPeriodEndTime(int periodIndex, uint64_t mLastPlayl
{
AAMPLOG_INFO("Period startTime is not present in MPD, so calculating start time with previous period durations");
if(mIsLiveManifest)
{
{
periodStartMs = GetPeriodStartTime(periodIndex,mLastPlaylistDownloadTimeMs) * 1000 - (mAvailabilityStartTime * 1000);
}
else
{
periodStartMs = GetPeriodStartTime(periodIndex,mLastPlaylistDownloadTimeMs) * 1000;
periodStartMs = GetPeriodStartTime(periodIndex,mLastPlaylistDownloadTimeMs) * 1000;
}
}
else
{
periodStartMs = ParseISO8601Duration(startTimeStr.c_str()) + (aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset(period)* 1000);
}
}
periodEndTime = ((double)(periodStartMs + periodDurationMs) /1000);
if(mIsLiveManifest)
{
Expand Down Expand Up @@ -855,14 +855,14 @@ std::shared_ptr<SegmentTemplates> AampMPDParseHelper::GetSegmentTemplateForVideo
double AampMPDParseHelper::GetPeriodDuration(int periodIndex,uint64_t mLastPlaylistDownloadTimeMs, bool checkIFrame, bool IsUninterruptedTSB)
{
auto it = std::find_if(mMPDPeriodDetails.begin(), mMPDPeriodDetails.end(),
[periodIndex](const PeriodInfo& period) {
return period.periodIndex == periodIndex;
});

if (it != mMPDPeriodDetails.end()) {
// Found a matching PeriodInfo object, return its Duration
return it->duration;
}
[periodIndex](const PeriodInfo& period) {
return period.periodIndex == periodIndex;
});

if (it != mMPDPeriodDetails.end()) {
// Found a matching PeriodInfo object, return its Duration
return it->duration;
}
else
{
double periodDuration = 0;
Expand Down
16 changes: 8 additions & 8 deletions AampMPDUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,15 @@ double ComputeFragmentDuration( uint32_t duration, uint32_t timeScale )
* @param[out] referenced_duration referenced duration
* @retval true on success
*/
bool ParseSegmentIndexBox( const char *start, size_t size, int segmentIndex, unsigned int *referenced_size, float *referenced_duration, unsigned int *firstOffset)
bool ParseSegmentIndexBox( const uint8_t *start, size_t size, int segmentIndex, unsigned int *referenced_size, float *referenced_duration, unsigned int *firstOffset)
{
if (!start)
{
// If the fragment pointer is NULL then return from here, no need to process it further.
return false;
}

const char **f = &start;
const uint8_t **f = &start;

unsigned int len = Read32(f);
if (len != size)
Expand Down Expand Up @@ -297,14 +297,14 @@ bool ParseSegmentIndexBox( const char *start, size_t size, int segmentIndex, uns
* @param[in] n word size in bytes
* @retval 32 bit value
*/
uint64_t ReadWordHelper( const char **pptr, int n )
uint64_t ReadWordHelper( const uint8_t **pptr, int n )
{
const char *ptr = *pptr;
const uint8_t *ptr = *pptr;
uint64_t rc = 0;
while( n-- )
{
rc <<= 8;
rc |= (unsigned char)*ptr++;
rc |= *ptr++;
}
*pptr = ptr;
return rc;
Expand All @@ -315,7 +315,7 @@ uint64_t ReadWordHelper( const char **pptr, int n )
* @param pptr pointer to read from
* @retval word value
*/
unsigned int Read16( const char **pptr)
unsigned int Read16( const uint8_t **pptr)
{
return (unsigned int)ReadWordHelper(pptr,2);
}
Expand All @@ -325,7 +325,7 @@ unsigned int Read16( const char **pptr)
* @param pptr pointer to read from
* @retval word value
*/
unsigned int Read32( const char **pptr)
unsigned int Read32( const uint8_t **pptr)
{
return (unsigned int)ReadWordHelper(pptr,4);
}
Expand All @@ -335,7 +335,7 @@ unsigned int Read32( const char **pptr)
* @param pptr pointer to read from
* @retval word value
*/
uint64_t Read64( const char **pptr)
uint64_t Read64( const uint8_t **pptr)
{
return ReadWordHelper(pptr,8);
}
Expand Down
10 changes: 5 additions & 5 deletions AampMPDUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,36 +93,36 @@ void ConstructFragmentURL( std::string& fragmentUrl, const FragmentDescriptor *f
* @param[out] referenced_duration referenced duration
* @retval true on success
*/
bool ParseSegmentIndexBox( const char *start, size_t size, int segmentIndex, unsigned int *referenced_size, float *referenced_duration, unsigned int *firstOffset);
bool ParseSegmentIndexBox( const uint8_t *start, size_t size, int segmentIndex, unsigned int *referenced_size, float *referenced_duration, unsigned int *firstOffset);

/**
* @brief Read 16 word helper function
* @param pptr pointer to read from
* @retval word value
*/
unsigned int Read16( const char **pptr);
unsigned int Read16( const uint8_t **pptr);

/**
* @brief Read 32 word helper function
* @param pptr pointer to read from
* @retval word value
*/
unsigned int Read32( const char **pptr);
unsigned int Read32( const uint8_t **pptr);

/**
* @brief Read 64 word helper function
* @param pptr pointer to read from
* @retval word value
*/
uint64_t Read64( const char **pptr);
uint64_t Read64( const uint8_t **pptr);

/**
* @brief read unsigned multi-byte value and update buffer pointer
* @param[in] pptr buffer
* @param[in] n word size in bytes
* @retval 32 bit value
*/
uint64_t ReadWordHelper( const char **pptr, int n );
uint64_t ReadWordHelper( const uint8_t **pptr, int n );

/**
* @brief Replace matching token with given number
Expand Down
9 changes: 4 additions & 5 deletions AampTSBSessionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,8 @@ std::shared_ptr<CachedFragment> AampTSBSessionManager::Read(TsbInitDataPtr initf
cachedFragment->fragment.resize(len);

UnlockReadMutex();
TSB::Status status = mTSBStore->Read(uniqueUrl, cachedFragment->fragment.GetPtr(), len);
TSB::Status status = mTSBStore->Read(uniqueUrl, cachedFragment->fragment.data(), len);
LockReadMutex();

if (status != TSB::Status::OK)
{
AAMPLOG_WARN("Failure in read from TSBLibrary");
Expand Down Expand Up @@ -279,7 +278,7 @@ std::shared_ptr<CachedFragment> AampTSBSessionManager::Read(TsbFragmentDataPtr f
cachedFragment->fragment.resize(len);

UnlockReadMutex();
status = mTSBStore->Read(uniqueUrl, cachedFragment->fragment.GetPtr(), len);
status = mTSBStore->Read(uniqueUrl, cachedFragment->fragment.data(), len);
LockReadMutex();

if (status == TSB::Status::OK)
Expand Down Expand Up @@ -323,7 +322,7 @@ void AampTSBSessionManager::EnqueueWrite(std::string url, std::shared_ptr<Cached
// The PTS value will be restamped by the injector thread.
// This function is called in the context of the fetcher thread before the fragment is added to the list to be injected, to avoid
// any race conditions; so it cannot be moved to ProcessWriteQueue() or any other functions called from a different context.
double pts = mAamp->RecalculatePTS(static_cast<AampMediaType>(cachedFragment->type), cachedFragment->fragment.GetPtr(), cachedFragment->fragment.size());
double pts = mAamp->RecalculatePTS(static_cast<AampMediaType>(cachedFragment->type), cachedFragment->fragment.data(), cachedFragment->fragment.size());

// Get or create the datamanager for the mediatype
std::shared_ptr<AampTsbDataManager> dataManager = GetTsbDataManager(mediaType);
Expand Down Expand Up @@ -404,7 +403,7 @@ void AampTSBSessionManager::ProcessWriteQueue()
std::string uniqueUrl = ToUniqueUrl(writeData.url, writeData.cachedFragment->absPosition);

// Call TSBHandler Write operation
TSB::Status status = mTSBStore->Write(uniqueUrl, writeData.cachedFragment->fragment.GetPtr(), writeData.cachedFragment->fragment.size());
TSB::Status status = mTSBStore->Write(uniqueUrl, writeData.cachedFragment->fragment.data(), writeData.cachedFragment->fragment.size());

if (status == TSB::Status::OK)
{
Expand Down
6 changes: 3 additions & 3 deletions ElementaryProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ ElementaryProcessor::~ElementaryProcessor()
* @brief Process and send Elementary fragment
*/
bool ElementaryProcessor::sendSegment(AampGrowableBuffer* pBuffer,double position,double duration, double fragmentPTSoffset, bool discontinuous,
bool isInit,process_fcn_t processor, bool &ptsError)
bool isInit,process_fcn_t processor, bool &ptsError)
{
ptsError = false;
bool ret = true;
ret = setTuneTimePTS(pBuffer->GetPtr(), pBuffer->size(), position, duration, discontinuous, ptsError);
ret = setTuneTimePTS(pBuffer->data(), pBuffer->size(), position, duration, discontinuous, ptsError);
if (ret)
{
AAMPLOG_INFO("IsoBmffProcessor:: eMEDIATYPE_SUBTITLE sending segment at pos:%f dur:%f", position, duration);
Expand All @@ -76,7 +76,7 @@ void ElementaryProcessor::sendStream(AampGrowableBuffer *pBuffer,double position
/**
* @brief Process and set tune time PTS
*/
bool ElementaryProcessor::setTuneTimePTS(char *segment, const size_t& size, double position, double duration, bool discontinuous, bool &ptsError)
bool ElementaryProcessor::setTuneTimePTS(const uint8_t *segment, size_t size, double position, double duration, bool discontinuous, bool &ptsError)
{
ptsError = false;
bool ret = true;
Expand Down
4 changes: 2 additions & 2 deletions ElementaryProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,15 @@ class ElementaryProcessor : public MediaProcessor
/**
* @fn setTuneTimePTS
*
* @param[in] segment - fragment buffer pointer
* @param[in] segment - fragment buffer pointer (binary data)
* @param[in] size - fragment buffer size
* @param[in] position - position of fragment
* @param[in] duration - duration of fragment
* @param[in] discontinuous - true if discontinuous fragment
* @param[out] ptsError - flag indicates if any PTS error occurred
* @return false if base was set, true otherwise
*/
bool setTuneTimePTS(char *segment, const size_t& size, double position, double duration, bool discontinuous, bool &ptsError);
bool setTuneTimePTS(const uint8_t *segment, size_t size, double position, double duration, bool discontinuous, bool &ptsError);

/**
* @fn setBasePTS
Expand Down
17 changes: 11 additions & 6 deletions MediaStreamContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,15 @@ bool MediaStreamContext::CacheFragment(std::string fragmentUrl, unsigned int cur
/**
* @brief Cache Fragment Chunk
*/
bool MediaStreamContext::CacheFragmentChunk(AampMediaType actualType, const char *ptr, size_t size, std::string remoteUrl, uint64_t dnldStartTime, uint64_t durationInTicks)
bool MediaStreamContext::CacheFragmentChunk(AampMediaType actualType, const uint8_t *ptr, size_t size, std::string remoteUrl, uint64_t dnldStartTime, uint64_t durationInTicks)
{
AAMPLOG_DEBUG("[%s] Chunk Buffer Length %zu Remote URL %s", name, size, remoteUrl.c_str());

if (ptr == NULL && size > 0)
{
AAMPLOG_WARN("[%s] Null fragment pointer with non-zero size %zu", name, size);
return false;
}
bool ret = true;
if (WaitForCachedFragmentChunkInjected())
{
Expand Down Expand Up @@ -245,7 +250,7 @@ bool MediaStreamContext::CacheFragmentChunk(AampMediaType actualType, const char
*/
cachedFragment->PTSOffsetSec = GetContext()->mPTSOffset.inSeconds();

AAMPLOG_TRACE("[%s] cachedFragment %p ptr %p", name, cachedFragment, cachedFragment->fragment.GetPtr());
AAMPLOG_TRACE("[%s] cachedFragment %p ptr %p", name, cachedFragment, cachedFragment->fragment.data());
UpdateTSAfterChunkFetch();
}
else
Expand Down Expand Up @@ -638,7 +643,7 @@ void MediaStreamContext::OnFragmentDownloadSuccess(DownloadInfoPtr dlInfo)
(IsLocalTSBInjection() || (isPipelinePaused && !aamp->GetBufUnderFlowStatus())))
{
AAMPLOG_TRACE("[%s] cachedFragment %p ptr %p not injecting IsLocalTSBInjection %d, aamp->mSinkPaused %d, aamp->GetBufUnderFlowStatus() %d",
name, cachedFragment, cachedFragment->fragment.GetPtr(), IsLocalTSBInjection(), isPipelinePaused, aamp->GetBufUnderFlowStatus());
name, cachedFragment, cachedFragment->fragment.data(), IsLocalTSBInjection(), isPipelinePaused, aamp->GetBufUnderFlowStatus());
cachedFragment->fragment.Free();
auto timeBasedBufferManager = GetTimeBasedBufferManager();
if(timeBasedBufferManager)
Expand Down Expand Up @@ -870,7 +875,7 @@ bool MediaStreamContext::DownloadFragment(DownloadInfoPtr dlInfo)
{
unsigned int firstOffset;
ParseSegmentIndexBox(
IDX.GetPtr(),
IDX.data(),
IDX.size(),
0,
NULL,
Expand All @@ -887,7 +892,7 @@ bool MediaStreamContext::DownloadFragment(DownloadInfoPtr dlInfo)
for (int i = 0; i < dlInfo->fragmentIndex; i++)
{
if (ParseSegmentIndexBox(
IDX.GetPtr(),
IDX.data(),
IDX.size(),
i,
&referenced_size,
Expand All @@ -901,7 +906,7 @@ bool MediaStreamContext::DownloadFragment(DownloadInfoPtr dlInfo)
unsigned int referenced_size;
float fragmentDuration;
if (ParseSegmentIndexBox(
IDX.GetPtr(),
IDX.data(),
IDX.size(),
dlInfo->fragmentIndex,
&referenced_size,
Expand Down
Loading
Loading