예제 #1
0
uint64_t iax2_format_compatibility_cap2bitfield(const struct ast_format_cap *cap)
{
	uint64_t bitfield = 0;
	int x;

	for (x = 0; x < ast_format_cap_count(cap); x++) {
		struct ast_format *format = ast_format_cap_get_format(cap, x);

		bitfield |= ast_format_compatibility_format2bitfield(format);

		ao2_ref(format, -1);
	}

	return bitfield;
}
예제 #2
0
/*! \brief Add format/lang pairs to the array embedded in the sound object */
static int add_format_information_cb(void *obj, void *arg, int flags)
{
	char *language = obj;
	struct lang_format_info *args = arg;
	int idx;
	RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
	RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);

	if (!sounds_index) {
		return CMP_STOP;
	}

	cap = ast_media_get_format_cap(sounds_index, args->filename, language);
	if (!cap) {
		return CMP_STOP;
	}

	for (idx = 0; idx < ast_format_cap_count(cap); idx++) {
		struct ast_format *format = ast_format_cap_get_format(cap, idx);
		struct ast_json *lang_format_pair;

		if (!ast_strlen_zero(args->format_filter)
			&& strcmp(args->format_filter, ast_format_get_name(format))) {
			ao2_ref(format, -1);
			continue;
		}

		lang_format_pair = ast_json_pack("{s: s, s: s}",
			"language", language,
			"format", ast_format_get_name(format));
		if (!lang_format_pair) {
			ao2_ref(format, -1);
			return CMP_STOP;
		}

		ast_json_array_append(args->format_list, lang_format_pair);
		ao2_ref(format, -1);
	}

	return 0;
}
예제 #3
0
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
		    const struct pjmedia_sdp_media *stream)
{
	RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
	RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
	RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
	enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
	struct ast_rtp_codecs codecs = AST_RTP_CODECS_NULL_INIT;
	int fmts = 0;
	int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
		ast_format_cap_count(session->direct_media_cap);
	int dsp_features = 0;

	if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
	    !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
	    !(joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
		ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
		return -1;
	}

	/* get the endpoint capabilities */
	if (direct_media_enabled) {
		ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
		format_cap_only_type(caps, media_type);
	} else {
		ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
	}

	/* get the capabilities on the peer */
	get_codecs(session, stream, &codecs,  session_media);
	ast_rtp_codecs_payload_formats(&codecs, peer, &fmts);

	/* get the joint capabilities between peer and endpoint */
	ast_format_cap_get_compatible(caps, peer, joint);
	if (!ast_format_cap_count(joint)) {
		struct ast_str *usbuf = ast_str_alloca(256);
		struct ast_str *thembuf = ast_str_alloca(256);

		ast_rtp_codecs_payloads_destroy(&codecs);
		ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
			session_media->stream_type,
			ast_format_cap_get_names(caps, &usbuf),
			ast_format_cap_get_names(peer, &thembuf));
		return -1;
	}

	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp),
				     session_media->rtp);

	ast_format_cap_append_from_cap(session->req_caps, joint, AST_MEDIA_TYPE_UNKNOWN);

	if (session->channel) {
		ast_channel_lock(session->channel);
		ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
		ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel),
			AST_MEDIA_TYPE_UNKNOWN);
		ast_format_cap_remove_by_type(caps, media_type);
		ast_format_cap_append_from_cap(caps, joint, media_type);

		/*
		 * Apply the new formats to the channel, potentially changing
		 * raw read/write formats and translation path while doing so.
		 */
		ast_channel_nativeformats_set(session->channel, caps);
		if (media_type == AST_MEDIA_TYPE_AUDIO) {
			ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
			ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
		}
		if ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO)
		    && (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833)
		    && (session->dsp)) {
			dsp_features = ast_dsp_get_features(session->dsp);
			dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
			if (dsp_features) {
				ast_dsp_set_features(session->dsp, dsp_features);
			} else {
				ast_dsp_free(session->dsp);
				session->dsp = NULL;
			}
		}
		ast_channel_unlock(session->channel);
	}

	ast_rtp_codecs_payloads_destroy(&codecs);
	return 0;
}
예제 #4
0
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, 
                                                            call->callToken);
   }
   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);
      }

      ao2_ref(format, -1);
   }
   return ret;
}
예제 #5
0
int ooh323c_set_capability
   (struct ast_format_cap *cap, int dtmf, int dtmfcodec)
{
   int ret = 0, x;
   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);

      }

    ao2_ref(format, -1);      
   }
   
   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;
}
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
		    const struct pjmedia_sdp_media *stream)
{
	RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
	RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
	RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
	enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
	struct ast_rtp_codecs codecs = AST_RTP_CODECS_NULL_INIT;
	int fmts = 0;
	int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
		ast_format_cap_count(session->direct_media_cap);

	if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
	    !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
	    !(joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
		ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
		return -1;
	}

	/* get the endpoint capabilities */
	if (direct_media_enabled) {
		ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
		format_cap_only_type(caps, media_type);
	} else {
		ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
	}

	/* get the capabilities on the peer */
	get_codecs(session, stream, &codecs);
	ast_rtp_codecs_payload_formats(&codecs, peer, &fmts);

	/* get the joint capabilities between peer and endpoint */
	ast_format_cap_get_compatible(caps, peer, joint);
	if (!ast_format_cap_count(joint)) {
		struct ast_str *usbuf = ast_str_alloca(64);
		struct ast_str *thembuf = ast_str_alloca(64);

		ast_rtp_codecs_payloads_destroy(&codecs);
		ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
			session_media->stream_type,
			ast_format_cap_get_names(caps, &usbuf),
			ast_format_cap_get_names(peer, &thembuf));
		return -1;
	}

	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp),
				     session_media->rtp);

	ast_format_cap_append_from_cap(session->req_caps, joint, AST_MEDIA_TYPE_UNKNOWN);

	if (session->channel) {
		struct ast_format *fmt;

		ast_channel_lock(session->channel);
		ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
		ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_UNKNOWN);
		ast_format_cap_remove_by_type(caps, media_type);

		/*
		 * XXX Historically we picked the "best" joint format to use
		 * and stuck with it.  It would be nice to just append the
		 * determined joint media capabilities to give translation
		 * more formats to choose from when necessary.  Unfortunately,
		 * there are some areas of the system where this doesn't work
		 * very well. (The softmix bridge in particular is reluctant
		 * to pick higher fidelity formats and has a problem with
		 * asymmetric sample rates.)
		 */
		fmt = ast_format_cap_get_format(joint, 0);
		ast_format_cap_append(caps, fmt, 0);

		/*
		 * Apply the new formats to the channel, potentially changing
		 * raw read/write formats and translation path while doing so.
		 */
		ast_channel_nativeformats_set(session->channel, caps);
		ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
		ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
		ast_channel_unlock(session->channel);

		ao2_ref(fmt, -1);
	}

	ast_rtp_codecs_payloads_destroy(&codecs);
	return 0;
}
예제 #7
0
static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1)
{
	enum ast_rtp_glue_result native_type;
	struct ast_rtp_glue *glue0;
	struct ast_rtp_glue *glue1;
	RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
	RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
	RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
	RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
	RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup);
	RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup);
	int read_ptime0;
	int read_ptime1;
	int write_ptime0;
	int write_ptime1;

	if (!native_rtp_bridge_capable(bc0->chan)) {
		ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
			bridge->uniqueid, ast_channel_name(bc0->chan));
		return 0;
	}

	if (!native_rtp_bridge_capable(bc1->chan)) {
		ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
			bridge->uniqueid, ast_channel_name(bc1->chan));
		return 0;
	}

	native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1,
		&instance0, &instance1, &vinstance0, &vinstance1);
	if (native_type == AST_RTP_GLUE_RESULT_FORBID) {
		ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n",
			bridge->uniqueid);
		return 0;
	}

	if (ao2_container_count(bc0->features->dtmf_hooks)
		&& ast_rtp_instance_dtmf_mode_get(instance0)) {
		ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
			bridge->uniqueid, ast_channel_name(bc0->chan));
		return 0;
	}

	if (ao2_container_count(bc1->features->dtmf_hooks)
		&& ast_rtp_instance_dtmf_mode_get(instance1)) {
		ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
			bridge->uniqueid, ast_channel_name(bc1->chan));
		return 0;
	}

	if (native_type == AST_RTP_GLUE_RESULT_LOCAL
		&& (ast_rtp_instance_get_engine(instance0)->local_bridge
			!= ast_rtp_instance_get_engine(instance1)->local_bridge
			|| (ast_rtp_instance_get_engine(instance0)->dtmf_compatible
				&& !ast_rtp_instance_get_engine(instance0)->dtmf_compatible(bc0->chan,
					instance0, bc1->chan, instance1)))) {
		ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n",
			bridge->uniqueid);
		return 0;
	}

	cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
	cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
	if (!cap0 || !cap1) {
		return 0;
	}

	/* Make sure that codecs match */
	if (glue0->get_codec) {
		glue0->get_codec(bc0->chan, cap0);
	}
	if (glue1->get_codec) {
		glue1->get_codec(bc1->chan, cap1);
	}
	if (ast_format_cap_count(cap0) != 0
		&& ast_format_cap_count(cap1) != 0
		&& !ast_format_cap_iscompatible(cap0, cap1)) {
		struct ast_str *codec_buf0 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
		struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);

		ast_debug(1, "Bridge '%s': Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
			bridge->uniqueid,
			ast_format_cap_get_names(cap0, &codec_buf0),
			ast_format_cap_get_names(cap1, &codec_buf1));
		return 0;
	}

	read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(bc0->chan));
	read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(bc1->chan));
	write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(bc0->chan));
	write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(bc1->chan));

	if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
		ast_debug(1, "Bridge '%s': Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
			bridge->uniqueid,
			read_ptime0, write_ptime1, read_ptime1, write_ptime0);
		return 0;
	}

	return 1;
}