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