Пример #1
0
bool CAudioCodecOpus::FiniCodec()
{
  if (AM_LIKELY(mEncoder)) {
    opus_encoder_destroy(mEncoder);
    mEncoder = NULL;
  }

  if (AM_LIKELY(mDecoder)) {
    opus_decoder_destroy(mDecoder);
    mDecoder = NULL;
  }

  if (AM_LIKELY(mRepacketizer)) {
    opus_repacketizer_destroy(mRepacketizer);
    mRepacketizer = NULL;
  }
  mIsInitialized = false;
  return true;
}
Пример #2
0
static void ms_opus_enc_process(MSFilter *f) {
	OpusEncData *d = (OpusEncData *)f->data;
	mblk_t *im;
	mblk_t *om = NULL;
	int i;
	int frameNumber, packet_size;
	uint8_t *signalFrameBuffer = NULL;
	uint8_t *codedFrameBuffer[MAX_INPUT_FRAMES];
	OpusRepacketizer *rp = opus_repacketizer_create();
	opus_int32 ret = 0;
	opus_int32 totalLength = 0;
	int frame_size = d->samplerate * FRAME_LENGTH / 1000; /* in samples */

	// lock the access while getting ptime
	ms_filter_lock(f);
	frameNumber = d->ptime/FRAME_LENGTH; /* encode 20ms frames, ptime is a multiple of 20ms */
	packet_size = d->samplerate * d->ptime / 1000; /* in samples */
	ms_filter_unlock(f);


	while ((im = ms_queue_get(f->inputs[0])) != NULL) {
		ms_bufferizer_put(d->bufferizer, im);
	}

	for (i=0; i<MAX_INPUT_FRAMES; i++) {
		codedFrameBuffer[i]=NULL;
	}
	while (ms_bufferizer_get_avail(d->bufferizer) >= (d->channels * packet_size * SIGNAL_SAMPLE_SIZE)) {
		totalLength = 0;
		opus_repacketizer_init(rp);
		for (i=0; i<frameNumber; i++) { /* encode 20ms by 20ms and repacketize all of them together */
			if (!codedFrameBuffer[i]) codedFrameBuffer[i] = ms_malloc(MAX_BYTES_PER_FRAME); /* the repacketizer need the pointer to packet to remain valid, so we shall have a buffer for each coded frame */
			if (!signalFrameBuffer) signalFrameBuffer = ms_malloc(frame_size * SIGNAL_SAMPLE_SIZE * d->channels);

			ms_bufferizer_read(d->bufferizer, signalFrameBuffer, frame_size * SIGNAL_SAMPLE_SIZE * d->channels);
			ret = opus_encode(d->state, (opus_int16 *)signalFrameBuffer, frame_size, codedFrameBuffer[i], MAX_BYTES_PER_FRAME);
			if (ret < 0) {
				ms_error("Opus encoder error: %s", opus_strerror(ret));
				break;
			}
			if (ret > 0) {
				int err = opus_repacketizer_cat(rp, codedFrameBuffer[i], ret); /* add the encoded frame into the current packet */
				if (err != OPUS_OK) {
					ms_error("Opus repacketizer error: %s", opus_strerror(err));
					break;
				}
				totalLength += ret;
			}
		}

		if (ret > 0) {
			om = allocb(totalLength+frameNumber + 1, 0); /* opus repacktizer API: allocate at leat number of frame + size of all data added before */
			ret = opus_repacketizer_out(rp, om->b_wptr, totalLength+frameNumber);

			om->b_wptr += ret;
			mblk_set_timestamp_info(om, d->ts);
			ms_queue_put(f->outputs[0], om);
			d->ts += packet_size*48000/d->samplerate; /* RFC payload RTP opus 03 - section 4: RTP timestamp multiplier : WARNING works only with sr at 48000 */
			ret = 0;
		}
	}

	opus_repacketizer_destroy(rp);

	if (signalFrameBuffer != NULL) {
		ms_free(signalFrameBuffer);
	}
	for (i=0; i<frameNumber; i++) {
		if (codedFrameBuffer[i] != NULL) {
			ms_free(codedFrameBuffer[i]);
		}
	}
}
Пример #3
0
static void ms_opus_enc_process(MSFilter *f) {
	OpusEncData *d = (OpusEncData *)f->data;
	OpusRepacketizer *repacketizer = NULL;
	mblk_t *om = NULL;
	int packet_size, pcm_buffer_size;
	int max_frame_byte_size, ptime = 20;
	int frame_count = 0, frame_size = 0;
	opus_int32 total_length = 0;
	uint8_t *repacketizer_frame_buffer[MAX_INPUT_FRAMES];
	int i;
	ms_filter_lock(f);
	ptime = d->ptime;
	packet_size = d->samplerate * ptime / 1000; /* in samples */
	ms_filter_unlock(f);
	
	switch (ptime) {
		case 10:
			frame_size = d->samplerate * 10 / 1000;
			frame_count = 1;
			break;
		case 20:
			frame_size = d->samplerate * 20 / 1000;
			frame_count = 1;
			break;
		case 40:
			frame_size = d->samplerate * 40 / 1000;
			frame_count = 1;
			break;
		case 60:
			frame_size = d->samplerate * 60 / 1000;
			frame_count = 1;
			break;
		case 80:
			frame_size = d->samplerate * 40 / 1000;
			frame_count = 2;
			break;
		case 100:
			frame_size = d->samplerate * 20 / 1000;
			frame_count = 5;
			break;
		case 120:
			frame_size = d->samplerate * 60 / 1000;
			frame_count = 2;
			break;
		default:
			frame_size = d->samplerate * 20 / 1000;
			frame_count = 1;
	}

	max_frame_byte_size = MAX_BYTES_PER_MS * ptime/frame_count;

	pcm_buffer_size = d->channels * frame_size * SIGNAL_SAMPLE_SIZE;
	if (pcm_buffer_size > d->pcmbufsize){
		if (d->pcmbuffer) ms_free(d->pcmbuffer);
		d->pcmbuffer = ms_malloc(pcm_buffer_size);
		d->pcmbufsize = pcm_buffer_size;
	}
	for (i=0; i<MAX_INPUT_FRAMES; i++) {
		repacketizer_frame_buffer[i]=NULL;
	}

	ms_bufferizer_put_from_queue(d->bufferizer, f->inputs[0]);
	while (ms_bufferizer_get_avail(d->bufferizer) >= (d->channels * packet_size * SIGNAL_SAMPLE_SIZE)) {
		opus_int32 ret = 0;

		if (frame_count == 1) { /* One Opus frame, not using the repacketizer */
			om = allocb(max_frame_byte_size, 0);
			ms_bufferizer_read(d->bufferizer, d->pcmbuffer, frame_size * SIGNAL_SAMPLE_SIZE * d->channels);
			ret = opus_encode(d->state, (opus_int16 *)d->pcmbuffer, frame_size, om->b_wptr, max_frame_byte_size);
			if (ret < 0) {
				freemsg(om);
				om=NULL;
				ms_error("Opus encoder error: %s", opus_strerror(ret));
				break;
			} else {
				total_length = ret;
				om->b_wptr += total_length;
			}
		} else if(frame_count > 1) { /* We have multiple Opus frames we will use the opus repacketizer */

			repacketizer = opus_repacketizer_create();
			opus_repacketizer_init(repacketizer);

			/* Do not include FEC/LBRR in any frame after the first one since it will be sent with the previous one */
			ret = opus_encoder_ctl(d->state, OPUS_SET_INBAND_FEC(0));
			if (ret != OPUS_OK) {
				ms_error("could not set inband FEC to opus encoder: %s", opus_strerror(ret));
			}
			for (i=0; i<frame_count; i++) {
				if(frame_count == i+1){ /* if configured, reactivate FEC on the last frame to tell the encoder he should restart saving LBRR frames */
					ret = opus_encoder_ctl(d->state, OPUS_SET_INBAND_FEC(d->useinbandfec));
					if (ret != OPUS_OK) {
						ms_error("could not set inband FEC to opus encoder: %s", opus_strerror(ret));
					}
				}
				if (!repacketizer_frame_buffer[i]) repacketizer_frame_buffer[i] = ms_malloc(max_frame_byte_size); /* the repacketizer need the pointer to packet to remain valid, so we shall have a buffer for each coded frame */
				ms_bufferizer_read(d->bufferizer, d->pcmbuffer, frame_size * SIGNAL_SAMPLE_SIZE * d->channels);
				ret = opus_encode(d->state, (opus_int16 *)d->pcmbuffer, frame_size, repacketizer_frame_buffer[i], max_frame_byte_size);
				if (ret < 0) {
					ms_error("Opus encoder error: %s", opus_strerror(ret));
					break;
				} else if (ret > 0) {
					int err = opus_repacketizer_cat(repacketizer, repacketizer_frame_buffer[i], ret); /* add the encoded frame into the current packet */
					if (err != OPUS_OK) {
						ms_error("Opus repacketizer error: %s", opus_strerror(err));
						break;
					}
					total_length += ret;
				}
			}

			om = allocb(total_length + frame_count + 1, 0); /* opus repacketizer API: allocate at least number of frame + size of all data added before */
			ret = opus_repacketizer_out(repacketizer, om->b_wptr, total_length+frame_count);
			if(ret < 0){
				freemsg(om);
				om=NULL;
				ms_error("Opus repacketizer out error: %s", opus_strerror(ret));
			} else {
				om->b_wptr += ret;
			}
			opus_repacketizer_destroy(repacketizer);
			for (i=0; i<frame_count; i++) {
				if (repacketizer_frame_buffer[i] != NULL) {
					ms_free(repacketizer_frame_buffer[i]);
				}
			}
		}

		if(om) { /* we have an encoded output message */
			mblk_set_timestamp_info(om, d->ts);
			ms_bufferizer_fill_current_metas(d->bufferizer, om);
			ms_queue_put(f->outputs[0], om);
			d->ts += packet_size*48000/d->samplerate; /* RFC payload RTP opus 03 - section 4: RTP timestamp multiplier : WARNING works only with sr at 48000 */
			total_length = 0;
		}
	}

}