RDK Documentation (Open Sourced RDK Components)
aampoutputprotection.cpp
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's license file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2018 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 /**
21  * @file aampoutputprotection.cpp
22  * @brief Output protection management for Aamp
23  */
24 
25 
26 #include "aampoutputprotection.h"
27 #include "config.h"
28 #include "priv_aamp.h"
29 
30 
31 //#define DEBUG_FUNC_TRACE 1
32 #ifdef DEBUG_FUNC_TRACE
33 #define DEBUG_FUNC fprintf(stdout, "%s --> %d\n", __FUNCTION__, __LINE__);
34 #else
35 #define DEBUG_FUNC
36 #endif
37 
38 /**< Static local variables */
39 AampOutputProtection* s_pAampOP = NULL;
40 
41 #define DISPLAY_WIDTH_UNKNOWN -1 /**< Parsing failed for getResolution().getName(); */
42 #define DISPLAY_HEIGHT_UNKNOWN -1 /**< Parsing failed for getResolution().getName(); */
43 #define DISPLAY_RESOLUTION_NA 0 /**< Resolution not available yet or not connected to HDMI */
44 
45 
46 /**
47  * @brief AampOutputProtection Constructor
48  */
50 : m_sourceWidth(0)
51 , m_sourceHeight(0)
52 , m_displayWidth(DISPLAY_RESOLUTION_NA)
53 , m_displayHeight(DISPLAY_RESOLUTION_NA)
54 , m_isHDCPEnabled(false)
55 , m_gstElement(NULL)
56 , m_hdcpCurrentProtocol(dsHDCP_VERSION_MAX)
57 , m_opProtectMutex()
58 {
59  DEBUG_FUNC;
60  pthread_mutex_init(&m_opProtectMutex,NULL);
61 
62 #ifndef USE_OPENCDM
63 #if defined(USE_PLAYREADY)
64  memset(&m_minOPLevels, 0, sizeof(MinOPLevelsplayReady));
65 #endif
66 #endif
67 
68  // Get initial HDCP status
69  SetHDMIStatus();
70 
71 #ifdef IARM_MGR
72  // Register IARM callbacks
73  IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, HDMIEventHandler);
74  IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDCP_STATUS, HDMIEventHandler);
75  IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE, ResolutionHandler);
76 #endif //IARM_MGR
77 }
78 
79 /**
80  * @brief AampOutputProtection Destructor
81  */
83 {
84  DEBUG_FUNC;
85 
86 #ifdef IARM_MGR
87  // Remove IARM callbacks
88  IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, HDMIEventHandler);
89  IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDCP_STATUS, HDMIEventHandler);
90  IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE, ResolutionHandler);
91 #endif //IARM_MGR
92 
93  s_pAampOP = NULL;
94 
95  pthread_mutex_destroy(&m_opProtectMutex);
96 }
97 
98 
99 /**
100  * @brief Check if source is UHD using video decoder dimensions
101  */
103 {
104  bool retVal = false;
105 
106 // DEBUG_FUNC;
107 
108 #ifdef CONTENT_4K_SUPPORTED
109  static gint sourceHeight = 0;
110  static gint sourceWidth = 0;
111 
112  if(m_gstElement == NULL) {
113  // Value not set, since there is no
114  // decoder yet the output size can not
115  // be determined
116  return false;
117  }
118 
119  g_object_get(m_gstElement, "video_height", &sourceHeight, NULL);
120  g_object_get(m_gstElement, "video_width", &sourceWidth, NULL);
121 
122  if(sourceWidth != m_sourceWidth || sourceHeight != m_sourceHeight) {
123  AAMPLOG_WARN("viddec (%p) --> says width %d, height %d", m_gstElement, sourceWidth, sourceHeight);
124  m_sourceWidth = sourceWidth;
125  m_sourceHeight = sourceHeight;
126  }
127  if(sourceWidth != 0 && sourceHeight != 0 &&
128  (sourceWidth >= UHD_WITDH || sourceHeight >= UHD_HEIGHT) ) {
129  // Source Material is UHD
130  retVal = true;
131  }
132 #endif
133  return retVal;
134 }
135 
136 
137 /**
138  * @brief Set the HDCP status using data from DeviceSettings
139  */
141 {
142 #ifdef IARM_MGR
143  bool isConnected = false;
144  bool isHDCPCompliant = false;
145  bool isHDCPEnabled = true;
146  dsHdcpProtocolVersion_t hdcpProtocol = dsHDCP_VERSION_MAX;
147  dsHdcpProtocolVersion_t hdcpReceiverProtocol = dsHDCP_VERSION_MAX;
148  dsHdcpProtocolVersion_t hdcpCurrentProtocol = dsHDCP_VERSION_MAX;
149 
150  DEBUG_FUNC;
151 
152 
153  try {
154  //Get the HDMI port
157  isConnected = vPort.isDisplayConnected();
158  hdcpProtocol = (dsHdcpProtocolVersion_t)vPort.getHDCPProtocol();
159  if(isConnected) {
160  isHDCPCompliant = (vPort.getHDCPStatus() == dsHDCP_STATUS_AUTHENTICATED);
161  isHDCPEnabled = vPort.isContentProtected();
162  hdcpReceiverProtocol = (dsHdcpProtocolVersion_t)vPort.getHDCPReceiverProtocol();
163  hdcpCurrentProtocol = (dsHdcpProtocolVersion_t)vPort.getHDCPCurrentProtocol();
164  //get the resolution of the TV
165  int width,height;
166  int iResID = vPort.getResolution().getPixelResolution().getId();
167  if( device::PixelResolution::k720x480 == iResID )
168  {
169  width = 720;
170  height = 480;
171  }
172  else if( device::PixelResolution::k720x576 == iResID )
173  {
174  width = 720;
175  height = 576;
176  }
177  else if( device::PixelResolution::k1280x720 == iResID )
178  {
179  width = 1280;
180  height = 720;
181  }
182  else if( device::PixelResolution::k1920x1080 == iResID )
183  {
184  width = 1920;
185  height = 1080;
186  }
187  else if( device::PixelResolution::k3840x2160 == iResID )
188  {
189  width = 3840;
190  height = 2160;
191  }
192  else if( device::PixelResolution::k4096x2160 == iResID )
193  {
194  width = 4096;
195  height = 2160;
196  }
197  else
198  {
199  width = DISPLAY_WIDTH_UNKNOWN;
200  height = DISPLAY_HEIGHT_UNKNOWN;
201  std::string _res = vPort.getResolution().getName();
202  AAMPLOG_ERR(" ERR parse failed for getResolution().getName():%s id:%d",(_res.empty() ? "NULL" : _res.c_str()),iResID);
203  }
204 
205  SetResolution(width, height);
206  }
207  else {
208  isHDCPCompliant = false;
209  isHDCPEnabled = false;
211  }
212 
214  }
215  catch (const std::exception e) {
216  AAMPLOG_WARN("DeviceSettings exception caught in ");
217  }
218 
219  m_isHDCPEnabled = isHDCPEnabled;
220 
221  if(m_isHDCPEnabled) {
222  if(hdcpCurrentProtocol == dsHDCP_VERSION_2X) {
223  m_hdcpCurrentProtocol = hdcpCurrentProtocol;
224  }
225  else {
226  m_hdcpCurrentProtocol = dsHDCP_VERSION_1X;
227  }
228  AAMPLOG_WARN(" detected HDCP version %s", m_hdcpCurrentProtocol == dsHDCP_VERSION_2X ? "2.x" : "1.4");
229  }
230  else {
231  AAMPLOG_WARN("DeviceSettings HDCP is not enabled");
232  }
233 
234  if(!isConnected) {
235  m_hdcpCurrentProtocol = dsHDCP_VERSION_1X;
236  AAMPLOG_WARN(" GetHDCPVersion: Did not detect HDCP version defaulting to 1.4 (%d)", m_hdcpCurrentProtocol);
237  }
238 #else
239  // No video output on device mark HDCP protection as valid
240  m_hdcpCurrentProtocol = dsHDCP_VERSION_1X;
241  m_isHDCPEnabled = true;
242 #endif // IARM_MGR
243 
244  return;
245 }
246 
247 /**
248  * @brief Set values of resolution member variable
249  */
250 void AampOutputProtection::SetResolution(int width, int height)
251 {
252  DEBUG_FUNC;
253  AAMPLOG_WARN(" Resolution : width %d height:%d",width,height);
254  m_displayWidth = width;
255  m_displayHeight = height;
256 }
257 
258 /**
259  * @brief gets display resolution
260  */
261 void AampOutputProtection::GetDisplayResolution(int &width, int &height)
262 {
263  width = m_displayWidth;
264  height = m_displayHeight;
265 }
266 
267 #ifndef USE_OPENCDM
268 #if defined(USE_PLAYREADY)
269 // TODO: this PlayReady-specific logic should ideally be split out into a separate subclass.
270 // Note that it is only used by the (non-OCDM) PlayReadyDRMSession class.
271 
272 // Pleayrady OP Callback
273 
274 /**
275  * @brief Pleayrady OP Callback to ensure HDCP compliance
276  * @retval DRM_SUCCESS if no errors encountered
277  */
278 DRM_RESULT DRM_CALL AampOutputProtection::PR_OP_Callback(const DRM_VOID *f_pvOutputLevelsData,
279  DRM_POLICY_CALLBACK_TYPE f_dwCallbackType,
280  const DRM_VOID *data)
281 {
282  DRM_RESULT res = DRM_SUCCESS;
283 
284  DEBUG_FUNC;
285 
286  AAMPLOG_WARN("outputLevelsCallback outputLevels=%p callbackType=%u data=%p",
287  f_pvOutputLevelsData, static_cast<uint32_t>(f_dwCallbackType), data);
288 
290 
291  // We only care about the play callback.
292  if (f_dwCallbackType != DRM_PLAY_OPL_CALLBACK)
293  return DRM_SUCCESS;
294 
295  // Pull out the protection levels.
296  DRM_PLAY_OPL_EX* pr_Levels = (DRM_PLAY_OPL_EX*)f_pvOutputLevelsData;
297  MinOPLevelsplayReady* pm_Levels = (MinOPLevelsplayReady*)data;
298 
299  if(pm_Levels != NULL) {
300  pm_Levels->compressedDigitalVideo = pr_Levels->minOPL.wCompressedDigitalVideo;
301  pm_Levels->uncompressedDigitalVideo = pr_Levels->minOPL.wUncompressedDigitalVideo;
302  pm_Levels->analogVideo = pr_Levels->minOPL.wAnalogVideo;
303  pm_Levels->compressedDigitalAudio = pr_Levels->minOPL.wCompressedDigitalAudio;
304  pm_Levels->uncompressedDigitalAudio = pr_Levels->minOPL.wUncompressedDigitalAudio;
305 
306  // At actual device, enable/disable device output protection will be needed
307  // upon receiving this protection information.
308  AAMPLOG_WARN(" compressed digital %d, uncompressed digital %d, analog video %d",
309  pm_Levels->compressedDigitalVideo,
310  pm_Levels->uncompressedDigitalVideo,
311  pm_Levels->analogVideo);
312 
313  // HDCP needs to be turned on for levels 270 and higher
314  if(pm_Levels->uncompressedDigitalVideo >= 270) {
315  // Get current HDCP level.
316  if(pInstance->m_isHDCPEnabled) {
317  // We have an HDCP connection
318  if(pInstance->m_hdcpCurrentProtocol == dsHDCP_VERSION_1X ||
319  pInstance->m_hdcpCurrentProtocol == dsHDCP_VERSION_2X) {
320  // We have an active HDCP connection
321  AAMPLOG_WARN(" HDCP is enabled version --> %d", pInstance->m_hdcpCurrentProtocol);
322  res = DRM_SUCCESS;
323  }
324  }
325  else {
326  AAMPLOG_WARN(" HDCP --> is not connected", pInstance->m_hdcpCurrentProtocol);
327  res = DRM_E_FAIL;
328  }
329  }
330  else {
331  AAMPLOG_WARN(" HDCP --> is not required, current version %d, uncompressedDigitalVideo = %d",
332  pInstance->m_hdcpCurrentProtocol, pm_Levels->uncompressedDigitalVideo);
333  res = DRM_SUCCESS;
334  }
335  }
336 
337  pInstance->Release();
338 
339  // All done.
340  return res;
341 }
342 #endif
343 #endif
344 
345 #ifdef IARM_MGR
346 
347 /**
348  * @brief IARM event handler for HDCP and HDMI hot plug events
349  */
350 void AampOutputProtection::HDMIEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len)
351 {
352  DEBUG_FUNC;
353 
355 
356  switch (eventId) {
358  {
360  int hdmi_hotplug_event = eventData->data.hdmi_hpd.event;
361 
362  const char *hdmihotplug = (hdmi_hotplug_event == dsDISPLAY_EVENT_CONNECTED) ? "connected" : "disconnected";
363  AAMPLOG_WARN(" Received IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG event data:%d status: %s",
364  hdmi_hotplug_event, hdmihotplug);
365 
366  pInstance->SetHDMIStatus();
367 
368  break;
369  }
371  {
373  int hdcpStatus = eventData->data.hdmi_hdcp.hdcpStatus;
374  const char *hdcpStatusStr = (hdcpStatus == dsHDCP_STATUS_AUTHENTICATED) ? "authenticated" : "authentication failure";
375  AAMPLOG_WARN(" Received IARM_BUS_DSMGR_EVENT_HDCP_STATUS event data:%d status:%s",
376  hdcpStatus, hdcpStatusStr);
377 
378  pInstance->SetHDMIStatus();
379  break;
380  }
381  default:
382  AAMPLOG_WARN(" Received unknown IARM bus event:%d", eventId);
383  break;
384  }
385 
386  pInstance->Release();
387 }
388 
389 /**
390  * @brief IARM event handler for resolution changes
391  */
392 void AampOutputProtection::ResolutionHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len)
393 {
394  DEBUG_FUNC;
395 
397 
398  switch (eventId) {
400  AAMPLOG_WARN(" Received IARM_BUS_DSMGR_EVENT_RES_PRECHANGE ");
401  break;
403  {
404  int width = 1280;
405  int height = 720;
406 
408  width = eventData->data.resn.width ;
409  height = eventData->data.resn.height ;
410 
411  AAMPLOG_WARN(" Received IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE event width : %d height : %d", width, height);
412  pInstance->SetResolution(width, height);
413  break;
414  }
415  default:
416  AAMPLOG_WARN(" Received unknown resolution event %d", eventId);
417  break;
418  }
419 
420  pInstance->Release();
421 }
422 
423 #endif //IARM_MGR
424 
425 /**
426  * @brief Check if AampOutputProcectionInstance active
427  */
429 {
430  bool retval = false;
431 
432  if(s_pAampOP != NULL) {
433  retval = true;
434  }
435  return retval;
436 }
437 
438 /**
439  * @brief Singleton for object creation
440  */
442 {
443  DEBUG_FUNC;
444  if(s_pAampOP == NULL) {
445  s_pAampOP = new AampOutputProtection();
446  }
447  s_pAampOP->AddRef();
448 
449  return s_pAampOP;
450 }
AampOutputProtection::IsAampOutputProcectionInstanceActive
static bool IsAampOutputProcectionInstanceActive()
Check if AampOutputProcectionInstance active.
Definition: aampoutputprotection.cpp:428
device::VideoOutputPort::isContentProtected
bool isContentProtected() const
This API is used to Check if the port or the content output on the port has DTCP or HDCP in use.
Definition: videoOutputPort.cpp:538
aampoutputprotection.h
Output protection management for Aamp.
dsHDCP_STATUS_AUTHENTICATED
@ dsHDCP_STATUS_AUTHENTICATED
Definition: dsTypes.h:416
device::PixelResolution::k1280x720
static const int k1280x720
Indicates 1280x720 video resolution.
Definition: pixelResolution.hpp:57
device::VideoOutputPort::isDisplayConnected
bool isDisplayConnected() const
This API is used to Check if the port is currently connected to any display device.
Definition: videoOutputPort.cpp:381
device::VideoOutputPort
Class extending enumerable to implement the videoooutputport interface.
Definition: videoOutputPort.hpp:59
DISPLAY_RESOLUTION_NA
#define DISPLAY_RESOLUTION_NA
Definition: aampoutputprotection.cpp:43
AampOutputProtection::GetDisplayResolution
void GetDisplayResolution(int &width, int &height)
gets display resolution
Definition: aampoutputprotection.cpp:261
dsHDCP_VERSION_MAX
@ dsHDCP_VERSION_MAX
Definition: dsTypes.h:407
DISPLAY_HEIGHT_UNKNOWN
#define DISPLAY_HEIGHT_UNKNOWN
Definition: aampoutputprotection.cpp:42
AampOutputProtection::IsSourceUHD
bool IsSourceUHD()
Check if source is UHD using video decoder dimensions.
Definition: aampoutputprotection.cpp:102
IARM_Bus_RegisterEventHandler
IARM_Result_t IARM_Bus_RegisterEventHandler(const char *ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler)
This API register to listen to event and provide the callback function for event notification....
Definition: iarmMgrMocks.cpp:43
AampOutputProtection::SetResolution
void SetResolution(int width, int height)
Set values of resolution member variable.
Definition: aampoutputprotection.cpp:250
DISPLAY_WIDTH_UNKNOWN
#define DISPLAY_WIDTH_UNKNOWN
Definition: aampoutputprotection.cpp:41
device::PixelResolution::k3840x2160
static const int k3840x2160
Indicates 3840x2160 video resolution.
Definition: pixelResolution.hpp:60
AampOutputProtection
Class to enforce HDCP authentication.
Definition: aampoutputprotection.h:119
IARM_Bus_RemoveEventHandler
IARM_Result_t IARM_Bus_RemoveEventHandler(const char *ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler)
Remove specific handler registered for the given event.
Definition: iarmMgrMocks.cpp:50
IARM_BUS_DSMGR_EVENT_HDCP_STATUS
@ IARM_BUS_DSMGR_EVENT_HDCP_STATUS
Definition: dsMgr.h:52
AampOutputProtection::SetHDMIStatus
void SetHDMIStatus()
Set the HDCP status using data from DeviceSettings.
Definition: aampoutputprotection.cpp:140
dsHDCP_VERSION_2X
@ dsHDCP_VERSION_2X
Definition: dsTypes.h:406
device::VideoOutputPort::getResolution
const VideoResolution & getResolution()
This API is used to get the current video resolution output from the video output port....
Definition: videoOutputPort.cpp:293
device::PixelResolution::k1920x1080
static const int k1920x1080
Indicates 1920x1080 video resolution.
Definition: pixelResolution.hpp:58
device::Manager::Initialize
static void Initialize()
This API is used to initialize the Device Setting module. Each API should be called by any client of ...
Definition: manager.cpp:97
device::PixelResolution::k720x480
static const int k720x480
Indicates 720x480 video resolution.
Definition: pixelResolution.hpp:55
dsDISPLAY_EVENT_CONNECTED
@ dsDISPLAY_EVENT_CONNECTED
Display connected event.
Definition: dsDisplay.h:51
AampOutputProtection::GetAampOutputProcectionInstance
static AampOutputProtection * GetAampOutputProcectionInstance()
Singleton for object creation.
Definition: aampoutputprotection.cpp:441
device::VideoResolution::getPixelResolution
const PixelResolution & getPixelResolution() const
This API is used to get the pixel format of the given video output port.
Definition: videoResolution.cpp:134
IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE
@ IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE
Definition: dsMgr.h:48
priv_aamp.h
Private functions and types used internally by AAMP.
device::DSConstant::getName
virtual const std::string & getName() const
This function is used to the get the data member name.
Definition: dsConstant.hpp:141
IARM_BUS_DSMGR_EVENT_RES_PRECHANGE
@ IARM_BUS_DSMGR_EVENT_RES_PRECHANGE
Definition: dsMgr.h:47
device::PixelResolution::k4096x2160
static const int k4096x2160
Indicates 4096x2160 video resolution.
Definition: pixelResolution.hpp:61
device::Manager::DeInitialize
static void DeInitialize()
This API is used to deinitialize the device settings module. DeInitialize() must be called to release...
Definition: manager.cpp:138
device::Host::getVideoOutputPort
VideoOutputPort & getVideoOutputPort(const std::string &name)
This API is used to get the reference to the video output port by its name. The name of the port must...
Definition: host.cpp:350
device::Host::getInstance
static Host & getInstance(void)
This API is used to get a reference to the single instance of the Host object.
Definition: host.cpp:88
IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG
@ IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG
Definition: dsMgr.h:50
AampOutputProtection::~AampOutputProtection
virtual ~AampOutputProtection()
AampOutputProtection Destructor.
Definition: aampoutputprotection.cpp:82
AampOutputProtection::AampOutputProtection
AampOutputProtection()
AampOutputProtection Constructor.
Definition: aampoutputprotection.cpp:49
device::PixelResolution::k720x576
static const int k720x576
Indicates 720x576 video resolution.
Definition: pixelResolution.hpp:56
dsHDCP_VERSION_1X
@ dsHDCP_VERSION_1X
Definition: dsTypes.h:405
DEBUG_FUNC
#define DEBUG_FUNC
Definition: aampoutputprotection.cpp:35
device::DSConstant::getId
virtual int getId() const
This function is used to get the id.
Definition: dsConstant.hpp:130
_DSMgr_EventData_t
Definition: dsMgr.h:81