Skip to content

Commit c0f98bd

Browse files
authored
Merge pull request #1828 from CastagnaIT/gui_feedback
Implemented GUI feedback for playback errors
2 parents 26b6c11 + 55a3499 commit c0f98bd

File tree

26 files changed

+501
-213
lines changed

26 files changed

+501
-213
lines changed

inputstream.adaptive/resources/language/resource.language.en_gb/strings.po

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,17 @@ msgstr ""
352352
msgctxt "#30243"
353353
msgid "Verbose debugging can be useful for debugging components, but in some cases it may expose sensitive information in the log."
354354
msgstr ""
355+
356+
#empty strings reserved for settings from id 30244 to 30299
357+
358+
#. A GUI window title, "InputStream Adaptive" its the add-on name, not to be translated
359+
msgctxt "#30300"
360+
msgid "InputStream Adaptive error"
361+
msgstr ""
362+
363+
#. A GUI message that is displayed when there is a problem playing a stream
364+
#. Do not translate placeholders: {error-details}
365+
#. Use of double graphes e.g. {whatyouwant{error-details}whatyouwant} allows you to add additional text printed only when a value is present
366+
msgctxt "#30301"
367+
msgid "Unable to play the stream.{[CR]Error: {error-details}}"
368+
msgstr ""

lib/cdm/cdm/debug.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ enum class LogLevel
2020
};
2121

2222
void Log(const LogLevel level, const char* format, ...);
23-
#define LogF(level, format, ...) Log((level), ("%s: " format), __FUNCTION__, ##__VA_ARGS__)
2423

2524
void SetDBGMsgCallback(void (*msgcb)(const LogLevel level, const char* msg));
2625

lib/cdm/cdm/media/cdm/cdm_adapter.cc

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -193,88 +193,60 @@ CdmAdapter::CdmAdapter(
193193
const std::string& base_path,
194194
const CdmConfig& cdm_config,
195195
CdmAdapterClient *client)
196-
: library_(0)
197-
, cdm_path_(cdm_path)
196+
: cdm_path_(cdm_path)
198197
, cdm_base_path_(base_path)
199198
, client_(client)
200199
, key_system_(key_system)
201200
, cdm_config_(cdm_config)
202-
, active_buffer_(0)
203-
, cdm9_(0), cdm10_(0), cdm11_(0)
204201
{
205202
//DCHECK(!key_system_.empty());
206-
Initialize();
207203
}
208204

209205
CdmAdapter::~CdmAdapter()
210206
{
211-
if (cdm9_)
212-
cdm9_->Destroy(), cdm9_ = nullptr;
213-
else if (cdm10_)
214-
cdm10_->Destroy(), cdm10_ = nullptr;
215-
else if (cdm11_)
216-
cdm11_->Destroy(), cdm11_ = nullptr;
217-
else
218-
return;
219-
220-
deinit_cdm_func();
221-
222-
base::UnloadNativeLibrary(library_);
207+
UnloadCDM();
223208
}
224209

225-
void CdmAdapter::Initialize()
210+
bool CdmAdapter::LoadCDM()
226211
{
227-
m_isClosingSession = false;
228-
if (cdm9_ || cdm10_ || cdm11_)
229-
{
230-
if (cdm9_)
231-
cdm9_->Destroy(), cdm9_ = nullptr;
232-
else if (cdm10_)
233-
cdm10_->Destroy(), cdm10_ = nullptr;
234-
else if (cdm11_)
235-
cdm11_->Destroy(), cdm11_ = nullptr;
236-
base::UnloadNativeLibrary(library_);
237-
library_ = 0;
238-
}
212+
UnloadCDM();
239213

240214
base::NativeLibraryLoadError error;
241215
library_ = base::LoadNativeLibrary(cdm_path_, &error);
242216

243217
if (!library_)
244218
{
245-
LogF(LogLevel::ERROR, "Failed to load library: %s", error.ToString().c_str());
246-
return;
219+
Log(LogLevel::ERROR, "Failed to load library: %s", error.ToString().c_str());
220+
return false;
247221
}
248222

249-
init_cdm_func = reinterpret_cast<InitializeCdmModuleFunc>(base::GetFunctionPointerFromNativeLibrary(library_, MAKE_STRING(INITIALIZE_CDM_MODULE)));
250-
deinit_cdm_func = reinterpret_cast<DeinitializeCdmModuleFunc>(base::GetFunctionPointerFromNativeLibrary(library_, "DeinitializeCdmModule"));
251-
create_cdm_func = reinterpret_cast<CreateCdmFunc>(base::GetFunctionPointerFromNativeLibrary(library_, "CreateCdmInstance"));
252-
get_cdm_verion_func = reinterpret_cast<GetCdmVersionFunc>(base::GetFunctionPointerFromNativeLibrary(library_, "GetCdmVersion"));
223+
init_cdm_func = reinterpret_cast<InitializeCdmModuleFunc>(
224+
base::GetFunctionPointerFromNativeLibrary(library_, MAKE_STRING(INITIALIZE_CDM_MODULE)));
225+
deinit_cdm_func = reinterpret_cast<DeinitializeCdmModuleFunc>(
226+
base::GetFunctionPointerFromNativeLibrary(library_, "DeinitializeCdmModule"));
227+
create_cdm_func = reinterpret_cast<CreateCdmFunc>(
228+
base::GetFunctionPointerFromNativeLibrary(library_, "CreateCdmInstance"));
229+
get_cdm_verion_func = reinterpret_cast<GetCdmVersionFunc>(
230+
base::GetFunctionPointerFromNativeLibrary(library_, "GetCdmVersion"));
253231

254232
if (!init_cdm_func || !create_cdm_func || !get_cdm_verion_func || !deinit_cdm_func)
255233
{
256-
base::UnloadNativeLibrary(library_);
257-
library_ = 0;
258-
return;
234+
Log(LogLevel::ERROR, "Failed to binding CDM library functions");
235+
return false;
259236
}
237+
return true;
238+
}
260239

261-
std::string version{get_cdm_verion_func()};
262-
263-
if (version == "4.10.2891.0")
264-
{
265-
// This version have unclear problems
266-
// such as crashes on OnStorageId() method calls and others video decoding crashes
267-
Log(LogLevel::ERROR,
268-
"THE CDM VERSION \"4.10.2891.0\" IS NOT SUPPORTED DUE TO UNCLEAR LIBRARY ISSUES.\n"
269-
"------------------------------> PLEASE INSTALL AN OLDER VERSION OF WIDEVINE CDM!");
270-
return;
271-
}
240+
bool CdmAdapter::Initialize()
241+
{
242+
m_isClosingSession = false;
272243

273-
Log(LogLevel::DEBUG, "CDM version: %s", version.c_str());
244+
Log(LogLevel::DEBUG, "CDM version: %s", GetVersion().c_str());
274245

275246
#if defined(OS_WIN)
276247
// Load DXVA before sandbox lockdown to give CDM access to Output Protection
277248
// Manager (OPM).
249+
base::NativeLibraryLoadError error;
278250
base::LoadNativeLibrary("dxva2.dll", &error);
279251
#endif // defined(OS_WIN)
280252

@@ -301,11 +273,45 @@ void CdmAdapter::Initialize()
301273
else if (cdm11_)
302274
cdm11_->Initialize(cdm_config_.allow_distinctive_identifier,
303275
cdm_config_.allow_persistent_state, false);
276+
277+
return true;
304278
}
305-
else
279+
280+
Log(LogLevel::ERROR, "Cannot get the ContentDecryptionModule interface");
281+
return false;
282+
}
283+
284+
std::string CdmAdapter::GetVersion() const
285+
{
286+
if (get_cdm_verion_func)
287+
return get_cdm_verion_func();
288+
289+
return "";
290+
}
291+
292+
void CdmAdapter::UnloadCDM()
293+
{
294+
if (cdm9_)
295+
cdm9_->Destroy(), cdm9_ = nullptr;
296+
else if (cdm10_)
297+
cdm10_->Destroy(), cdm10_ = nullptr;
298+
else if (cdm11_)
299+
cdm11_->Destroy(), cdm11_ = nullptr;
300+
301+
init_cdm_func = nullptr;
302+
create_cdm_func = nullptr;
303+
get_cdm_verion_func = nullptr;
304+
305+
if (deinit_cdm_func)
306+
{
307+
deinit_cdm_func();
308+
deinit_cdm_func = nullptr;
309+
}
310+
311+
if (library_)
306312
{
307313
base::UnloadNativeLibrary(library_);
308-
library_ = 0;
314+
library_ = nullptr;
309315
}
310316
}
311317

@@ -770,7 +776,7 @@ void CdmFileIoImpl::Write(const uint8_t* data, uint32_t data_size)
770776
{
771777
if (!ExistsDir(base_path_.c_str()) && !CreateDirs(base_path_.c_str()))
772778
{
773-
LogF(LogLevel::ERROR, "Cannot create directory: %s", base_path_.c_str());
779+
Log(LogLevel::ERROR, "Cannot create directory: %s", base_path_.c_str());
774780
client_->OnWriteComplete(cdm::FileIOClient::Status::kError);
775781
return;
776782
}

lib/cdm/cdm/media/cdm/cdm_adapter.h

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,14 @@ class CdmAdapter : public std::enable_shared_from_this<CdmAdapter>
210210
void OnInitialized(bool success) override;
211211

212212

213-
public: //Misc
214-
~CdmAdapter();
215-
bool valid(){ return library_ != 0; };
213+
//Misc
214+
~CdmAdapter();
215+
bool LoadCDM();
216+
bool Initialize();
217+
std::string GetVersion() const;
218+
216219
private:
220+
void UnloadCDM();
217221
using InitializeCdmModuleFunc = void(*)();
218222
using DeinitializeCdmModuleFunc = void(*)();
219223
using GetCdmVersionFunc = char* (*)();
@@ -223,20 +227,19 @@ class CdmAdapter : public std::enable_shared_from_this<CdmAdapter>
223227
GetCdmHostFunc get_cdm_host_func,
224228
void* user_data);
225229

226-
InitializeCdmModuleFunc init_cdm_func;
227-
CreateCdmFunc create_cdm_func;
228-
GetCdmVersionFunc get_cdm_verion_func;
229-
DeinitializeCdmModuleFunc deinit_cdm_func;
230+
InitializeCdmModuleFunc init_cdm_func{nullptr};
231+
CreateCdmFunc create_cdm_func{nullptr};
232+
GetCdmVersionFunc get_cdm_verion_func{nullptr};
233+
DeinitializeCdmModuleFunc deinit_cdm_func{nullptr};
230234

231-
void Initialize();
232235
void SendClientMessage(const char* session, uint32_t session_size, CdmAdapterClient::CDMADPMSG msg, const uint8_t *data, size_t data_size, uint32_t status);
233236

234237
// Keep a reference to the CDM.
235-
base::NativeLibrary library_;
238+
base::NativeLibrary library_{nullptr};
236239

237240
std::string cdm_path_;
238241
std::string cdm_base_path_;
239-
CdmAdapterClient *client_;
242+
CdmAdapterClient* client_{nullptr};
240243
std::mutex client_mutex_;
241244
std::mutex decrypt_mutex_;
242245
std::mutex m_closeSessionMutex;
@@ -247,12 +250,11 @@ class CdmAdapter : public std::enable_shared_from_this<CdmAdapter>
247250
std::string key_system_;
248251
CdmConfig cdm_config_;
249252

250-
cdm::MessageType message_type_;
251-
cdm::Buffer *active_buffer_;
253+
cdm::Buffer* active_buffer_{nullptr};
252254

253-
cdm::ContentDecryptionModule_9 *cdm9_;
254-
cdm::ContentDecryptionModule_10 *cdm10_;
255-
cdm::ContentDecryptionModule_11 *cdm11_;
255+
cdm::ContentDecryptionModule_9* cdm9_{nullptr};
256+
cdm::ContentDecryptionModule_10* cdm10_{nullptr};
257+
cdm::ContentDecryptionModule_11* cdm11_{nullptr};
256258

257259
DISALLOW_COPY_AND_ASSIGN(CdmAdapter);
258260
};

src/Session.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "samplereader/SampleReaderFactory.h"
2222
#include "utils/Base64Utils.h"
2323
#include "utils/CurlUtils.h"
24+
#include "utils/GUIUtils.h"
2425
#include "utils/StringUtils.h"
2526
#include "utils/UrlUtils.h"
2627
#include "utils/Utils.h"
@@ -59,7 +60,7 @@ void SESSION::CSession::DeleteStreams()
5960
| initialize
6061
+---------------------------------------------------------------------*/
6162

62-
bool SESSION::CSession::Initialize(std::string manifestUrl)
63+
SResult SESSION::CSession::Initialize(std::string manifestUrl)
6364
{
6465
m_reprChooser = CHOOSER::CreateRepresentationChooser();
6566

@@ -100,7 +101,7 @@ bool SESSION::CSession::Initialize(std::string manifestUrl)
100101

101102
CURL::HTTPResponse manifestResp;
102103
if (!CURL::DownloadFile(manifestUrl, manifestHeaders, {"etag", "last-modified"}, manifestResp))
103-
return false;
104+
return SResult::Error("Cannot download the manifest file.");
104105

105106
// The download speed with small file sizes is not accurate, we should download at least 512Kb
106107
// to have a sufficient acceptable value to calculate the bandwidth,
@@ -115,15 +116,12 @@ bool SESSION::CSession::Initialize(std::string manifestUrl)
115116

116117
m_adaptiveTree = PLAYLIST_FACTORY::CreateAdaptiveTree(manifestResp);
117118
if (!m_adaptiveTree)
118-
return false;
119+
return SResult::Error("Unable to determine type of manifest file.");
119120

120121
m_adaptiveTree->Configure(m_reprChooser, kodiProps.GetManifestUpdParams());
121122

122123
if (!m_adaptiveTree->Open(manifestResp.effectiveUrl, manifestResp.headers, manifestResp.data))
123-
{
124-
LOG::Log(LOGERROR, "Cannot parse the manifest (%s)", manifestUrl.c_str());
125-
return false;
126-
}
124+
return SResult::Error("Cannot parse the manifest file.");
127125

128126
m_adaptiveTree->PostOpen();
129127
m_reprChooser->PostInit();
@@ -132,7 +130,7 @@ bool SESSION::CSession::Initialize(std::string manifestUrl)
132130

133131
InitializePeriod();
134132

135-
return true;
133+
return SResultCode::OK;
136134
}
137135

138136
bool SESSION::CSession::CheckPlayableStreams(PLAYLIST::CPeriod* period)
@@ -347,6 +345,13 @@ void SESSION::CSession::InitializePeriod()
347345
AddStream(adp.get(), defaultRepr, isDefaultAdpSet, uniqueId, audioLanguageOrig);
348346
}
349347
}
348+
349+
if (m_streams.empty())
350+
{
351+
LOG::LogF(LOGERROR,
352+
"No stream can be played, common causes: resolution limits or HDCP problem");
353+
GUI::ErrorDialog("No stream can be played");
354+
}
350355
}
351356

352357
void SESSION::CSession::AddStream(PLAYLIST::CAdaptationSet* adp,

src/Session.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "common/AdaptiveTree.h"
1414
#include "decrypters/DrmEngine.h"
1515
#include "decrypters/IDecrypter.h"
16+
#include "utils/ResultType.h"
1617

1718
#if defined(ANDROID)
1819
#include <kodi/platform/android/System.h>
@@ -36,7 +37,7 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
3637
* \param manifestUrl The manifest URL
3738
* \return True if has success, false otherwise
3839
*/
39-
bool Initialize(std::string manifestUrl);
40+
SResult Initialize(std::string manifestUrl);
4041

4142
bool CheckPlayableStreams(PLAYLIST::CPeriod* period);
4243

0 commit comments

Comments
 (0)