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
d8b6aff2
Commit
d8b6aff2
authored
Nov 07, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
encoder: migrate from class Error to C++ exceptions
parent
b8aac3f8
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
300 additions
and
478 deletions
+300
-478
EncoderInterface.hxx
src/encoder/EncoderInterface.hxx
+15
-19
FlacEncoderPlugin.cxx
src/encoder/plugins/FlacEncoderPlugin.cxx
+40
-78
LameEncoderPlugin.cxx
src/encoder/plugins/LameEncoderPlugin.cxx
+32
-61
NullEncoderPlugin.cxx
src/encoder/plugins/NullEncoderPlugin.cxx
+2
-3
OggEncoder.hxx
src/encoder/plugins/OggEncoder.hxx
+2
-8
OpusEncoderPlugin.cxx
src/encoder/plugins/OpusEncoderPlugin.cxx
+24
-43
ShineEncoderPlugin.cxx
src/encoder/plugins/ShineEncoderPlugin.cxx
+20
-33
TwolameEncoderPlugin.cxx
src/encoder/plugins/TwolameEncoderPlugin.cxx
+33
-57
VorbisEncoderPlugin.cxx
src/encoder/plugins/VorbisEncoderPlugin.cxx
+24
-46
WaveEncoderPlugin.cxx
src/encoder/plugins/WaveEncoderPlugin.cxx
+4
-6
RecorderOutputPlugin.cxx
src/output/plugins/RecorderOutputPlugin.cxx
+31
-49
ShoutOutputPlugin.cxx
src/output/plugins/ShoutOutputPlugin.cxx
+29
-15
HttpdInternal.hxx
src/output/plugins/httpd/HttpdInternal.hxx
+7
-2
HttpdOutputPlugin.cxx
src/output/plugins/httpd/HttpdOutputPlugin.cxx
+28
-25
run_encoder.cxx
test/run_encoder.cxx
+3
-17
test_vorbis_encoder.cxx
test/test_vorbis_encoder.cxx
+6
-16
No files found.
src/encoder/EncoderInterface.hxx
View file @
d8b6aff2
...
...
@@ -28,7 +28,6 @@
struct
AudioFormat
;
struct
Tag
;
class
Error
;
class
Encoder
{
const
bool
implements_tag
;
...
...
@@ -51,20 +50,18 @@ public:
* usable for more data, and only Read() and Close() can be
* called.
*
*
@return true on success
*
Throws #std::runtime_error on error.
*/
virtual
bool
End
(
gcc_unused
Error
&
error
)
{
return
true
;
virtual
void
End
()
{
}
/**
* Flushes an encoder object, make everything which might
* currently be buffered available by Read().
*
*
@return true on success
*
Throws #std::runtime_error on error.
*/
virtual
bool
Flush
(
gcc_unused
Error
&
error
)
{
return
true
;
virtual
void
Flush
()
{
}
/**
...
...
@@ -72,10 +69,9 @@ public:
* some encoders to flush the previous sub-stream, in
* preparation to begin a new one.
*
*
@return true on success
*
Throws #std::runtime_error on error.
*/
virtual
bool
PreTag
(
gcc_unused
Error
&
error
)
{
return
true
;
virtual
void
PreTag
()
{
}
/**
...
...
@@ -84,23 +80,22 @@ public:
* Instructions: call PreTag(); then obtain flushed data with
* Read(); finally call Tag().
*
* Throws #std::runtime_error on error.
*
* @param tag the tag object
* @return true on success
*/
virtual
bool
SendTag
(
gcc_unused
const
Tag
&
tag
,
gcc_unused
Error
&
error
)
{
return
true
;
virtual
void
SendTag
(
gcc_unused
const
Tag
&
tag
)
{
}
/**
* Writes raw PCM data to the encoder.
*
* Throws #std::runtime_error on error.
*
* @param data the buffer containing PCM samples
* @param length the length of the buffer in bytes
* @return true on success
*/
virtual
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
error
)
=
0
;
virtual
void
Write
(
const
void
*
data
,
size_t
length
)
=
0
;
/**
* Reads encoded data from the encoder.
...
...
@@ -127,11 +122,12 @@ public:
* first encoder_write() call, you should invoke
* encoder_read() to obtain the file header.
*
* Throws #std::runtime_error on error.
*
* @param audio_format the encoder's input audio format; the plugin
* may modify the struct to adapt it to its abilities
* @return true on success
*/
virtual
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
=
0
;
virtual
Encoder
*
Open
(
AudioFormat
&
audio_format
)
=
0
;
/**
* Get mime type of encoded content.
...
...
src/encoder/plugins/FlacEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -24,8 +24,7 @@
#include "pcm/PcmBuffer.hxx"
#include "config/ConfigError.hxx"
#include "util/DynamicFifoBuffer.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/RuntimeError.hxx"
#include <FLAC/stream_encoder.h>
...
...
@@ -47,29 +46,22 @@ class FlacEncoder final : public Encoder {
DynamicFifoBuffer
<
uint8_t
>
output_buffer
;
public
:
FlacEncoder
(
AudioFormat
_audio_format
,
FLAC__StreamEncoder
*
_fse
)
:
Encoder
(
false
),
audio_format
(
_audio_format
),
fse
(
_fse
),
output_buffer
(
8192
)
{}
FlacEncoder
(
AudioFormat
_audio_format
,
FLAC__StreamEncoder
*
_fse
);
~
FlacEncoder
()
override
{
FLAC__stream_encoder_delete
(
fse
);
}
bool
Init
(
Error
&
error
);
/* virtual methods from class Encoder */
bool
End
(
Error
&
)
override
{
void
End
(
)
override
{
(
void
)
FLAC__stream_encoder_finish
(
fse
);
return
true
;
}
bool
Flush
(
Error
&
)
override
{
void
Flush
(
)
override
{
(
void
)
FLAC__stream_encoder_finish
(
fse
);
return
true
;
}
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
;
void
Write
(
const
void
*
data
,
size_t
length
)
override
;
size_t
Read
(
void
*
dest
,
size_t
length
)
override
{
return
output_buffer
.
Read
((
uint8_t
*
)
dest
,
length
);
...
...
@@ -95,15 +87,13 @@ public:
PreparedFlacEncoder
(
const
ConfigBlock
&
block
);
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
)
override
;
Encoder
*
Open
(
AudioFormat
&
audio_format
)
override
;
const
char
*
GetMimeType
()
const
override
{
return
"audio/flac"
;
}
};
static
constexpr
Domain
flac_encoder_domain
(
"vorbis_encoder"
);
PreparedFlacEncoder
::
PreparedFlacEncoder
(
const
ConfigBlock
&
block
)
:
compression
(
block
.
GetBlockValue
(
"compression"
,
5u
))
{
...
...
@@ -115,45 +105,32 @@ flac_encoder_init(const ConfigBlock &block)
return
new
PreparedFlacEncoder
(
block
);
}
static
bool
static
void
flac_encoder_setup
(
FLAC__StreamEncoder
*
fse
,
unsigned
compression
,
const
AudioFormat
&
audio_format
,
unsigned
bits_per_sample
,
Error
&
error
)
const
AudioFormat
&
audio_format
,
unsigned
bits_per_sample
)
{
if
(
!
FLAC__stream_encoder_set_compression_level
(
fse
,
compression
))
{
error
.
Format
(
config_domain
,
"error setting flac compression to %d"
,
compression
);
return
false
;
}
if
(
!
FLAC__stream_encoder_set_compression_level
(
fse
,
compression
))
throw
FormatRuntimeError
(
"error setting flac compression to %d"
,
compression
);
if
(
!
FLAC__stream_encoder_set_channels
(
fse
,
audio_format
.
channels
))
{
error
.
Format
(
config_domain
,
"error setting flac channels num to %d"
,
audio_format
.
channels
);
return
false
;
}
if
(
!
FLAC__stream_encoder_set_channels
(
fse
,
audio_format
.
channels
))
throw
FormatRuntimeError
(
"error setting flac channels num to %d"
,
audio_format
.
channels
);
if
(
!
FLAC__stream_encoder_set_bits_per_sample
(
fse
,
bits_per_sample
))
{
error
.
Format
(
config_domain
,
"error setting flac bit format to %d"
,
bits_per_sample
);
return
false
;
}
if
(
!
FLAC__stream_encoder_set_bits_per_sample
(
fse
,
bits_per_sample
))
throw
FormatRuntimeError
(
"error setting flac bit format to %d"
,
bits_per_sample
);
if
(
!
FLAC__stream_encoder_set_sample_rate
(
fse
,
audio_format
.
sample_rate
))
{
error
.
Format
(
config_domain
,
"error setting flac sample rate to %d"
,
audio_format
.
sample_rate
);
return
false
;
}
return
true
;
audio_format
.
sample_rate
))
throw
FormatRuntimeError
(
"error setting flac sample rate to %d"
,
audio_format
.
sample_rate
);
}
bool
FlacEncoder
::
Init
(
Error
&
error
)
FlacEncoder
::
FlacEncoder
(
AudioFormat
_audio_format
,
FLAC__StreamEncoder
*
_fse
)
:
Encoder
(
false
),
audio_format
(
_audio_format
),
fse
(
_fse
),
output_buffer
(
8192
)
{
/* this immediately outputs data through callback */
...
...
@@ -163,18 +140,13 @@ FlacEncoder::Init(Error &error)
nullptr
,
nullptr
,
nullptr
,
this
);
if
(
init_status
!=
FLAC__STREAM_ENCODER_INIT_STATUS_OK
)
{
error
.
Format
(
flac_encoder_domain
,
"failed to initialize encoder: %s
\n
"
,
FLAC__StreamEncoderInitStatusString
[
init_status
]);
return
false
;
}
return
true
;
if
(
init_status
!=
FLAC__STREAM_ENCODER_INIT_STATUS_OK
)
throw
FormatRuntimeError
(
"failed to initialize encoder: %s
\n
"
,
FLAC__StreamEncoderInitStatusString
[
init_status
]);
}
Encoder
*
PreparedFlacEncoder
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
PreparedFlacEncoder
::
Open
(
AudioFormat
&
audio_format
)
{
unsigned
bits_per_sample
;
...
...
@@ -199,24 +171,18 @@ PreparedFlacEncoder::Open(AudioFormat &audio_format, Error &error)
/* allocate the encoder */
auto
fse
=
FLAC__stream_encoder_new
();
if
(
fse
==
nullptr
)
{
error
.
Set
(
flac_encoder_domain
,
"FLAC__stream_encoder_new() failed"
);
return
nullptr
;
}
if
(
fse
==
nullptr
)
throw
std
::
runtime_error
(
"FLAC__stream_encoder_new() failed"
);
if
(
!
flac_encoder_setup
(
fse
,
compression
,
audio_format
,
bits_per_sample
,
error
))
{
try
{
flac_encoder_setup
(
fse
,
compression
,
audio_format
,
bits_per_sample
);
}
catch
(...)
{
FLAC__stream_encoder_delete
(
fse
);
return
nullptr
;
throw
;
}
auto
*
e
=
new
FlacEncoder
(
audio_format
,
fse
);
if
(
!
e
->
Init
(
error
))
{
delete
e
;
return
nullptr
;
}
return
e
;
return
new
FlacEncoder
(
audio_format
,
fse
);
}
static
inline
void
...
...
@@ -237,8 +203,8 @@ pcm16_to_flac(int32_t *out, const int16_t *in, unsigned num_samples)
}
}
bool
FlacEncoder
::
Write
(
const
void
*
data
,
size_t
length
,
Error
&
error
)
void
FlacEncoder
::
Write
(
const
void
*
data
,
size_t
length
)
{
void
*
exbuffer
;
const
void
*
buffer
=
nullptr
;
...
...
@@ -278,12 +244,8 @@ FlacEncoder::Write(const void *data, size_t length, Error &error)
if
(
!
FLAC__stream_encoder_process_interleaved
(
fse
,
(
const
FLAC__int32
*
)
buffer
,
num_frames
))
{
error
.
Set
(
flac_encoder_domain
,
"flac encoder process failed"
);
return
false
;
}
return
true
;
num_frames
))
throw
std
::
runtime_error
(
"flac encoder process failed"
);
}
const
EncoderPlugin
flac_encoder_plugin
=
{
...
...
src/encoder/plugins/LameEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -25,11 +25,11 @@
#include "util/NumberParser.hxx"
#include "util/ReusableArray.hxx"
#include "util/RuntimeError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <lame/lame.h>
#include <stdexcept>
#include <assert.h>
#include <string.h>
...
...
@@ -50,7 +50,7 @@ public:
~
LameEncoder
()
override
;
/* virtual methods from class Encoder */
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
;
void
Write
(
const
void
*
data
,
size_t
length
)
override
;
size_t
Read
(
void
*
dest
,
size_t
length
)
override
;
};
...
...
@@ -62,15 +62,13 @@ public:
PreparedLameEncoder
(
const
ConfigBlock
&
block
);
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
)
override
;
Encoder
*
Open
(
AudioFormat
&
audio_format
)
override
;
const
char
*
GetMimeType
()
const
override
{
return
"audio/mpeg"
;
}
};
static
constexpr
Domain
lame_encoder_domain
(
"lame_encoder"
);
PreparedLameEncoder
::
PreparedLameEncoder
(
const
ConfigBlock
&
block
)
{
const
char
*
value
;
...
...
@@ -110,76 +108,53 @@ lame_encoder_init(const ConfigBlock &block)
return
new
PreparedLameEncoder
(
block
);
}
static
bool
static
void
lame_encoder_setup
(
lame_global_flags
*
gfp
,
float
quality
,
int
bitrate
,
const
AudioFormat
&
audio_format
,
Error
&
error
)
const
AudioFormat
&
audio_format
)
{
if
(
quality
>=
-
1.0
)
{
/* a quality was configured (VBR) */
if
(
0
!=
lame_set_VBR
(
gfp
,
vbr_rh
))
{
error
.
Set
(
lame_encoder_domain
,
"error setting lame VBR mode"
);
return
false
;
}
if
(
0
!=
lame_set_VBR_q
(
gfp
,
quality
))
{
error
.
Set
(
lame_encoder_domain
,
"error setting lame VBR quality"
);
return
false
;
}
if
(
0
!=
lame_set_VBR
(
gfp
,
vbr_rh
))
throw
std
::
runtime_error
(
"error setting lame VBR mode"
);
if
(
0
!=
lame_set_VBR_q
(
gfp
,
quality
))
throw
std
::
runtime_error
(
"error setting lame VBR quality"
);
}
else
{
/* a bit rate was configured */
if
(
0
!=
lame_set_brate
(
gfp
,
bitrate
))
{
error
.
Set
(
lame_encoder_domain
,
"error setting lame bitrate"
);
return
false
;
}
}
if
(
0
!=
lame_set_num_channels
(
gfp
,
audio_format
.
channels
))
{
error
.
Set
(
lame_encoder_domain
,
"error setting lame num channels"
);
return
false
;
if
(
0
!=
lame_set_brate
(
gfp
,
bitrate
))
throw
std
::
runtime_error
(
"error setting lame bitrate"
);
}
if
(
0
!=
lame_set_in_samplerate
(
gfp
,
audio_format
.
sample_rate
))
{
error
.
Set
(
lame_encoder_domain
,
"error setting lame sample rate"
);
return
false
;
}
if
(
0
!=
lame_set_num_channels
(
gfp
,
audio_format
.
channels
))
throw
std
::
runtime_error
(
"error setting lame num channels"
);
if
(
0
!=
lame_set_out_samplerate
(
gfp
,
audio_format
.
sample_rate
))
{
error
.
Set
(
lame_encoder_domain
,
"error setting lame out sample rate"
);
return
false
;
}
if
(
0
!=
lame_set_in_samplerate
(
gfp
,
audio_format
.
sample_rate
))
throw
std
::
runtime_error
(
"error setting lame sample rate"
);
if
(
0
>
lame_init_params
(
gfp
))
{
error
.
Set
(
lame_encoder_domain
,
"error initializing lame params"
);
return
false
;
}
if
(
0
!=
lame_set_out_samplerate
(
gfp
,
audio_format
.
sample_rate
))
throw
std
::
runtime_error
(
"error setting lame out sample rate"
);
return
true
;
if
(
0
>
lame_init_params
(
gfp
))
throw
std
::
runtime_error
(
"error initializing lame params"
);
}
Encoder
*
PreparedLameEncoder
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
PreparedLameEncoder
::
Open
(
AudioFormat
&
audio_format
)
{
audio_format
.
format
=
SampleFormat
::
S16
;
audio_format
.
channels
=
2
;
auto
gfp
=
lame_init
();
if
(
gfp
==
nullptr
)
{
error
.
Set
(
lame_encoder_domain
,
"lame_init() failed"
);
return
nullptr
;
}
if
(
gfp
==
nullptr
)
throw
std
::
runtime_error
(
"lame_init() failed"
);
if
(
!
lame_encoder_setup
(
gfp
,
quality
,
bitrate
,
audio_format
,
error
))
{
try
{
lame_encoder_setup
(
gfp
,
quality
,
bitrate
,
audio_format
);
}
catch
(...)
{
lame_close
(
gfp
);
return
nullptr
;
throw
;
}
return
new
LameEncoder
(
audio_format
,
gfp
);
...
...
@@ -190,9 +165,8 @@ LameEncoder::~LameEncoder()
lame_close
(
gfp
);
}
bool
LameEncoder
::
Write
(
const
void
*
data
,
size_t
length
,
gcc_unused
Error
&
error
)
void
LameEncoder
::
Write
(
const
void
*
data
,
size_t
length
)
{
const
int16_t
*
src
=
(
const
int16_t
*
)
data
;
...
...
@@ -212,14 +186,11 @@ LameEncoder::Write(const void *data, size_t length,
num_frames
,
dest
,
output_buffer_size
);
if
(
bytes_out
<
0
)
{
error
.
Set
(
lame_encoder_domain
,
"lame encoder failed"
);
return
false
;
}
if
(
bytes_out
<
0
)
throw
std
::
runtime_error
(
"lame encoder failed"
);
output_begin
=
dest
;
output_end
=
dest
+
bytes_out
;
return
true
;
}
size_t
...
...
src/encoder/plugins/NullEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -32,9 +32,8 @@ public:
buffer
(
8192
)
{}
/* virtual methods from class Encoder */
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
{
void
Write
(
const
void
*
data
,
size_t
length
)
override
{
buffer
.
Append
((
const
uint8_t
*
)
data
,
length
);
return
true
;
}
size_t
Read
(
void
*
dest
,
size_t
length
)
override
{
...
...
@@ -45,7 +44,7 @@ public:
class
PreparedNullEncoder
final
:
public
PreparedEncoder
{
public
:
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
,
Error
&
)
override
{
Encoder
*
Open
(
AudioFormat
&
)
override
{
return
new
NullEncoder
();
}
};
...
...
src/encoder/plugins/OggEncoder.hxx
View file @
d8b6aff2
...
...
@@ -47,9 +47,8 @@ public:
}
/* virtual methods from class Encoder */
bool
Flush
(
Error
&
)
override
{
Flush
();
return
true
;
void
Flush
()
final
{
flush
=
true
;
}
size_t
Read
(
void
*
dest
,
size_t
length
)
override
{
...
...
@@ -67,11 +66,6 @@ public:
return
ReadPage
(
page
,
dest
,
length
);
}
protected
:
void
Flush
()
{
flush
=
true
;
}
};
#endif
src/encoder/plugins/OpusEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -23,8 +23,6 @@
#include "AudioFormat.hxx"
#include "config/ConfigError.hxx"
#include "util/Alloc.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "system/ByteOrder.hxx"
#include <opus.h>
...
...
@@ -61,14 +59,14 @@ public:
~
OpusEncoder
()
override
;
/* virtual methods from class Encoder */
bool
End
(
Error
&
)
override
;
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
;
void
End
(
)
override
;
void
Write
(
const
void
*
data
,
size_t
length
)
override
;
size_t
Read
(
void
*
dest
,
size_t
length
)
override
;
private
:
bool
DoEncode
(
bool
eos
,
Error
&
error
);
bool
WriteSilence
(
unsigned
fill_frames
,
Error
&
error
);
void
DoEncode
(
bool
eos
);
void
WriteSilence
(
unsigned
fill_frames
);
void
GenerateHead
();
void
GenerateTags
();
...
...
@@ -83,15 +81,13 @@ public:
PreparedOpusEncoder
(
const
ConfigBlock
&
block
);
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
)
override
;
Encoder
*
Open
(
AudioFormat
&
audio_format
)
override
;
const
char
*
GetMimeType
()
const
override
{
return
"audio/ogg"
;
}
};
static
constexpr
Domain
opus_encoder_domain
(
"opus_encoder"
);
PreparedOpusEncoder
::
PreparedOpusEncoder
(
const
ConfigBlock
&
block
)
{
const
char
*
value
=
block
.
GetBlockValue
(
"bitrate"
,
"auto"
);
...
...
@@ -141,7 +137,7 @@ OpusEncoder::OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc)
}
Encoder
*
PreparedOpusEncoder
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
PreparedOpusEncoder
::
Open
(
AudioFormat
&
audio_format
)
{
/* libopus supports only 48 kHz */
audio_format
.
sample_rate
=
48000
;
...
...
@@ -168,11 +164,8 @@ PreparedOpusEncoder::Open(AudioFormat &audio_format, Error &error)
audio_format
.
channels
,
OPUS_APPLICATION_AUDIO
,
&
error_code
);
if
(
enc
==
nullptr
)
{
error
.
Set
(
opus_encoder_domain
,
error_code
,
opus_strerror
(
error_code
));
return
nullptr
;
}
if
(
enc
==
nullptr
)
throw
std
::
runtime_error
(
opus_strerror
(
error_code
));
opus_encoder_ctl
(
enc
,
OPUS_SET_BITRATE
(
bitrate
));
opus_encoder_ctl
(
enc
,
OPUS_SET_COMPLEXITY
(
complexity
));
...
...
@@ -187,8 +180,8 @@ OpusEncoder::~OpusEncoder()
opus_encoder_destroy
(
enc
);
}
bool
OpusEncoder
::
DoEncode
(
bool
eos
,
Error
&
error
)
void
OpusEncoder
::
DoEncode
(
bool
eos
)
{
assert
(
buffer_position
==
buffer_size
);
...
...
@@ -204,10 +197,8 @@ OpusEncoder::DoEncode(bool eos, Error &error)
buffer_frames
,
buffer2
,
sizeof
(
buffer2
));
if
(
result
<
0
)
{
error
.
Set
(
opus_encoder_domain
,
"Opus encoder error"
);
return
false
;
}
if
(
result
<
0
)
throw
std
::
runtime_error
(
"Opus encoder error"
);
granulepos
+=
buffer_frames
;
...
...
@@ -221,12 +212,10 @@ OpusEncoder::DoEncode(bool eos, Error &error)
stream
.
PacketIn
(
packet
);
buffer_position
=
0
;
return
true
;
}
bool
OpusEncoder
::
End
(
Error
&
error
)
void
OpusEncoder
::
End
()
{
Flush
();
...
...
@@ -234,11 +223,11 @@ OpusEncoder::End(Error &error)
buffer_size
-
buffer_position
);
buffer_position
=
buffer_size
;
return
DoEncode
(
true
,
error
);
DoEncode
(
true
);
}
bool
OpusEncoder
::
WriteSilence
(
unsigned
fill_frames
,
Error
&
error
)
void
OpusEncoder
::
WriteSilence
(
unsigned
fill_frames
)
{
size_t
fill_bytes
=
fill_frames
*
frame_size
;
...
...
@@ -251,16 +240,13 @@ OpusEncoder::WriteSilence(unsigned fill_frames, Error &error)
buffer_position
+=
nbytes
;
fill_bytes
-=
nbytes
;
if
(
buffer_position
==
buffer_size
&&
!
DoEncode
(
false
,
error
))
return
false
;
if
(
buffer_position
==
buffer_size
)
DoEncode
(
false
);
}
return
true
;
}
bool
OpusEncoder
::
Write
(
const
void
*
_data
,
size_t
length
,
Error
&
error
)
void
OpusEncoder
::
Write
(
const
void
*
_data
,
size_t
length
)
{
const
uint8_t
*
data
=
(
const
uint8_t
*
)
_data
;
...
...
@@ -270,9 +256,7 @@ OpusEncoder::Write(const void *_data, size_t length, Error &error)
assert
(
buffer_position
==
0
);
if
(
!
WriteSilence
(
lookahead
,
error
))
return
false
;
WriteSilence
(
lookahead
);
lookahead
=
0
;
}
...
...
@@ -286,12 +270,9 @@ OpusEncoder::Write(const void *_data, size_t length, Error &error)
length
-=
nbytes
;
buffer_position
+=
nbytes
;
if
(
buffer_position
==
buffer_size
&&
!
DoEncode
(
false
,
error
))
return
false
;
if
(
buffer_position
==
buffer_size
)
DoEncode
(
false
);
}
return
true
;
}
void
...
...
src/encoder/plugins/ShineEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -23,7 +23,7 @@
#include "AudioFormat.hxx"
#include "config/ConfigError.hxx"
#include "util/DynamicFifoBuffer.hxx"
#include "util/Error.hxx"
#include "util/
Runtime
Error.hxx"
extern
"C"
{
...
...
@@ -71,13 +71,13 @@ public:
bool
WriteChunk
(
bool
flush
);
/* virtual methods from class Encoder */
bool
End
(
Error
&
error
)
override
{
return
Flush
(
error
);
void
End
(
)
override
{
return
Flush
();
}
bool
Flush
(
Error
&
)
override
;
void
Flush
(
)
override
;
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
;
void
Write
(
const
void
*
data
,
size_t
length
)
override
;
size_t
Read
(
void
*
dest
,
size_t
length
)
override
{
return
output_buffer
.
Read
((
uint8_t
*
)
dest
,
length
);
...
...
@@ -91,7 +91,7 @@ public:
PreparedShineEncoder
(
const
ConfigBlock
&
block
);
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
)
override
;
Encoder
*
Open
(
AudioFormat
&
audio_format
)
override
;
const
char
*
GetMimeType
()
const
override
{
return
"audio/mpeg"
;
...
...
@@ -111,8 +111,7 @@ shine_encoder_init(const ConfigBlock &block)
}
static
shine_t
SetupShine
(
shine_config_t
config
,
AudioFormat
&
audio_format
,
Error
&
error
)
SetupShine
(
shine_config_t
config
,
AudioFormat
&
audio_format
)
{
audio_format
.
format
=
SampleFormat
::
S16
;
audio_format
.
channels
=
CHANNELS
;
...
...
@@ -122,32 +121,24 @@ SetupShine(shine_config_t config, AudioFormat &audio_format,
config
.
wave
.
channels
=
audio_format
.
channels
==
2
?
PCM_STEREO
:
PCM_MONO
;
if
(
shine_check_config
(
config
.
wave
.
samplerate
,
config
.
mpeg
.
bitr
)
<
0
)
{
error
.
Format
(
config_domain
,
"error configuring shine. "
"samplerate %d and bitrate %d configuration"
" not supported."
,
config
.
wave
.
samplerate
,
config
.
mpeg
.
bitr
);
return
nullptr
;
}
if
(
shine_check_config
(
config
.
wave
.
samplerate
,
config
.
mpeg
.
bitr
)
<
0
)
throw
FormatRuntimeError
(
"error configuring shine. "
"samplerate %d and bitrate %d configuration"
" not supported."
,
config
.
wave
.
samplerate
,
config
.
mpeg
.
bitr
);
auto
shine
=
shine_initialise
(
&
config
);
if
(
!
shine
)
error
.
Format
(
config_domain
,
"error initializing shine."
);
throw
std
::
runtime_error
(
"error initializing shine"
);
return
shine
;
}
Encoder
*
PreparedShineEncoder
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
PreparedShineEncoder
::
Open
(
AudioFormat
&
audio_format
)
{
auto
shine
=
SetupShine
(
config
,
audio_format
,
error
);
if
(
!
shine
)
return
nullptr
;
auto
shine
=
SetupShine
(
config
,
audio_format
);
return
new
ShineEncoder
(
audio_format
,
shine
);
}
...
...
@@ -175,8 +166,8 @@ ShineEncoder::WriteChunk(bool flush)
return
true
;
}
bool
ShineEncoder
::
Write
(
const
void
*
_data
,
size_t
length
,
gcc_unused
Error
&
error
)
void
ShineEncoder
::
Write
(
const
void
*
_data
,
size_t
length
)
{
const
int16_t
*
data
=
(
const
int16_t
*
)
_data
;
length
/=
sizeof
(
*
data
)
*
audio_format
.
channels
;
...
...
@@ -198,12 +189,10 @@ ShineEncoder::Write(const void *_data, size_t length, gcc_unused Error &error)
/* write if chunk is filled */
WriteChunk
(
false
);
}
return
true
;
}
bool
ShineEncoder
::
Flush
(
gcc_unused
Error
&
error
)
void
ShineEncoder
::
Flush
()
{
/* flush buffers and flush shine */
WriteChunk
(
true
);
...
...
@@ -213,8 +202,6 @@ ShineEncoder::Flush(gcc_unused Error &error)
if
(
written
>
0
)
output_buffer
.
Append
(
data
,
written
);
return
true
;
}
const
EncoderPlugin
shine_encoder_plugin
=
{
...
...
src/encoder/plugins/TwolameEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -24,12 +24,13 @@
#include "config/ConfigError.hxx"
#include "util/NumberParser.hxx"
#include "util/RuntimeError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
#include <twolame.h>
#include <stdexcept>
#include <assert.h>
#include <string.h>
...
...
@@ -59,17 +60,15 @@ public:
/* virtual methods from class Encoder */
bool
End
(
Error
&
)
override
{
void
End
(
)
override
{
flush
=
true
;
return
true
;
}
bool
Flush
(
Error
&
)
override
{
void
Flush
(
)
override
{
flush
=
true
;
return
true
;
}
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
;
void
Write
(
const
void
*
data
,
size_t
length
)
override
;
size_t
Read
(
void
*
dest
,
size_t
length
)
override
;
};
...
...
@@ -81,7 +80,7 @@ public:
PreparedTwolameEncoder
(
const
ConfigBlock
&
block
);
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
)
override
;
Encoder
*
Open
(
AudioFormat
&
audio_format
)
override
;
const
char
*
GetMimeType
()
const
override
{
return
"audio/mpeg"
;
...
...
@@ -132,71 +131,52 @@ twolame_encoder_init(const ConfigBlock &block)
return
new
PreparedTwolameEncoder
(
block
);
}
static
bool
static
void
twolame_encoder_setup
(
twolame_options
*
options
,
float
quality
,
int
bitrate
,
const
AudioFormat
&
audio_format
,
Error
&
error
)
const
AudioFormat
&
audio_format
)
{
if
(
quality
>=
-
1.0
)
{
/* a quality was configured (VBR) */
if
(
0
!=
twolame_set_VBR
(
options
,
true
))
{
error
.
Set
(
twolame_encoder_domain
,
"error setting twolame VBR mode"
);
return
false
;
}
if
(
0
!=
twolame_set_VBR_q
(
options
,
quality
))
{
error
.
Set
(
twolame_encoder_domain
,
"error setting twolame VBR quality"
);
return
false
;
}
if
(
0
!=
twolame_set_VBR
(
options
,
true
))
throw
std
::
runtime_error
(
"error setting twolame VBR mode"
);
if
(
0
!=
twolame_set_VBR_q
(
options
,
quality
))
throw
std
::
runtime_error
(
"error setting twolame VBR quality"
);
}
else
{
/* a bit rate was configured */
if
(
0
!=
twolame_set_brate
(
options
,
bitrate
))
{
error
.
Set
(
twolame_encoder_domain
,
"error setting twolame bitrate"
);
return
false
;
}
if
(
0
!=
twolame_set_brate
(
options
,
bitrate
))
throw
std
::
runtime_error
(
"error setting twolame bitrate"
);
}
if
(
0
!=
twolame_set_num_channels
(
options
,
audio_format
.
channels
))
{
error
.
Set
(
twolame_encoder_domain
,
"error setting twolame num channels"
);
return
false
;
}
if
(
0
!=
twolame_set_num_channels
(
options
,
audio_format
.
channels
))
throw
std
::
runtime_error
(
"error setting twolame num channels"
);
if
(
0
!=
twolame_set_in_samplerate
(
options
,
audio_format
.
sample_rate
))
{
error
.
Set
(
twolame_encoder_domain
,
"error setting twolame sample rate"
);
return
false
;
}
if
(
0
>
twolame_init_params
(
options
))
{
error
.
Set
(
twolame_encoder_domain
,
"error initializing twolame params"
);
return
false
;
}
audio_format
.
sample_rate
))
throw
std
::
runtime_error
(
"error setting twolame sample rate"
);
return
true
;
if
(
0
>
twolame_init_params
(
options
))
throw
std
::
runtime_error
(
"error initializing twolame params"
);
}
Encoder
*
PreparedTwolameEncoder
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
PreparedTwolameEncoder
::
Open
(
AudioFormat
&
audio_format
)
{
audio_format
.
format
=
SampleFormat
::
S16
;
audio_format
.
channels
=
2
;
auto
options
=
twolame_init
();
if
(
options
==
nullptr
)
{
error
.
Set
(
twolame_encoder_domain
,
"twolame_init() failed"
);
return
nullptr
;
}
if
(
options
==
nullptr
)
throw
std
::
runtime_error
(
"twolame_init() failed"
);
if
(
!
twolame_encoder_setup
(
options
,
quality
,
bitrate
,
audio_format
,
error
))
{
try
{
twolame_encoder_setup
(
options
,
quality
,
bitrate
,
audio_format
);
}
catch
(...)
{
twolame_close
(
&
options
);
return
nullptr
;
throw
;
}
return
new
TwolameEncoder
(
audio_format
,
options
);
...
...
@@ -207,9 +187,8 @@ TwolameEncoder::~TwolameEncoder()
twolame_close
(
&
options
);
}
bool
TwolameEncoder
::
Write
(
const
void
*
data
,
size_t
length
,
gcc_unused
Error
&
error
)
void
TwolameEncoder
::
Write
(
const
void
*
data
,
size_t
length
)
{
const
int16_t
*
src
=
(
const
int16_t
*
)
data
;
...
...
@@ -221,14 +200,11 @@ TwolameEncoder::Write(const void *data, size_t length,
src
,
num_frames
,
output_buffer
,
sizeof
(
output_buffer
));
if
(
bytes_out
<
0
)
{
error
.
Set
(
twolame_encoder_domain
,
"twolame encoder failed"
);
return
false
;
}
if
(
bytes_out
<
0
)
throw
std
::
runtime_error
(
"twolame encoder failed"
);
output_buffer_length
=
(
size_t
)
bytes_out
;
output_buffer_position
=
0
;
return
true
;
}
size_t
...
...
src/encoder/plugins/VorbisEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -26,8 +26,6 @@
#include "util/StringUtil.hxx"
#include "util/NumberParser.hxx"
#include "util/RuntimeError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <vorbis/vorbisenc.h>
...
...
@@ -39,10 +37,7 @@ class VorbisEncoder final : public OggEncoder {
vorbis_info
vi
;
public
:
VorbisEncoder
()
:
OggEncoder
(
true
)
{
vorbis_info_init
(
&
vi
);
}
VorbisEncoder
(
float
quality
,
int
bitrate
,
AudioFormat
&
_audio_format
);
virtual
~
VorbisEncoder
()
{
vorbis_block_clear
(
&
vb
);
...
...
@@ -50,18 +45,15 @@ public:
vorbis_info_clear
(
&
vi
);
}
bool
Open
(
float
quality
,
int
bitrate
,
AudioFormat
&
audio_format
,
Error
&
error
);
/* virtual methods from class Encoder */
bool
End
(
Error
&
error
)
override
{
return
PreTag
(
error
);
void
End
(
)
override
{
PreTag
(
);
}
bool
PreTag
(
Error
&
error
)
override
;
bool
SendTag
(
const
Tag
&
tag
,
Error
&
error
)
override
;
void
PreTag
(
)
override
;
void
SendTag
(
const
Tag
&
tag
)
override
;
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
;
void
Write
(
const
void
*
data
,
size_t
length
)
override
;
private
:
void
HeaderOut
(
vorbis_comment
&
vc
);
...
...
@@ -77,15 +69,13 @@ public:
PreparedVorbisEncoder
(
const
ConfigBlock
&
block
);
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
)
override
;
Encoder
*
Open
(
AudioFormat
&
audio_format
)
override
;
const
char
*
GetMimeType
()
const
override
{
return
"audio/ogg"
;
}
};
static
constexpr
Domain
vorbis_encoder_domain
(
"vorbis_encoder"
);
PreparedVorbisEncoder
::
PreparedVorbisEncoder
(
const
ConfigBlock
&
block
)
{
const
char
*
value
=
block
.
GetBlockValue
(
"quality"
);
...
...
@@ -124,10 +114,12 @@ vorbis_encoder_init(const ConfigBlock &block)
return
new
PreparedVorbisEncoder
(
block
);
}
bool
VorbisEncoder
::
Open
(
float
quality
,
int
bitrate
,
AudioFormat
&
_audio_format
,
Error
&
error
)
VorbisEncoder
::
VorbisEncoder
(
float
quality
,
int
bitrate
,
AudioFormat
&
_audio_format
)
:
OggEncoder
(
true
)
{
vorbis_info_init
(
&
vi
);
_audio_format
.
format
=
SampleFormat
::
FLOAT
;
audio_format
=
_audio_format
;
...
...
@@ -138,9 +130,8 @@ VorbisEncoder::Open(float quality, int bitrate, AudioFormat &_audio_format,
audio_format
.
channels
,
audio_format
.
sample_rate
,
quality
*
0.1
))
{
error
.
Set
(
vorbis_encoder_domain
,
"error initializing vorbis vbr"
);
return
false
;
vorbis_info_clear
(
&
vi
);
throw
std
::
runtime_error
(
"error initializing vorbis vbr"
);
}
}
else
{
/* a bit rate was configured */
...
...
@@ -149,9 +140,8 @@ VorbisEncoder::Open(float quality, int bitrate, AudioFormat &_audio_format,
audio_format
.
channels
,
audio_format
.
sample_rate
,
-
1.0
,
bitrate
*
1000
,
-
1.0
))
{
error
.
Set
(
vorbis_encoder_domain
,
"error initializing vorbis encoder"
);
return
false
;
vorbis_info_clear
(
&
vi
);
throw
std
::
runtime_error
(
"error initializing vorbis encoder"
);
}
}
...
...
@@ -159,8 +149,6 @@ VorbisEncoder::Open(float quality, int bitrate, AudioFormat &_audio_format,
vorbis_block_init
(
&
vd
,
&
vb
);
SendHeader
();
return
true
;
}
void
...
...
@@ -184,15 +172,9 @@ VorbisEncoder::SendHeader()
}
Encoder
*
PreparedVorbisEncoder
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
PreparedVorbisEncoder
::
Open
(
AudioFormat
&
audio_format
)
{
auto
*
e
=
new
VorbisEncoder
();
if
(
!
e
->
Open
(
quality
,
bitrate
,
audio_format
,
error
))
{
delete
e
;
return
nullptr
;
}
return
e
;
return
new
VorbisEncoder
(
quality
,
bitrate
,
audio_format
);
}
void
...
...
@@ -208,8 +190,8 @@ VorbisEncoder::BlockOut()
}
}
bool
VorbisEncoder
::
PreTag
(
gcc_unused
Error
&
error
)
void
VorbisEncoder
::
PreTag
()
{
vorbis_analysis_wrote
(
&
vd
,
0
);
BlockOut
();
...
...
@@ -222,7 +204,6 @@ VorbisEncoder::PreTag(gcc_unused Error &error)
vorbis_block_init
(
&
vd
,
&
vb
);
Flush
();
return
true
;
}
static
void
...
...
@@ -235,8 +216,8 @@ copy_tag_to_vorbis_comment(VorbisComment &vc, const Tag &tag)
}
}
bool
VorbisEncoder
::
SendTag
(
const
Tag
&
tag
,
gcc_unused
Error
&
error
)
void
VorbisEncoder
::
SendTag
(
const
Tag
&
tag
)
{
/* write the vorbis_comment object */
...
...
@@ -250,8 +231,6 @@ VorbisEncoder::SendTag(const Tag &tag, gcc_unused Error &error)
/* send that vorbis_comment to the ogg_stream_state */
HeaderOut
(
comment
);
return
true
;
}
static
void
...
...
@@ -263,8 +242,8 @@ interleaved_to_vorbis_buffer(float **dest, const float *src,
dest
[
j
][
i
]
=
*
src
++
;
}
bool
VorbisEncoder
::
Write
(
const
void
*
data
,
size_t
length
,
gcc_unused
Error
&
error
)
void
VorbisEncoder
::
Write
(
const
void
*
data
,
size_t
length
)
{
unsigned
num_frames
=
length
/
audio_format
.
GetFrameSize
();
...
...
@@ -277,7 +256,6 @@ VorbisEncoder::Write(const void *data, size_t length, gcc_unused Error &error)
vorbis_analysis_wrote
(
&
vd
,
num_frames
);
BlockOut
();
return
true
;
}
const
EncoderPlugin
vorbis_encoder_plugin
=
{
...
...
src/encoder/plugins/WaveEncoderPlugin.cxx
View file @
d8b6aff2
...
...
@@ -37,7 +37,7 @@ public:
WaveEncoder
(
AudioFormat
&
audio_format
);
/* virtual methods from class Encoder */
bool
Write
(
const
void
*
data
,
size_t
length
,
Error
&
)
override
;
void
Write
(
const
void
*
data
,
size_t
length
)
override
;
size_t
Read
(
void
*
dest
,
size_t
length
)
override
{
return
buffer
.
Read
((
uint8_t
*
)
dest
,
length
);
...
...
@@ -46,7 +46,7 @@ public:
class
PreparedWaveEncoder
final
:
public
PreparedEncoder
{
/* virtual methods from class PreparedEncoder */
Encoder
*
Open
(
AudioFormat
&
audio_format
,
Error
&
)
override
{
Encoder
*
Open
(
AudioFormat
&
audio_format
)
override
{
return
new
WaveEncoder
(
audio_format
);
}
...
...
@@ -186,9 +186,8 @@ pcm24_to_wave(uint8_t *dst8, const uint32_t *src32, size_t length)
return
(
dst8
-
dst_old
);
}
bool
WaveEncoder
::
Write
(
const
void
*
src
,
size_t
length
,
gcc_unused
Error
&
error
)
void
WaveEncoder
::
Write
(
const
void
*
src
,
size_t
length
)
{
uint8_t
*
dst
=
buffer
.
Write
(
length
);
...
...
@@ -223,7 +222,6 @@ WaveEncoder::Write(const void *src, size_t length,
}
buffer
.
Append
(
length
);
return
true
;
}
const
EncoderPlugin
wave_encoder_plugin
=
{
...
...
src/output/plugins/RecorderOutputPlugin.cxx
View file @
d8b6aff2
...
...
@@ -110,8 +110,10 @@ private:
/**
* Finish the encoder and commit the file.
*
* Throws #std::runtime_error on error.
*/
bool
Commit
(
Error
&
error
);
void
Commit
(
);
void
FinishFormat
();
bool
ReopenFormat
(
AllocatedPath
&&
new_path
,
Error
&
error
);
...
...
@@ -209,10 +211,11 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error)
/* open the encoder */
encoder
=
prepared_encoder
->
Open
(
audio_format
,
error
);
if
(
encoder
==
nullptr
)
{
try
{
encoder
=
prepared_encoder
->
Open
(
audio_format
);
}
catch
(
const
std
::
runtime_error
&
)
{
delete
file
;
return
false
;
throw
;
}
if
(
!
HasDynamicPath
())
{
...
...
@@ -235,39 +238,33 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error)
return
true
;
}
inline
bool
RecorderOutput
::
Commit
(
Error
&
error
)
inline
void
RecorderOutput
::
Commit
()
{
assert
(
!
path
.
IsNull
());
/* flush the encoder and write the rest to the file */
bool
success
=
encoder
->
End
(
error
);
if
(
success
)
{
try
{
EncoderToFile
();
}
catch
(...)
{
delete
encoder
;
throw
;
}
try
{
encoder
->
End
();
EncoderToFile
();
}
catch
(...)
{
delete
encoder
;
throw
;
}
/* now really close everything */
delete
encoder
;
if
(
success
)
{
try
{
file
->
Commit
();
}
catch
(...)
{
delete
file
;
throw
;
}
try
{
file
->
Commit
();
}
catch
(...)
{
delete
file
;
throw
;
}
delete
file
;
return
success
;
}
inline
void
...
...
@@ -282,9 +279,7 @@ RecorderOutput::Close()
}
try
{
Error
error
;
if
(
!
Commit
(
error
))
LogError
(
error
);
Commit
();
}
catch
(
const
std
::
exception
&
e
)
{
LogError
(
e
);
}
...
...
@@ -304,9 +299,7 @@ RecorderOutput::FinishFormat()
return
;
try
{
Error
error
;
if
(
!
Commit
(
error
))
LogError
(
error
);
Commit
();
}
catch
(
const
std
::
exception
&
e
)
{
LogError
(
e
);
}
...
...
@@ -331,10 +324,12 @@ RecorderOutput::ReopenFormat(AllocatedPath &&new_path, Error &error)
}
AudioFormat
new_audio_format
=
effective_audio_format
;
encoder
=
prepared_encoder
->
Open
(
new_audio_format
,
error
);
if
(
encoder
==
nullptr
)
{
try
{
encoder
=
prepared_encoder
->
Open
(
new_audio_format
);
}
catch
(...)
{
delete
new_file
;
return
false
;
throw
;
}
/* reopening the encoder must always result in the same
...
...
@@ -395,21 +390,9 @@ RecorderOutput::SendTag(const Tag &tag)
}
}
Error
error
;
if
(
!
encoder
->
PreTag
(
error
))
{
LogError
(
error
);
return
;
}
try
{
EncoderToFile
();
}
catch
(
const
std
::
exception
&
e
)
{
LogError
(
e
);
return
;
}
if
(
!
encoder
->
SendTag
(
tag
,
error
))
LogError
(
error
);
encoder
->
PreTag
();
EncoderToFile
();
encoder
->
SendTag
(
tag
);
}
inline
size_t
...
...
@@ -423,8 +406,7 @@ RecorderOutput::Play(const void *chunk, size_t size, Error &error)
return
size
;
}
if
(
!
encoder
->
Write
(
chunk
,
size
,
error
))
return
0
;
encoder
->
Write
(
chunk
,
size
);
try
{
EncoderToFile
();
...
...
src/output/plugins/ShoutOutputPlugin.cxx
View file @
d8b6aff2
...
...
@@ -32,6 +32,8 @@
#include <shout/shout.h>
#include <stdexcept>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
...
...
@@ -366,8 +368,12 @@ void
ShoutOutput
::
Close
()
{
if
(
encoder
!=
nullptr
)
{
if
(
encoder
->
End
(
IgnoreError
()))
try
{
encoder
->
End
();
write_page
(
this
,
IgnoreError
());
}
catch
(
const
std
::
runtime_error
&
)
{
/* ignore */
}
delete
encoder
;
}
...
...
@@ -410,16 +416,22 @@ ShoutOutput::Open(AudioFormat &audio_format, Error &error)
if
(
!
shout_connect
(
this
,
error
))
return
false
;
encoder
=
prepared_encoder
->
Open
(
audio_format
,
error
);
if
(
encoder
==
nullptr
)
{
shout_close
(
shout_conn
);
return
false
;
}
if
(
!
write_page
(
this
,
error
))
{
delete
encoder
;
try
{
encoder
=
prepared_encoder
->
Open
(
audio_format
);
try
{
if
(
!
write_page
(
this
,
error
))
{
delete
encoder
;
shout_close
(
shout_conn
);
return
false
;
}
}
catch
(
const
std
::
runtime_error
&
)
{
delete
encoder
;
throw
;
}
}
catch
(
const
std
::
runtime_error
&
)
{
shout_close
(
shout_conn
);
return
false
;
throw
;
}
return
true
;
...
...
@@ -438,8 +450,8 @@ ShoutOutput::Delay() const
size_t
ShoutOutput
::
Play
(
const
void
*
chunk
,
size_t
size
,
Error
&
error
)
{
return
encoder
->
Write
(
chunk
,
size
,
error
)
&&
write_page
(
this
,
error
)
encoder
->
Write
(
chunk
,
size
);
return
write_page
(
this
,
error
)
?
size
:
0
;
}
...
...
@@ -484,13 +496,15 @@ ShoutOutput::SendTag(const Tag &tag)
if
(
encoder
->
ImplementsTag
())
{
/* encoder plugin supports stream tags */
encoder
->
PreTag
();
Error
error
;
if
(
!
encoder
->
PreTag
(
error
)
||
!
write_page
(
this
,
error
)
||
!
encoder
->
SendTag
(
tag
,
error
))
{
if
(
!
write_page
(
this
,
error
))
{
LogError
(
error
);
return
;
}
encoder
->
SendTag
(
tag
);
}
else
{
/* no stream tag support: fall back to icy-metadata */
char
song
[
1024
];
...
...
src/output/plugins/httpd/HttpdInternal.hxx
View file @
d8b6aff2
...
...
@@ -171,8 +171,10 @@ public:
/**
* Caller must lock the mutex.
*
* Throws #std::runtime_error on error.
*/
bool
OpenEncoder
(
AudioFormat
&
audio_format
,
Error
&
error
);
void
OpenEncoder
(
AudioFormat
&
audio_format
);
/**
* Caller must lock the mutex.
...
...
@@ -237,7 +239,10 @@ public:
*/
void
BroadcastFromEncoder
();
bool
EncodeAndPlay
(
const
void
*
chunk
,
size_t
size
,
Error
&
error
);
/**
* Throws #std::runtime_error on error.
*/
void
EncodeAndPlay
(
const
void
*
chunk
,
size_t
size
);
void
SendTag
(
const
Tag
&
tag
);
...
...
src/output/plugins/httpd/HttpdOutputPlugin.cxx
View file @
d8b6aff2
...
...
@@ -221,7 +221,12 @@ HttpdOutput::ReadPage()
/* we have fed a lot of input into the encoder, but it
didn't give anything back yet - flush now to avoid
buffer underruns */
encoder
->
Flush
(
IgnoreError
());
try
{
encoder
->
Flush
();
}
catch
(
const
std
::
runtime_error
&
)
{
/* ignore */
}
unflushed_input
=
0
;
}
...
...
@@ -260,12 +265,10 @@ httpd_output_disable(AudioOutput *ao)
httpd
->
Unbind
();
}
inline
bool
HttpdOutput
::
OpenEncoder
(
AudioFormat
&
audio_format
,
Error
&
error
)
inline
void
HttpdOutput
::
OpenEncoder
(
AudioFormat
&
audio_format
)
{
encoder
=
prepared_encoder
->
Open
(
audio_format
,
error
);
if
(
encoder
==
nullptr
)
return
false
;
encoder
=
prepared_encoder
->
Open
(
audio_format
);
/* we have to remember the encoder header, i.e. the first
bytes of encoder output after opening it, because it has to
...
...
@@ -273,20 +276,15 @@ HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error)
header
=
ReadPage
();
unflushed_input
=
0
;
return
true
;
}
inline
bool
HttpdOutput
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
HttpdOutput
::
Open
(
AudioFormat
&
audio_format
,
Error
&
)
{
assert
(
!
open
);
assert
(
clients
.
empty
());
/* open the encoder */
if
(
!
OpenEncoder
(
audio_format
,
error
))
return
false
;
OpenEncoder
(
audio_format
);
/* initialize other attributes */
...
...
@@ -410,25 +408,21 @@ HttpdOutput::BroadcastFromEncoder()
DeferredMonitor
::
Schedule
();
}
inline
bool
HttpdOutput
::
EncodeAndPlay
(
const
void
*
chunk
,
size_t
size
,
Error
&
error
)
inline
void
HttpdOutput
::
EncodeAndPlay
(
const
void
*
chunk
,
size_t
size
)
{
if
(
!
encoder
->
Write
(
chunk
,
size
,
error
))
return
false
;
encoder
->
Write
(
chunk
,
size
);
unflushed_input
+=
size
;
BroadcastFromEncoder
();
return
true
;
}
inline
size_t
HttpdOutput
::
Play
(
const
void
*
chunk
,
size_t
size
,
Error
&
error
)
HttpdOutput
::
Play
(
const
void
*
chunk
,
size_t
size
,
Error
&
)
{
if
(
LockHasClients
())
{
if
(
!
EncodeAndPlay
(
chunk
,
size
,
error
))
return
0
;
}
if
(
LockHasClients
())
EncodeAndPlay
(
chunk
,
size
);
if
(
!
timer
->
IsStarted
())
timer
->
Start
();
...
...
@@ -468,13 +462,22 @@ HttpdOutput::SendTag(const Tag &tag)
/* flush the current stream, and end it */
encoder
->
PreTag
(
IgnoreError
());
try
{
encoder
->
PreTag
();
}
catch
(
const
std
::
runtime_error
&
)
{
/* ignore */
}
BroadcastFromEncoder
();
/* send the tag to the encoder - which starts a new
stream now */
encoder
->
SendTag
(
tag
,
IgnoreError
());
try
{
encoder
->
SendTag
(
tag
);
}
catch
(
const
std
::
runtime_error
&
)
{
/* ignore */
}
/* the first page generated by the encoder will now be
used as the new "header" page, which is sent to all
...
...
test/run_encoder.cxx
View file @
d8b6aff2
...
...
@@ -26,7 +26,6 @@
#include "AudioParser.hxx"
#include "config/Block.hxx"
#include "fs/io/StdioOutputStream.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
#include <memory>
...
...
@@ -66,7 +65,6 @@ int main(int argc, char **argv)
block
.
AddBlockParam
(
"quality"
,
"5.0"
,
-
1
);
try
{
Error
error
;
std
::
unique_ptr
<
PreparedEncoder
>
p_encoder
(
encoder_init
(
*
plugin
,
block
));
/* open the encoder */
...
...
@@ -75,11 +73,7 @@ int main(int argc, char **argv)
if
(
argc
>
2
)
audio_format
=
ParseAudioFormat
(
argv
[
2
],
false
);
std
::
unique_ptr
<
Encoder
>
encoder
(
p_encoder
->
Open
(
audio_format
,
error
));
if
(
encoder
==
nullptr
)
{
LogError
(
error
,
"Failed to open encoder"
);
return
EXIT_FAILURE
;
}
std
::
unique_ptr
<
Encoder
>
encoder
(
p_encoder
->
Open
(
audio_format
));
StdioOutputStream
os
(
stdout
);
...
...
@@ -89,19 +83,11 @@ int main(int argc, char **argv)
ssize_t
nbytes
;
while
((
nbytes
=
read
(
0
,
buffer
,
sizeof
(
buffer
)))
>
0
)
{
if
(
!
encoder
->
Write
(
buffer
,
nbytes
,
error
))
{
LogError
(
error
,
"encoder_write() failed"
);
return
EXIT_FAILURE
;
}
encoder
->
Write
(
buffer
,
nbytes
);
EncoderToOutputStream
(
os
,
*
encoder
);
}
if
(
!
encoder
->
End
(
error
))
{
LogError
(
error
,
"encoder_flush() failed"
);
return
EXIT_FAILURE
;
}
encoder
->
End
();
EncoderToOutputStream
(
os
,
*
encoder
);
return
EXIT_SUCCESS
;
...
...
test/test_vorbis_encoder.cxx
View file @
d8b6aff2
...
...
@@ -27,7 +27,6 @@
#include "fs/io/StdioOutputStream.hxx"
#include "tag/Tag.hxx"
#include "tag/TagBuilder.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
#include <memory>
...
...
@@ -40,8 +39,6 @@ static uint8_t zero[256];
int
main
(
gcc_unused
int
argc
,
gcc_unused
char
**
argv
)
try
{
gcc_unused
bool
success
;
/* create the encoder */
const
auto
plugin
=
encoder_plugin_get
(
"vorbis"
);
...
...
@@ -56,8 +53,7 @@ try {
/* open the encoder */
AudioFormat
audio_format
(
44100
,
SampleFormat
::
S16
,
2
);
std
::
unique_ptr
<
Encoder
>
encoder
(
p_encoder
->
Open
(
audio_format
,
IgnoreError
()));
std
::
unique_ptr
<
Encoder
>
encoder
(
p_encoder
->
Open
(
audio_format
));
assert
(
encoder
!=
nullptr
);
StdioOutputStream
os
(
stdout
);
...
...
@@ -66,15 +62,13 @@ try {
/* write a block of data */
success
=
encoder
->
Write
(
zero
,
sizeof
(
zero
),
IgnoreError
());
assert
(
success
);
encoder
->
Write
(
zero
,
sizeof
(
zero
));
EncoderToOutputStream
(
os
,
*
encoder
);
/* write a tag */
success
=
encoder
->
PreTag
(
IgnoreError
());
assert
(
success
);
encoder
->
PreTag
();
EncoderToOutputStream
(
os
,
*
encoder
);
...
...
@@ -87,21 +81,17 @@ try {
tag_builder
.
Commit
(
tag
);
}
success
=
encoder
->
SendTag
(
tag
,
IgnoreError
());
assert
(
success
);
encoder
->
SendTag
(
tag
);
EncoderToOutputStream
(
os
,
*
encoder
);
/* write another block of data */
success
=
encoder
->
Write
(
zero
,
sizeof
(
zero
),
IgnoreError
());
assert
(
success
);
encoder
->
Write
(
zero
,
sizeof
(
zero
));
/* finish */
success
=
encoder
->
End
(
IgnoreError
());
assert
(
success
);
encoder
->
End
();
EncoderToOutputStream
(
os
,
*
encoder
);
return
EXIT_SUCCESS
;
...
...
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