isac_dec.c 6.58 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 isac_dec.c
 Copyright (C) 2013 Belledonne Communications, Grenoble, France

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include "isacfix.h"

#include "mediastreamer2/mscodecutils.h"
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msticker.h"
#include "ortp/rtp.h"

27 28
#include <stdint.h>

29
#include "isac_constants.h"
30

31 32
/*filter common method*/
struct _isac_decoder_struct_t {
33
	ISACFIX_MainStruct* isac;
34

35 36 37
	MSConcealerContext* plc_ctx;
	unsigned short int  seq_nb;
	unsigned int        ptime;
38 39 40 41
};

typedef struct _isac_decoder_struct_t isac_decoder_t;

42
static void filter_init(MSFilter *f){
43 44 45
	ISACFIX_MainStruct* isac_mainstruct = NULL;
	isac_decoder_t *obj = NULL;
	int instance_size;
46
	int16_t ret;
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

	f->data = ms_new0(isac_decoder_t, 1);
	obj = (isac_decoder_t*)f->data;

	ret = WebRtcIsacfix_AssignSize( &instance_size );
	if( ret ) {
		ms_error("WebRtcIsacfix_AssignSize returned size %d", instance_size);
	}
	isac_mainstruct = ms_malloc(instance_size);

	ret = WebRtcIsacfix_Assign(&obj->isac, isac_mainstruct);
	if( ret ) {
		ms_error("WebRtcIsacfix_Create failed (%d)", ret);
	}

62
	WebRtcIsacfix_DecoderInit(obj->isac);
63 64

	obj->ptime = 30; // default ptime is 30ms per packet
65 66 67
}

static void filter_preprocess(MSFilter *f){
68 69
	isac_decoder_t* obj = (isac_decoder_t*)f->data;
	obj->plc_ctx = ms_concealer_context_new(UINT32_MAX);
70 71
}

72 73

static void decode(MSFilter *f, mblk_t *im) {
74
	isac_decoder_t* obj = (isac_decoder_t*)f->data;
75 76 77
	int16_t ret;
	int16_t speech_type; // needed but not used..
	size_t samples_nb;
78 79

	// im is one packet from the encoder, so it's either 30 or 60 ms of audio
80
	ret = WebRtcIsacfix_ReadFrameLen( (const uint8_t*)im->b_rptr, msgdsize(im), &samples_nb);
81 82 83 84 85 86 87 88 89 90
	//     ms_message("WebRtcIsacfix_ReadFrameLen -> %d", samples_nb);

	if( ret == 0 ) {
		mblk_t *om = allocb(samples_nb*2, 0);
		mblk_meta_copy(im, om);

		obj->ptime = (samples_nb == ISAC_30MS_SAMPLE_COUNT) ? 30 : 60; // update ptime
		//         ms_message("DECODED om datap @%p", om->b_datap);

		ret = WebRtcIsacfix_Decode(obj->isac,
91
								(const uint8_t*)im->b_rptr,
92
								(im->b_wptr - im->b_rptr),
93
								(int16_t*)om->b_wptr,
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
								&speech_type );
		if( ret < 0 ) {
			ms_error( "WebRtcIsacfix_Decode error: %d", WebRtcIsacfix_GetErrorCode(obj->isac) );
			freeb(om);
		} else {
			//             ms_message("Decoded %d samples", ret);
			om->b_wptr+= ret*2;
			mblk_set_plc_flag(om, 0);
			ms_queue_put(f->outputs[0], om);
		}

	} else {
		ms_error( "WebRtcIsacfix_ReadFrameLen failed: %d", WebRtcIsacfix_GetErrorCode(obj->isac) );
	}

	obj->seq_nb = mblk_get_cseq(im);

	ms_concealer_inc_sample_time(obj->plc_ctx, f->ticker->time, obj->ptime, TRUE);

	return;
114
}
115 116

static void filter_process(MSFilter *f){
117 118 119
	isac_decoder_t* obj = (isac_decoder_t*)f->data;
	mblk_t* im;
	int count = 0;
120

121 122 123 124 125 126 127
	im = ms_queue_get( f->inputs[0] );
	while( im != NULL ){
		decode(f, im);
		freemsg(im);
		count++;
		im = ms_queue_get( f->inputs[0] );
	}
128

129
	if( ms_concealer_context_is_concealement_required(obj->plc_ctx, f->ticker->time) ) {
130

131
		int16_t flen =  (obj->ptime == 30) ? ISAC_30MS_SAMPLE_COUNT
132 133 134
												 : ISAC_60MS_SAMPLE_COUNT;
		mblk_t* plc_blk = allocb(flen*2, 0 );
		//        ms_message("PLC for %d ms", obj->ptime);
135

136
		// interpolate 1 frame for 30ms ptime, 2 frames for 60ms
137 138
		int16_t ret = WebRtcIsacfix_DecodePlc(obj->isac,
													(int16_t*)plc_blk->b_wptr,
139
													(obj->ptime == 30) ? 1 : 2);
140

141
		if( ret < 0 ) {
142

143 144
			ms_error("WebRtcIsacfix_DecodePlc error: %d", WebRtcIsacfix_GetErrorCode(obj->isac) );
			freeb(plc_blk);
145

146
		} else {
147

148 149
			plc_blk->b_wptr += ret*2;
			obj->seq_nb++;
150

151 152 153
			// insert this interpolated block into the output, with correct args:
			mblk_set_cseq(plc_blk, obj->seq_nb );
			mblk_set_plc_flag(plc_blk, 1); // this one's a PLC packet
154

155
			ms_queue_put(f->outputs[0], plc_blk);
156

157
			ms_concealer_inc_sample_time(obj->plc_ctx, f->ticker->time, obj->ptime, FALSE);
158

159 160
		}
	}
161 162 163
}

static void filter_postprocess(MSFilter *f){
164 165 166
	isac_decoder_t* obj = (isac_decoder_t*)f->data;
	ms_concealer_context_destroy(obj->plc_ctx);
	obj->plc_ctx = NULL;
167 168
}

169
static void filter_uninit(MSFilter *f){
170 171 172 173
	isac_decoder_t* obj = (isac_decoder_t*)f->data;
	ms_free(obj->isac);
	ms_free(f->data);
	f->data = NULL;
174 175 176 177 178 179
}


/*filter specific method*/

static int filter_set_sample_rate(MSFilter *f, void *arg) {
180 181 182 183 184
	if( *(int*)arg != ISAC_SAMPLE_RATE) {
		ms_error("iSAC doesn't support sampling rate %d, only %d",
				 *(int*)arg, ISAC_SAMPLE_RATE);
	}
	return 0;
185 186 187
}

static int filter_get_sample_rate(MSFilter *f, void *arg) {
188 189
	*(int*)arg = ISAC_SAMPLE_RATE;
	return 0;
190
}
191

192 193
static int filter_have_plc(MSFilter *f, void *arg)
{
194 195
	*(int*)arg = 1;
	return 0;
196
}
197 198

static MSFilterMethod filter_methods[] = {
199 200
	{ MS_FILTER_SET_SAMPLE_RATE, filter_set_sample_rate },
	{ MS_FILTER_GET_SAMPLE_RATE, filter_get_sample_rate },
201 202
	{ MS_DECODER_HAVE_PLC,       filter_have_plc        },
	{ 0,                         NULL                   }
203 204 205 206
};



207 208 209 210 211 212 213 214
#define MS_ISAC_DEC_NAME        "MSiSACDec"
#define MS_ISAC_DEC_DESCRIPTION "iSAC audio decoder filter."
#define MS_ISAC_DEC_CATEGORY    MS_FILTER_DECODER
#define MS_ISAC_DEC_ENC_FMT     "iSAC"
#define MS_ISAC_DEC_NINPUTS     1
#define MS_ISAC_DEC_NOUTPUTS    1
#define MS_ISAC_DEC_FLAGS       MS_FILTER_IS_PUMP

215 216
#ifdef _MSC_VER

217 218 219 220 221 222 223 224
MSFilterDesc ms_isac_dec_desc = {
	MS_FILTER_PLUGIN_ID,
	MS_ISAC_DEC_NAME,
	MS_ISAC_DEC_DESCRIPTION,
	MS_ISAC_DEC_CATEGORY,
	MS_ISAC_DEC_ENC_FMT,
	MS_ISAC_DEC_NINPUTS,
	MS_ISAC_DEC_NOUTPUTS,
225 226 227 228 229 230
	filter_init,
	filter_preprocess,
	filter_process,
	filter_postprocess,
	filter_uninit,
	filter_methods,
231
	MS_ISAC_DEC_FLAGS
232 233 234 235
};

#else

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
MSFilterDesc ms_isac_dec_desc = {
	.id = MS_FILTER_PLUGIN_ID,
	.name = MS_ISAC_DEC_NAME,
	.text = MS_ISAC_DEC_DESCRIPTION,
	.category = MS_ISAC_DEC_CATEGORY,
	.enc_fmt = MS_ISAC_DEC_ENC_FMT,
	.ninputs = MS_ISAC_DEC_NINPUTS,
	.noutputs = MS_ISAC_DEC_NOUTPUTS,
	.init = filter_init,
	.preprocess = filter_preprocess,
	.process = filter_process,
	.postprocess = filter_postprocess,
	.uninit = filter_uninit,
	.methods = filter_methods,
	.flags = MS_ISAC_DEC_FLAGS
251 252 253 254 255
};

#endif

MS_FILTER_DESC_EXPORT(ms_isac_dec_desc)