src/3rdparty/phonon/ds9/iodevicereader.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /*  This file is part of the KDE project.
       
     2 
       
     3 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 
       
     5 This library is free software: you can redistribute it and/or modify
       
     6 it under the terms of the GNU Lesser General Public License as published by
       
     7 the Free Software Foundation, either version 2.1 or 3 of the License.
       
     8 
       
     9 This library is distributed in the hope that it will be useful,
       
    10 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 GNU Lesser General Public License for more details.
       
    13 
       
    14 You should have received a copy of the GNU Lesser General Public License
       
    15 along with this library.  If not, see <http://www.gnu.org/licenses/>.
       
    16 */
       
    17 
       
    18 #include "iodevicereader.h"
       
    19 #include "qasyncreader.h"
       
    20 
       
    21 #include "mediagraph.h"
       
    22 
       
    23 #include <phonon/streaminterface.h>
       
    24 
       
    25 #include <dshow.h>
       
    26 #include <initguid.h>
       
    27 
       
    28 QT_BEGIN_NAMESPACE
       
    29 
       
    30 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
       
    31 
       
    32 namespace Phonon
       
    33 {
       
    34     namespace DS9
       
    35     {
       
    36         //these mediatypes define a stream, its type will be autodetected by DirectShow
       
    37         static QVector<AM_MEDIA_TYPE> getMediaTypes()
       
    38         {
       
    39             AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
       
    40 
       
    41             QVector<AM_MEDIA_TYPE> ret;
       
    42             //normal auto-detect stream
       
    43             ret << mt;
       
    44             //AVI stream
       
    45             mt.subtype = MEDIASUBTYPE_Avi;
       
    46             ret << mt;
       
    47             //WAVE stream
       
    48             mt.subtype = MEDIASUBTYPE_WAVE;
       
    49             ret << mt;
       
    50             return ret;
       
    51         }
       
    52 
       
    53         class StreamReader : public QAsyncReader, public Phonon::StreamInterface
       
    54         {
       
    55         public:
       
    56             StreamReader(QBaseFilter *parent, const Phonon::MediaSource &source, const MediaGraph *mg) : 
       
    57               QAsyncReader(parent, getMediaTypes()),
       
    58                   m_seekable(false), m_pos(0), m_size(-1), m_mediaGraph(mg)
       
    59               {
       
    60                   connectToSource(source);
       
    61               }
       
    62 
       
    63               //for Phonon::StreamInterface
       
    64               void writeData(const QByteArray &data)
       
    65               {
       
    66                   m_pos += data.size();
       
    67                   m_buffer += data;
       
    68               }
       
    69 
       
    70               void endOfData()
       
    71               {
       
    72               }
       
    73 
       
    74               void setStreamSize(qint64 newSize)
       
    75               {
       
    76                   QMutexLocker locker(&m_mutex);
       
    77                   m_size = newSize;
       
    78               }
       
    79 
       
    80               void setStreamSeekable(bool s)
       
    81               {
       
    82                   QMutexLocker locker(&m_mutex);
       
    83                   m_seekable = s;
       
    84               }
       
    85 
       
    86               //virtual pure members
       
    87 
       
    88               //implementation from IAsyncReader
       
    89               STDMETHODIMP Length(LONGLONG *total, LONGLONG *available)
       
    90               {
       
    91                   QMutexLocker locker(&m_mutex);
       
    92                   if (total) {
       
    93                       *total = m_size;
       
    94                   }
       
    95 
       
    96                   if (available) {
       
    97                       *available = m_size;
       
    98                   }
       
    99 
       
   100                   return S_OK;
       
   101               }
       
   102 
       
   103 
       
   104               HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual)
       
   105               {
       
   106                   Q_ASSERT(!m_mutex.tryLock());
       
   107                   if (m_mediaGraph->isStopping()) {
       
   108                       return VFW_E_WRONG_STATE;
       
   109                   }
       
   110 
       
   111                   if(m_size != 1 && pos + length > m_size) {
       
   112                       //it tries to read outside of the boundaries
       
   113                       return E_FAIL;
       
   114                   }
       
   115 
       
   116                   if (m_pos - m_buffer.size() != pos) {
       
   117                       if (!m_seekable) {
       
   118                           return S_FALSE;
       
   119                       }
       
   120                       m_pos = pos;
       
   121                       seekStream(pos);
       
   122                       m_buffer.clear();
       
   123                   }
       
   124 
       
   125                   int oldSize = m_buffer.size();
       
   126                   while (m_buffer.size() < int(length)) {
       
   127                       needData();
       
   128                       if (m_mediaGraph->isStopping()) {
       
   129                           return VFW_E_WRONG_STATE;
       
   130                       }
       
   131 
       
   132                       if (oldSize == m_buffer.size()) {
       
   133                           break; //we didn't get any data
       
   134                       }
       
   135                       oldSize = m_buffer.size();
       
   136                   }
       
   137 
       
   138                   int bytesRead = qMin(m_buffer.size(), int(length));
       
   139                   qMemCopy(buffer, m_buffer.data(), bytesRead);
       
   140                   //truncate the buffer
       
   141                   m_buffer = m_buffer.mid(bytesRead);
       
   142 
       
   143                   if (actual) {
       
   144                       *actual = bytesRead; //initialization
       
   145                   }
       
   146 
       
   147                   return bytesRead == length ? S_OK : S_FALSE;
       
   148               }
       
   149 
       
   150         public:
       
   151             //for Phonon::StreamInterface
       
   152             QByteArray m_buffer;
       
   153             bool m_seekable;
       
   154             qint64 m_pos;
       
   155             qint64 m_size;
       
   156 
       
   157             const MediaGraph *m_mediaGraph;
       
   158         };
       
   159 
       
   160         IODeviceReader::IODeviceReader(const Phonon::MediaSource &source, const MediaGraph *mg) :
       
   161         QBaseFilter(CLSID_NULL)
       
   162         {
       
   163             //create the output pin
       
   164             m_streamReader = new StreamReader(this, source, mg);
       
   165         }
       
   166 
       
   167         IODeviceReader::~IODeviceReader()
       
   168         {
       
   169         }
       
   170     }
       
   171 }
       
   172 
       
   173 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
       
   174 
       
   175 QT_END_NAMESPACE