text: /******************************************************************************
      QtAV:  Multimedia framework based on Qt and FFmpeg
      Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
  
  *   This file is part of QtAV (from 2014)
  
      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_MediaIO_H
  #define QTAV_MediaIO_H
  
  #include <stdio.h> //SEEK_SET
  #include <QtAV/QtAV_Global.h>
  #include <QtCore/QStringList>
  #include <QtCore/QObject>
  
  namespace QtAV {
  /*!
   * \brief MediaIO
   * Built-in io (use MediaIO::create(name), example: MediaIO *qio = MediaIO::create("QIODevice"))
   * "QIODevice":
   *   properties:
   *     device - read/write. parameter: QIODevice*. example: io->setDevice(mydev)
   * "QFile"
   *   properties:
   *     device - read only. example: io->device()
   *   protocols: "", "qrc"
   */
  typedef int MediaIOId;
  class MediaIOPrivate;
  class Q_AV_EXPORT MediaIO : public QObject
  {
      Q_OBJECT
      DPTR_DECLARE_PRIVATE(MediaIO)
      Q_DISABLE_COPY(MediaIO)
      Q_ENUMS(AccessMode)
  public:
      enum AccessMode {
          Read, // default
          Write
      };
  
      /// Registered MediaIO::name(): "QIODevice", "QFile"
      static QStringList builtInNames();
      /*!
       * \brief createForProtocol
       * If an MediaIO subclass SomeInput.protocols() contains the protocol, return it's instance.
       * "QFile" input has protocols "qrc"(and empty "" means "qrc")
       * \return Null if none of registered MediaIO supports the protocol
       */
      static MediaIO* createForProtocol(const QString& protocol);
      /*!
       * \brief createForUrl
       * Create a MediaIO and setUrl(url) if protocol of url is supported.
       * Example: MediaIO *qrc = MediaIO::createForUrl("qrc:/icon/test.mkv");
       * \return MediaIO instance with url set. Null if protocol is not supported.
       */
      static MediaIO* createForUrl(const QString& url);
  
      virtual ~MediaIO();
      virtual QString name() const = 0;
      /*!
       * \brief setUrl
       * onUrlChange() will be called if url is different. onUrlChange() will close the old url and open the new url if it's not empty
       * \param url
       */
      void setUrl(const QString& url = QString());
      QString url() const;
      /*!
       * \brief setAccessMode
       * A MediaIO instance can be 1 mode, Read (default) or Write. If !isWritable(), then set to Write will fail and mode does not change
       * Call it before any function!
       * \return false if set failed
       */
      bool setAccessMode(AccessMode value);
      AccessMode accessMode() const;
  
      /// supported protocols. default is empty
      virtual const QStringList& protocols() const;
      virtual bool isSeekable() const = 0;
      virtual bool isWritable() const { return false;}
      /*!
       * \brief read
       * read at most maxSize bytes to data, and return the bytes were actually read
       */
      virtual qint64 read(char *data, qint64 maxSize) = 0;
      /*!
       * \brief write
       * write at most maxSize bytes from data, and return the bytes were actually written
       */
      virtual qint64 write(const char* data, qint64 maxSize) {
          Q_UNUSED(data);
          Q_UNUSED(maxSize);
          return 0;
      }
      /*!
       * \brief seek
       * \param from SEEK_SET, SEEK_CUR and SEEK_END from stdio.h
       * \return true if success
       */
      virtual bool seek(qint64 offset, int from = SEEK_SET) = 0;
      /*!
       * \brief position
       * MUST implement this. Used in seek
       * TODO: implement internally by default
       */
      virtual qint64 position() const = 0;
      /*!
       * \brief size
       * \return <=0 if not support
       */
      virtual qint64 size() const = 0;
      /*!
       * \brief isVariableSize
       * Experiment: A hack for size() changes during playback.
       * If true, containers that estimate duration from pts(or bit rate) will get an invalid duration. Thus no eof get
       * when the size of playback start reaches. So playback will not stop.
       * Demuxer seeking should work for this case.
       */
      virtual bool isVariableSize() const { return false;}
      /*!
       * \brief setBufferSize
       * \param value <0: use default value
       */
      void setBufferSize(int value = -1);
      int bufferSize() const;
      // The followings are for internal use. used by AVDemuxer, AVMuxer
      //struct AVIOContext; //anonymous struct in FFmpeg1.0.x
      void* avioContext(); //const?
      void release(); //TODO: how to remove it?
  public:
      static void registerAll();
      template<class C> static bool Register(MediaIOId id, const char* name) { return Register(id, create<C>, name);}
      static MediaIO* create(MediaIOId id);
      static MediaIO* create(const char* name);
      /*!
       * \brief next
       * \param id NULL to get the first id address
       * \return address of id or NULL if not found/end
       */
      static MediaIOId* next(MediaIOId* id = 0);
      static const char* name(MediaIOId id);
      static MediaIOId id(const char* name);
  private:
      template<class C> static MediaIO* create() { return new C();}
      typedef MediaIO* (*MediaIOCreator)();
      static bool Register(MediaIOId id, MediaIOCreator, const char *name);
  protected:
      MediaIO(MediaIOPrivate& d, QObject* parent = 0);
      /*!
       * \brief onUrlChanged
       * Here you can close old url, parse new url() and open it
       */
      virtual void onUrlChanged();
      DPTR_DECLARE(MediaIO)
  //private: // must add QT+=av-private if default ctor is private
      // base class, not direct create. only final class has public ctor is enough
      // FIXME: it's required by Q_DECLARE_METATYPE (also copy ctor)
      MediaIO(QObject* parent = 0);
  };
  Q_DECL_DEPRECATED typedef MediaIO AVInput; // for source compatibility
  } //namespace QtAV
  
  #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
  #include <QtCore/QMetaType>
  Q_DECLARE_METATYPE(QtAV::MediaIO*)
  Q_DECLARE_METATYPE(QIODevice*)
  #endif
  #endif // QTAV_MediaIO_H
  