/* 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(); */ } }