kwave  18.07.70
Kwave::OggDecoder Class Reference

#include <OggDecoder.h>

Inheritance diagram for Kwave::OggDecoder:
Inheritance graph
Collaboration diagram for Kwave::OggDecoder:
Collaboration graph

Public Member Functions

 OggDecoder ()
 
virtual ~OggDecoder () Q_DECL_OVERRIDE
 
virtual Kwave::Decoderinstance () Q_DECL_OVERRIDE
 
virtual bool open (QWidget *widget, QIODevice &source) Q_DECL_OVERRIDE
 
virtual bool decode (QWidget *widget, Kwave::MultiWriter &dst) Q_DECL_OVERRIDE
 
virtual void close () Q_DECL_OVERRIDE
 
- Public Member Functions inherited from Kwave::Decoder
 Decoder ()
 
virtual ~Decoder ()
 
virtual Kwave::MetaDataListmetaData ()
 
- Public Member Functions inherited from Kwave::CodecBase
 CodecBase ()
 
virtual ~CodecBase ()
 
virtual bool supports (const QMimeType &mimetype)
 
virtual bool supports (const QString &mimetype_name)
 
virtual QStringList extensions (const QString &mimetype_name) const
 
virtual const QList< CodecBase::MimeTypemimeTypes ()
 
virtual const QList< Kwave::Compression::TypecompressionTypes ()
 
virtual void addMimeType (const char *name, const QString &description, const char *patterns)
 
virtual void addCompression (Kwave::Compression::Type compression)
 
virtual QString mimeTypeOf (const QUrl &url)
 

Protected Member Functions

int parseHeader (QWidget *widget)
 

Private Attributes

Kwave::OggSubDecoderm_sub_decoder
 
QIODevice * m_source
 
ogg_sync_state m_oy
 
ogg_stream_state m_os
 
ogg_page m_og
 
ogg_packet m_op
 

Additional Inherited Members

- Signals inherited from Kwave::Decoder
void sourceProcessed (quint64 pos)
 
- Protected Attributes inherited from Kwave::Decoder
Kwave::MetaDataList m_meta_data
 

Detailed Description

Definition at line 32 of file OggDecoder.h.

Constructor & Destructor Documentation

◆ OggDecoder()

Kwave::OggDecoder::OggDecoder ( )

Constructor

Definition at line 44 of file OggDecoder.cpp.

References Kwave::CodecBase::addMimeType(), REGISTER_COMPRESSION_TYPE_OGG_OPUS, REGISTER_COMPRESSION_TYPE_OGG_VORBIS, REGISTER_OGG_OPUS_MIME_TYPES, and REGISTER_OGG_VORBIS_MIME_TYPES.

45  :Kwave::Decoder(), m_sub_decoder(Q_NULLPTR), m_source(Q_NULLPTR)
46 {
47 #ifdef HAVE_OGG_OPUS
50 #endif /* HAVE_OGG_OPUS */
51 
52 #ifdef HAVE_OGG_VORBIS
55 #endif /* HAVE_OGG_VORBIS */
56 
57  /* Ogg audio, as per RFC5334 */
58  addMimeType("audio/ogg", i18n("Ogg audio"), "*.oga");
59  addMimeType("application/ogg", i18n("Ogg audio"), "*.ogx");
60 
61 }
QIODevice * m_source
Definition: OggDecoder.h:84
virtual void addMimeType(const char *name, const QString &description, const char *patterns)
Definition: CodecBase.cpp:47
#define REGISTER_OGG_VORBIS_MIME_TYPES
#define REGISTER_COMPRESSION_TYPE_OGG_OPUS
Kwave::OggSubDecoder * m_sub_decoder
Definition: OggDecoder.h:81
#define REGISTER_OGG_OPUS_MIME_TYPES
#define REGISTER_COMPRESSION_TYPE_OGG_VORBIS
Here is the call graph for this function:

◆ ~OggDecoder()

Kwave::OggDecoder::~OggDecoder ( )
virtual

Destructor

Definition at line 64 of file OggDecoder.cpp.

References close(), and m_source.

65 {
66  if (m_source) close();
67 }
QIODevice * m_source
Definition: OggDecoder.h:84
virtual void close() Q_DECL_OVERRIDE
Definition: OggDecoder.cpp:275
Here is the call graph for this function:

Member Function Documentation

◆ close()

void Kwave::OggDecoder::close ( )
virtual

Closes the source.

Implements Kwave::Decoder.

Definition at line 275 of file OggDecoder.cpp.

References m_source, and m_sub_decoder.

Referenced by ~OggDecoder().

276 {
277  m_source = Q_NULLPTR;
278  delete m_sub_decoder;
279  m_sub_decoder = Q_NULLPTR;
280 }
QIODevice * m_source
Definition: OggDecoder.h:84
Kwave::OggSubDecoder * m_sub_decoder
Definition: OggDecoder.h:81
Here is the caller graph for this function:

◆ decode()

bool Kwave::OggDecoder::decode ( QWidget *  widget,
Kwave::MultiWriter dst 
)
virtual

Decodes a stream of bytes into a MultiWriter

Parameters
widgeta widget that can be used for displaying message boxes or dialogs
dstMultiWriter that receives the audio data
Returns
true if succeeded, false on errors

Implements Kwave::Decoder.

Definition at line 200 of file OggDecoder.cpp.

References Kwave::OggSubDecoder::close(), Kwave::OggSubDecoder::decode(), Kwave::MessageBox::error(), Kwave::MultiWriter::isCanceled(), m_og, m_op, m_os, m_oy, m_source, m_sub_decoder, Kwave::Decoder::metaData(), parseHeader(), Kwave::MetaDataList::replace(), Kwave::OggSubDecoder::reset(), Kwave::Decoder::sourceProcessed(), and Kwave::toInt().

201 {
202  int eos = 0;
203 
204  Q_ASSERT(m_source);
205  Q_ASSERT(m_sub_decoder);
206  if (!m_source || !m_sub_decoder) return false;
207 
208  // we repeat if the bitstream is chained
209  while (!dst.isCanceled()) {
210  // The rest is just a straight decode loop until end of stream
211  while (!eos) {
212  while (!eos) {
213  int result = ogg_sync_pageout(&m_oy, &m_og);
214  if (result == 0) break; // need more data
215  if (result < 0) {
216  // missing or corrupt data at this page position
217  Kwave::MessageBox::error(widget, i18n(
218  "Corrupt or missing data in bitstream. Continuing."
219  ));
220  } else {
221  // can safely ignore errors at this point
222  ogg_stream_pagein(&m_os, &m_og);
223  while (1) {
224  result = ogg_stream_packetout(&m_os, &m_op);
225 
226  if (result == 0) break; // need more data
227  if (result < 0) {
228  // missing or corrupt data at this page position
229  // no reason to complain; already complained above
230  } else {
231  result = m_sub_decoder->decode(dst);
232  if (result < 0)
233  break;
234 
235  // signal the current position
236  emit sourceProcessed(m_source->pos());
237  }
238  }
239  if (ogg_page_eos(&m_og) || dst.isCanceled()) eos = 1;
240  }
241  }
242 
243  if (!eos) {
244  char *buffer = ogg_sync_buffer(&m_oy, 4096);
245  int bytes = Kwave::toInt(m_source->read(buffer, 4096));
246  ogg_sync_wrote(&m_oy, bytes);
247  if (!bytes) eos = 1;
248  }
249  }
250 
251  // clean up this logical bitstream; before exit we see if we're
252  // followed by another [chained]
253  ogg_stream_clear(&m_os);
254  m_sub_decoder->reset();
255 
256  // parse the next header, maybe we parse a stream or chain...
257  if (eos || (parseHeader(widget) < 1)) break;
258  }
259 
260  // OK, clean up the framer
261  ogg_sync_clear(&m_oy);
262 
263  // signal the current position
264  emit sourceProcessed(m_source->pos());
265 
266  Kwave::FileInfo info(metaData());
267  m_sub_decoder->close(info);
269 
270  // return with a valid Signal, even if the user pressed cancel !
271  return true;
272 }
virtual void reset()=0
void sourceProcessed(quint64 pos)
ogg_sync_state m_oy
Definition: OggDecoder.h:87
QIODevice * m_source
Definition: OggDecoder.h:84
int parseHeader(QWidget *widget)
Definition: OggDecoder.cpp:76
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
virtual int decode(Kwave::MultiWriter &dst)=0
int toInt(T x)
Definition: Utils.h:127
virtual void close(Kwave::FileInfo &info)=0
virtual void replace(const MetaDataList &list)
virtual Kwave::MetaDataList & metaData()
Definition: Decoder.h:78
Kwave::OggSubDecoder * m_sub_decoder
Definition: OggDecoder.h:81
bool isCanceled() const
Definition: MultiWriter.h:64
ogg_stream_state m_os
Definition: OggDecoder.h:90
ogg_packet m_op
Definition: OggDecoder.h:96
Here is the call graph for this function:

◆ instance()

Kwave::Decoder * Kwave::OggDecoder::instance ( )
virtual

Returns a new instance of the decoder

Implements Kwave::Decoder.

Definition at line 70 of file OggDecoder.cpp.

71 {
72  return new Kwave::OggDecoder();
73 }

◆ open()

bool Kwave::OggDecoder::open ( QWidget *  widget,
QIODevice &  source 
)
virtual

Opens the source and decodes the header information.

Parameters
widgeta widget that can be used for displaying message boxes or dialogs
sourcefile or other source with a stream of bytes
Returns
true if succeeded, false on errors

Implements Kwave::Decoder.

Definition at line 173 of file OggDecoder.cpp.

References m_oy, m_source, Kwave::Decoder::metaData(), and parseHeader().

174 {
175  metaData().clear();
176  Q_ASSERT(!m_source);
177  if (m_source) qWarning("OggDecoder::open(), already open !");
178 
179  // try to open the source
180  if (!src.open(QIODevice::ReadOnly)) {
181  qWarning("failed to open source !");
182  return false;
183  }
184 
185  // take over the source
186  m_source = &src;
187 
188  /********** Decode setup ************/
189  qDebug("--- OggDecoder::open() ---");
190  ogg_sync_init(&m_oy); // Now we can read pages
191 
192  // read the header the first time
193  if (parseHeader(widget) < 0)
194  return false;
195 
196  return true;
197 }
ogg_sync_state m_oy
Definition: OggDecoder.h:87
QIODevice * m_source
Definition: OggDecoder.h:84
int parseHeader(QWidget *widget)
Definition: OggDecoder.cpp:76
virtual Kwave::MetaDataList & metaData()
Definition: Decoder.h:78
Here is the call graph for this function:

◆ parseHeader()

int Kwave::OggDecoder::parseHeader ( QWidget *  widget)
protected

Try to parse header frames.

Parameters
widgeta QWidget for displaying error messages
Returns
-1 for error (return false) 1 if ready to continue

Definition at line 76 of file OggDecoder.cpp.

References _, Kwave::MessageBox::error(), Kwave::INF_MIMETYPE, m_og, m_op, m_os, m_oy, m_source, m_sub_decoder, Kwave::Decoder::metaData(), Kwave::OggSubDecoder::open(), Kwave::MetaDataList::replace(), SAMPLE_BITS, Kwave::FileInfo::set(), Kwave::FileInfo::setBits(), and Kwave::FileInfo::setLength().

Referenced by decode(), and open().

77 {
78  // grab some data at the head of the stream. We want the first page
79  // (which is guaranteed to be small and only contain the Vorbis
80  // stream initial header) We need the first page to get the stream
81  // serialno.
82 
83  // submit a 4k block to libvorbis' Ogg layer
84  char *buffer = ogg_sync_buffer(&m_oy, 4096);
85  Q_ASSERT(buffer);
86  if (!buffer) return -1;
87 
88  long int bytes = static_cast<long int>(m_source->read(buffer, 4096));
89  if ((bytes <= 0) && (!m_source->pos())) {
90  Kwave::MessageBox::error(widget, i18n(
91  "Ogg bitstream has zero-length."));
92  return -1;
93  }
94  ogg_sync_wrote(&m_oy, bytes);
95 
96  // Get the first page.
97  if (ogg_sync_pageout(&m_oy, &m_og) != 1) {
98  // have we simply run out of data? If so, we're done.
99  if (bytes < 4096) return 0;
100 
101  // error case. seems not be Vorbis data
102  Kwave::MessageBox::error(widget, i18n(
103  "Input does not appear to be an Ogg bitstream."));
104  return -1;
105  }
106 
107  // Get the serial number and set up the rest of decode.
108  // serialno first; use it to set up a logical stream
109  ogg_stream_init(&m_os, ogg_page_serialno(&m_og));
110 
111  // get the first packet
112  if (ogg_stream_pagein(&m_os, &m_og) < 0) {
113  // error; stream version mismatch perhaps
114  Kwave::MessageBox::error(widget, i18n(
115  "Error reading first page of the Ogg bitstream data."));
116  return -1;
117  }
118 
119  if ((ogg_stream_packetout(&m_os, &m_op) != 1) || (m_op.bytes < 8)) {
120  // no page? must not be vorbis
121  Kwave::MessageBox::error(widget, i18n(
122  "Error reading initial header packet."));
123  return -1;
124  }
125 
126  // get rid of the previous sub decoder
127  if (m_sub_decoder) {
128  delete m_sub_decoder;
129  m_sub_decoder = Q_NULLPTR;
130  }
131 
132  Kwave::FileInfo info(metaData());
133 
134  // ---------------------------------
135  // auto-detect the sub decoder
136 #ifdef HAVE_OGG_OPUS
137  if (memcmp(m_op.packet, "OpusHead", 8) == 0) {
138  qDebug(" OggDecoder: detected Opus codec");
139  m_sub_decoder =
141  info.set(Kwave::INF_MIMETYPE, _("audio/opus"));
142  }
143 #endif /* HAVE_OGG_OPUS */
144 #ifdef HAVE_OGG_VORBIS
145  if (memcmp(m_op.packet + 1, "vorbis", 6) == 0) {
146  qDebug(" OggDecoder: detected Vorbis codec");
147  m_sub_decoder =
149  info.set(Kwave::INF_MIMETYPE, _("audio/x-vorbis+ogg"));
150  }
151 #endif /* HAVE_OGG_VORBIS */
152 
153  if (!m_sub_decoder) {
154  qDebug("--- dump of the first 8 bytes of the packet: ---");
155  for (unsigned int i = 0; i < 8; i++)
156  qDebug("%2d: 0x%02X - '%c'", i, m_op.packet[i], m_op.packet[i]);
157 
158  Kwave::MessageBox::error(widget, i18n(
159  "Error: Codec not supported"));
160  return -1;
161  }
162 
163  info.setLength(0); // use streaming
164  info.setBits(SAMPLE_BITS); // use Kwave's internal resolution
165  if (m_sub_decoder->open(widget, info) < 0)
166  return -1;
167 
169  return 1;
170 }
ogg_sync_state m_oy
Definition: OggDecoder.h:87
QIODevice * m_source
Definition: OggDecoder.h:84
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
virtual void replace(const MetaDataList &list)
virtual Kwave::MetaDataList & metaData()
Definition: Decoder.h:78
Kwave::OggSubDecoder * m_sub_decoder
Definition: OggDecoder.h:81
virtual int open(QWidget *widget, Kwave::FileInfo &info)=0
#define _(m)
Definition: memcpy.c:66
ogg_stream_state m_os
Definition: OggDecoder.h:90
#define SAMPLE_BITS
Definition: Sample.h:43
ogg_packet m_op
Definition: OggDecoder.h:96
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_og

ogg_page Kwave::OggDecoder::m_og
private

one Ogg bitstream page. Vorbis packets are inside

Definition at line 93 of file OggDecoder.h.

Referenced by decode(), and parseHeader().

◆ m_op

ogg_packet Kwave::OggDecoder::m_op
private

one raw packet of data for decode

Definition at line 96 of file OggDecoder.h.

Referenced by decode(), and parseHeader().

◆ m_os

ogg_stream_state Kwave::OggDecoder::m_os
private

take physical pages, weld into a logical stream of packets

Definition at line 90 of file OggDecoder.h.

Referenced by decode(), and parseHeader().

◆ m_oy

ogg_sync_state Kwave::OggDecoder::m_oy
private

sync and verify incoming physical bitstream

Definition at line 87 of file OggDecoder.h.

Referenced by decode(), open(), and parseHeader().

◆ m_source

QIODevice* Kwave::OggDecoder::m_source
private

source of the audio data

Definition at line 84 of file OggDecoder.h.

Referenced by close(), decode(), open(), parseHeader(), and ~OggDecoder().

◆ m_sub_decoder

Kwave::OggSubDecoder* Kwave::OggDecoder::m_sub_decoder
private

sub decoder, can be Vorbis, Opus, Speex or whatever...

Definition at line 81 of file OggDecoder.h.

Referenced by close(), decode(), and parseHeader().


The documentation for this class was generated from the following files: