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