Commit d632f7d0 authored by jehan's avatar jehan

first SILK integration

parent 17170823
/*
filter-template.m
Copyright (C) 2011 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 "msfilter.h"
#include "SKP_Silk_SDK_API.h"
/*filter common method*/
struct silk_dec_struct {
SKP_SILK_SDK_DecControlStruct control;
void *psDec;
};
static void filter_init(MSFilter *f){
f->data = ms_new0(struct silk_dec_struct,1);
}
static void filter_preprocess(MSFilter *f){
struct silk_dec_struct* obj= (struct silk_dec_struct*) f->data;
SKP_int16 ret;
SKP_int32 decSizeBytes;
/* Initialize to one frame per packet, for proper concealment before first packet arrives */
obj->control.framesPerPacket = 1;
/* Create decoder */
ret = SKP_Silk_SDK_Get_Decoder_Size(&decSizeBytes );
if( ret ) {
ms_error("SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
}
obj->psDec = ms_malloc(decSizeBytes);
/* Reset decoder */
ret = SKP_Silk_SDK_InitDecoder(obj->psDec);
if(ret) {
ms_error( "SKP_Silk_InitDecoder returned %d", ret );
}
}
static void filter_process(MSFilter *f){
struct silk_dec_struct* obj= (struct silk_dec_struct*) f->data;
mblk_t *im;
mblk_t *om;
SKP_int16 len;
SKP_int16 ret;
while((im=ms_queue_get(f->inputs[0]))) {
do {
/* Decode 20 ms */
om=allocb(obj->control.API_sampleRate*4/100,0); /*samplingrate*0.02*2*/
ret = SKP_Silk_SDK_Decode( obj->psDec, &obj->control, 0, im->b_rptr, im->b_wptr - im->b_rptr, (SKP_int16*)om->b_wptr, &len );
if( ret ) {
ms_error( "SKP_Silk_SDK_Decode returned %d", ret );
ms_free(om);
} else {
om->b_wptr+=len*2;
ms_queue_put(f->outputs[0],om);
}
/* Until last 20 ms frame of packet has been decoded */
} while(obj->control.moreInternalDecoderFrames);
}
}
static void filter_postprocess(MSFilter *f){
struct silk_dec_struct* obj= (struct silk_dec_struct*) f->data;
ms_free(obj->psDec);
}
static void filter_unit(MSFilter *f){
ms_free(f->data);
}
/*filter specific method*/
static int filter_set_sample_rate(MSFilter *f, void *arg) {
struct silk_dec_struct* obj= (struct silk_dec_struct*) f->data;
switch (*(SKP_int32*)arg) {
case 8000:
case 12000:
case 16000:
case 24000:
case 32000:
case 44000:
case 48000:
obj->control.API_sampleRate=*(SKP_int32*)arg;
break;
default:
ms_warning("unsupported output sampling rate [%i] for silk, using 44 000",*(SKP_int32*)arg);
obj->control.API_sampleRate=44000;
}
return 0;
}
static int filter_get_sample_rate(MSFilter *f, void *arg) {
struct silk_dec_struct* obj= (struct silk_dec_struct*) f->data;
*(int*)arg = obj->control.API_sampleRate;
return 0;
}
static MSFilterMethod filter_methods[]={
{ MS_FILTER_SET_SAMPLE_RATE , filter_set_sample_rate },
{ MS_FILTER_GET_SAMPLE_RATE , filter_get_sample_rate },
{ 0, NULL}
};
MSFilterDesc ms_silk_dec_desc={
.id=MS_FILTER_PLUGIN_ID, /* from Allfilters.h*/
.name="MSSILKDec",
.text="Silk decoder filter.",
.category=MS_FILTER_DECODER,
.enc_fmt="SILK",
.ninputs=1, /*number of inputs*/
.noutputs=1, /*number of outputs*/
.init=filter_init,
.preprocess=filter_preprocess,
.process=filter_process,
.postprocess=filter_postprocess,
.uninit=filter_unit,
.methods=filter_methods
};
MS_FILTER_DESC_EXPORT(ms_silk_dec_desc)
\ No newline at end of file
/*
silk_enc.c
Copyright (C) 2011 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 "msfilter.h"
#include "SKP_Silk_SDK_API.h"
/* Define codec specific settings */
#define MAX_BYTES_PER_FRAME 250 // Equals peak bitrate of 100 kbps
#define MAX_INPUT_FRAMES 5
/*filter common method*/
struct silk_enc_struct {
SKP_SILK_SDK_EncControlStruct control;
void* psEnc;
uint32_t ts;
MSBufferizer *bufferizer;
unsigned char ptime;
};
static void filter_init(MSFilter *f){
struct silk_enc_struct* obj;
f->data = ms_new0(struct silk_enc_struct,1);
obj = (struct silk_enc_struct*) f->data;
SKP_int16 ret;
SKP_int32 encSizeBytes;
/* Create encoder */
ret = SKP_Silk_SDK_Get_Encoder_Size(&encSizeBytes );
if( ret ) {
ms_error("SKP_Silk_SDK_Get_Encoder_Size returned %i", ret );
}
obj->psEnc = ms_malloc(encSizeBytes);
/* Reset decoder */
ret = SKP_Silk_SDK_InitEncoder(obj->psEnc,&obj->control);
if(ret) {
ms_error( "SKP_Silk_SDK_InitEncoder returned %i", ret );
}
obj->ptime=20;
obj->bufferizer=ms_bufferizer_new();
}
static void filter_preprocess(MSFilter *f){
}
static void filter_process(MSFilter *f){
mblk_t *im;
mblk_t *om=NULL;
SKP_int16 ret;
SKP_int16 nBytes;
uint8_t * buff=NULL;
struct silk_enc_struct* obj= (struct silk_enc_struct*) f->data;
obj->control.packetSize = obj->control.API_sampleRate*obj->ptime/1000; /*in sample*/
while((im=ms_queue_get(f->inputs[0]))!=NULL){
ms_bufferizer_put(obj->bufferizer,im);
}
while(ms_bufferizer_get_avail(obj->bufferizer)>=obj->control.packetSize*2){
/* max payload size */
nBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES;
om = allocb(nBytes,0);
if (!buff) buff=ms_malloc(obj->control.packetSize*2);
ms_bufferizer_read(obj->bufferizer,buff,obj->control.packetSize*2);
ret = SKP_Silk_SDK_Encode(obj->psEnc
, &obj->control
, (const SKP_int16*)buff
, (SKP_int16)(obj->control.packetSize)
, om->b_wptr
, &nBytes );
if(ret) {
ms_error( "SKP_Silk_Encode returned %i", ret );
freeb(om);
} else if (nBytes > 0) {
obj->ts+=obj->control.packetSize;
om->b_wptr+=nBytes;
mblk_set_timestamp_info(om,obj->ts);
ms_queue_put(f->outputs[0],om);
om=NULL;
}
}
if (buff!=NULL) {
ms_free(buff);
}
}
static void filter_postprocess(MSFilter *f){
}
static void filter_unit(MSFilter *f){
struct silk_enc_struct* obj= (struct silk_enc_struct*) f->data;
ms_bufferizer_destroy(obj->bufferizer);
ms_free(obj->psEnc);
ms_free(f->data);
}
/*filter specific method*/
static int filter_set_sample_rate(MSFilter *f, void *arg) {
struct silk_enc_struct* obj= (struct silk_enc_struct*) f->data;
switch (*(SKP_int32*)arg) {
case 8000:
case 12000:
case 16000:
case 24000:
obj->control.maxInternalSampleRate=*(SKP_int32*)arg;
obj->control.API_sampleRate=*(SKP_int32*)arg;
break;
default:
ms_warning("unsupported max sampling rate [%i] for silk, using 16 000",*(SKP_int32*)arg);
obj->control.API_sampleRate=obj->control.maxInternalSampleRate=16000;
}
return 0;
}
static int filter_get_sample_rate(MSFilter *f, void *arg) {
struct silk_enc_struct* obj= (struct silk_enc_struct*) f->data;
*(int*)arg = obj->control.maxInternalSampleRate;
return 0;
}
static int filter_add_fmtp(MSFilter *f, void *arg){
char buf[64];
struct silk_enc_struct* obj= (struct silk_enc_struct*) f->data;
const char *fmtp=(const char *)arg;
buf[0] ='\0';
if (fmtp_get_value(fmtp,"ptime",buf,sizeof(buf))){
obj->ptime=atoi(buf);
if (obj->ptime >100) {
obj->ptime=100;
} else if (obj->ptime%20) {
//if the ptime is not a mulptiple of 20, go to the next multiple
obj->ptime = obj->ptime - obj->ptime%20 + 20;
}
ms_message("MSSilkEnc: got ptime=%i",obj->ptime);
}
return 0;
}
static int filter_set_bitrate(MSFilter *f, void *arg){
struct silk_enc_struct* obj= (struct silk_enc_struct*) f->data;
obj->control.bitRate=*(int*)arg;
return 0;
}
static int filter_get_bitrate(MSFilter *f, void *arg){
struct silk_enc_struct* obj= (struct silk_enc_struct*) f->data;
*(int*)arg=obj->control.bitRate;
return 0;
}
static MSFilterMethod filter_methods[]={
{ MS_FILTER_SET_SAMPLE_RATE , filter_set_sample_rate },
{ MS_FILTER_GET_SAMPLE_RATE , filter_get_sample_rate },
{ MS_FILTER_SET_BITRATE , filter_set_bitrate },
{ MS_FILTER_GET_BITRATE , filter_get_bitrate },
{ MS_FILTER_ADD_FMTP , filter_add_fmtp },
{ 0, NULL}
};
MSFilterDesc ms_silk_enc_desc={
.id=MS_FILTER_PLUGIN_ID, /* from Allfilters.h*/
.name="MSSILKEnc",
.text="SILK audio encoder filter.",
.category=MS_FILTER_ENCODER,
.enc_fmt="SILK",
.ninputs=1, /*number of inputs*/
.noutputs=1, /*number of outputs*/
.init=filter_init,
.preprocess=filter_preprocess,
.process=filter_process,
.postprocess=filter_postprocess,
.uninit=filter_unit,
.methods=filter_methods
};
MS_FILTER_DESC_EXPORT(ms_silk_enc_desc)
extern MSFilterDesc ms_silk_dec_desc;
#ifndef VERSION
#define VERSION "debug"
#endif
void libmssilk_init(){
ms_filter_register(&ms_silk_enc_desc);
ms_filter_register(&ms_silk_dec_desc);
ms_message(" libmssilk " VERSION " plugin loaded");
}
......@@ -45,12 +45,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef __APPLE__
#include <CoreFoundation/CFRunLoop.h>
#endif
#ifdef TARGET_OS_IPHONE
#if TARGET_OS_IPHONE==1 || defined (ANDROID)
#import <UIKit/UIKit.h>
extern void ms_set_video_stream(VideoStream* video);
#ifdef HAVE_X264
extern void libmsx264_init();
#endif
#ifdef HAVE_SILK
extern void libmssilk_init();
#endif
#endif
#ifdef ANDROID
......@@ -410,16 +413,23 @@ void setup_media_streams(MediastreamDatas* args) {
ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
}
#if TARGET_OS_IPHONE==1 || defined (ANDROID)
#if defined (HAVE_X264) && defined (VIDEO_ENABLED)
libmsx264_init(); /*no plugin on IOS*/
#endif
#if defined (HAVE_SILK)
libmssilk_init(); /*no plugin on IOS*/
#endif
#endif
rtp_profile_set_payload(&av_profile,110,&payload_type_speex_nb);
rtp_profile_set_payload(&av_profile,111,&payload_type_speex_wb);
rtp_profile_set_payload(&av_profile,112,&payload_type_ilbc);
rtp_profile_set_payload(&av_profile,113,&payload_type_amr);
rtp_profile_set_payload(&av_profile,114,args->custom_pt);
rtp_profile_set_payload(&av_profile,115,&payload_type_lpc1015);
#ifdef VIDEO_ENABLED
#if defined (TARGET_OS_IPHONE) && defined (HAVE_X264)
libmsx264_init(); /*no plugin on IOS*/
#endif
rtp_profile_set_payload(&av_profile,26,&payload_type_jpeg);
rtp_profile_set_payload(&av_profile,98,&payload_type_h263_1998);
rtp_profile_set_payload(&av_profile,97,&payload_type_theora);
......@@ -427,7 +437,6 @@ void setup_media_streams(MediastreamDatas* args) {
rtp_profile_set_payload(&av_profile,100,&payload_type_x_snow);
rtp_profile_set_payload(&av_profile,102,&payload_type_h264);
rtp_profile_set_payload(&av_profile,103,&payload_type_vp8);
#endif
#ifdef VIDEO_ENABLED
args->video=NULL;
......
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