MythTV  master
mythbdinfo.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QDir>
3 #include <QCryptographicHash>
4 
5 // MythTV
7 #include "libmythbase/mythdirs.h"
9 
10 #include "io/mythiowrapper.h"
11 #include "Bluray/mythbdiowrapper.h"
12 #include "Bluray/mythbdinfo.h"
13 
14 // Std
15 #include <fcntl.h>
16 
17 // BluRay
18 #ifdef HAVE_LIBBLURAY
19 #include <libbluray/bluray.h>
20 #include <libbluray/log_control.h>
21 #include <libbluray/meta_data.h>
22 #else
23 #include "libbluray/bluray.h"
24 #include "util/log_control.h"
25 #include "libbluray/bdnav/meta_data.h"
26 #endif
27 
28 #define LOC QString("BDInfo: ")
29 
30 MythBDInfo::MythBDInfo(const QString &Filename)
31 {
32  LOG(VB_PLAYBACK, LOG_INFO, QString("BDInfo: Trying %1").arg(Filename));
33  QString name = Filename;
34 
35  if (name.startsWith("bd:"))
36  {
37  name.remove(0,3);
38  while (name.startsWith("//"))
39  name.remove(0,1);
40  }
41 
42  // clean path filename
43  name = QDir(QDir::cleanPath(name)).canonicalPath();
44  if (name.isEmpty())
45  {
46  LOG(VB_GENERAL, LOG_ERR, LOC + QString("'%1' nonexistent").arg(name));
47  name = Filename;
48  }
49 
50  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened MythBDBuffer device at '%1'").arg(name));
51 
52  // Make sure log messages from the Bluray library appear in our logs
53  bd_set_debug_handler([](const char *Message) { LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(Message).trimmed()); });
54  bd_set_debug_mask(DBG_CRIT | DBG_NAV | DBG_BLURAY);
55 
56  // Use our own wrappers for file and directory access
58 
59  int bdhandle = -1;
60  BLURAY* bdnav = nullptr;
61  if (Filename.startsWith("myth:") && MythCDROM::inspectImage(Filename) != MythCDROM::kUnknown)
62  {
63  // Use streaming for remote images.
64  // Streaming encrypted images causes a SIGSEGV in aacs code when
65  // using the makemkv libraries due to the missing "device" name.
66  // Since a local device (which is likely to be encrypted) can be
67  // opened directly, only use streaming for remote images, which
68  // presumably won't be encrypted.
69  bdhandle = MythFileOpen(Filename.toLocal8Bit().data(), O_RDONLY);
70  if (bdhandle >= 0)
71  {
72  bdnav = bd_init();
73  if (bdnav)
74  {
75  bd_open_stream(bdnav, &bdhandle,
76  [](void *Handle, void *Buf, int LBA, int NumBlocks) {
77  if (MythFileSeek(*(static_cast<int*>(Handle)), LBA * 2048LL, SEEK_SET) != -1)
78  return static_cast<int>(MythFileRead(*(static_cast<int*>(Handle)), Buf,
79  static_cast<size_t>(NumBlocks) * 2048) / 2048);
80  return -1;
81  });
82  }
83  }
84  }
85  else
86  {
87  QByteArray keyfile = QString("%1/KEYDB.cfg").arg(GetConfDir()).toLatin1();
88  bdnav = bd_open(name.toLocal8Bit().data(), keyfile.constData());
89  }
90 
91  if (!bdnav)
92  {
93  m_lastError = tr("Could not open Blu-ray device: %1").arg(name);
94  LOG(VB_GENERAL, LOG_ERR, LOC + m_lastError);
95  m_isValid = false;
96  }
97  else
98  {
99  GetNameAndSerialNum(bdnav, m_name, m_serialnumber, name, QString("BDInfo: "));
100  bd_close(bdnav);
101  }
102 
103  if (bdhandle >= 0)
104  MythfileClose(bdhandle);
105 
106  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Done");
107 }
108 
109 void MythBDInfo::GetNameAndSerialNum(BLURAY* BluRay, QString &Name,
110  QString &SerialNum, const QString &Filename,
111  const QString &LogPrefix)
112 {
113  const meta_dl *metaDiscLibrary = bd_get_meta(BluRay);
114 
115  if (metaDiscLibrary)
116  {
117  Name = QString(metaDiscLibrary->di_name);
118  }
119  else
120  {
121  // Use the directory name for the Bluray name
122  QDir dir(Filename);
123  Name = dir.dirName();
124  LOG(VB_PLAYBACK, LOG_DEBUG, LogPrefix + QString("Generated bd name '%1'")
125  .arg(Name));
126  }
127 
128  SerialNum.clear();
129 
130  // Try to find the first clip info file and
131  // use its SHA1 hash as a serial number.
132  for (uint32_t idx = 0; idx < 200; idx++)
133  {
134  QString clip = QString("BDMV/CLIPINF/%1.clpi").arg(idx, 5, 10, QChar('0'));
135  void* buffer = nullptr;
136  int64_t buffersize = 0;
137  if (bd_read_file(BluRay, clip.toLocal8Bit().data(), &buffer, &buffersize) != 0)
138  {
139  QCryptographicHash crypto(QCryptographicHash::Sha1);
140  // Add the clip number to the hash
141  crypto.addData(reinterpret_cast<const char*>(&idx), sizeof(idx));
142  // then the length of the file
143  crypto.addData(reinterpret_cast<const char*>(&buffersize), sizeof(buffersize));
144  // and then the contents
145  crypto.addData(reinterpret_cast<const char*>(buffer), static_cast<int>(buffersize));
146  SerialNum = QString("%1__gen").arg(QString(crypto.result().toBase64()));
147  free(buffer);
148  LOG(VB_PLAYBACK, LOG_DEBUG, LogPrefix + QString("Generated serial number '%1'")
149  .arg(SerialNum));
150  break;
151  }
152  }
153 
154  if (SerialNum.isEmpty())
155  LOG(VB_GENERAL, LOG_ERR, LogPrefix + "Unable to generate serial number");
156 }
157 
158 bool MythBDInfo::IsValid(void) const
159 {
160  return m_isValid;
161 }
162 
163 bool MythBDInfo::GetNameAndSerialNum(QString &Name, QString &SerialNum)
164 {
165  Name = m_name;
166  SerialNum = m_serialnumber;
167  return !(Name.isEmpty() && SerialNum.isEmpty());
168 }
169 
170 QString MythBDInfo::GetLastError(void) const
171 {
172  return m_lastError;
173 }
MythCDROM::kUnknown
@ kUnknown
Definition: mythcdrom.h:28
mythcdrom.h
MythfileClose
int MythfileClose(int FileID)
Definition: mythiowrapper.cpp:205
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythFileRead
ssize_t MythFileRead(int FileID, void *Buffer, size_t Count)
Definition: mythiowrapper.cpp:285
mythdirs.h
mythbdiowrapper.h
MythBDInfo::IsValid
bool IsValid(void) const
Definition: mythbdinfo.cpp:158
MythBDInfo::m_serialnumber
QString m_serialnumber
Definition: mythbdinfo.h:33
MythBDInfo::MythBDInfo
MythBDInfo(const QString &Filename)
Definition: mythbdinfo.cpp:30
mythlogging.h
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:256
MythBDInfo::GetNameAndSerialNum
bool GetNameAndSerialNum(QString &Name, QString &SerialNum)
Definition: mythbdinfo.cpp:163
LOC
#define LOC
Definition: mythbdinfo.cpp:28
MythCDROM::inspectImage
static ImageType inspectImage(const QString &path)
Definition: mythcdrom.cpp:188
Name
Definition: channelsettings.cpp:71
MythFileOpen
int MythFileOpen(const char *Pathname, int Flags)
Definition: mythiowrapper.cpp:115
MythBDInfo::m_isValid
bool m_isValid
Definition: mythbdinfo.h:35
Buf
IFSPoint * Buf
Definition: ifs.cpp:105
MythBDInfo::GetLastError
QString GetLastError(void) const
Definition: mythbdinfo.cpp:170
MythBDInfo::m_name
QString m_name
Definition: mythbdinfo.h:32
MythBDIORedirect
void MythBDIORedirect(void)
Definition: mythbdiowrapper.cpp:144
MythFileSeek
off_t MythFileSeek(int FileID, off_t Offset, int Whence)
Definition: mythiowrapper.cpp:243
mythbdinfo.h
mythiowrapper.h
MythBDInfo::m_lastError
QString m_lastError
Definition: mythbdinfo.h:34