ref: ccd67677f91db97d1d65f79ae05ba4df224cb75b
parent: 3e73d2ee6c3dedcb4b361cae6db327973e771ae0
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Fri Feb 2 11:29:33 EST 2018
Trimming the end of files like opus-tools did
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -184,6 +184,7 @@
opus_int64 curr_granule;
opus_int64 write_granule;
opus_int64 last_page_granule;
+ int draining;
float *lpc_buffer;
unsigned char *chaining_keyframe;
int chaining_keyframe_length;
@@ -334,6 +335,7 @@
enc->curr_granule = 0;
enc->write_granule = 0;
enc->last_page_granule = 0;
+ enc->draining = 0;
if ( (enc->buffer = malloc(sizeof(*enc->buffer)*BUFFER_SAMPLES*channels)) == NULL) goto fail;
if (rate != 48000) {
/* Allocate an extra LPC_PADDING samples so we can do the padding in-place. */
@@ -425,6 +427,11 @@
}
}
+static int compute_frame_samples(int size_request) {
+ if (size_request <= OPUS_FRAMESIZE_40_MS) return 120<<(size_request-OPUS_FRAMESIZE_2_5_MS);
+ else return (size_request-OPUS_FRAMESIZE_2_5_MS-2)*960;
+}
+
static void encode_buffer(OggOpusEnc *enc) {
opus_int32 max_packet_size;
/* Round up when converting the granule pos because the decoder will round down. */
@@ -446,6 +453,15 @@
opus_multistream_encoder_ctl(enc->st, OPUS_SET_PREDICTION_DISABLED(1));
is_keyframe = 1;
}
+ /* Handle the last packet by making sure not to encode too much padding. */
+ if (enc->curr_granule+enc->frame_size >= end_granule48k && enc->draining) {
+ int min_samples;
+ int frame_size_request = OPUS_FRAMESIZE_2_5_MS;
+ /* Minimum frame size required for the current frame to still meet the e_o_s condition. */
+ min_samples = end_granule48k - enc->curr_granule;
+ while (compute_frame_samples(frame_size_request) < min_samples) frame_size_request++;
+ ope_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(frame_size_request));
+ }
packet = oggp_get_packet_buffer(enc->oggp, max_packet_size);
nbBytes = opus_multistream_encode_float(enc->st, &enc->buffer[enc->channels*enc->buffer_start],
enc->buffer_end-enc->buffer_start, packet, max_packet_size);
@@ -662,6 +678,7 @@
enc->buffer_end += pad_samples;
}
enc->decision_delay = 0;
+ enc->draining = 1;
assert(enc->buffer_end <= BUFFER_SAMPLES);
encode_buffer(enc);
if (enc->unrecoverable) return OPE_UNRECOVERABLE;
@@ -784,12 +801,7 @@
break;
}
ret = opus_multistream_encoder_ctl(enc->st, request, value);
- if (ret == OPUS_OK) {
- if (value <= OPUS_FRAMESIZE_40_MS)
- enc->frame_size = 120<<(value-OPUS_FRAMESIZE_2_5_MS);
- else
- enc->frame_size = (value-OPUS_FRAMESIZE_2_5_MS-2)*960;
- }
+ if (ret == OPUS_OK) enc->frame_size = compute_frame_samples(value);
}
break;
case OPUS_GET_APPLICATION_REQUEST: