Skip to content

Commit d85cb77

Browse files
slkanthiarjunbinu
authored andcommitted
Context based implementation for setBacklight and getBacklight
1 parent f04c156 commit d85cb77

File tree

3 files changed

+327
-3
lines changed

3 files changed

+327
-3
lines changed

AVOutput/AVOutputTV.cpp

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ namespace Plugin {
394394
registerMethod("resetMEMC", &AVOutputTV::resetMEMC, this);
395395
registerMethod("getMEMCCaps", &AVOutputTV::getMEMCCaps, this);
396396

397+
registerMethod("setBacklightV2", &AVOutputTV::setBacklightV2, this);
398+
registerMethod("getBacklightV2", &AVOutputTV::getBacklightV2, this);
399+
397400
registerMethod("getBacklightCapsV2", &AVOutputTV::getBacklightCapsV2, this);
398401
registerMethod("getBrightnessCapsV2", &AVOutputTV::getBrightnessCapsV2, this);
399402
registerMethod("getContrastCapsV2", &AVOutputTV::getContrastCapsV2, this);
@@ -509,6 +512,73 @@ namespace Plugin {
509512

510513
LOGINFO("Exit\n");
511514
}
515+
uint32_t AVOutputTV::getBacklightV2(const JsonObject& parameters, JsonObject& response)
516+
{
517+
LOGINFO("Entry: %s", __FUNCTION__);
518+
std::vector<tvConfigContext_t> validContexts = getValidContextsFromParameters(parameters);
519+
if (validContexts.empty()) {
520+
LOGERR("%s: No valid context found for the given parameters", __FUNCTION__);
521+
returnResponse(false);
522+
}
523+
// Only one valid context is expected in this simplified version
524+
const auto& ctx = validContexts.front();
525+
paramIndex_t indexInfo {
526+
.sourceIndex = static_cast<uint8_t>(ctx.videoSrcType),
527+
.pqmodeIndex = static_cast<uint8_t>(ctx.pq_mode),
528+
.formatIndex = static_cast<uint8_t>(ctx.videoFormatType)
529+
};
530+
int backlight = 0;
531+
int err = getLocalparam("Backlight", indexInfo, backlight, PQ_PARAM_BACKLIGHT);
532+
if (err == tvERROR_NONE) {
533+
response["backlight"] = backlight;
534+
LOGINFO("Exit: Backlight Value: %d", backlight);
535+
returnResponse(true);
536+
} else {
537+
LOGERR("Failed to get backlight. Error code: %d", err);
538+
returnResponse(false);
539+
}
540+
}
541+
uint32_t AVOutputTV::setBacklightV2(const JsonObject& parameters, JsonObject& response)
542+
{
543+
LOGINFO("Entry\n");
544+
std::string value;
545+
int backlight = 0;
546+
#define TODO_MOVE_TO_INIT 1
547+
#if TODO_MOVE_TO_INIT
548+
// Retrieve Backlight Caps (Initialization)
549+
LOGINFO("Calling GetBacklightCaps\n");
550+
tvError_t error = GetBacklightCaps(&m_maxBacklight, &m_backlightCaps);
551+
if (error == tvERROR_NONE) {
552+
LOGINFO("Backlight capabilities retrieved successfully. Max: %d\n", m_maxBacklight);
553+
} else {
554+
LOGERR("Failed to retrieve backlight capabilities. Error code: %d\n", error);
555+
returnResponse(false);
556+
}
557+
#endif
558+
// Input parameter validation
559+
LOGINFO("InputParm validation\n");
560+
value = parameters.HasLabel("backlight") ? parameters["backlight"].String() : "";
561+
returnIfParamNotFound(parameters,"backlight");
562+
try {
563+
backlight = std::stoi(value);
564+
} catch (const std::exception& e) {
565+
LOGERR("Invalid backlight value: %s. Exception: %s", value.c_str(), e.what());
566+
returnResponse(false);
567+
}
568+
if (backlight < 0 || backlight > m_maxBacklight) {
569+
LOGERR("Input value %d is out of range (0 - %d)", backlight, m_maxBacklight);
570+
returnResponse(false);
571+
}
572+
// Update the TV parameter
573+
LOGINFO("Updating AVOutputTVParamV2\n");
574+
int retval = updateAVoutputTVParamV2("set", "Backlight", parameters, PQ_PARAM_BACKLIGHT, backlight);
575+
if (retval != 0) {
576+
LOGERR("Failed to Save Backlight to ssm_data. retval: %d\n", retval);
577+
returnResponse(false);
578+
}
579+
LOGINFO("Exit: setBacklight successful to value: %d\n", backlight);
580+
returnResponse(true);
581+
}
512582

513583
uint32_t AVOutputTV::getCapsV2(
514584
const std::function<tvError_t( tvContextCaps_t**,int*, std::vector<std::string>&)>& getCapsFunc,
@@ -776,7 +846,7 @@ namespace Plugin {
776846
case tvDisplayMode_4x3: optionsArray.Add("TV 4X3 PILLARBOX"); break;
777847
case tvDisplayMode_ZOOM: optionsArray.Add("TV ZOOM"); break;
778848
case tvDisplayMode_FULL: optionsArray.Add("TV FULL"); break;
779-
default: break;
849+
default: break;
780850
}
781851
}
782852
rangeInfo["options"] = optionsArray;

AVOutput/AVOutputTV.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class AVOutputTV : public AVOutputBase {
188188
AVOutputTV& operator=(const AVOutputTV&) = delete;
189189
public:
190190
/*Get API's*/
191+
DECLARE_JSON_RPC_METHOD(getBacklightV2)
191192
DECLARE_JSON_RPC_METHOD(getBacklight)
192193
DECLARE_JSON_RPC_METHOD(getBrightness )
193194
DECLARE_JSON_RPC_METHOD(getContrast )
@@ -263,6 +264,7 @@ class AVOutputTV : public AVOutputBase {
263264
DECLARE_JSON_RPC_METHOD(getTVPictureModeCapsV2)
264265

265266
/*Set API's*/
267+
DECLARE_JSON_RPC_METHOD(setBacklightV2)
266268
DECLARE_JSON_RPC_METHOD(setBacklight)
267269
DECLARE_JSON_RPC_METHOD(setBrightness)
268270
DECLARE_JSON_RPC_METHOD(setContrast )
@@ -459,6 +461,17 @@ class AVOutputTV : public AVOutputBase {
459461
const JsonObject& parameters,
460462
JsonObject& response);
461463
JsonObject parseContextCaps(tvContextCaps_t* context_caps);
464+
// Helper functions to extract modes/sources/formats from parameters
465+
std::vector<tvPQModeIndex_t> extractPQModes(const JsonObject& parameters, bool& isCurrent);
466+
std::vector<tvVideoSrcType_t> extractVideoSources(const JsonObject& parameters, bool& isCurrent);
467+
std::vector<tvVideoFormatType_t> extractVideoFormats(const JsonObject& parameters, bool& isCurrent); // Checks if the given context matches the system's current context
468+
bool isCurrentContext(const tvConfigContext_t& ctx) const;
469+
template<typename T>
470+
std::vector<T> collectFieldFromCaps(std::function<T(const tvConfigContext_t&)> accessor) const;
471+
static bool isGlobalParam(const JsonArray& arr);
472+
int updateAVoutputTVParamV2(std::string action, std::string tr181ParamName,
473+
const JsonObject& parameters, tvPQParameterIndex_t pqParamIndex, int level);
474+
std::vector<tvConfigContext_t> getValidContextsFromParameters(const JsonObject& parameters);
462475

463476

464477
public:
@@ -468,6 +481,8 @@ class AVOutputTV : public AVOutputBase {
468481
char rfc_caller_id[RFC_BUFF_MAX];
469482
bool appUsesGlobalBackLightFactor;
470483
int pic_mode_index[PIC_MODES_SUPPORTED_MAX];
484+
int m_maxBacklight = 0;
485+
tvContextCaps_t *m_backlightCaps = nullptr;
471486

472487
static const std::map<int, std::string> pqModeMap;
473488
static const std::map<int, std::string> videoFormatMap;

AVOutput/AVOutputTVHelper.cpp

Lines changed: 241 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,8 +2311,7 @@ const std::map<int, std::string> AVOutputTV::pqModeMap = {
23112311
{PQ_MODE_STANDARD, "Standard"},
23122312
{PQ_MODE_VIVID, "Vivid"},
23132313
{PQ_MODE_ENERGY_SAVING, "EnergySaving"},
2314-
{PQ_MODE_CUSTOM, "Custom"},
2315-
{PQ_MODE_THEATER, "Movie"}
2314+
{PQ_MODE_CUSTOM, "Custom"}
23162315
};
23172316

23182317
const std::map<int, std::string> AVOutputTV::videoFormatMap = {
@@ -2333,6 +2332,246 @@ const std::map<int, std::string> AVOutputTV::videoSrcMap = {
23332332
{VIDEO_SOURCE_TUNER, "Tuner"}
23342333
};
23352334

2335+
template<typename T>
2336+
std::vector<T> AVOutputTV::collectFieldFromCaps(std::function<T(const tvConfigContext_t&)> accessor) const {
2337+
std::set<T> uniqueValues;
2338+
if (!m_backlightCaps || m_backlightCaps->num_contexts <= 0) {
2339+
LOGERR("collectFieldFromCaps: Backlight capabilities are null or empty");
2340+
return {};
2341+
}
2342+
2343+
for (size_t i = 0; i < m_backlightCaps->num_contexts; ++i) {
2344+
uniqueValues.insert(accessor(m_backlightCaps->contexts[i]));
2345+
}
2346+
2347+
return std::vector<T>(uniqueValues.begin(), uniqueValues.end());
2348+
}
2349+
2350+
bool AVOutputTV::isGlobalParam(const JsonArray& arr) {
2351+
return (arr.Length() == 0) ||
2352+
(arr.Length() == 1 && (
2353+
arr[0].String() == "Global" || arr[0].String() == "none"));
2354+
}
2355+
2356+
2357+
// Modular helper functions
2358+
std::vector<tvPQModeIndex_t> AVOutputTV::extractPQModes(const JsonObject& parameters, bool& isCurrent) {
2359+
std::vector<tvPQModeIndex_t> pqModes;
2360+
isCurrent = false;
2361+
2362+
if (!parameters.HasLabel("pictureMode")) return pqModes;
2363+
2364+
JsonArray pqmodeArray = parameters["pictureMode"].Array();
2365+
if (isGlobalParam(pqmodeArray)) {
2366+
pqModes = collectFieldFromCaps<tvPQModeIndex_t>([](const tvConfigContext_t& ctx) { return ctx.pq_mode; });
2367+
} else {
2368+
for (uint32_t i = 0; i < pqmodeArray.Length(); ++i) {
2369+
std::string modeStr = pqmodeArray[i].String();
2370+
if (modeStr == "Current") {
2371+
isCurrent = true;
2372+
char picMode[PIC_MODE_NAME_MAX] = {0};
2373+
if (getCurrentPictureMode(picMode)) {
2374+
for (const auto& entry : pqModeMap) {
2375+
if (entry.second == picMode) {
2376+
pqModes.push_back(static_cast<tvPQModeIndex_t>(entry.first));
2377+
}
2378+
}
2379+
}
2380+
} else {
2381+
for (const auto& entry : pqModeMap) {
2382+
if (entry.second == modeStr) {
2383+
pqModes.push_back(static_cast<tvPQModeIndex_t>(entry.first));
2384+
}
2385+
}
2386+
}
2387+
}
2388+
}
2389+
2390+
return pqModes;
2391+
}
2392+
2393+
std::vector<tvVideoSrcType_t> AVOutputTV::extractVideoSources(const JsonObject& parameters, bool& isCurrent) {
2394+
std::vector<tvVideoSrcType_t> sources;
2395+
isCurrent = false;
2396+
2397+
if (!parameters.HasLabel("videoSource")) return sources;
2398+
2399+
JsonArray sourceArray = parameters["videoSource"].Array();
2400+
if (isGlobalParam(sourceArray)) {
2401+
sources = collectFieldFromCaps<tvVideoSrcType_t>([](const tvConfigContext_t& ctx) { return ctx.videoSrcType; });
2402+
} else {
2403+
for (uint32_t i = 0; i < sourceArray.Length(); ++i) {
2404+
std::string srcStr = sourceArray[i].String();
2405+
if (srcStr == "Current") {
2406+
isCurrent = true;
2407+
tvVideoSrcType_t sourceIndex = VIDEO_SOURCE_IP;
2408+
if (GetCurrentVideoSource(&sourceIndex) == tvERROR_NONE) {
2409+
sources.push_back(sourceIndex);
2410+
}
2411+
} else {
2412+
for (const auto& entry : videoSrcMap) {
2413+
if (entry.second == srcStr) {
2414+
sources.push_back(static_cast<tvVideoSrcType_t>(entry.first));
2415+
}
2416+
}
2417+
}
2418+
}
2419+
}
2420+
2421+
return sources;
2422+
}
2423+
2424+
std::vector<tvVideoFormatType_t> AVOutputTV::extractVideoFormats(const JsonObject& parameters, bool& isCurrent) {
2425+
std::vector<tvVideoFormatType_t> formats;
2426+
isCurrent = false;
2427+
2428+
if (!parameters.HasLabel("videoFormat")) return formats;
2429+
2430+
JsonArray formatArray = parameters["videoFormat"].Array();
2431+
if (isGlobalParam(formatArray)) {
2432+
formats = collectFieldFromCaps<tvVideoFormatType_t>([](const tvConfigContext_t& ctx) { return ctx.videoFormatType; });
2433+
} else {
2434+
for (uint32_t i = 0; i < formatArray.Length(); ++i) {
2435+
std::string fmtStr = formatArray[i].String();
2436+
if (fmtStr == "Current") {
2437+
isCurrent = true;
2438+
tvVideoFormatType_t formatIndex = VIDEO_FORMAT_NONE;
2439+
GetCurrentVideoFormat(&formatIndex);
2440+
if (formatIndex == VIDEO_FORMAT_NONE) {
2441+
formatIndex = VIDEO_FORMAT_SDR;
2442+
}
2443+
formats.push_back(formatIndex);
2444+
} else {
2445+
for (const auto& entry : videoFormatMap) {
2446+
if (entry.second == fmtStr) {
2447+
formats.push_back(static_cast<tvVideoFormatType_t>(entry.first));
2448+
}
2449+
}
2450+
}
2451+
}
2452+
}
2453+
2454+
return formats;
2455+
}
2456+
2457+
2458+
std::vector<tvConfigContext_t> AVOutputTV::getValidContextsFromParameters(const JsonObject& parameters)
2459+
{
2460+
std::vector<tvConfigContext_t> validContexts;
2461+
2462+
if (!m_backlightCaps || m_backlightCaps->num_contexts <= 0) {
2463+
LOGERR("Backlight capabilities unavailable or empty");
2464+
return validContexts;
2465+
}
2466+
2467+
bool pqCurrent = false, srcCurrent = false, fmtCurrent = false;
2468+
2469+
std::vector<tvPQModeIndex_t> pqModes = extractPQModes(parameters, pqCurrent);
2470+
std::vector<tvVideoSrcType_t> sources = extractVideoSources(parameters, srcCurrent);
2471+
std::vector<tvVideoFormatType_t> formats = extractVideoFormats(parameters, fmtCurrent);
2472+
2473+
if (pqModes.empty() || sources.empty() || formats.empty()) {
2474+
LOGWARN("One or more parameter vectors are empty: PQModes[%zu], Sources[%zu], Formats[%zu]",
2475+
pqModes.size(), sources.size(), formats.size());
2476+
return validContexts;
2477+
}
2478+
2479+
std::set<std::tuple<int, int, int>> seenContexts;
2480+
2481+
for (const auto& pq : pqModes) {
2482+
for (const auto& fmt : formats) {
2483+
for (const auto& src : sources) {
2484+
tvConfigContext_t testCtx = { pq, fmt, src };
2485+
for (size_t i = 0; i < m_backlightCaps->num_contexts; ++i) {
2486+
const tvConfigContext_t& available = m_backlightCaps->contexts[i];
2487+
if (available.pq_mode == testCtx.pq_mode &&
2488+
available.videoFormatType == testCtx.videoFormatType &&
2489+
available.videoSrcType == testCtx.videoSrcType) {
2490+
std::tuple<int, int, int> key = std::make_tuple(pq, fmt, src);
2491+
if (seenContexts.find(key) == seenContexts.end()) {
2492+
validContexts.push_back(testCtx);
2493+
seenContexts.insert(key);
2494+
}
2495+
}
2496+
}
2497+
}
2498+
}
2499+
}
2500+
// std::tie(...) creates a tuple of values from struct a and b.
2501+
// The < operator for tuples performs lexicographic comparison, like dictionary order:
2502+
// It compares the first elements;If they're equal, it compares the second;If still equal, it compares the third.
2503+
std::sort(validContexts.begin(), validContexts.end(), [](const tvConfigContext_t& a, const tvConfigContext_t& b) {
2504+
return std::tie(a.pq_mode, a.videoFormatType, a.videoSrcType) <
2505+
std::tie(b.pq_mode, b.videoFormatType, b.videoSrcType);
2506+
});
2507+
2508+
#if DEBUG
2509+
for (const auto& ctx : validContexts) {
2510+
std::string pqStr = pqModeMap.count(ctx.pq_mode) ? pqModeMap.at(ctx.pq_mode) : std::to_string(ctx.pq_mode);
2511+
std::string fmtStr = videoFormatMap.count(ctx.videoFormatType) ? videoFormatMap.at(ctx.videoFormatType) : std::to_string(ctx.videoFormatType);
2512+
std::string srcStr = videoSrcMap.count(ctx.videoSrcType) ? videoSrcMap.at(ctx.videoSrcType) : std::to_string(ctx.videoSrcType);
2513+
LOGINFO("Valid Context - PQMode: %s, Format: %s, Source: %s", pqStr.c_str(), fmtStr.c_str(), srcStr.c_str());
2514+
}
2515+
#endif
2516+
2517+
return validContexts;
2518+
}
2519+
2520+
int AVOutputTV::updateAVoutputTVParamV2(std::string action, std::string tr181ParamName,
2521+
const JsonObject& parameters,
2522+
tvPQParameterIndex_t pqParamIndex, int level)
2523+
{
2524+
LOGINFO("Entry: %s", __FUNCTION__);
2525+
int ret = 0;
2526+
const bool isSet = (action == "set");
2527+
2528+
std::vector<tvConfigContext_t> validContexts = getValidContextsFromParameters(parameters);
2529+
LOGINFO("%s: Action: %s, Param: %s, Level: %d", __FUNCTION__, action.c_str(), tr181ParamName.c_str(), level);
2530+
2531+
if (validContexts.empty()) {
2532+
LOGWARN("%s: No valid contexts found for parameters", __FUNCTION__);
2533+
return ret;
2534+
}
2535+
2536+
for (const auto& ctx : validContexts) {
2537+
paramIndex_t paramIndex {
2538+
.sourceIndex = static_cast<uint8_t>(ctx.videoSrcType),
2539+
.pqmodeIndex = static_cast<uint8_t>(ctx.pq_mode),
2540+
.formatIndex = static_cast<uint8_t>(ctx.videoFormatType)
2541+
};
2542+
2543+
if (isSet) {
2544+
ret |= updateAVoutputTVParamToHAL(tr181ParamName, paramIndex, level, true);
2545+
ret |= SaveBacklight(static_cast<tvVideoSrcType_t>(paramIndex.sourceIndex),
2546+
paramIndex.pqmodeIndex,
2547+
static_cast<tvVideoFormatType_t>(paramIndex.formatIndex),
2548+
level);
2549+
2550+
std::string pqStr = pqModeMap.count(ctx.pq_mode) ? pqModeMap.at(ctx.pq_mode) : std::to_string(ctx.pq_mode);
2551+
std::string fmtStr = videoFormatMap.count(ctx.videoFormatType) ? videoFormatMap.at(ctx.videoFormatType) : std::to_string(ctx.videoFormatType);
2552+
std::string srcStr = videoSrcMap.count(ctx.videoSrcType) ? videoSrcMap.at(ctx.videoSrcType) : std::to_string(ctx.videoSrcType);
2553+
2554+
LOGINFO("Checking Context to SetBacklight - PQMode: %s, Format: %s, Source: %s", pqStr.c_str(), fmtStr.c_str(), srcStr.c_str());
2555+
2556+
if (isSetRequired(pqStr, srcStr, fmtStr)) {
2557+
LOGINFO("Proceed with SetBacklight: %d", level);
2558+
int setRet = SetBacklight(level);
2559+
ret |= setRet;
2560+
2561+
if (setRet != tvERROR_NONE) {
2562+
LOGERR("SetBacklight failed: %d", setRet);
2563+
return ret;
2564+
}
2565+
} else {
2566+
LOGINFO("SetBacklight not required for this context.");
2567+
}
2568+
}
2569+
}
2570+
2571+
LOGINFO("Exit: %s, Return Value: %d", __FUNCTION__, ret);
2572+
return ret;
2573+
}
2574+
23362575

23372576
tvError_t AVOutputTV::ReadJsonFile(JsonObject& root) {
23382577
std::ifstream file(CAPABLITY_FILE_NAMEV2);

0 commit comments

Comments
 (0)