shithub: libopusenc

Download patch

ref: 14bcd76f79da9a225528a5fb9fe781c57a9ca1ad
parent: b718267504c90df4854218b4ffe2d38a4e552da7
author: Jean-Marc Valin <[email protected]>
date: Fri May 5 13:35:14 EDT 2017

Implement pull API

--- a/include/opusenc.h
+++ b/include/opusenc.h
@@ -108,11 +108,17 @@
 OPE_EXPORT OggOpusEnc *ope_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data,
     int rate, int channels, int family, int *error);
 
+/** Create a new OggOpus stream, pulling one page at a time. */
+OPE_EXPORT OggOpusEnc *ope_create_pull(int rate, int channels, int family, int *error);
+
 /** Add/encode any number of float samples to the file. */
 OPE_EXPORT int ope_write_float(OggOpusEnc *enc, const float *pcm, int samples_per_channel);
 
 /** Add/encode any number of int16 samples to the file. */
 OPE_EXPORT int ope_write(OggOpusEnc *enc, const opus_int16 *pcm, int samples_per_channel);
+
+/** Get the next page from the stream. Returns 1 if there is a page available, 0 if not. */
+OPE_EXPORT int ope_get_page(OggOpusEnc *enc, unsigned char **page, int *len, int flush);
 
 /** Finalizes the stream, but does not deallocate the object. */
 OPE_EXPORT int ope_drain(OggOpusEnc *enc);
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -93,6 +93,7 @@
 #ifdef USE_OGGP
   oggpacker *oggp;
 #endif
+  int pull_api;
   int rate;
   int channels;
   float *buffer;
@@ -126,7 +127,7 @@
 }
 static void oe_flush_page(OggOpusEnc *enc) {
   oggp_flush_page(enc->oggp);
-  output_pages(enc);
+  if (!enc->pull_api) output_pages(enc);
 }
 
 #else
@@ -255,6 +256,7 @@
 #ifdef USE_OGGP
   enc->oggp = NULL;
 #endif
+  enc->pull_api = 0;
   enc->packet_callback = NULL;
   enc->rate = rate;
   enc->channels = channels;
@@ -313,6 +315,13 @@
   return NULL;
 }
 
+/* Create a new OggOpus stream, pulling one page at a time. */
+OPE_EXPORT OggOpusEnc *ope_create_pull(int rate, int channels, int family, int *error) {
+  OggOpusEnc *enc = ope_create_callbacks(NULL, NULL, rate, channels, family, error);
+  enc->pull_api = 1;
+  return enc;
+}
+
 static void init_stream(OggOpusEnc *enc) {
   assert(!enc->streams->stream_is_init);
   if (!enc->streams->serialno_is_set) {
@@ -436,7 +445,7 @@
 #ifdef USE_OGGP
       flush_needed = op.e_o_s;
       if (flush_needed) oe_flush_page(enc);
-      else output_pages(enc);
+      else if (!enc->pull_api) output_pages(enc);
 #else
       flush_needed = op.e_o_s || enc->curr_granule - enc->last_page_granule >= enc->max_ogg_delay;
       if (flush_needed) {
@@ -577,6 +586,15 @@
   return OPE_OK;
 }
 
+/* Get the next page from the stream. Returns 1 if there is a page available, 0 if not. */
+OPE_EXPORT int ope_get_page(OggOpusEnc *enc, unsigned char **page, int *len, int flush) {
+  if (!enc->pull_api) return 0;
+  else {
+    if (flush) oggp_flush_page(enc->oggp);
+    return oggp_get_next_page(enc->oggp, page, len);
+  }
+}
+
 int ope_drain(OggOpusEnc *enc) {
   /* FIXME: Use a better value. */
   int pad_samples = 3000;
@@ -592,7 +610,6 @@
   return OPE_OK;
 }
 
-/* Close/finalize the stream. */
 void ope_destroy(OggOpusEnc *enc) {
   /* FIXME: cleanup non-closed streams if any remain. */
   if (enc->chaining_keyframe) free(enc->chaining_keyframe);