forked from mirrors/linphone-iphone
179 lines
5.7 KiB
C
179 lines
5.7 KiB
C
/*
|
|
The objective of the media_api is to construct and run the necessary processing
|
|
on audio and video data flows for a given call (two party call) or conference.
|
|
Copyright (C) 2001 Sharath Udupa skuds@gmx.net
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#include "common.h"
|
|
#include "mediaflow.h"
|
|
#include "callmember.h"
|
|
|
|
|
|
MediaFlow *media_flow_new(char *id_string, int type){
|
|
MediaFlow *flow = (MediaFlow *) g_malloc(sizeof(MediaFlow)); //malloc required?
|
|
api_trace("media_flow_new: creating %s",id_string);
|
|
flow->id = id_string;
|
|
flow->type = type;
|
|
flow->flowDirections = NULL;
|
|
flow->members = NULL;
|
|
return flow;
|
|
}
|
|
|
|
int media_flow_destroy(MediaFlow *flow){
|
|
g_free(flow);
|
|
return 1;
|
|
}
|
|
|
|
int media_flow_setup_fd(MediaFlow *flow, CallMember* csource, CallMember *cdestination, int direction){
|
|
GList *source, *destination;
|
|
char *dir;
|
|
FlowDirections *fd = (FlowDirections *) g_malloc(sizeof(FlowDirections));
|
|
if(direction == MEDIA_FLOW_DUPLEX) dir = "DUPLEX";
|
|
else if(direction == MEDIA_FLOW_HALF_DUPLEX) dir = "HALF_DUPLEX";
|
|
api_trace("media_flow_setup_fd: setting up %s flow for %s , %s",dir, csource->name, cdestination->name);
|
|
source = g_list_find_custom(flow->members, csource, &find);
|
|
destination =g_list_find_custom(flow->members, cdestination, &find);
|
|
if(source == NULL){
|
|
api_error("media_flow_setup_fd: Invalid source %s specified", csource->name);
|
|
}
|
|
if(destination == NULL){
|
|
api_error("media_flow_setup_fd: Invalid destination %s specified", cdestination->name);
|
|
//ERROR handling to be done here
|
|
}
|
|
fd->source = (Members*)source->data;
|
|
fd->destination = (Members*)destination->data;
|
|
fd->type = direction;
|
|
flow->flowDirections = g_list_append(flow->flowDirections, fd);
|
|
return 1;
|
|
}
|
|
|
|
int find(gconstpointer mem, gconstpointer cmember){
|
|
if(!strcmp(((Members*)mem)->member->name, ((CallMember*)cmember)->name)){
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int media_flow_start_fd(FlowDirections *fd, MSSync *sync){
|
|
Members *source, *destination;
|
|
source = fd->source;
|
|
destination = fd->destination;
|
|
if(fd->type == MEDIA_FLOW_DUPLEX){
|
|
fd->recv = set_MSFilter(source->tx_endpoint,1,fd);
|
|
fd->dec = set_CODECFilter(source->member->profile, source->tx_endpoint->pt,MEDIA_API_DECODER);
|
|
fd->play = set_MSFilter(destination->rx_endpoint,0,fd);
|
|
|
|
ms_filter_add_link(fd->recv,fd->dec);
|
|
ms_filter_add_link(fd->dec,fd->play);
|
|
ms_sync_attach(sync, fd->recv);
|
|
|
|
fd->read = set_MSFilter(destination->tx_endpoint,1,fd);
|
|
fd->enc = set_CODECFilter(destination->member->profile, destination->tx_endpoint->pt,MEDIA_API_ENCODER);
|
|
fd->send = set_MSFilter(source->rx_endpoint,0,fd);
|
|
|
|
ms_filter_add_link(fd->read, fd->enc);
|
|
ms_filter_add_link(fd->enc, fd->send);
|
|
ms_sync_attach(sync, fd->read);
|
|
|
|
}
|
|
else if(fd->type == MEDIA_FLOW_HALF_DUPLEX){
|
|
|
|
fd->recv = set_MSFilter(source->tx_endpoint,1,fd);
|
|
fd->dec = set_CODECFilter(sourcec->member->profile, source->tx_endpoint->pt,MEDIA_API_DECODER);
|
|
fd->play = set_MSFilter(destination->rx_endpoint,0,fd);
|
|
|
|
ms_filter_add_link(fd->recv,fd->dec);
|
|
ms_filter_add_link(fd->dec,fd->play);
|
|
ms_sync_attach(sync, fd->recv);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
MSFilter *set_MSFilter(EndPoint *endpoint, int type, FlowDirections *fdir){
|
|
MSFilter *filter;
|
|
RtpSession *rtps;
|
|
switch(endpoint->protocol){
|
|
case MEDIA_RTP:
|
|
rtps = rtp_session_new(RTP_SESSION_RECVONLY);
|
|
rtp_session_set_local_addr(rtps,"0.0.0.0",8000);
|
|
rtp_session_set_scheduling_mode(rtps,0);
|
|
rtp_session_set_blocking_mode(rtps,0);
|
|
|
|
if(type == 1){
|
|
filter = ms_rtp_recv_new();
|
|
ms_rtp_recv_set_session(MS_RTP_RECV(filter), rtps);
|
|
fdir->rtpSessions = g_list_append(fdir->rtpSessions, rtps);
|
|
return filter;
|
|
}
|
|
else{
|
|
//ms_rtp_send_new
|
|
}
|
|
case MEDIA_OSS:
|
|
if(type == 1){
|
|
filter = ms_oss_read_new();
|
|
ms_sound_read_set_device(MS_SOUND_READ(filter),0);
|
|
return filter;
|
|
}
|
|
else{
|
|
filter = ms_oss_write_new();
|
|
ms_sound_write_set_device(MS_SOUND_WRITE(filter),0);
|
|
return filter;
|
|
}
|
|
case MEDIA_FILE:
|
|
if(type == 1){
|
|
filter = ms_read_new(endpoint->file);
|
|
return filter;
|
|
}
|
|
if(type == 0){
|
|
filter = ms_write_new(endpoint->file);
|
|
return filter;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
MSFilter *set_CODECFilter(RtpProfile *profile, int pt, int mode){
|
|
PayloadType *payload;
|
|
|
|
switch(mode){
|
|
case MEDIA_API_DECODER:
|
|
payload = rtp_profile_get_payload(profile, pt);
|
|
if(payload == NULL){
|
|
api_error("media_api: undefined payload in URL\n");
|
|
return NULL;
|
|
}
|
|
return ms_decoder_new_with_string_id(payload->mime_type);
|
|
|
|
//Commented this to include the new RtpProfile
|
|
/*if(pt != -1) return ms_decoder_new_with_pt(pt);
|
|
*else return ms_copy_new();
|
|
*/
|
|
case MEDIA_API_ENCODER:
|
|
|
|
payload = rtp_profile_get_payload(profile, pt);
|
|
if(payload == NULL){
|
|
api_error("media_api: undefined payload in URL\n");
|
|
return NULL;
|
|
}
|
|
return ms_encoder_new_with_string_id(payload->mime_type);
|
|
/*if(pt != -1) return ms_encoder_new_with_pt(pt);
|
|
*else return ms_copy_new();
|
|
*/
|
|
}
|
|
}
|
|
|
|
|