ref: d8cae227349529c25ce64376fdaa050b5f64ef43
parent: b84512ec76f92590264ae39b11d9369b297a4261
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Wed May 3 21:59:16 EDT 2017
Add packet and page callbacks
--- a/include/opusenc.h
+++ b/include/opusenc.h
@@ -61,14 +61,18 @@
/* These are the "raw" request values -- they should usually not be used. */
-#define OPE_SET_DECISION_DELAY_REQUEST 14000
-#define OPE_GET_DECISION_DELAY_REQUEST 14001
-#define OPE_SET_MUXING_DELAY_REQUEST 14002
-#define OPE_GET_MUXING_DELAY_REQUEST 14003
-#define OPE_SET_COMMENT_PADDING_REQUEST 14004
-#define OPE_GET_COMMENT_PADDING_REQUEST 14005
-#define OPE_SET_SERIALNO_REQUEST 14006
-#define OPE_GET_SERIALNO_REQUEST 14007
+#define OPE_SET_DECISION_DELAY_REQUEST 14000
+#define OPE_GET_DECISION_DELAY_REQUEST 14001
+#define OPE_SET_MUXING_DELAY_REQUEST 14002
+#define OPE_GET_MUXING_DELAY_REQUEST 14003
+#define OPE_SET_COMMENT_PADDING_REQUEST 14004
+#define OPE_GET_COMMENT_PADDING_REQUEST 14005
+#define OPE_SET_SERIALNO_REQUEST 14006
+#define OPE_GET_SERIALNO_REQUEST 14007
+#define OPE_SET_PACKET_CALLBACK_REQUEST 14008
+#define OPE_GET_PACKET_CALLBACK_REQUEST 14009
+#define OPE_SET_PAGE_CALLBACK_REQUEST 14010
+#define OPE_GET_PAGE_CALLBACK_REQUEST 14011
#define OPE_SET_DECISION_DELAY(x) OPE_SET_DECISION_DELAY_REQUEST, __opus_check_int(x)
#define OPE_GET_DECISION_DELAY(x) OPE_GET_DECISION_DELAY_REQUEST, __opus_check_int_ptr(x)
@@ -78,12 +82,20 @@
#define OPE_GET_COMMENT_PADDING(x) OPE_GET_COMMENT_PADDING_REQUEST, __opus_check_int_ptr(x)
#define OPE_SET_SERIALNO(x) OPE_SET_SERIALNO_REQUEST, __opus_check_int(x)
#define OPE_GET_SERIALNO(x) OPE_GET_SERIALNO_REQUEST, __opus_check_int_ptr(x)
+/* FIXME: Add type-checking macros to these. */
+#define OPE_SET_PACKET_CALLBACK(x) OPE_SET_PACKET_CALLBACK_REQUEST, (x)
+#define OPE_GET_PACKET_CALLBACK(x) OPE_GET_PACKET_CALLBACK_REQUEST, (x)
+#define OPE_SET_PAGE_CALLBACK(x) OPE_SET_PAGE_CALLBACK_REQUEST, (x)
+#define OPE_GET_PAGE_CALLBACK(x) OPE_GET_PAGE_CALLBACK_REQUEST, (x)
-
typedef int (*ope_write_func)(void *user_data, const unsigned char *ptr, int len);
typedef int (*ope_close_func)(void *user_data);
+typedef int (*ope_packet_func)(void *user_data, const unsigned char *packet_ptr, int packet_len, opus_uint32 flags);
+
+typedef int (*ope_page_func)(void *user_data, int page_len, opus_uint32 flags);
+
/** Callback functions for accessing the stream. */
typedef struct {
/** Callback for writing to the stream. */
@@ -134,9 +146,6 @@
/** Goes straight to the libopus ctl() functions. */
OPE_EXPORT int ope_encoder_ctl(OggOpusEnc *enc, int request, ...);
-
-/** ctl()-type call for the OggOpus layer. */
-OPE_EXPORT int ope_set_params(OggOpusEnc *enc, int request, ...);
# if defined(__cplusplus)
}
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -60,16 +60,6 @@
#define MAX_PACKET_SIZE (1276*8)
-static int oe_write_page(ogg_page *page, OpusEncCallbacks *cb, void *user_data)
-{
- int err;
- err = cb->write(user_data, page->header, page->header_len);
- if (err) return -1;
- err = cb->write(user_data, page->body, page->body_len);
- if (err) return -1;
- return page->header_len+page->body_len;
-}
-
struct StdioObject {
FILE *file;
};
@@ -111,6 +101,8 @@
unsigned char *chaining_keyframe;
int chaining_keyframe_length;
OpusEncCallbacks callbacks;
+ ope_packet_func packet_callback;
+ ope_page_func page_callback;
OpusHeader header;
int comment_padding;
EncStream *streams;
@@ -117,6 +109,19 @@
EncStream *last_stream;
};
+static int oe_write_page(OggOpusEnc *enc, ogg_page *page, void *user_data)
+{
+ int length;
+ int err;
+ err = enc->callbacks.write(user_data, page->header, page->header_len);
+ if (err) return -1;
+ err = enc->callbacks.write(user_data, page->body, page->body_len);
+ if (err) return -1;
+ length = page->header_len+page->body_len;
+ if (enc->page_callback) enc->page_callback(user_data, length, 0);
+ return length;
+}
+
static int oe_flush_page(OggOpusEnc *enc) {
ogg_page og;
int ret;
@@ -123,7 +128,7 @@
int written = 0;
while ( (ret = ogg_stream_flush(&enc->streams->os, &og)) ) {
if (!ret) break;
- ret = oe_write_page(&og, &enc->callbacks, enc->streams->user_data);
+ ret = oe_write_page(enc, &og, enc->streams->user_data);
if (ret == -1) {
return -1;
}
@@ -225,6 +230,8 @@
if ( (enc->streams = stream_create()) == NULL) goto fail;
enc->streams->next = NULL;
enc->last_stream = enc->streams;
+ enc->packet_callback = NULL;
+ enc->page_callback = NULL;
enc->rate = rate;
enc->channels = channels;
enc->frame_size = 960;
@@ -366,12 +373,13 @@
cont = 0;
if (op.e_o_s) op.granulepos=end_granule48k-enc->streams->granule_offset;
ogg_stream_packetin(&enc->streams->os, &op);
+ if (enc->packet_callback) enc->packet_callback(enc->streams->user_data, op.packet, op.bytes, 0);
/* FIXME: Also flush on too many segments. */
flush_needed = op.e_o_s || enc->curr_granule - enc->last_page_granule > enc->max_ogg_delay;
if (flush_needed) {
while (ogg_stream_flush_fill(&enc->streams->os, &og, 255*255)) {
if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og) + enc->streams->granule_offset;
- int ret = oe_write_page(&og, &enc->callbacks, enc->streams->user_data);
+ int ret = oe_write_page(enc, &og, enc->streams->user_data);
/* FIXME: what do we do if this fails? */
assert(ret != -1);
}
@@ -378,7 +386,7 @@
} else {
while (ogg_stream_pageout_fill(&enc->streams->os, &og, 255*255)) {
if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og) + enc->streams->granule_offset;
- int ret = oe_write_page(&og, &enc->callbacks, enc->streams->user_data);
+ int ret = oe_write_page(enc, &og, enc->streams->user_data);
/* FIXME: what do we do if this fails? */
assert(ret != -1);
}
@@ -408,6 +416,7 @@
op2.packetno=enc->streams->packetno++;
op2.granulepos=enc->curr_granule - enc->streams->granule_offset - enc->frame_size;
ogg_stream_packetin(&enc->streams->os, &op2);
+ if (enc->packet_callback) enc->packet_callback(enc->streams->user_data, op2.packet, op2.bytes, 0);
}
end_granule48k = (enc->streams->end_granule*48000 + enc->rate - 1)/enc->rate + enc->global_granule_offset;
cont = 1;
@@ -700,6 +709,19 @@
if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
enc->last_stream->serialno = value;
enc->last_stream->serialno_is_set = 1;
+ ret = OPE_OK;
+ }
+ case OPE_SET_PACKET_CALLBACK_REQUEST:
+ {
+ ope_packet_func value = va_arg(ap, ope_packet_func);
+ enc->packet_callback = value;
+ ret = OPE_OK;
+ }
+ break;
+ case OPE_SET_PAGE_CALLBACK_REQUEST:
+ {
+ ope_page_func value = va_arg(ap, ope_page_func);
+ enc->page_callback = value;
ret = OPE_OK;
}
break;