Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
b5ecfb4c
Commit
b5ecfb4c
authored
May 11, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
decoder/opus: move code to class OggVisitor
parent
07fa3764
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
222 additions
and
100 deletions
+222
-100
Makefile.am
Makefile.am
+1
-0
OpusDecoderPlugin.cxx
src/decoder/plugins/OpusDecoderPlugin.cxx
+50
-100
OggVisitor.cxx
src/lib/xiph/OggVisitor.cxx
+101
-0
OggVisitor.hxx
src/lib/xiph/OggVisitor.hxx
+70
-0
No files found.
Makefile.am
View file @
b5ecfb4c
...
...
@@ -585,6 +585,7 @@ if HAVE_XIPH
noinst_LIBRARIES
+=
libxiph.a
libxiph_a_SOURCES
=
\
src/lib/xiph/OggVisitor.cxx src/lib/xiph/OggVisitor.hxx
\
src/lib/xiph/VorbisComment.hxx
\
src/lib/xiph/VorbisComments.cxx src/lib/xiph/VorbisComments.hxx
\
src/lib/xiph/XiphTags.cxx src/lib/xiph/XiphTags.hxx
...
...
src/decoder/plugins/OpusDecoderPlugin.cxx
View file @
b5ecfb4c
...
...
@@ -23,8 +23,7 @@
#include "OpusHead.hxx"
#include "OpusTags.hxx"
#include "OggFind.hxx"
#include "lib/xiph/OggStreamState.hxx"
#include "lib/xiph/OggSyncState.hxx"
#include "lib/xiph/OggVisitor.hxx"
#include "../DecoderAPI.hxx"
#include "decoder/Reader.hxx"
#include "input/Reader.hxx"
...
...
@@ -73,13 +72,10 @@ mpd_opus_init(gcc_unused const ConfigBlock &block)
return
true
;
}
class
MPDOpusDecoder
{
class
MPDOpusDecoder
final
:
public
OggVisitor
{
Decoder
&
decoder
;
InputStream
&
input_stream
;
OggSyncState
oy
;
OggStreamState
os
;
OpusDecoder
*
opus_decoder
=
nullptr
;
opus_int16
*
output_buffer
=
nullptr
;
...
...
@@ -97,40 +93,32 @@ class MPDOpusDecoder {
public
:
MPDOpusDecoder
(
DecoderReader
&
reader
)
:
decoder
(
reader
.
GetDecoder
()),
input_stream
(
reader
.
GetInputStream
()),
oy
(
reader
),
os
(
0
)
{}
:
OggVisitor
(
reader
),
decoder
(
reader
.
GetDecoder
()),
input_stream
(
reader
.
GetInputStream
())
{}
~
MPDOpusDecoder
();
/**
* Has the OggStreamState been initialized with the first
* serial?
*/
bool
HasSerial
()
const
{
return
os
.
GetSerialNo
()
!=
0
;
}
/**
* Has decoder_initialized() been called yet?
*/
bool
IsInitialized
()
const
{
return
previous_channels
!=
0
;
}
bool
ReadNextPage
();
DecoderCommand
HandlePackets
();
bool
Seek
(
uint64_t
where_frame
);
private
:
DecoderCommand
HandlePacket
(
const
ogg_packet
&
packet
);
void
HandleBOS
(
const
ogg_packet
&
packet
);
void
HandleEOS
();
DecoderCommand
HandleTags
(
const
ogg_packet
&
packet
);
DecoderCommand
HandleAudio
(
const
ogg_packet
&
packet
);
void
HandleTags
(
const
ogg_packet
&
packet
);
void
HandleAudio
(
const
ogg_packet
&
packet
);
protected
:
/* virtual methods from class OggVisitor */
void
OnOggBeginning
(
const
ogg_packet
&
packet
)
override
;
void
OnOggPacket
(
const
ogg_packet
&
packet
)
override
;
void
OnOggEnd
()
override
;
};
MPDOpusDecoder
::~
MPDOpusDecoder
()
...
...
@@ -141,52 +129,13 @@ MPDOpusDecoder::~MPDOpusDecoder()
opus_decoder_destroy
(
opus_decoder
);
}
inline
bool
MPDOpusDecoder
::
ReadNextPage
(
)
void
MPDOpusDecoder
::
OnOggPacket
(
const
ogg_packet
&
packet
)
{
ogg_page
page
;
if
(
!
oy
.
ExpectPage
(
page
))
return
false
;
const
auto
page_serialno
=
ogg_page_serialno
(
&
page
);
if
(
page_serialno
!=
os
.
GetSerialNo
())
os
.
Reinitialize
(
page_serialno
);
os
.
PageIn
(
page
);
return
true
;
}
inline
DecoderCommand
MPDOpusDecoder
::
HandlePackets
()
{
ogg_packet
packet
;
while
(
os
.
PacketOut
(
packet
)
==
1
)
{
auto
cmd
=
HandlePacket
(
packet
);
if
(
cmd
!=
DecoderCommand
::
NONE
)
return
cmd
;
}
return
DecoderCommand
::
NONE
;
}
inline
DecoderCommand
MPDOpusDecoder
::
HandlePacket
(
const
ogg_packet
&
packet
)
{
if
(
packet
.
e_o_s
)
{
HandleEOS
();
return
decoder_get_command
(
decoder
);
}
if
(
packet
.
b_o_s
)
{
HandleBOS
(
packet
);
return
decoder_get_command
(
decoder
);
}
else
if
(
opus_decoder
==
nullptr
)
throw
std
::
runtime_error
(
"BOS packet expected"
);
if
(
IsOpusTags
(
packet
))
return
HandleTags
(
packet
);
return
HandleAudio
(
packet
);
HandleTags
(
packet
);
else
HandleAudio
(
packet
);
}
/**
...
...
@@ -240,8 +189,8 @@ LoadEOSGranulePos(InputStream &is, Decoder &decoder, int serialno)
return
packet
.
granulepos
;
}
inline
void
MPDOpusDecoder
::
HandleBOS
(
const
ogg_packet
&
packet
)
void
MPDOpusDecoder
::
OnOggBeginning
(
const
ogg_packet
&
packet
)
{
assert
(
packet
.
b_o_s
);
...
...
@@ -260,7 +209,7 @@ MPDOpusDecoder::HandleBOS(const ogg_packet &packet)
throw
FormatRuntimeError
(
"Next stream has different channels (%u -> %u)"
,
previous_channels
,
channels
);
const
auto
opus_serialno
=
os
.
GetSerialNo
();
const
auto
opus_serialno
=
GetSerialNo
();
/* TODO: parse attributes from the OpusHead (sample rate,
channels, ...) */
...
...
@@ -295,10 +244,14 @@ MPDOpusDecoder::HandleBOS(const ogg_packet &packet)
output_buffer
=
new
opus_int16
[
opus_output_buffer_frames
*
audio_format
.
channels
];
auto
cmd
=
decoder_get_command
(
decoder
);
if
(
cmd
!=
DecoderCommand
::
NONE
)
throw
cmd
;
}
inline
void
MPDOpusDecoder
::
HandleEOS
()
void
MPDOpusDecoder
::
OnOggEnd
()
{
if
(
eos_granulepos
<
0
&&
IsInitialized
())
{
/* allow chaining of (unseekable) streams */
...
...
@@ -311,7 +264,7 @@ MPDOpusDecoder::HandleEOS()
throw
StopDecoder
();
}
inline
DecoderComman
d
inline
voi
d
MPDOpusDecoder
::
HandleTags
(
const
ogg_packet
&
packet
)
{
ReplayGainInfo
rgi
;
...
...
@@ -319,7 +272,6 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet)
TagBuilder
tag_builder
;
DecoderCommand
cmd
;
if
(
ScanOpusTags
(
packet
.
packet
,
packet
.
bytes
,
&
rgi
,
add_tag_handler
,
&
tag_builder
)
&&
...
...
@@ -327,14 +279,13 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet)
decoder_replay_gain
(
decoder
,
&
rgi
);
Tag
tag
=
tag_builder
.
Commit
();
cmd
=
decoder_tag
(
decoder
,
input_stream
,
std
::
move
(
tag
));
}
else
cmd
=
decoder_get_command
(
decoder
);
return
cmd
;
auto
cmd
=
decoder_tag
(
decoder
,
input_stream
,
std
::
move
(
tag
));
if
(
cmd
!=
DecoderCommand
::
NONE
)
throw
cmd
;
}
}
inline
DecoderComman
d
inline
voi
d
MPDOpusDecoder
::
HandleAudio
(
const
ogg_packet
&
packet
)
{
assert
(
opus_decoder
!=
nullptr
);
...
...
@@ -354,15 +305,13 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet)
output_buffer
,
nbytes
,
0
);
if
(
cmd
!=
DecoderCommand
::
NONE
)
return
cmd
;
throw
cmd
;
if
(
packet
.
granulepos
>
0
)
decoder_timestamp
(
decoder
,
double
(
packet
.
granulepos
)
/
opus_sample_rate
);
}
return
DecoderCommand
::
NONE
;
}
bool
...
...
@@ -380,7 +329,11 @@ MPDOpusDecoder::Seek(uint64_t where_frame)
offset_type
offset
(
where_granulepos
*
input_stream
.
GetSize
()
/
eos_granulepos
);
return
OggSeekPageAtOffset
(
oy
,
os
,
input_stream
,
offset
);
if
(
!
input_stream
.
LockSeek
(
offset
,
IgnoreError
()))
return
false
;
PostSeek
();
return
true
;
}
static
void
...
...
@@ -399,21 +352,18 @@ mpd_opus_stream_decode(Decoder &decoder,
MPDOpusDecoder
d
(
reader
);
while
(
true
)
{
auto
cmd
=
d
.
HandlePackets
();
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
if
(
d
.
Seek
(
decoder_seek_where_frame
(
decoder
)))
decoder_command_finished
(
decoder
);
else
decoder_seek_error
(
decoder
);
continue
;
}
if
(
cmd
!=
DecoderCommand
::
NONE
)
break
;
if
(
!
d
.
ReadNextPage
())
try
{
d
.
Visit
();
break
;
}
catch
(
DecoderCommand
cmd
)
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
if
(
d
.
Seek
(
decoder_seek_where_frame
(
decoder
)))
decoder_command_finished
(
decoder
);
else
decoder_seek_error
(
decoder
);
}
else
if
(
cmd
!=
DecoderCommand
::
NONE
)
break
;
}
}
}
...
...
src/lib/xiph/OggVisitor.cxx
0 → 100644
View file @
b5ecfb4c
/*
* Copyright 2003-2016 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "OggVisitor.hxx"
#include <stdexcept>
void
OggVisitor
::
EndStream
()
{
if
(
!
has_stream
)
return
;
has_stream
=
false
;
OnOggEnd
();
}
inline
bool
OggVisitor
::
ReadNextPage
()
{
ogg_page
page
;
if
(
!
sync
.
ExpectPage
(
page
))
return
false
;
const
auto
page_serialno
=
ogg_page_serialno
(
&
page
);
if
(
page_serialno
!=
stream
.
GetSerialNo
())
{
EndStream
();
stream
.
Reinitialize
(
page_serialno
);
}
stream
.
PageIn
(
page
);
return
true
;
}
inline
void
OggVisitor
::
HandlePacket
(
const
ogg_packet
&
packet
)
{
if
(
packet
.
b_o_s
)
{
EndStream
();
has_stream
=
true
;
OnOggBeginning
(
packet
);
return
;
}
if
(
!
has_stream
)
/* fail if BOS is missing */
throw
std
::
runtime_error
(
"BOS packet expected"
);
if
(
packet
.
e_o_s
)
{
EndStream
();
return
;
}
OnOggPacket
(
packet
);
}
inline
void
OggVisitor
::
HandlePackets
()
{
ogg_packet
packet
;
while
(
stream
.
PacketOut
(
packet
)
==
1
)
HandlePacket
(
packet
);
}
void
OggVisitor
::
Visit
()
{
do
{
HandlePackets
();
}
while
(
ReadNextPage
());
}
void
OggVisitor
::
PostSeek
()
{
sync
.
Reset
();
/* reset the stream to clear any previous partial packet
data */
stream
.
Reset
();
/* find the next Ogg page and feed it into the stream */
sync
.
ExpectPageSeekIn
(
stream
);
}
src/lib/xiph/OggVisitor.hxx
0 → 100644
View file @
b5ecfb4c
/*
* Copyright 2003-2016 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_OGG_VISITOR_HXX
#define MPD_OGG_VISITOR_HXX
#include "check.h"
#include "OggSyncState.hxx"
#include "OggStreamState.hxx"
#include <ogg/ogg.h>
#include <stddef.h>
class
Reader
;
/**
* Abstract class which iterates over Ogg packets in a #Reader.
* Subclass it and implement the virtual methods.
*/
class
OggVisitor
{
OggSyncState
sync
;
OggStreamState
stream
;
bool
has_stream
=
false
;
public
:
explicit
OggVisitor
(
Reader
&
reader
)
:
sync
(
reader
),
stream
(
0
)
{}
long
GetSerialNo
()
const
{
return
stream
.
GetSerialNo
();
}
void
Visit
();
/**
* Call this method after seeking the #Reader.
*/
void
PostSeek
();
private
:
void
EndStream
();
bool
ReadNextPage
();
void
HandlePacket
(
const
ogg_packet
&
packet
);
void
HandlePackets
();
protected
:
virtual
void
OnOggBeginning
(
const
ogg_packet
&
packet
)
=
0
;
virtual
void
OnOggPacket
(
const
ogg_packet
&
packet
)
=
0
;
virtual
void
OnOggEnd
()
=
0
;
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment