Unverified Commit ba73b31b authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

Add ope_encoder_deferred_init_with_mapping()

Makes it possible to manually specify a channel mapping
parent ccd67677
...@@ -264,6 +264,17 @@ OPE_EXPORT OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *call ...@@ -264,6 +264,17 @@ OPE_EXPORT OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *call
*/ */
OPE_EXPORT OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error); OPE_EXPORT OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error);
/** Deferred initialization of the encoder to force an explicit channel mapping.
\param[in,out] enc Encoder
\param family Mapping family (0 for mono/stereo, 1 for surround)
\param streams Total number of streams
\param coupled_streams Number of coupled streams
\param mapping Channel mapping
\return Error code
*/
OPE_EXPORT int ope_encoder_deferred_init_with_mapping(OggOpusEnc *enc, int family, int streams,
int coupled_streams, const unsigned char *mapping);
/** Add/encode any number of float samples to the stream. /** Add/encode any number of float samples to the stream.
\param[in,out] enc Encoder \param[in,out] enc Encoder
\param pcm Floating-point PCM values in the +/-1 range (interleaved if multiple channels) \param pcm Floating-point PCM values in the +/-1 range (interleaved if multiple channels)
......
...@@ -283,7 +283,7 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void ...@@ -283,7 +283,7 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void
OpusMSEncoder *st=NULL; OpusMSEncoder *st=NULL;
OggOpusEnc *enc=NULL; OggOpusEnc *enc=NULL;
int ret; int ret;
if (family != 0 && family != 1 && family != 255) { if (family != 0 && family != 1 && family != 255 && family != -1) {
if (error) *error = OPE_UNIMPLEMENTED; if (error) *error = OPE_UNIMPLEMENTED;
return NULL; return NULL;
} }
...@@ -302,7 +302,8 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void ...@@ -302,7 +302,8 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void
if ( (enc->streams = stream_create(comments)) == NULL) goto fail; if ( (enc->streams = stream_create(comments)) == NULL) goto fail;
enc->last_stream = enc->streams; enc->last_stream = enc->streams;
enc->oggp = NULL; enc->oggp = NULL;
enc->unrecoverable = 0; /* Not initializing anything is an unrecoverable error. */
enc->unrecoverable = family == -1;
enc->pull_api = 0; enc->pull_api = 0;
enc->packet_callback = NULL; enc->packet_callback = NULL;
enc->rate = rate; enc->rate = rate;
...@@ -317,12 +318,16 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void ...@@ -317,12 +318,16 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void
enc->header.channel_mapping=family; enc->header.channel_mapping=family;
enc->header.input_sample_rate=rate; enc->header.input_sample_rate=rate;
enc->header.gain=0; enc->header.gain=0;
if (family != -1) {
st=opus_multistream_surround_encoder_create(48000, channels, enc->header.channel_mapping, st=opus_multistream_surround_encoder_create(48000, channels, enc->header.channel_mapping,
&enc->header.nb_streams, &enc->header.nb_coupled, &enc->header.nb_streams, &enc->header.nb_coupled,
enc->header.stream_map, OPUS_APPLICATION_AUDIO, &ret); enc->header.stream_map, OPUS_APPLICATION_AUDIO, &ret);
if (! (ret == OPUS_OK && st != NULL) ) { if (! (ret == OPUS_OK && st != NULL) ) {
goto fail; goto fail;
} }
enc->st = st;
opus_multistream_encoder_ctl(st, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
}
if (rate != 48000) { if (rate != 48000) {
enc->re = speex_resampler_init(channels, rate, 48000, 5, NULL); enc->re = speex_resampler_init(channels, rate, 48000, 5, NULL);
if (enc->re == NULL) goto fail; if (enc->re == NULL) goto fail;
...@@ -330,7 +335,6 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void ...@@ -330,7 +335,6 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void
} else { } else {
enc->re = NULL; enc->re = NULL;
} }
opus_multistream_encoder_ctl(st, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
enc->global_granule_offset = -1; enc->global_granule_offset = -1;
enc->curr_granule = 0; enc->curr_granule = 0;
enc->write_granule = 0; enc->write_granule = 0;
...@@ -343,7 +347,6 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void ...@@ -343,7 +347,6 @@ OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void
memset(enc->lpc_buffer, 0, sizeof(*enc->lpc_buffer)*LPC_INPUT*channels); memset(enc->lpc_buffer, 0, sizeof(*enc->lpc_buffer)*LPC_INPUT*channels);
} }
enc->buffer_start = enc->buffer_end = 0; enc->buffer_start = enc->buffer_end = 0;
enc->st = st;
if (callbacks != NULL) if (callbacks != NULL)
{ {
enc->callbacks = *callbacks; enc->callbacks = *callbacks;
...@@ -372,6 +375,32 @@ OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate, ...@@ -372,6 +375,32 @@ OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate,
return enc; return enc;
} }
int ope_encoder_deferred_init_with_mapping(OggOpusEnc *enc, int family, int streams,
int coupled_streams, const unsigned char *mapping) {
int ret;
int i;
OpusMSEncoder *st;
if (enc->st!=NULL) {
return OPE_TOO_LATE;
}
if (streams <= 0 || streams>255 || coupled_streams<0 || coupled_streams >= 128 || streams+coupled_streams > 255) return OPE_BAD_ARG;
st=opus_multistream_encoder_create(48000, enc->channels, streams, coupled_streams, mapping, OPUS_APPLICATION_AUDIO, &ret);
if (! (ret == OPUS_OK && st != NULL) ) {
goto fail;
}
enc->st = st;
opus_multistream_encoder_ctl(st, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
enc->unrecoverable = 0;
enc->header.channel_mapping=family;
enc->header.nb_streams = streams;
enc->header.nb_coupled = coupled_streams;
for (i=0;i<streams+coupled_streams;i++)
enc->header.stream_map[i] = mapping[i];
return OPE_OK;
fail:
return OPE_ALLOC_FAIL;
}
static void init_stream(OggOpusEnc *enc) { static void init_stream(OggOpusEnc *enc) {
assert(!enc->streams->stream_is_init); assert(!enc->streams->stream_is_init);
if (!enc->streams->serialno_is_set) { if (!enc->streams->serialno_is_set) {
...@@ -699,7 +728,7 @@ void ope_encoder_destroy(OggOpusEnc *enc) { ...@@ -699,7 +728,7 @@ void ope_encoder_destroy(OggOpusEnc *enc) {
if (enc->chaining_keyframe) free(enc->chaining_keyframe); if (enc->chaining_keyframe) free(enc->chaining_keyframe);
free(enc->buffer); free(enc->buffer);
if (enc->oggp) oggp_destroy(enc->oggp); if (enc->oggp) oggp_destroy(enc->oggp);
opus_multistream_encoder_destroy(enc->st); if (enc->st) opus_multistream_encoder_destroy(enc->st);
if (enc->re) speex_resampler_destroy(enc->re); if (enc->re) speex_resampler_destroy(enc->re);
if (enc->lpc_buffer) free(enc->lpc_buffer); if (enc->lpc_buffer) free(enc->lpc_buffer);
free(enc); free(enc);
......
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