Skip to content
Snippets Groups Projects
ooh323cDriver.c 24.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * Copyright (C) 2004-2005 by Objective Systems, Inc.
     *
     * This software is furnished under an open source license and may be 
     * used and copied only in accordance with the terms of this license. 
     * The text of the license may generally be found in the root 
     * directory of this installation in the COPYING file.  It 
     * can also be viewed online at the following URL:
     *
     *   http://www.obj-sys.com/open/license.html
     *
     * Any redistributions of this file including modified versions must 
     * maintain this copyright notice.
     *
     *****************************************************************************/
    
    #include "ooh323cDriver.h"
    
    
    #include "asterisk.h"
    #include "asterisk/lock.h"
    
    #include "asterisk/pbx.h"
    #include "asterisk/logger.h"
    
    #undef AST_BACKGROUND_STACKSIZE
    #define AST_BACKGROUND_STACKSIZE 768 * 1024
    
    #define SEC_TO_HOLD_THREAD 24
    
    extern struct ast_module *myself;
    
    extern OOH323EndPoint gH323ep;
    
    /* ooh323c stack thread. */
    static pthread_t ooh323c_thread = AST_PTHREADT_NULL;
    
    static pthread_t ooh323cmd_thread = AST_PTHREADT_NULL;
    
    static int grxframes = 240;
    
    static int gtxframes = 20;
    
    
    static struct callthread {
    	ast_mutex_t		lock;
    	int			thePipe[2];
    	OOBOOL			inUse;
    	ooCallData*		call;
    	struct callthread	*next, *prev;
    } *callThreads = NULL;
    
    AST_MUTEX_DEFINE_STATIC(callThreadsLock);
    
    
    
    int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel);
    int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel);
    int ooh323c_stop_receive_channel(ooCallData *call, ooLogicalChannel *pChannel);
    int ooh323c_stop_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel);
    
    
    int ooh323c_start_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
    int ooh323c_start_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
    int ooh323c_stop_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
    int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
    
    void* ooh323c_stack_thread(void* dummy);
    void* ooh323c_cmd_thread(void* dummy);
    void* ooh323c_call_thread(void* dummy);
    int ooh323c_set_aliases(ooAliases * aliases);
    
    
    void* ooh323c_stack_thread(void* dummy)
    {
    
      ooMonitorChannels();
      return dummy;
    }
    
    
    void* ooh323c_cmd_thread(void* dummy)
    {
    
      ooMonitorCmdChannels();
      return dummy;
    }
    
    void* ooh323c_call_thread(void* dummy)
    {
     struct callthread* mycthread = (struct callthread *)dummy;
     struct pollfd pfds[1];
     char c;
    
    Alexandr Anikin's avatar
    Alexandr Anikin committed
     int res = 0;
    
    
     do {
    
     	ooMonitorCallChannels((ooCallData*)mycthread->call);
    	mycthread->call = NULL;
    	mycthread->prev = NULL;
    	mycthread->inUse = FALSE;
    
    	ast_mutex_lock(&callThreadsLock);
    	mycthread->next = callThreads;
    	callThreads = mycthread;
    	if (mycthread->next) mycthread->next->prev = mycthread;
    	ast_mutex_unlock(&callThreadsLock);
    
    	pfds[0].fd = mycthread->thePipe[0];
    	pfds[0].events = POLLIN;
    	ooSocketPoll(pfds, 1, SEC_TO_HOLD_THREAD * 1000);
    	if (ooPDRead(pfds, 1, mycthread->thePipe[0]))
    		res = read(mycthread->thePipe[0], &c, 1);
    
     	ast_mutex_lock(&callThreadsLock);
    	ast_mutex_lock(&mycthread->lock);
     	if (mycthread->prev)
    		mycthread->prev->next = mycthread->next;
     	else
    		callThreads = mycthread->next;
     	if (mycthread->next)
    		mycthread->next->prev = mycthread->prev;
    	ast_mutex_unlock(&mycthread->lock);
     	ast_mutex_unlock(&callThreadsLock);
    
    
     } while (mycthread->call != NULL && res >= 0);
    
    
     
     ast_mutex_destroy(&mycthread->lock);
    
     close(mycthread->thePipe[0]);
     close(mycthread->thePipe[1]);
    
     ast_module_unref(myself);
     ast_update_use_count();
    
    }
    
    int ooh323c_start_call_thread(ooCallData *call) {
     char c = 'c';
     struct callthread *cur = callThreads;
    
     ast_mutex_lock(&callThreadsLock);
     while (cur != NULL && (cur->inUse || ast_mutex_trylock(&cur->lock))) {
    	cur = cur->next;
     }
     ast_mutex_unlock(&callThreadsLock);
    
    
    Alexandr Anikin's avatar
    Alexandr Anikin committed
     if (cur != NULL) {
       if (cur->inUse || write(cur->thePipe[1], &c, 1) < 0) {
    
    	ast_mutex_unlock(&cur->lock);
    	cur = NULL;
    
     }
    
    /* make new thread */
     if (cur == NULL) {
    
    	if (!(cur = ast_calloc(1, sizeof(struct callthread)))) {
    
    		ast_log(LOG_ERROR, "Unable to allocate thread structure for call %s\n",
    							call->callToken);
    		return -1;
    	}
    
    	ast_module_ref(myself);
    	if ((socketpair(PF_LOCAL, SOCK_STREAM, 0, cur->thePipe)) == -1) {
    		ast_log(LOG_ERROR, "Can't create thread pipe for call %s\n", call->callToken);
    
    		return -1;
    	}
    	cur->inUse = TRUE;
    	cur->call = call;
    
    	ast_mutex_init(&cur->lock);
    
    	if (gH323Debug)
    		ast_debug(1,"new call thread created for call %s\n", call->callToken);
    
    	if(ast_pthread_create_detached_background(&call->callThread, NULL, ooh323c_call_thread, cur) < 0)
     	{
      		ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n",
    					call->callToken);
    		ast_mutex_destroy(&cur->lock);
    		close(cur->thePipe[0]);
    		close(cur->thePipe[1]);
    
      		return -1;
     	}
    
     } else {
    	if (gH323Debug)
    		ast_debug(1,"using existing call thread for call %s\n", call->callToken);
    	cur->inUse = TRUE;
    	cur->call = call;
    	ast_mutex_unlock(&cur->lock);
    
     }
     return 0;
    }
    
    
    int ooh323c_stop_call_thread(ooCallData *call) {
     if (call->callThread != AST_PTHREADT_NULL) {
      ooStopMonitorCallChannels(call);
     }
     return 0;
    }
    
    
    int ooh323c_start_stack_thread()
    {
    
       if(ast_pthread_create_background(&ooh323c_thread, NULL, ooh323c_stack_thread, NULL) < 0)
    
       {
          ast_log(LOG_ERROR, "Unable to start ooh323c thread.\n");
          return -1;
       }
    
       if(ast_pthread_create_background(&ooh323cmd_thread, NULL, ooh323c_cmd_thread, NULL) < 0)
       {
          ast_log(LOG_ERROR, "Unable to start ooh323cmd thread.\n");
          return -1;
       }
    
       return 0;
    }
    
    int ooh323c_stop_stack_thread(void)
    {
       if(ooh323c_thread !=  AST_PTHREADT_NULL)
       {
          ooStopMonitor();
          pthread_join(ooh323c_thread, NULL);
          ooh323c_thread =  AST_PTHREADT_NULL;
    
          pthread_join(ooh323cmd_thread, NULL);
          ooh323cmd_thread =  AST_PTHREADT_NULL;
    
       (struct ast_format_cap *cap, int dtmf, int dtmfcodec)
    
       if (gH323Debug) {
         ast_verb(0, "\tAdding capabilities to H323 endpoint\n");
       }
    
    
       for(x=0; x<ast_format_cap_count(cap); x++)
    
        struct ast_format *format = ast_format_cap_get_format(cap, x);
          if(ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g711 ulaw capability to H323 endpoint\n");
    	 }
    
             ret= ooH323EpAddG711Capability(OO_G711ULAW64K, gtxframes, grxframes, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
          }
    
          if(ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g711 alaw capability to H323 endpoint\n");
    	 }
    
             ret= ooH323EpAddG711Capability(OO_G711ALAW64K, gtxframes, grxframes, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
          }
    
    
          if(ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
    	    ast_verb(0, "\tAdding g729A capability to H323 endpoint\n");
    	 }
    
             ret = ooH323EpAddG729Capability(OO_G729A, 2, 24, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g729 capability to H323 endpoint\n");
    	 }
    
             ret |= ooH323EpAddG729Capability(OO_G729, 2, 24, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g729b capability to H323 endpoint\n");
    	 }
    
             ret |= ooH323EpAddG729Capability(OO_G729B, 2, 24, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          if(ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g7231 capability to H323 endpoint\n");
    	 }
    
             ret = ooH323EpAddG7231Capability(OO_G7231, 1, 1, FALSE, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g726 capability to H323 endpoint\n");
    	 }
    
             ret = ooH323EpAddG726Capability(OO_G726, gtxframes, grxframes, FALSE, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g726aal2 capability to H323 endpoint\n");
    	 }
    
             ret = ooH323EpAddG726Capability(OO_G726AAL2, gtxframes, grxframes, FALSE, 
    
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding h263 capability to H323 endpoint\n");
    	 }
    
             ret = ooH323EpAddH263VideoCapability(OO_H263VIDEO, 1, 0, 0, 0, 0, 320*1024, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding gsm capability to H323 endpoint\n");
    	 }
    
             ret = ooH323EpAddGSMCapability(OO_GSMFULLRATE, 4, FALSE, FALSE, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
          if(ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding speex capability to H323 endpoint\n");
    	 }
    
             ret = ooH323EpAddSpeexCapability(OO_SPEEX, 4, 4, FALSE, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
       if(dtmf & H323_DTMF_CISCO)
          ret |= ooH323EpEnableDTMFCISCO(0);
    
       if(dtmf & H323_DTMF_RFC2833)
          ret |= ooH323EpEnableDTMFRFC2833(0);
       else if(dtmf & H323_DTMF_H245ALPHANUMERIC)
          ret |= ooH323EpEnableDTMFH245Alphanumeric();
       else if(dtmf & H323_DTMF_H245SIGNAL)
          ret |= ooH323EpEnableDTMFH245Signal();
    
       return ret;
    }
    
    int ooh323c_set_capability_for_call
    
       (ooCallData *call, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
    
    		 int t38support, int g729onlyA)
    
       int ret = 0, x, txframes;
    
       if (gH323Debug) {
         ast_verb(0, "\tAdding capabilities to call(%s, %s)\n", call->callType, 
    
       if(dtmf & H323_DTMF_CISCO || 1)
          ret |= ooCallEnableDTMFCISCO(call,dtmfcodec);
       if(dtmf & H323_DTMF_RFC2833 || 1)
          ret |= ooCallEnableDTMFRFC2833(call,dtmfcodec);
       if(dtmf & H323_DTMF_H245ALPHANUMERIC || 1)
    
          ret |= ooCallEnableDTMFH245Alphanumeric(call);
    
       if(dtmf & H323_DTMF_H245SIGNAL || 1)
    
          ret |= ooCallEnableDTMFH245Signal(call);
    
    
       if (t38support)
       	ooCapabilityAddT38Capability(call, OO_T38, OORXANDTX, 
    					&ooh323c_start_receive_datachannel,
    					&ooh323c_start_transmit_datachannel,
    					&ooh323c_stop_receive_datachannel,
    					&ooh323c_stop_transmit_datachannel,
    					0);
    
       for(x=0; x<ast_format_cap_count(cap); x++)
    
        struct ast_format *format = ast_format_cap_get_format(cap, x);
          if(ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g711 ulaw capability to call(%s, %s)\n", 
    
                                                  call->callType, call->callToken);
    
    	 txframes = ast_format_cap_get_format_framing(cap, format);
    
             ret= ooCallAddG711Capability(call, OO_G711ULAW64K, txframes, 
    
                                          txframes, OORXANDTX, 
    
                                          &ooh323c_start_receive_channel,
                                          &ooh323c_start_transmit_channel,
                                          &ooh323c_stop_receive_channel, 
                                          &ooh323c_stop_transmit_channel);
          }
    
          if(ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g711 alaw capability to call(%s, %s)\n",
    
                                                call->callType, call->callToken);
    
             txframes = ast_format_cap_get_format_framing(cap, format);
    
             ret= ooCallAddG711Capability(call, OO_G711ALAW64K, txframes, 
    
                                         txframes, OORXANDTX, 
    
                                         &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
          }
    
    
          if(ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g726 capability to call (%s, %s)\n",
    
                                               call->callType, call->callToken);
    
    	 txframes = ast_format_cap_get_format_framing(cap, format);
    
             ret = ooCallAddG726Capability(call, OO_G726, txframes, grxframes, FALSE,
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g726aal2 capability to call (%s, %s)\n",
    
                                               call->callType, call->callToken);
    
    	 txframes = ast_format_cap_get_format_framing(cap, format);
    
             ret = ooCallAddG726Capability(call, OO_G726AAL2, txframes, grxframes, FALSE,
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL)
    
             txframes = (ast_format_cap_get_format_framing(cap, format))/10;
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g729A capability to call(%s, %s)\n",
    
                                                call->callType, call->callToken);
    
             ret= ooCallAddG729Capability(call, OO_G729A, txframes, txframes, 
    
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
    	 if (g729onlyA)
    		continue;
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g729 capability to call(%s, %s)\n",
    
                                                call->callType, call->callToken);
    
             ret|= ooCallAddG729Capability(call, OO_G729, txframes, txframes, 
    
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g729B capability to call(%s, %s)\n",
    
                                                call->callType, call->callToken);
    
             ret|= ooCallAddG729Capability(call, OO_G729B, txframes, txframes, 
    
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          if(ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding g7231 capability to call (%s, %s)\n",
    
                                               call->callType, call->callToken);
    
             ret = ooCallAddG7231Capability(call, OO_G7231, 1, 1, FALSE, 
    
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding h263 capability to call (%s, %s)\n",
    
                                               call->callType, call->callToken);
    
             ret = ooCallAddH263VideoCapability(call, OO_H263VIDEO, 1, 0, 0, 0, 0, 320*1024, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
    
          }
    
    
          if(ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding gsm capability to call(%s, %s)\n", 
    
                                                 call->callType, call->callToken);
    
             ret = ooCallAddGSMCapability(call, OO_GSMFULLRATE, 4, FALSE, FALSE, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
          }
    
          if(ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL)
    
             if (gH323Debug) {
                ast_verb(0, "\tAdding Speex capability to call(%s, %s)\n", 
    
                                                 call->callType, call->callToken);
    
             ret = ooCallAddSpeexCapability(call, OO_SPEEX, 4, 4, FALSE, 
                                         OORXANDTX, &ooh323c_start_receive_channel,
                                         &ooh323c_start_transmit_channel,
                                         &ooh323c_stop_receive_channel, 
                                         &ooh323c_stop_transmit_channel);
          }
    
    }
    
    int ooh323c_set_aliases(ooAliases * aliases)
    {
       ooAliases *cur = aliases;
       while(cur)
       {
          switch(cur->type)
          { 
          case T_H225AliasAddress_dialedDigits:
             ooH323EpAddAliasDialedDigits(cur->value);
             break;
          case T_H225AliasAddress_h323_ID:
             ooH323EpAddAliasH323ID(cur->value);
             break;
          case T_H225AliasAddress_url_ID:
             ooH323EpAddAliasURLID(cur->value);
             break;
          case T_H225AliasAddress_email_ID:
             ooH323EpAddAliasEmailID(cur->value);
             break;
          default:
             ast_debug(1, "Ignoring unknown alias type\n");
          }
          cur = cur->next;
       }
       return 1;
    }
       
    int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel)
    {
    
       struct ast_format *tmpfmt = NULL;
       tmpfmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
       if(tmpfmt) {
    
          /* ooh323_set_read_format(call, fmt); */
       }else{
    
         ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
                                                              call->callToken);
         return -1;
       }
       return 1;
    }
    
    int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel)
    {
    
       struct ast_format *tmpfmt = NULL;
       tmpfmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
    
       if (tmpfmt) {
        if ((ast_format_cmp(tmpfmt, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ||
          (ast_format_cmp(tmpfmt, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)) {
      	ooh323_set_write_format(call, tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes);
        } else if (ast_format_cmp(tmpfmt, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
    	 ooh323_set_write_format(call, tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10);
      } else {
    	ooh323_set_write_format(call, tmpfmt, 0);
    
          ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
                                                              call->callToken);
          return -1;
       }
       setup_rtp_connection(call, pChannel->remoteIP, pChannel->remoteMediaPort);
        return 1;
    }
    
    int ooh323c_stop_receive_channel(ooCallData *call, ooLogicalChannel *pChannel)
    {
       return 1;
    }
    
    int ooh323c_stop_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel)
    {
       close_rtp_connection(call);
       return 1;
    }
    
    
    
    int ooh323c_start_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
    {
       return 1;
    }
    
    int ooh323c_start_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
    {
       setup_udptl_connection(call, pChannel->remoteIP, pChannel->remoteMediaPort);
       return 1;
    }
    
    int ooh323c_stop_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
    {
       return 1;
    }
    
    int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
    {
       close_udptl_connection(call);
       return 1;
    }
    
    
    struct ast_format *convertH323CapToAsteriskCap(int cap)
    
          case OO_SPEEX:
    
          case OO_G729B:
    
          case OO_G726:
    
          case OO_G726AAL2:
    
          default:
             ast_debug(1, "Cap %d is not supported by driver yet\n", cap);