Commit 5acee73f authored by Max Kellermann's avatar Max Kellermann

encoder/vorbis: generate end-of-stream packet when playback ends

Add the encoder_plugin method end(). This is important for the recorder plugin.
parent 466c337b
...@@ -5,6 +5,7 @@ ver 0.16.8 (2012/??/??) ...@@ -5,6 +5,7 @@ ver 0.16.8 (2012/??/??)
- ffmpeg: read the "year" tag - ffmpeg: read the "year" tag
* encoder: * encoder:
- vorbis: generate end-of-stream packet before tag - vorbis: generate end-of-stream packet before tag
- vorbis: generate end-of-stream packet when playback ends
* output: * output:
- jack: check for connection failure before starting playback - jack: check for connection failure before starting playback
- jack: workaround for libjack1 crash bug - jack: workaround for libjack1 crash bug
......
...@@ -354,6 +354,7 @@ const struct encoder_plugin flac_encoder_plugin = { ...@@ -354,6 +354,7 @@ const struct encoder_plugin flac_encoder_plugin = {
.finish = flac_encoder_finish, .finish = flac_encoder_finish,
.open = flac_encoder_open, .open = flac_encoder_open,
.close = flac_encoder_close, .close = flac_encoder_close,
.end = flac_encoder_flush,
.flush = flac_encoder_flush, .flush = flac_encoder_flush,
.write = flac_encoder_write, .write = flac_encoder_write,
.read = flac_encoder_read, .read = flac_encoder_read,
......
...@@ -300,6 +300,7 @@ const struct encoder_plugin twolame_encoder_plugin = { ...@@ -300,6 +300,7 @@ const struct encoder_plugin twolame_encoder_plugin = {
.finish = twolame_encoder_finish, .finish = twolame_encoder_finish,
.open = twolame_encoder_open, .open = twolame_encoder_open,
.close = twolame_encoder_close, .close = twolame_encoder_close,
.end = twolame_encoder_flush,
.flush = twolame_encoder_flush, .flush = twolame_encoder_flush,
.write = twolame_encoder_write, .write = twolame_encoder_write,
.read = twolame_encoder_read, .read = twolame_encoder_read,
......
...@@ -405,6 +405,7 @@ const struct encoder_plugin vorbis_encoder_plugin = { ...@@ -405,6 +405,7 @@ const struct encoder_plugin vorbis_encoder_plugin = {
.finish = vorbis_encoder_finish, .finish = vorbis_encoder_finish,
.open = vorbis_encoder_open, .open = vorbis_encoder_open,
.close = vorbis_encoder_close, .close = vorbis_encoder_close,
.end = vorbis_encoder_pre_tag,
.flush = vorbis_encoder_flush, .flush = vorbis_encoder_flush,
.pre_tag = vorbis_encoder_pre_tag, .pre_tag = vorbis_encoder_pre_tag,
.tag = vorbis_encoder_tag, .tag = vorbis_encoder_tag,
......
...@@ -35,7 +35,7 @@ struct encoder { ...@@ -35,7 +35,7 @@ struct encoder {
const struct encoder_plugin *plugin; const struct encoder_plugin *plugin;
#ifndef NDEBUG #ifndef NDEBUG
bool open, pre_tag, tag; bool open, pre_tag, tag, end;
#endif #endif
}; };
...@@ -53,6 +53,8 @@ struct encoder_plugin { ...@@ -53,6 +53,8 @@ struct encoder_plugin {
void (*close)(struct encoder *encoder); void (*close)(struct encoder *encoder);
bool (*end)(struct encoder *encoder, GError **error);
bool (*flush)(struct encoder *encoder, GError **error); bool (*flush)(struct encoder *encoder, GError **error);
bool (*pre_tag)(struct encoder *encoder, GError **error); bool (*pre_tag)(struct encoder *encoder, GError **error);
...@@ -132,7 +134,7 @@ encoder_open(struct encoder *encoder, struct audio_format *audio_format, ...@@ -132,7 +134,7 @@ encoder_open(struct encoder *encoder, struct audio_format *audio_format,
bool success = encoder->plugin->open(encoder, audio_format, error); bool success = encoder->plugin->open(encoder, audio_format, error);
#ifndef NDEBUG #ifndef NDEBUG
encoder->open = success; encoder->open = success;
encoder->pre_tag = encoder->tag = false; encoder->pre_tag = encoder->tag = encoder->end = false;
#endif #endif
return success; return success;
} }
...@@ -157,6 +159,35 @@ encoder_close(struct encoder *encoder) ...@@ -157,6 +159,35 @@ encoder_close(struct encoder *encoder)
} }
/** /**
* Ends the stream: flushes the encoder object, generate an
* end-of-stream marker (if applicable), make everything which might
* currently be buffered available by encoder_read().
*
* After this function has been called, the encoder may not be usable
* for more data, and only encoder_read() and encoder_close() can be
* called.
*
* @param encoder the encoder
* @param error location to store the error occuring, or NULL to ignore errors.
* @return true on success
*/
static inline bool
encoder_end(struct encoder *encoder, GError **error)
{
assert(encoder->open);
assert(!encoder->end);
#ifndef NDEBUG
encoder->end = true;
#endif
/* this method is optional */
return encoder->plugin->end != NULL
? encoder->plugin->end(encoder, error)
: true;
}
/**
* Flushes an encoder object, make everything which might currently be * Flushes an encoder object, make everything which might currently be
* buffered available by encoder_read(). * buffered available by encoder_read().
* *
...@@ -170,6 +201,7 @@ encoder_flush(struct encoder *encoder, GError **error) ...@@ -170,6 +201,7 @@ encoder_flush(struct encoder *encoder, GError **error)
assert(encoder->open); assert(encoder->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
assert(!encoder->tag); assert(!encoder->tag);
assert(!encoder->end);
/* this method is optional */ /* this method is optional */
return encoder->plugin->flush != NULL return encoder->plugin->flush != NULL
...@@ -193,6 +225,7 @@ encoder_pre_tag(struct encoder *encoder, GError **error) ...@@ -193,6 +225,7 @@ encoder_pre_tag(struct encoder *encoder, GError **error)
assert(encoder->open); assert(encoder->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
assert(!encoder->tag); assert(!encoder->tag);
assert(!encoder->end);
/* this method is optional */ /* this method is optional */
bool success = encoder->plugin->pre_tag != NULL bool success = encoder->plugin->pre_tag != NULL
...@@ -222,6 +255,7 @@ encoder_tag(struct encoder *encoder, const struct tag *tag, GError **error) ...@@ -222,6 +255,7 @@ encoder_tag(struct encoder *encoder, const struct tag *tag, GError **error)
assert(encoder->open); assert(encoder->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
assert(encoder->tag); assert(encoder->tag);
assert(!encoder->end);
#ifndef NDEBUG #ifndef NDEBUG
encoder->tag = false; encoder->tag = false;
...@@ -249,6 +283,7 @@ encoder_write(struct encoder *encoder, const void *data, size_t length, ...@@ -249,6 +283,7 @@ encoder_write(struct encoder *encoder, const void *data, size_t length,
assert(encoder->open); assert(encoder->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
assert(!encoder->tag); assert(!encoder->tag);
assert(!encoder->end);
return encoder->plugin->write(encoder, data, length, error); return encoder->plugin->write(encoder, data, length, error);
} }
......
...@@ -191,7 +191,7 @@ recorder_output_close(void *data) ...@@ -191,7 +191,7 @@ recorder_output_close(void *data)
/* flush the encoder and write the rest to the file */ /* flush the encoder and write the rest to the file */
if (encoder_flush(recorder->encoder, NULL)) if (encoder_end(recorder->encoder, NULL))
recorder_output_encoder_to_file(recorder, NULL); recorder_output_encoder_to_file(recorder, NULL);
/* now really close everything */ /* now really close everything */
......
...@@ -358,7 +358,7 @@ static void close_shout_conn(struct shout_data * sd) ...@@ -358,7 +358,7 @@ static void close_shout_conn(struct shout_data * sd)
sd->buf.len = 0; sd->buf.len = 0;
if (sd->encoder != NULL) { if (sd->encoder != NULL) {
if (encoder_flush(sd->encoder, NULL)) if (encoder_end(sd->encoder, NULL))
write_page(sd, NULL); write_page(sd, NULL);
encoder_close(sd->encoder); encoder_close(sd->encoder);
......
...@@ -121,7 +121,7 @@ int main(int argc, char **argv) ...@@ -121,7 +121,7 @@ int main(int argc, char **argv)
encoder_to_stdout(encoder); encoder_to_stdout(encoder);
} }
ret = encoder_flush(encoder, &error); ret = encoder_end(encoder, &error);
if (!ret) { if (!ret) {
g_printerr("encoder_flush() failed: %s\n", g_printerr("encoder_flush() failed: %s\n",
error->message); error->message);
......
...@@ -99,7 +99,7 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) ...@@ -99,7 +99,7 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
/* finish */ /* finish */
success = encoder_flush(encoder, NULL); success = encoder_end(encoder, NULL);
assert(success); assert(success);
encoder_to_stdout(encoder); encoder_to_stdout(encoder);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment