encoder/wave: use fifo_buffer instead of pcm_buffer
This fixes a buffer corruption bug; pcm_buffer is not designed to be a persistent buffers, and will discard anything between two consecutive calls.
This commit is contained in:
parent
cee5036aca
commit
399a3abefc
2
NEWS
2
NEWS
@ -2,7 +2,7 @@ ver 0.16.6 (2010/??/??)
|
|||||||
* decoder:
|
* decoder:
|
||||||
- fix assertion failure when resuming streams
|
- fix assertion failure when resuming streams
|
||||||
* encoder:
|
* encoder:
|
||||||
- flac: fix buffer corruption bug
|
- flac, wave: fix buffer corruption bug
|
||||||
* event_pipe: fix WIN32 regression
|
* event_pipe: fix WIN32 regression
|
||||||
* define WINVER in ./configure
|
* define WINVER in ./configure
|
||||||
* WIN32: autodetect filesystem encoding
|
* WIN32: autodetect filesystem encoding
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "encoder_api.h"
|
#include "encoder_api.h"
|
||||||
#include "encoder_plugin.h"
|
#include "encoder_plugin.h"
|
||||||
#include "pcm_buffer.h"
|
#include "fifo_buffer.h"
|
||||||
|
#include "growing_fifo.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -29,8 +30,7 @@ struct wave_encoder {
|
|||||||
struct encoder encoder;
|
struct encoder encoder;
|
||||||
unsigned bits;
|
unsigned bits;
|
||||||
|
|
||||||
struct pcm_buffer buffer;
|
struct fifo_buffer *buffer;
|
||||||
size_t buffer_length;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wave_header {
|
struct wave_header {
|
||||||
@ -92,7 +92,6 @@ wave_encoder_init(G_GNUC_UNUSED const struct config_param *param,
|
|||||||
|
|
||||||
encoder = g_new(struct wave_encoder, 1);
|
encoder = g_new(struct wave_encoder, 1);
|
||||||
encoder_struct_init(&encoder->encoder, &wave_encoder_plugin);
|
encoder_struct_init(&encoder->encoder, &wave_encoder_plugin);
|
||||||
pcm_buffer_init(&encoder->buffer);
|
|
||||||
|
|
||||||
return &encoder->encoder;
|
return &encoder->encoder;
|
||||||
}
|
}
|
||||||
@ -102,7 +101,6 @@ wave_encoder_finish(struct encoder *_encoder)
|
|||||||
{
|
{
|
||||||
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
|
|
||||||
pcm_buffer_deinit(&encoder->buffer);
|
|
||||||
g_free(encoder);
|
g_free(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +110,6 @@ wave_encoder_open(struct encoder *_encoder,
|
|||||||
G_GNUC_UNUSED GError **error)
|
G_GNUC_UNUSED GError **error)
|
||||||
{
|
{
|
||||||
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
void *buffer;
|
|
||||||
|
|
||||||
assert(audio_format_valid(audio_format));
|
assert(audio_format_valid(audio_format));
|
||||||
|
|
||||||
@ -139,19 +136,29 @@ wave_encoder_open(struct encoder *_encoder,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = pcm_buffer_get(&encoder->buffer, sizeof(struct wave_header) );
|
encoder->buffer = growing_fifo_new();
|
||||||
|
struct wave_header *header =
|
||||||
|
growing_fifo_write(&encoder->buffer, sizeof(*header));
|
||||||
|
|
||||||
/* create PCM wave header in initial buffer */
|
/* create PCM wave header in initial buffer */
|
||||||
fill_wave_header((struct wave_header *) buffer,
|
fill_wave_header(header,
|
||||||
audio_format->channels,
|
audio_format->channels,
|
||||||
encoder->bits,
|
encoder->bits,
|
||||||
audio_format->sample_rate,
|
audio_format->sample_rate,
|
||||||
(encoder->bits / 8) * audio_format->channels );
|
(encoder->bits / 8) * audio_format->channels );
|
||||||
|
fifo_buffer_append(encoder->buffer, sizeof(*header));
|
||||||
|
|
||||||
encoder->buffer_length = sizeof(struct wave_header);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wave_encoder_close(struct encoder *_encoder)
|
||||||
|
{
|
||||||
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
|
|
||||||
|
fifo_buffer_free(encoder->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
pcm16_to_wave(uint16_t *dst16, const uint16_t *src16, size_t length)
|
pcm16_to_wave(uint16_t *dst16, const uint16_t *src16, size_t length)
|
||||||
{
|
{
|
||||||
@ -198,9 +205,8 @@ wave_encoder_write(struct encoder *_encoder,
|
|||||||
G_GNUC_UNUSED GError **error)
|
G_GNUC_UNUSED GError **error)
|
||||||
{
|
{
|
||||||
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
void *dst;
|
|
||||||
|
|
||||||
dst = pcm_buffer_get(&encoder->buffer, encoder->buffer_length + length);
|
void *dst = growing_fifo_write(&encoder->buffer, length);
|
||||||
|
|
||||||
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
|
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
|
||||||
switch (encoder->bits) {
|
switch (encoder->bits) {
|
||||||
@ -232,7 +238,7 @@ wave_encoder_write(struct encoder *_encoder,
|
|||||||
#error G_BYTE_ORDER set to G_PDP_ENDIAN is not supported by wave_encoder
|
#error G_BYTE_ORDER set to G_PDP_ENDIAN is not supported by wave_encoder
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
encoder->buffer_length += length;
|
fifo_buffer_append(encoder->buffer, length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,16 +246,17 @@ static size_t
|
|||||||
wave_encoder_read(struct encoder *_encoder, void *dest, size_t length)
|
wave_encoder_read(struct encoder *_encoder, void *dest, size_t length)
|
||||||
{
|
{
|
||||||
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
uint8_t *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length );
|
|
||||||
|
|
||||||
if (length > encoder->buffer_length)
|
size_t max_length;
|
||||||
length = encoder->buffer_length;
|
const void *src = fifo_buffer_read(encoder->buffer, &max_length);
|
||||||
|
if (src == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
memcpy(dest, buffer, length);
|
if (length > max_length)
|
||||||
|
length = max_length;
|
||||||
encoder->buffer_length -= length;
|
|
||||||
memmove(buffer, buffer + length, encoder->buffer_length);
|
|
||||||
|
|
||||||
|
memcpy(dest, src, length);
|
||||||
|
fifo_buffer_consume(encoder->buffer, length);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,6 +271,7 @@ const struct encoder_plugin wave_encoder_plugin = {
|
|||||||
.init = wave_encoder_init,
|
.init = wave_encoder_init,
|
||||||
.finish = wave_encoder_finish,
|
.finish = wave_encoder_finish,
|
||||||
.open = wave_encoder_open,
|
.open = wave_encoder_open,
|
||||||
|
.close = wave_encoder_close,
|
||||||
.write = wave_encoder_write,
|
.write = wave_encoder_write,
|
||||||
.read = wave_encoder_read,
|
.read = wave_encoder_read,
|
||||||
.get_mime_type = wave_encoder_get_mime_type,
|
.get_mime_type = wave_encoder_get_mime_type,
|
||||||
|
Loading…
Reference in New Issue
Block a user