⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amrcodec.c

📁 开源的openh323的v1.18.0版,有1.19.0版无法编译过的朋友可以用这版
💻 C
字号:
/*
 * AMR Plugin codec for OpenH323/OPAL
 *
 * Copyright (C) 2004 MX Telecom Ltd.
 *
 * $Id: amrcodec.c,v 1.3 2005/06/08 15:36:00 shorne Exp $
 */


/*Disable some warnings on VC++*/
#ifdef _MSC_VER
#pragma warning(disable : 4018)
#pragma warning(disable : 4100)
#endif

#include "opalplugin.h"
#include "src/interf_enc.h"
#include "src/interf_dec.h"

PLUGIN_CODEC_IMPLEMENT("AMR")
#include <stdio.h>
#include <malloc.h>

/***************************************************************************
 *
 * This plugin implements an interface to the AMR-NB codec for OpenH323.
 *
 * The amr codec itself is not distributed with this plugin. See amrcodec.txt
 * in the src subdirectory of the plugin source.
 *
 **************************************************************************/
    
/* generic parameters; see H.245 Annex I */
enum
{
    GENERIC_PARAMETER_AMR_MAXAL_SDUFRAMES = 0,
    GENERIC_PARAMETER_AMR_BITRATE,
    GENERIC_PARAMETER_AMR_GSMAMRCOMFORTNOISE,
    GENERIC_PARAMETER_AMR_GSMEFRCOMFORTNOISE,
    GENERIC_PARAMETER_AMR_IS_641COMFORTNOISE,
    GENERIC_PARAMETER_AMR_PDCEFRCOMFORTNOISE
};

/* values of the bit rate parameter */
enum
{
    AMR_BITRATE_475 = 0,
    AMR_BITRATE_515,
    AMR_BITRATE_590,
    AMR_BITRATE_670,
    AMR_BITRATE_740,
    AMR_BITRATE_795,
    AMR_BITRATE_1020,
    AMR_BITRATE_1220
};
    

/* expected number of bytes, for a given mode */
static short bytes_per_frame[16]={ 13, 14, 16, 18, 19, 21, 26, 31, 6, 0, 0, 0, 0, 0, 0, 0 };

#define AMR_Mode  7

// this is what we hand back when we are asked to create an encoder
typedef struct
{
    void *encoder_state;  // Encoder interface's opaque state
    int mode;             // current mode
} AmrEncoderContext;

/////////////////////////////////////////////////////////////////////////////

static void * amr_create_encoder(const struct PluginCodec_Definition * codec)
{
    AmrEncoderContext *ctx = malloc(sizeof(AmrEncoderContext));
    if(ctx == NULL ) {
        fprintf(stderr,"AMR codec: unable to allocate context");
        return NULL;
    }

    ctx->encoder_state = Encoder_Interface_init(0);
    if(ctx->encoder_state == NULL ) {
        // Encoder_Interface_init writes an error msg in this case; no need to
        // repeat
        free(ctx);
        return NULL;
    }

    ctx->mode = (int)codec->userData; // start off in mode 7
    return ctx;
}

static void * amr_create_decoder(const struct PluginCodec_Definition * codec)
{
    return Decoder_Interface_init();
}

static void amr_destroy_encoder(const struct PluginCodec_Definition * codec, void * context)
{
    AmrEncoderContext *ctx = (AmrEncoderContext *)context;
    Encoder_Interface_exit(ctx->encoder_state);
    free(ctx);
}

static void amr_destroy_decoder(const struct PluginCodec_Definition * codec, void * context)
{
    Decoder_Interface_exit(context);
}

static int amr_codec_encoder(const struct PluginCodec_Definition * codec, 
                                           void * context,
                                     const void * from, 
                                       unsigned * fromLen,
                                           void * to,         
                                       unsigned * toLen,
                                   unsigned int * flag)
{
    AmrEncoderContext *ctx = (AmrEncoderContext *)context;
    unsigned int mode = ctx->mode;

    if( *fromLen != 160*sizeof(short)) {
	fprintf(stderr,"AMR codec: audio frame of size %u doesn't match expected %u\n",
		*fromLen,160*sizeof(short));
	return 0;
    }

    if(*toLen < bytes_per_frame[mode]) {
	fprintf(stderr,"AMR codec: output buffer of size %u too short for mode %u\n", *toLen, mode );
	return 0;
    }

  /*   fprintf(stderr,"AMR codec: encoding to mode %u size %u\n", mode, *toLen); */

    *toLen = Encoder_Interface_Encode(ctx->encoder_state,mode,(void *)from,to,0);
    return 1; 
}

#if 0
static void hexprint(const void *ptr, unsigned len)
{
    int i;
    const char *p = (const char *)ptr;
    
    for(i=0; i<len; i++) {
        fprintf(stderr,"%02x",p[i]);
    }
}
#endif

static int amr_codec_decoder(const struct PluginCodec_Definition * codec, 
                                           void * context,
                                     const void * from, 
                                       unsigned * fromLen,
                                           void * to,         
                                       unsigned * toLen,
                                   unsigned int * flag)
{
//  unsigned int mode;
    
    if( *fromLen < 1 )
	return 0;

/*   // get the AMR mode from the first nibble of the frame
    mode = *(char *)from & 0xF;

    // check that the input is long enough for the decoder
    if( *fromLen != bytes_per_frame[mode] ) {
	fprintf(stderr,"AMR codec: packet size %u doesn't match expected %u for mode %u\n", *fromLen,bytes_per_frame[mode], mode );
	return 0;
    }
*/  
    Decoder_Interface_Decode( context, (void *)from, (short *)to, 0 );
#if 0
    fprintf(stderr,"Decoded AMR frame [");
    hexprint(from,*fromLen);
    fprintf(stderr,"]\nResult: [");
    hexprint(to,40);
    fprintf(stderr,"...]\n");
#endif

    // return the number of decoded bytes to the caller
    *toLen = 160*sizeof(short);

    return 1;
}

static int amr_set_quality(const struct PluginCodec_Definition * codec, void * context, 
                           const char * name, void * parm, unsigned * parmLen)
{
    AmrEncoderContext *ctx = (AmrEncoderContext *)context;
    int q;

    if(*parmLen != sizeof(q))
        return -1;
    q = *(int *)parm;

    if( q < 1 || q > 31)
        return -1;
    /* 1-3   -> mode 7
       4-7   -> mode 6
       ...
       28-31 -> mode 0
    */
    ctx->mode = 7-(q/4);
    return 0;
}

static int amr_get_quality(const struct PluginCodec_Definition * codec, void * context, 
                           const char * name, void * parm, unsigned * parmLen)
{
    AmrEncoderContext *ctx = (AmrEncoderContext *)context;

    if(*parmLen != sizeof(int))
        return -1;

    *(int *)parm = (7-ctx->mode)*4;
    return 0;
}


/////////////////////////////////////////////////////////////////////////////


static struct PluginCodec_information licenseInfo = {
    // Tue 13 Jul 2004 00:11:32 UTC =
    1089677492,

    "Richard van der Hoff, MX Telecom Ltd.",                     // source code author
    "$Ver$",                                                     // source code version
    "richardv@mxtelecom.com",                                    // source code email
    "http://www.mxtelecom.com",                                  // source code URL
    "Copyright (C) 2004 MX Telecom Ltd.", 		         // source code copyright
    "None",                                                      // source code license  // FIXME
    PluginCodec_License_None,                                    // source code license
    
    "GSM-AMR (Adaptive Multirate Codec)",                        // codec description
    "3rd Generation Partnership Project",                        // codec author
    NULL,                                                        // codec version
    NULL,	                                                 // codec email
    "http://www.3gpp.org",	                                 // codec URL
    "",          						 // codec copyright information
    "", 							 // codec license
    PluginCodec_License_RoyaltiesRequired                        // codec license code
};


static const struct PluginCodec_H323GenericParameterDefinition amr_params[] =
{
    {1,
     GENERIC_PARAMETER_AMR_MAXAL_SDUFRAMES,
     PluginCodec_GenericParameter_ShortMin,
     {1}}
};
     
static const struct PluginCodec_H323GenericCodecData amrcap =
{
    "0.0.8.245.1.1.1",						// capability identifier (Ref: Table I.1 in H.245)
    122,
    1,
    amr_params
};

static struct PluginCodec_ControlDefn amrEncoderControlDefn[] = {
    {"set_quality", amr_set_quality},
    {"get_quality", amr_get_quality},
    {NULL, NULL}
};



static const struct PluginCodec_Definition amrCodecDefn[] = {
    { 
	// encoder
	PLUGIN_CODEC_VERSION,               	// codec API version
	&licenseInfo,                       	// license information

	PluginCodec_MediaTypeAudio |        	// audio codec
	PluginCodec_InputTypeRaw |          	// raw input data
	PluginCodec_OutputTypeRaw |         	// raw output data
	PluginCodec_RTPTypeDynamic,         	// dynamic RTP type
	
	"GSM-AMR",	                        // text decription
	"L16",                              	// source format
	"GSM-AMR",                             	// destination format
	
	(void *)AMR_Mode,                       // user data

	8000,                               	// samples per second
	0,		                        // raw bits per second
	20000,                              	// nanoseconds per frame
	160,                      		// samples per frame
	32,                  			// bytes per frame; 32 because
						// the sample coder stomps on
						// an extra byte
	
	1,                                  	// recommended number of frames per packet
	1,                                  	// maximum number of frames per packet
	0,                                  	// IANA RTP payload code
	"AMR",                                  // RTP payload name
	
	amr_create_encoder,                    	// create codec function
	amr_destroy_encoder,                   	// destroy codec
	amr_codec_encoder,                     	// encode/decode
	amrEncoderControlDefn,                 	// codec controls
        
	PluginCodec_H323Codec_generic,  	// h323CapabilityType
	(struct PluginCodec_H323GenericCodecData *)&amrcap
						// h323CapabilityData
    },

    { 
	// decoder
	PLUGIN_CODEC_VERSION,               	// codec API version
	&licenseInfo,                       	// license information

	PluginCodec_MediaTypeAudio |        	// audio codec
	PluginCodec_InputTypeRaw |          	// raw input data
	PluginCodec_OutputTypeRaw |         	// raw output data
	PluginCodec_RTPTypeDynamic,         	// dynamic RTP type

	"GSM-AMR",                           	// text decription
	"GSM-AMR",                           	// source format
	"L16",                            	// destination format

	(void *)AMR_Mode,                       // user data

	8000,                               	// samples per second
	0,		                        // raw bits per second
	30000,                              	// nanoseconds per frame
	160,                      		// samples per frame
	31,                  			// bytes per frame
	1,                                  	// recommended number of frames per packet
	1,                                  	// maximum number of frames per packet
	0,                                  	// IANA RTP payload code
	"AMR",                                  // RTP payload name

	amr_create_decoder,                    	// create codec function
	amr_destroy_decoder,                   	// destroy codec
	amr_codec_decoder,                     	// encode/decode
	NULL,                                	// codec controls
	
	PluginCodec_H323Codec_generic,  	// h323CapabilityType 
	(struct PluginCodec_H323GenericCodecData *)&amrcap
						// h323CapabilityData
    }
};

#define NUM_DEFNS   (sizeof(amrCodecDefn) / sizeof(struct PluginCodec_Definition))

/////////////////////////////////////////////////////////////////////////////

PLUGIN_CODEC_DLL_API const struct PluginCodec_Definition * PLUGIN_CODEC_GET_CODEC_FN(unsigned * count, unsigned version)
{
  *count = NUM_DEFNS;
  return amrCodecDefn;
}


#ifdef _MSC_VER
#pragma warning(default : 4018)
#pragma warning(default : 4100)
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -