forked from wang-bin/QtAV
-
Notifications
You must be signed in to change notification settings - Fork 0
/
QIODeviceIO.cpp
249 lines (227 loc) · 6.83 KB
/
QIODeviceIO.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2014-2015 Wang Bin <[email protected]>
* This file is part of QtAV
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#include "QtAV/MediaIO.h"
#include "QtAV/private/MediaIO_p.h"
#include "QtAV/private/mkid.h"
#include "QtAV/private/factory.h"
#include <QtCore/QFile>
#ifndef TEST_QTAV_QIODeviceIO
#include "utils/Logger.h"
#else
#include <QtDebug>
#endif
namespace QtAV {
class QIODeviceIOPrivate;
class QIODeviceIO : public MediaIO
{
Q_OBJECT
Q_PROPERTY(QIODevice* device READ device WRITE setDevice NOTIFY deviceChanged)
DPTR_DECLARE_PRIVATE(QIODeviceIO)
public:
QIODeviceIO();
virtual QString name() const Q_DECL_OVERRIDE;
// MUST open/close outside
void setDevice(QIODevice *dev); // set private in QFileIO etc
QIODevice* device() const;
virtual bool isSeekable() const Q_DECL_OVERRIDE;
virtual bool isWritable() const Q_DECL_OVERRIDE;
virtual qint64 read(char *data, qint64 maxSize) Q_DECL_OVERRIDE;
virtual qint64 write(const char *data, qint64 maxSize) Q_DECL_OVERRIDE;
virtual bool seek(qint64 offset, int from) Q_DECL_OVERRIDE;
virtual qint64 position() const Q_DECL_OVERRIDE;
/*!
* \brief size
* \return <=0 if not support
*/
virtual qint64 size() const Q_DECL_OVERRIDE;
Q_SIGNALS:
void deviceChanged();
protected:
QIODeviceIO(QIODeviceIOPrivate &d);
};
typedef QIODeviceIO MediaIOQIODevice;
static const MediaIOId MediaIOId_QIODevice = mkid::id32base36_6<'Q','I','O','D','e','v'>::value;
static const char kQIODevName[] = "QIODevice";
FACTORY_REGISTER(MediaIO, QIODevice, kQIODevName)
class QIODeviceIOPrivate : public MediaIOPrivate
{
public:
QIODeviceIOPrivate()
: MediaIOPrivate()
, dev(0)
{}
QIODevice *dev;
};
QIODeviceIO::QIODeviceIO() : MediaIO(*new QIODeviceIOPrivate()) {}
QIODeviceIO::QIODeviceIO(QIODeviceIOPrivate &d) : MediaIO(d) {}
QString QIODeviceIO::name() const { return QLatin1String(kQIODevName);}
void QIODeviceIO::setDevice(QIODevice *dev)
{
DPTR_D(QIODeviceIO);
if (d.dev == dev)
return;
d.dev = dev;
emit deviceChanged();
}
QIODevice* QIODeviceIO::device() const
{
return d_func().dev;
}
bool QIODeviceIO::isSeekable() const
{
DPTR_D(const QIODeviceIO);
return d.dev && !d.dev->isSequential();
}
bool QIODeviceIO::isWritable() const
{
DPTR_D(const QIODeviceIO);
return d.dev && d.dev->isWritable();
}
qint64 QIODeviceIO::read(char *data, qint64 maxSize)
{
DPTR_D(QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->read(data, maxSize);
}
qint64 QIODeviceIO::write(const char *data, qint64 maxSize)
{
DPTR_D(QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->write(data, maxSize);
}
bool QIODeviceIO::seek(qint64 offset, int from)
{
DPTR_D(QIODeviceIO);
if (!d.dev)
return false;
if (from == SEEK_END) {
offset = d.dev->size() - offset;
} else if (from == SEEK_CUR) {
offset = d.dev->pos() offset;
}
return d.dev->seek(offset);
}
qint64 QIODeviceIO::position() const
{
DPTR_D(const QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->pos();
}
qint64 QIODeviceIO::size() const
{
DPTR_D(const QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->size(); // sequential device returns bytesAvailable()
}
// qrc support
static const char kQFileName[] = "QFile";
class QFileIOPrivate;
class QFileIO Q_DECL_FINAL: public QIODeviceIO
{
DPTR_DECLARE_PRIVATE(QFileIO)
public:
QFileIO();
QString name() const Q_DECL_OVERRIDE { return QLatin1String(kQFileName);}
const QStringList& protocols() const Q_DECL_OVERRIDE
{
static QStringList p = QStringList() << QStringLiteral("") << QStringLiteral("qrc") << QStringLiteral("qfile");
return p;
}
protected:
void onUrlChanged() Q_DECL_OVERRIDE;
private:
using QIODeviceIO::setDevice;
};
typedef QFileIO MediaIOQFile;
static const MediaIOId MediaIOId_QFile = mkid::id32base36_5<'Q','F','i','l','e'>::value;
FACTORY_REGISTER(MediaIO, QFile, kQFileName)
class QFileIOPrivate Q_DECL_FINAL: public QIODeviceIOPrivate
{
public:
QFileIOPrivate() : QIODeviceIOPrivate() {}
~QFileIOPrivate() {
if (file.isOpen())
file.close();
}
QFile file;
};
QFileIO::QFileIO()
: QIODeviceIO(*new QFileIOPrivate())
{
setDevice(&d_func().file);
}
void QFileIO::onUrlChanged()
{
DPTR_D(QFileIO);
if (d.file.isOpen())
d.file.close();
QString path(url());
if (path.startsWith(QLatin1String("qrc:"))) {
path = path.mid(3);
} else if (path.startsWith(QLatin1String("qfile:"))) {
path = path.mid(6);
#ifdef Q_OS_WIN
int p = path.indexOf(QLatin1Char(':'));
if (p < 1) {
qWarning("invalid path. ':' wrong position");
return;
}
p -= 1;
QChar c = path.at(p).toUpper();
if (c < QLatin1Char('A') || c > QLatin1Char('Z')) {
qWarning("invalid path. wrong driver");
return;
}
const QString path_maybe = path.mid(p);
qDebug() << path_maybe;
--p;
while (p > 0) {
c = path.at(p);
if (c != QLatin1Char('\\') && c != QLatin1Char('/')) {
qWarning("invalid path. wrong dir seperator");
return;
}
--p;
}
path = path_maybe;
#endif
}
d.file.setFileName(path);
if (path.isEmpty())
return;
if (!d.file.open(QIODevice::ReadOnly))
qWarning() << "Failed to open [" << d.file.fileName() << "]: " << d.file.errorString();
}
} //namespace QtAV
#include "QIODeviceIO.moc"
#ifdef TEST_QTAV_QIODeviceIO
int main(int, char**)
{
QtAV::QFileIO fi;
qDebug() << "protocols: " << fi.protocols();
fi.setUrl("qrc:/QtAV.svg");
QByteArray data(1024, 0);
fi.read(data.data(), data.size());
qDebug("QFileIO url: %s, seekable: %d, size: %lld", fi.url().toUtf8().constData(), fi.isSeekable(), fi.size());
qDebug() << data;
return 0;
}
#endif