//go:build !nolibopusfile // +build !nolibopusfile // Copyright © Go Opus Authors (see AUTHORS file) // // License for use of this code is detailed in the LICENSE file // Allocate callback struct in C to ensure it's not managed by the Go GC. This // plays nice with the CGo rules and avoids any confusion. #include #include #include #include // Defined in Go. Uses the same signature as Go, no need for proxy function. int go_readcallback(void *p, unsigned char *buf, int nbytes); int go_writecallback(void *p, const unsigned char *buf, opus_int32 len); int closecallback(void *p) { return 0; } static struct OpusFileCallbacks callbacks = { .read = go_readcallback, }; static OpusEncCallbacks encodeCallbacks = { .write = go_writecallback, .close = closecallback, }; static OggOpusComments* emptyComment = NULL; // Proxy function for op_open_callbacks, because it takes a void * context but // we want to pass it non-pointer data, namely an arbitrary uintptr_t // value. This is legal C, but go test -race (-d=checkptr) complains anyway. So // we have this wrapper function to shush it. // https://groups.google.com/g/golang-nuts/c/995uZyRPKlU OggOpusFile * my_open_callbacks(uintptr_t p, int *error) { return op_open_callbacks((void *)p, &callbacks, NULL, 0, error); } OpusEncCallbacks * my_write_callbacks() { return &encodeCallbacks; } OggOpusComments* my_empty_comment() { if (emptyComment == NULL) { emptyComment = ope_comments_create(); } return emptyComment; } int bridge_encoder_set_dtx(OggOpusEnc *st, opus_int32 use_dtx) { return ope_encoder_ctl(st, OPUS_SET_DTX(use_dtx)); } int bridge_encoder_set_application(OggOpusEnc *st, opus_int32 application) { return ope_encoder_ctl(st, OPUS_SET_APPLICATION(application)); } int bridge_encoder_get_dtx(OggOpusEnc *st, opus_int32 *dtx) { return ope_encoder_ctl(st, OPUS_GET_DTX(dtx)); } int bridge_encoder_get_sample_rate(OggOpusEnc *st, opus_int32 *sample_rate) { return ope_encoder_ctl(st, OPUS_GET_SAMPLE_RATE(sample_rate)); } int bridge_encoder_set_muxing_delay(OggOpusEnc *st, opus_int32 delay) { return ope_encoder_ctl(st, OPE_SET_MUXING_DELAY(delay)); } int bridge_encoder_get_muxing_delay(OggOpusEnc *st, opus_int32 *delay) { return ope_encoder_ctl(st, OPE_GET_MUXING_DELAY(delay)); } int bridge_encoder_set_bitrate(OggOpusEnc *st, opus_int32 bitrate) { return ope_encoder_ctl(st, OPUS_SET_BITRATE(bitrate)); } int bridge_encoder_get_bitrate(OggOpusEnc *st, opus_int32 *bitrate) { return ope_encoder_ctl(st, OPUS_GET_BITRATE(bitrate)); } int bridge_encoder_set_complexity(OggOpusEnc *st, opus_int32 complexity) { return ope_encoder_ctl(st, OPUS_SET_COMPLEXITY(complexity)); } int bridge_encoder_get_complexity(OggOpusEnc *st, opus_int32 *complexity) { return ope_encoder_ctl(st, OPUS_GET_COMPLEXITY(complexity)); } int bridge_encoder_set_max_bandwidth(OggOpusEnc *st, opus_int32 max_bw) { return ope_encoder_ctl(st, OPUS_SET_MAX_BANDWIDTH(max_bw)); } int bridge_encoder_get_max_bandwidth(OggOpusEnc *st, opus_int32 *max_bw) { return ope_encoder_ctl(st, OPUS_GET_MAX_BANDWIDTH(max_bw)); } int bridge_encoder_set_inband_fec(OggOpusEnc *st, opus_int32 fec) { return ope_encoder_ctl(st, OPUS_SET_INBAND_FEC(fec)); } int bridge_encoder_get_inband_fec(OggOpusEnc *st, opus_int32 *fec) { return ope_encoder_ctl(st, OPUS_GET_INBAND_FEC(fec)); } int bridge_encoder_set_packet_loss_perc(OggOpusEnc *st, opus_int32 loss_perc) { return ope_encoder_ctl(st, OPUS_SET_PACKET_LOSS_PERC(loss_perc)); } int bridge_encoder_get_packet_loss_perc(OggOpusEnc *st, opus_int32 *loss_perc) { return ope_encoder_ctl(st, OPUS_GET_PACKET_LOSS_PERC(loss_perc)); }