decoder: use audio_format_init_checked()

Let the audio_check library verify the audio format in all (relevant,
i.e. non-hardcoded) plugins.
This commit is contained in:
Max Kellermann 2009-11-10 19:01:38 +01:00
parent f47bb8c1db
commit 719990b1c5
15 changed files with 124 additions and 85 deletions

View File

@ -789,6 +789,7 @@ test_run_decoder_SOURCES = test/run_decoder.c \
src/replay_gain.c \
src/uri.c \
src/fd_util.c \
src/audio_check.c \
$(ARCHIVE_SRC) \
$(INPUT_SRC) \
$(TAG_SRC) \
@ -809,6 +810,7 @@ test_read_tags_SOURCES = test/read_tags.c \
src/replay_gain.c \
src/uri.c \
src/fd_util.c \
src/audio_check.c \
$(ARCHIVE_SRC) \
$(INPUT_SRC) \
$(TAG_SRC) \

View File

@ -25,6 +25,7 @@
#include "_flac_common.h"
#include "flac_metadata.h"
#include "flac_pcm.h"
#include "audio_check.h"
#include <glib.h>
@ -63,20 +64,19 @@ bool
flac_data_get_audio_format(struct flac_data *data,
struct audio_format *audio_format)
{
GError *error = NULL;
if (!data->have_stream_info) {
g_warning("no STREAMINFO packet found");
return false;
}
audio_format_init(audio_format, data->stream_info.sample_rate,
data->stream_info.bits_per_sample,
data->stream_info.channels);
if (!audio_format_valid(audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format->sample_rate,
audio_format->bits,
audio_format->channels);
if (!audio_format_init_checked(audio_format,
data->stream_info.sample_rate,
data->stream_info.bits_per_sample,
data->stream_info.channels, &error)) {
g_warning("%s", error->message);
g_error_free(error);
return false;
}

View File

@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
#include <audiofile.h>
#include <af_vfs.h>
@ -103,6 +104,7 @@ setup_virtual_fops(struct input_stream *stream)
static void
audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
{
GError *error = NULL;
AFvirtualfile *vf;
int fs, frame_count;
AFfilehandle af_fp;
@ -138,13 +140,13 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
AF_SAMPFMT_TWOSCOMP, bits);
afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
audio_format_init(&audio_format, afGetRate(af_fp, AF_DEFAULT_TRACK),
bits, afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK));
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate, audio_format.bits,
audio_format.channels);
if (!audio_format_init_checked(&audio_format,
afGetRate(af_fp, AF_DEFAULT_TRACK),
bits,
afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK),
&error)) {
g_warning("%s", error->message);
g_error_free(error);
afCloseFile(af_fp);
return;
}

View File

@ -20,6 +20,7 @@
#include "config.h"
#include "decoder_api.h"
#include "decoder_buffer.h"
#include "audio_check.h"
#define AAC_MAX_CHANNELS 6
@ -36,6 +37,15 @@ static const unsigned adts_sample_rates[] =
16000, 12000, 11025, 8000, 7350, 0, 0, 0
};
/**
* The GLib quark used for errors reported by this plugin.
*/
static inline GQuark
faad_decoder_quark(void)
{
return g_quark_from_static_string("faad");
}
/**
* Check whether the buffer head is an AAC frame, and return the frame
* length. Returns 0 if it is not a frame.
@ -232,7 +242,7 @@ faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is)
*/
static bool
faad_decoder_init(faacDecHandle decoder, struct decoder_buffer *buffer,
struct audio_format *audio_format)
struct audio_format *audio_format, GError **error_r)
{
union {
/* deconst hack for libfaad */
@ -247,28 +257,33 @@ faad_decoder_init(faacDecHandle decoder, struct decoder_buffer *buffer,
/* neaacdec.h declares all arguments as "unsigned long", but
internally expects uint32_t pointers. To avoid gcc
warnings, use this workaround. */
unsigned long *sample_rate_r = (unsigned long *)(void *)&sample_rate;
unsigned long *sample_rate_p = (unsigned long *)(void *)&sample_rate;
#else
uint32_t *sample_rate_r = &sample_rate;
uint32_t *sample_rate_p = &sample_rate;
#endif
u.in = decoder_buffer_read(buffer, &length);
if (u.in == NULL)
if (u.in == NULL) {
g_set_error(error_r, faad_decoder_quark(), 0,
"Empty file");
return false;
}
nbytes = faacDecInit(decoder, u.out,
#ifdef HAVE_FAAD_BUFLEN_FUNCS
length,
#endif
sample_rate_r, &channels);
if (nbytes < 0)
sample_rate_p, &channels);
if (nbytes < 0) {
g_set_error(error_r, faad_decoder_quark(), 0,
"Not an AAC stream");
return false;
}
decoder_buffer_consume(buffer, nbytes);
audio_format_init(audio_format, sample_rate, 16, channels);
return true;
return audio_format_init_checked(audio_format, sample_rate,
16, channels, error_r);
}
/**
@ -334,8 +349,8 @@ faad_get_file_time_float(const char *file)
decoder_buffer_fill(buffer);
ret = faad_decoder_init(decoder, buffer, &audio_format);
if (ret && audio_format_valid(&audio_format))
ret = faad_decoder_init(decoder, buffer, &audio_format, NULL);
if (ret)
length = 0;
faacDecClose(decoder);
@ -367,6 +382,7 @@ faad_get_file_time(const char *file)
static void
faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
{
GError *error = NULL;
float file_time;
float total_time = 0;
faacDecHandle decoder;
@ -404,15 +420,10 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
/* initialize it */
ret = faad_decoder_init(decoder, buffer, &audio_format);
ret = faad_decoder_init(decoder, buffer, &audio_format, &error);
if (!ret) {
g_warning("Error not a AAC stream.\n");
faacDecClose(decoder);
return;
}
if (!audio_format_valid(&audio_format)) {
g_warning("invalid audio format\n");
g_warning("%s", error->message);
g_error_free(error);
faacDecClose(decoder);
return;
}

View File

@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
#include <glib.h>
@ -260,6 +261,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
static bool
ffmpeg_decode_internal(struct ffmpeg_context *ctx)
{
GError *error = NULL;
struct decoder *decoder = ctx->decoder;
AVCodecContext *codec_context = ctx->codec_context;
AVFormatContext *format_context = ctx->format_context;
@ -281,13 +283,11 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
/* XXX fixme 16-bit for older ffmpeg (13 Aug 2007) */
bits = (uint8_t) 16;
#endif
audio_format_init(&audio_format, codec_context->sample_rate, bits,
codec_context->channels);
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate, audio_format.bits,
audio_format.channels);
if (!audio_format_init_checked(&audio_format,
codec_context->sample_rate, bits,
codec_context->channels, &error)) {
g_warning("%s", error->message);
g_error_free(error);
return false;
}

View File

@ -21,6 +21,7 @@
#include "decoder_api.h"
#include "conf.h"
#include "tag_id3.h"
#include "audio_check.h"
#include <assert.h>
#include <unistd.h>
@ -1174,6 +1175,7 @@ static void
mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
{
struct mp3_data data;
GError *error = NULL;
struct tag *tag = NULL;
struct replay_gain_info *replay_gain_info = NULL;
struct audio_format audio_format;
@ -1185,8 +1187,20 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
return;
}
audio_format_init(&audio_format, data.frame.header.samplerate, 24,
MAD_NCHANNELS(&data.frame.header));
if (!audio_format_init_checked(&audio_format,
data.frame.header.samplerate, 24,
MAD_NCHANNELS(&data.frame.header),
&error)) {
g_warning("%s", error->message);
g_error_free(error);
if (tag != NULL)
tag_free(tag);
if (replay_gain_info != NULL)
replay_gain_info_free(replay_gain_info);
mp3_data_finish(&data);
return;
}
decoder_initialized(decoder, &audio_format,
data.input_stream->seekable, data.total_time);

View File

@ -22,6 +22,7 @@
#include <glib.h>
#include <mikmod.h>
#include <assert.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "mikmod"
@ -177,6 +178,7 @@ mod_decode(struct decoder *decoder, const char *path)
}
audio_format_init(&audio_format, 44100, 16, 2);
assert(audio_format_valid(&audio_format));
secPerByte =
1.0 / ((audio_format.bits * audio_format.channels / 8.0) *

View File

@ -22,6 +22,7 @@
#include <glib.h>
#include <modplug.h>
#include <assert.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "modplug"
@ -123,6 +124,7 @@ mod_decode(struct decoder *decoder, struct input_stream *is)
}
audio_format_init(&audio_format, 44100, 16, 2);
assert(audio_format_valid(&audio_format));
sec_perbyte =
1.0 / ((audio_format.bits * audio_format.channels / 8.0) *

View File

@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
#include <glib.h>
@ -110,6 +111,7 @@ mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format)
int track;
uint32_t sample_rate;
unsigned char channels;
GError *error = NULL;
decoder = faacDecOpen();
@ -130,18 +132,16 @@ mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format)
return NULL;
}
*track_r = track;
audio_format_init(audio_format, sample_rate, 16, channels);
if (!audio_format_valid(audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format->sample_rate,
audio_format->bits,
audio_format->channels);
if (!audio_format_init_checked(audio_format, sample_rate, 16, channels,
&error)) {
g_warning("%s", error->message);
g_error_free(error);
faacDecClose(decoder);
return NULL;
}
*track_r = track;
return decoder;
}

View File

@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
#ifdef MPC_IS_OLD_API
#include <mpcdec/mpcdec.h>
@ -27,6 +28,7 @@
#endif
#include <glib.h>
#include <assert.h>
#include <unistd.h>
#undef G_LOG_DOMAIN
@ -140,6 +142,7 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
#endif
mpc_reader reader;
mpc_streaminfo info;
GError *error = NULL;
struct audio_format audio_format;
struct mpc_decoder_data data;
@ -193,16 +196,13 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
mpc_demux_get_info(demux, &info);
#endif
audio_format_init(&audio_format, info.sample_freq, 24, info.channels);
if (!audio_format_valid(&audio_format)) {
if (!audio_format_init_checked(&audio_format, info.sample_freq, 16,
info.channels, &error)) {
g_warning("%s", error->message);
g_error_free(error);
#ifndef MPC_IS_OLD_API
mpc_demux_exit(demux);
#endif
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
return;
}

View File

@ -19,6 +19,7 @@
#include "config.h" /* must be first for large file support */
#include "decoder_api.h"
#include "audio_check.h"
#include <glib.h>
@ -54,6 +55,7 @@ static bool
mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
struct audio_format *audio_format)
{
GError *gerror = NULL;
char *path_dup;
int error;
int channels, encoding;
@ -85,9 +87,10 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
return false;
}
audio_format_init(audio_format, rate, 16, channels);
if (!audio_format_valid(audio_format)) {
g_warning("invalid audio format");
if (!audio_format_init_checked(audio_format, rate, 16,
channels, &gerror)) {
g_warning("%s", gerror->message);
g_error_free(gerror);
return false;
}

View File

@ -278,6 +278,7 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs)
struct audio_format audio_format;
audio_format_init(&audio_format, 48000, 16, 2);
assert(audio_format_valid(&audio_format));
decoder_initialized(decoder, &audio_format, true, (float)song_len);

View File

@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
#include <sndfile.h>
@ -109,6 +110,7 @@ time_to_frame(float t, const struct audio_format *audio_format)
static void
sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
{
GError *error = NULL;
SNDFILE *sf;
SF_INFO info;
struct audio_format audio_format;
@ -128,10 +130,10 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
/* for now, always read 32 bit samples. Later, we could lower
MPD's CPU usage by reading 16 bit samples with
sf_readf_short() on low-quality source files. */
audio_format_init(&audio_format, info.samplerate, 32, info.channels);
if (!audio_format_valid(&audio_format)) {
g_warning("invalid audio format");
if (!audio_format_init_checked(&audio_format, info.samplerate, 32,
info.channels, &error)) {
g_warning("%s", error->message);
g_error_free(error);
return;
}

View File

@ -19,6 +19,7 @@
#include "config.h"
#include "_ogg_common.h"
#include "audio_check.h"
#include "uri.h"
#ifndef HAVE_TREMOR
@ -264,6 +265,7 @@ static void
vorbis_stream_decode(struct decoder *decoder,
struct input_stream *input_stream)
{
GError *error = NULL;
OggVorbis_File vf;
ov_callbacks callbacks;
struct vorbis_decoder_data data;
@ -309,13 +311,10 @@ vorbis_stream_decode(struct decoder *decoder,
return;
}
audio_format_init(&audio_format, vi->rate, 16, vi->channels);
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
if (!audio_format_init_checked(&audio_format, vi->rate, 16,
vi->channels, &error)) {
g_warning("%s", error->message);
g_error_free(error);
return;
}

View File

@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_api.h"
#include "audio_check.h"
#include "path.h"
#include "utils.h"
@ -130,6 +131,8 @@ static void
wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
struct replay_gain_info *replay_gain_info)
{
GError *error = NULL;
unsigned bits;
struct audio_format audio_format;
format_samples_t format_samples;
char chunk[CHUNK_SIZE];
@ -138,24 +141,22 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
int bytes_per_sample, output_sample_size;
int position;
audio_format_init(&audio_format, WavpackGetSampleRate(wpc),
WavpackGetBitsPerSample(wpc),
WavpackGetNumChannels(wpc));
bits = WavpackGetBitsPerSample(wpc);
/* round bitwidth to 8-bit units */
audio_format.bits = (audio_format.bits + 7) & (~7);
bits = (bits + 7) & (~7);
/* MPD handles max 32-bit samples */
if (audio_format.bits > 32)
audio_format.bits = 32;
if (bits > 32)
bits = 32;
if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT)
audio_format.bits = 24;
bits = 24;
if (!audio_format_valid(&audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n",
audio_format.sample_rate,
audio_format.bits,
audio_format.channels);
if (!audio_format_init_checked(&audio_format,
WavpackGetSampleRate(wpc), bits,
WavpackGetNumChannels(wpc), &error)) {
g_warning("%s", error->message);
g_error_free(error);
return;
}