Example #1
0
int tdav_audiounit_handle_destroy(tdav_audiounit_handle_t** self){
	if(!self || !*self){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}
	tsk_list_lock(__audioUnitInstances);
	if(tsk_object_get_refcount(*self)==1){
		tsk_list_remove_item_by_data(__audioUnitInstances, *self);
	}
	else {
		tsk_object_unref(*self);
	}
	tsk_list_unlock(__audioUnitInstances);
	*self = tsk_null;
	return 0;
}
Example #2
0
const tnet_ice_candidate_t* tnet_ice_candidate_find_by_fd(tnet_ice_candidates_L_t* candidates, tnet_fd_t fd)
{
	if(candidates){
		const tsk_list_item_t *item;
		const tnet_ice_candidate_t* candidate;

		tsk_list_lock(candidates);
		tsk_list_foreach(item, candidates){
			if(!(candidate = item->data)){
				continue;
			}
			if(candidate->socket && (candidate->socket->fd == fd)){
				tsk_list_unlock(candidates);
				return candidate;
			}
		}
	}

	return tsk_null;
}
Example #3
0
int tdav_video_jb_put(tdav_video_jb_t* self, trtp_rtp_packet_t* rtp_pkt)
{
#if TDAV_VIDEO_JB_DISABLE
    self->cb_data_rtp.rtp.pkt = rtp_pkt;
    self->callback(&self->cb_data_rtp);
#else
	const tdav_video_frame_t* old_frame;
	tsk_bool_t pt_matched = tsk_false, is_frame_late_or_dup = tsk_false, is_restarted = tsk_false;
	uint16_t* seq_num;

	if(!self || !rtp_pkt || !rtp_pkt->header){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	if(!self->started){
		TSK_DEBUG_INFO("Video jitter buffer not started");
		return 0;
	}

	seq_num = &self->seq_nums[rtp_pkt->header->payload_type];

	tsk_safeobj_lock(self);

	//TSK_DEBUG_INFO("receive seqnum=%u", rtp_pkt->header->seq_num);

	if(self->decode_last_timestamp && (self->decode_last_timestamp > rtp_pkt->header->timestamp)){
		if((self->decode_last_timestamp - rtp_pkt->header->timestamp) < TDAV_VIDEO_JB_MAX_DROPOUT){
			TSK_DEBUG_INFO("--------Frame already Decoded [seqnum=%u]------------", rtp_pkt->header->seq_num);
			tsk_safeobj_unlock(self);
			return 0;
		}
	}

	old_frame = _tdav_video_jb_get_frame(self, rtp_pkt->header->timestamp, rtp_pkt->header->payload_type, &pt_matched);	

	if((*seq_num && *seq_num != 0xFFFF) && (*seq_num + 1) != rtp_pkt->header->seq_num){
		int32_t diff = ((int32_t)rtp_pkt->header->seq_num - (int32_t)*seq_num);
		tsk_bool_t is_frame_loss = (diff > 0);
		is_restarted = (TSK_ABS(diff) > TDAV_VIDEO_JB_MAX_DROPOUT);
		is_frame_late_or_dup = !is_frame_loss;
		tdav_video_jb_reset_fps_prob(self);
		TSK_DEBUG_INFO("Packet %s (from JB) [%hu - %hu]", is_frame_loss ? "loss" : "late/duplicated/nack", *seq_num, rtp_pkt->header->seq_num);
		
		if(is_frame_loss && !is_restarted){
			if(self->callback){			
				self->cb_data_any.type = tdav_video_jb_cb_data_type_fl;
				self->cb_data_any.ssrc = rtp_pkt->header->ssrc;
				self->cb_data_any.fl.seq_num = (*seq_num + 1);
				self->cb_data_any.fl.count = diff - 1;
				self->callback(&self->cb_data_any);
			}
		}
	}

	if(!old_frame){
		tdav_video_frame_t* new_frame;
		if(pt_matched){
			// if we have a frame with the same payload type but without this timestamp this means that we moved to a new frame
			// this happens if the frame is waiting to be decoded or the marker is lost
		}
		if((new_frame = tdav_video_frame_create(rtp_pkt))){
			// compute avg frame duration
			if(self->last_timestamp && self->last_timestamp < rtp_pkt->header->timestamp){
				uint32_t duration = (rtp_pkt->header->timestamp - self->last_timestamp)/self->rate;
				self->avg_duration = self->avg_duration ? ((self->avg_duration + duration) >> 1) : duration;
				--self->fps_prob;
			}
			self->last_timestamp = rtp_pkt->header->timestamp;
			
			tsk_list_lock(self->frames);
			if(self->frames_count >= self->tail_max){
				if(++self->conseq_frame_drop >= self->tail_max){
					TSK_DEBUG_ERROR("Too many frames dropped and fps=%d", self->fps);
					tsk_list_clear_items(self->frames);
					self->conseq_frame_drop = 0;
					self->frames_count = 1;
					if(self->callback){
						self->cb_data_any.type = tdav_video_jb_cb_data_type_tmfr;
						self->cb_data_any.ssrc = rtp_pkt->header->ssrc;
						self->callback(&self->cb_data_any);
					}
				}
				else{
					TSK_DEBUG_INFO("Dropping video frame because frames_count(%lld)>=tail_max(%d)", self->frames_count, self->tail_max);
					tsk_list_remove_first_item(self->frames);
				}
				tdav_video_jb_reset_fps_prob(self);
			}
			else{
				++self->frames_count;
			}
			tsk_list_push_ascending_data(self->frames, (void**)&new_frame);
			tsk_list_unlock(self->frames);
		}
Example #4
0
tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id)
{
	tdav_audiounit_instance_t* inst = tsk_null;
	
	// create audio unit component
	if(!__audioSystem){
		AudioComponentDescription audioDescription;
		audioDescription.componentType = kAudioUnitType_Output;
		audioDescription.componentSubType = kDoubangoAudioUnitSubType;
		audioDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
		audioDescription.componentFlags = 0;
		audioDescription.componentFlagsMask = 0;
		if((__audioSystem = AudioComponentFindNext(NULL, &audioDescription))){
			// leave blank
		}
		else {
			TSK_DEBUG_ERROR("Failed to find new audio component");
			goto done;
		}

	}
	// create list used to hold instances
	if(!__audioUnitInstances && !(__audioUnitInstances = tsk_list_create())){
		TSK_DEBUG_ERROR("Failed to create new list");
		goto done;
	}
	
	//= lock the list
	tsk_list_lock(__audioUnitInstances);
	
	// For iOS we are using full-duplex AudioUnit and to keep it unique for both
	// the consumer and producer we use the session id.
#if TARGET_OS_IPHONE
	// find the instance from the list
	const tsk_list_item_t* item;
	tsk_list_foreach(item,__audioUnitInstances){
		if(((tdav_audiounit_instance_t*)item->data)->session_id == session_id){
			inst = tsk_object_ref(item->data);
			goto done;
		}
	}
#endif
	
	// create instance object and put it into the list
	if((inst = tsk_object_new(tdav_audiounit_instance_def_t))){
		OSStatus status = noErr;
		tdav_audiounit_instance_t* _inst;
		
		// create new instance
		if((status= AudioComponentInstanceNew(__audioSystem, &inst->audioUnit)) != noErr){
			TSK_DEBUG_ERROR("AudioComponentInstanceNew() failed with status=%ld", (signed long)status);
			TSK_OBJECT_SAFE_FREE(inst);
			goto done;
		}
		_inst = inst, _inst->session_id = session_id;
		tsk_list_push_back_data(__audioUnitInstances, (void**)&_inst);
	}
	
done:
	//= unlock the list
	tsk_list_unlock(__audioUnitInstances);
	return (tdav_audiounit_handle_t*)inst;
}