From 496c8d7dcd5a32c7a493bf5bfca7d2eee5163ea6 Mon Sep 17 00:00:00 2001 From: wang-bin Date: Fri, 5 Dec 2014 19:41:36 +0800 Subject: [PATCH] implements QIODevice as input --- src/QtAV/AVInput.h | 8 +- src/QtAV/private/AVInput_p.h | 2 + src/input/AVInput.cpp | 24 +++++ src/input/QIODeviceInput.cpp | 163 ++++++++++++++++++++++++++++++---- src/input/QIODeviceInput.h | 57 ++++++++++++ src/input/tst_qiodevinput.pro | 5 ++ src/libQtAV.pro | 1 + 7 files changed, 242 insertions(+), 18 deletions(-) create mode 100644 src/input/QIODeviceInput.h create mode 100644 src/input/tst_qiodevinput.pro diff --git a/src/QtAV/AVInput.h b/src/QtAV/AVInput.h index 6084ac7a..b536c7de 100644 --- a/src/QtAV/AVInput.h +++ b/src/QtAV/AVInput.h @@ -23,6 +23,7 @@ #define QTAV_AVINPUT_H #include +#include namespace QtAV { @@ -34,7 +35,11 @@ class Q_AV_EXPORT AVInput public: AVInput(); virtual ~AVInput(); - virtual bool isSeekable() = 0; + virtual void setUrl(const QString& url); + QString url() const; + /// supported protocols. default is empty + virtual const QStringList& protocols() const; + virtual bool isSeekable() const = 0; virtual qint64 read(char *data, qint64 maxSize) = 0; /*! * \brief seek @@ -60,6 +65,7 @@ public: void release(); //TODO: how to remove it? protected: AVInput(AVInputPrivate& d); + virtual void onUrlChanged(); DPTR_DECLARE(AVInput) }; diff --git a/src/QtAV/private/AVInput_p.h b/src/QtAV/private/AVInput_p.h index ba4ca154..a5ccc188 100644 --- a/src/QtAV/private/AVInput_p.h +++ b/src/QtAV/private/AVInput_p.h @@ -24,6 +24,7 @@ #include "QtAV/QtAV_Global.h" #include "QtAV/private/AVCompat.h" +#include namespace QtAV { @@ -36,6 +37,7 @@ public: {} // TODO: how to manage ctx? AVIOContext *ctx; + QString url; }; } //namespace QtAV diff --git a/src/input/AVInput.cpp b/src/input/AVInput.cpp index 5b42309f..b2393344 100644 --- a/src/input/AVInput.cpp +++ b/src/input/AVInput.cpp @@ -21,6 +21,7 @@ #include "QtAV/AVInput.h" #include "QtAV/private/AVInput_p.h" +#include namespace QtAV { @@ -64,6 +65,29 @@ AVInput::~AVInput() { } +void AVInput::setUrl(const QString &url) +{ + DPTR_D(AVInput); + if (d.url == url) + return; + d.url = url; + onUrlChanged(); +} + +QString AVInput::url() const +{ + return d_func().url; +} + +void AVInput::onUrlChanged() +{} + +const QStringList& AVInput::protocols() const +{ + static QStringList no_protocols; + return no_protocols; +} + #define IODATA_BUFFER_SIZE 32768 // void* AVInput::avioContext() diff --git a/src/input/QIODeviceInput.cpp b/src/input/QIODeviceInput.cpp index a2f08b35..d257c991 100644 --- a/src/input/QIODeviceInput.cpp +++ b/src/input/QIODeviceInput.cpp @@ -1,33 +1,162 @@ -#include "QtAV/AVInput.h" +/****************************************************************************** + QtAV: Media play library based on Qt and FFmpeg + Copyright (C) 2014 Wang Bin + +* 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 "QIODeviceInput.h" #include "QtAV/private/AVInput_p.h" #include +#include +#ifndef TEST_QTAV_QIODEVICEINPUT #include "utils/Logger.h" - +#else +#include +#endif namespace QtAV { -class QIODeviceInput : public AVInput +class QIODeviceInputPrivate : public AVInputPrivate { public: - void setIODevice(QIODevice *dev); - QIODevice* device() const; - - virtual bool isSeekable() Q_DECL_OVERRIDE; - virtual qint64 read(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; + QIODeviceInputPrivate() + : AVInputPrivate() + , dev(0) + {} + QIODevice *dev; }; +QIODeviceInput::QIODeviceInput() : AVInput(*new QIODeviceInputPrivate()) {} +QIODeviceInput::QIODeviceInput(QIODeviceInputPrivate &d) : AVInput(d) {} + +void QIODeviceInput::setIODevice(QIODevice *dev) +{ + d_func().dev = dev; +} + +QIODevice* QIODeviceInput::device() const +{ + return d_func().dev; +} + +bool QIODeviceInput::isSeekable() const +{ + DPTR_D(const QIODeviceInput); + return d.dev && !d.dev->isSequential(); +} + +qint64 QIODeviceInput::read(char *data, qint64 maxSize) +{ + DPTR_D(QIODeviceInput); + if (!d.dev) + return 0; + return d.dev->read(data, maxSize); +} + +bool QIODeviceInput::seek(qint64 offset, int from) +{ + DPTR_D(QIODeviceInput); + if (!d.dev) + return false; + if (from == 2) { + offset = d.dev->size() - offset; + } else if (from == 1) { + offset = d.dev->pos() + offset; + } + return d.dev->seek(offset); +} + +qint64 QIODeviceInput::position() const +{ + DPTR_D(const QIODeviceInput); + if (!d.dev) + return 0; + return d.dev->pos(); +} + +qint64 QIODeviceInput::size() const +{ + DPTR_D(const QIODeviceInput); + if (!d.dev) + return 0; + return d.dev->size(); // sequential device returns bytesAvailable() +} // qrc support +class QFileInputPrivate; class QFileInput : public QIODeviceInput { + DPTR_DECLARE_PRIVATE(QFileInput) public: - void setFileName(const QString& name); - QString fileName() const; + QFileInput(); + const QStringList& protocols() const Q_DECL_OVERRIDE + { + static QStringList p = QStringList() << "" << "qrc"; + return p; + } +protected: + void onUrlChanged() Q_DECL_OVERRIDE; +private: + using QIODeviceInput::setIODevice; }; +class QFileInputPrivate : public QIODeviceInputPrivate +{ +public: + QFileInputPrivate() : QIODeviceInputPrivate() {} + ~QFileInputPrivate() { + if (file.isOpen()) + file.close(); + } + QFile file; +}; + +QFileInput::QFileInput() + : QIODeviceInput(*new QFileInputPrivate()) +{ + setIODevice(&d_func().file); +} + +void QFileInput::onUrlChanged() +{ + DPTR_D(QFileInput); + if (d.file.isOpen()) + d.file.close(); + QString path(url()); + if (path.startsWith("qrc:")) + path = path.mid(3); + 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 + +#ifdef TEST_QTAV_QIODEVICEINPUT +int main(int, char**) +{ + QtAV::QFileInput fi; + qDebug() << "protocols: " << fi.protocols(); + fi.setUrl("qrc:/QtAV.svg"); + QByteArray data(1024, 0); + fi.read(data.data(), data.size()); + qDebug("QFileInput url: %s, seekable: %d, size: %lld", fi.url().toUtf8().constData(), fi.isSeekable(), fi.size()); + qDebug() << data; + return 0; +} +#endif diff --git a/src/input/QIODeviceInput.h b/src/input/QIODeviceInput.h new file mode 100644 index 00000000..b555fab9 --- /dev/null +++ b/src/input/QIODeviceInput.h @@ -0,0 +1,57 @@ +/****************************************************************************** + QtAV: Media play library based on Qt and FFmpeg + Copyright (C) 2014 Wang Bin + +* 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 +******************************************************************************/ + +#ifndef QTAV_QIODEVICEINPUT +#define QTAV_QIODEVICEINPUT + +#include +#include + +namespace QtAV { + +class QIODeviceInputPrivate; +class QIODeviceInput : public AVInput +{ + DPTR_DECLARE_PRIVATE(QIODeviceInput) +public: + QIODeviceInput(); + // MUST open/close outside + void setIODevice(QIODevice *dev); // set private in QFileInput etc + QIODevice* device() const; + + virtual bool isSeekable() const Q_DECL_OVERRIDE; + virtual qint64 read(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; +protected: + QIODeviceInput(QIODeviceInputPrivate &d); +}; + +} //namespace QtAV +#include "QtAV/AVInput.h" + +#endif // QTAV_QIODEVICEINPUT + diff --git a/src/input/tst_qiodevinput.pro b/src/input/tst_qiodevinput.pro new file mode 100644 index 00000000..73b40d6f --- /dev/null +++ b/src/input/tst_qiodevinput.pro @@ -0,0 +1,5 @@ +QT += av av-private +CONFIG -= app_bundle +DEFINES += TEST_QTAV_QIODEVICEINPUT +INCLUDEPATH += $$[QT_INSTALL_HEADERS] +SOURCES = QIODeviceInput.cpp diff --git a/src/libQtAV.pro b/src/libQtAV.pro index cf01ea7d..c78156c7 100644 --- a/src/libQtAV.pro +++ b/src/libQtAV.pro @@ -427,6 +427,7 @@ HEADERS *= \ AudioThread.h \ VideoThread.h \ filter/FilterManager.h \ + input/QIODeviceInput.h \ subtitle/CharsetDetector.h \ subtitle/PlainText.h \ utils/BlockingQueue.h \