Exemplo n.º 1
0
int tdav_codec_h264_init(tdav_codec_h264_t* self, profile_idc_t profile)
{
	int ret = 0;
	level_idc_t level;

	if(!self){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	if((ret = tdav_codec_h264_common_init(TDAV_CODEC_H264_COMMON(self)))){
		TSK_DEBUG_ERROR("tdav_codec_h264_common_init() faile with error code=%d", ret);
		return ret;
	}

	if((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))){
		TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
		return ret;
	}

	(self)->encoder.max_bw_kpbs = TMEDIA_CODEC(self)->bandwidth_max_upload;
	TDAV_CODEC_H264_COMMON(self)->pack_mode_local = H264_PACKETIZATION_MODE;
	TDAV_CODEC_H264_COMMON(self)->profile = profile;
	TDAV_CODEC_H264_COMMON(self)->level = level;
	TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS*1000;
	TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR*1000;

#if HAVE_FFMPEG
	if(!(self->encoder.codec = avcodec_find_encoder(CODEC_ID_H264))){
		TSK_DEBUG_ERROR("Failed to find H.264 encoder");
		ret = -2;
	}

	if(!(self->decoder.codec = avcodec_find_decoder(CODEC_ID_H264))){
		TSK_DEBUG_ERROR("Failed to find H.264 decoder");
		ret = -3;
	}
#endif
#if HAVE_H264_PASSTHROUGH
	TMEDIA_CODEC(self)->passthrough = tsk_true;
	self->decoder.passthrough = tsk_true;
	self->encoder.passthrough = tsk_true;
#endif

	self->encoder.quality = 1;

	/* allocations MUST be done by open() */
	return ret;
}
Exemplo n.º 2
0
/**@ingroup tmedia_codec_group
* Creates a new codec using an already registered plugin.
* @param format The format of the codec to create (e.g. "0" for PCMU or "8" for PCMA or "*" for MSRP)
* @sa @ref tmedia_codec_plugin_register()
*/
tmedia_codec_t* tmedia_codec_create(const char* format)
{
    tmedia_codec_t* codec = tsk_null;
    const tmedia_codec_plugin_def_t* plugin;
    tsk_size_t i = 0;

    while((i < TMED_CODEC_MAX_PLUGINS) && (plugin = __tmedia_codec_plugins[i++])) {
        if(plugin->objdef && tsk_striequals(plugin->format, format)) {
            if((codec = tsk_object_new(plugin->objdef))) {
                /* initialize the newly created codec */
                codec->id = plugin->codec_id;
                codec->dyn = plugin->dyn;
                codec->plugin = plugin;
                codec->bl = tmedia_bl_medium;
                switch(plugin->type) {
                case tmedia_audio: {
                    /* Audio codec */
                    tmedia_codec_audio_t* audio = TMEDIA_CODEC_AUDIO(codec);
                    tmedia_codec_audio_init(TMEDIA_CODEC(audio), plugin->name, plugin->desc, plugin->format);
                    break;
                }
                case tmedia_video: {
                    /* Video codec */
                    tmedia_codec_video_t* video = TMEDIA_CODEC_VIDEO(codec);
                    tmedia_codec_video_init(TMEDIA_CODEC(video), plugin->name, plugin->desc, plugin->format);
                    break;
                }
                case tmedia_msrp: {
                    /* Msrp codec */
                    tmedia_codec_msrp_init(codec, plugin->name, plugin->desc);
                    break;
                }
                default: {
                    /* Any other codec */
                    tmedia_codec_init(codec, plugin->type, plugin->name, plugin->desc, plugin->format);
                    break;
                }
                }
                break;
            }
        }
    }

    return codec;
}
Exemplo n.º 3
0
static tsk_bool_t tdav_codec_opus_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
    tdav_codec_opus_t* opus = (tdav_codec_opus_t*)codec;

    if(!opus) {
        TSK_DEBUG_ERROR("Invalid parameter");
        return tsk_false;
    }

    TSK_DEBUG_INFO("[OPUS] Trying to match [%s:%s]", att_name, att_value);

    if(tsk_striequals(att_name, "fmtp")) {
        int val_int;
        tsk_params_L_t* params;
        /* e.g. FIXME */
        if((params = tsk_params_fromstring(att_value, ";", tsk_true))) {
            tsk_bool_t ret = tsk_false;
            /* === maxplaybackrate ===*/
            if((val_int = tsk_params_get_param_value_as_int(params, "maxplaybackrate")) != -1) {
                if(!_tdav_codec_opus_rate_is_valid(val_int)) {
                    TSK_DEBUG_ERROR("[OPUS] %d not valid as maxplaybackrate value", val_int);
                    goto done;
                }
                TMEDIA_CODEC(opus)->out.rate = TSK_MIN((int32_t)TMEDIA_CODEC(opus)->out.rate, val_int);
                TMEDIA_CODEC_AUDIO(opus)->out.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(codec->id, codec->out.rate);
            }
            /* === sprop-maxcapturerate ===*/
            if((val_int = tsk_params_get_param_value_as_int(params, "sprop-maxcapturerate")) != -1) {
                if(!_tdav_codec_opus_rate_is_valid(val_int)) {
                    TSK_DEBUG_ERROR("[OPUS] %d not valid as sprop-maxcapturerate value", val_int);
                    goto done;
                }
                TMEDIA_CODEC(opus)->in.rate = TSK_MIN((int32_t)TMEDIA_CODEC(opus)->in.rate, val_int);
                TMEDIA_CODEC_AUDIO(opus)->in.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(codec->id, codec->in.rate);
            }
            ret = tsk_true;
done:
            TSK_OBJECT_SAFE_FREE(params);
            return ret;
        }
    }

    return tsk_true;
}
Exemplo n.º 4
0
/* constructor */
static tsk_object_t* tdav_codec_opus_ctor(tsk_object_t * self, va_list * app)
{
    tdav_codec_opus_t *opus = self;
    if(opus) {
        /* init base: called by tmedia_codec_create() */
        /* init self */
        TMEDIA_CODEC(opus)->in.rate = tmedia_defaults_get_opus_maxplaybackrate();
        TMEDIA_CODEC(opus)->out.rate = tmedia_defaults_get_opus_maxcapturerate();
        TMEDIA_CODEC_AUDIO(opus)->in.channels = 1;
        TMEDIA_CODEC_AUDIO(opus)->out.channels = 1;
#if TDAV_OPUS_FEC_ENABLED
        opus->decoder.fec_enabled = tsk_true;
#endif
#if TDAV_OPUS_DTX_ENABLED
        opus->decoder.dtx_enabled = tsk_true;
#endif
    }
    return self;
}
Exemplo n.º 5
0
static char* tdav_codec_opus_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
    tdav_codec_opus_t* opus = (tdav_codec_opus_t*)codec;

    if(!opus) {
        TSK_DEBUG_ERROR("Invalid parameter");
        return tsk_null;
    }

    if(tsk_striequals(att_name, "fmtp")) {
        char* fmtp = tsk_null;
        tsk_sprintf(&fmtp, "maxplaybackrate=%d; sprop-maxcapturerate=%d; stereo=%d; sprop-stereo=%d; useinbandfec=%d; usedtx=%d",
                    TMEDIA_CODEC(opus)->in.rate,
                    TMEDIA_CODEC(opus)->out.rate,
                    (TMEDIA_CODEC_AUDIO(opus)->in.channels == 2) ? 1 : 0,
                    (TMEDIA_CODEC_AUDIO(opus)->out.channels == 2) ? 1 : 0,
                    opus->decoder.fec_enabled ? 1 : 0,
                    opus->decoder.dtx_enabled ? 1 : 0
                   );
        return fmtp;
    }

    return tsk_null;
}
Exemplo n.º 6
0
int tdav_codec_h264_open_decoder(tdav_codec_h264_t* self)
{
#if HAVE_FFMPEG
	int ret;

	if(self->decoder.context){
		TSK_DEBUG_ERROR("Decoder already opened");
		return -1;
	}

	self->decoder.context = avcodec_alloc_context();
	avcodec_get_context_defaults(self->decoder.context);
	
	self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
	self->decoder.context->flags2 |= CODEC_FLAG2_FAST;
	self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->in.width;
	self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->in.height;

	// Picture (YUV 420)
	if(!(self->decoder.picture = avcodec_alloc_frame())){
		TSK_DEBUG_ERROR("Failed to create decoder picture");
		return -2;
	}
	avcodec_get_frame_defaults(self->decoder.picture);

	// Open decoder
	if((ret = avcodec_open(self->decoder.context, self->decoder.codec)) < 0){
		TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
		return ret;
	}
    self->decoder.last_seq = 0;

	return ret;

#elif HAVE_H264_PASSTHROUGH
	return 0;
#endif

	TSK_DEBUG_ERROR("Unexpected code called");
	return -1;
	
}
Exemplo n.º 7
0
static void tdav_codec_mp4ves_rtp_callback(tdav_codec_mp4ves_t *mp4v, const void *data, tsk_size_t size, tsk_bool_t marker)
{
	// Send data over the network
	if(TMEDIA_CODEC_VIDEO(mp4v)->out.callback){
		TMEDIA_CODEC_VIDEO(mp4v)->out.result.buffer.ptr = data;
		TMEDIA_CODEC_VIDEO(mp4v)->out.result.buffer.size = size;
		TMEDIA_CODEC_VIDEO(mp4v)->out.result.duration =  (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(mp4v)->out.fps) * TMEDIA_CODEC(mp4v)->plugin->rate);
		TMEDIA_CODEC_VIDEO(mp4v)->out.result.last_chunck = marker;
		TMEDIA_CODEC_VIDEO(mp4v)->out.callback(&TMEDIA_CODEC_VIDEO(mp4v)->out.result);
	}
}
Exemplo n.º 8
0
int tdav_codec_h264_open_encoder(tdav_codec_h264_t* self)
{
#if HAVE_FFMPEG
	int ret;
	tsk_size_t size;

	if(self->encoder.context){
		TSK_DEBUG_ERROR("Encoder already opened");
		return -1;
	}
    
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 35, 0))
    if((self->encoder.context = avcodec_alloc_context3(self->encoder.codec))){
        avcodec_get_context_defaults3(self->encoder.context, self->encoder.codec);
    }
#else
    if((self->encoder.context = avcodec_alloc_context())){
        avcodec_get_context_defaults(self->encoder.context);
    }
#endif
    
    if(!self->encoder.context){
        TSK_DEBUG_ERROR("Failed to allocate context");
		return -1;
    }

#if TDAV_UNDER_X86 && LIBAVCODEC_VERSION_MAJOR <= 53
	self->encoder.context->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE);
#endif

	self->encoder.context->pix_fmt		= PIX_FMT_YUV420P;
	self->encoder.context->time_base.num  = 1;
	self->encoder.context->time_base.den  = TMEDIA_CODEC_VIDEO(self)->out.fps;
	self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
	self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
	self->encoder.max_bw_kpbs = TSK_CLAMP(
		0,
		tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps), 
		TMEDIA_CODEC(self)->bandwidth_max_upload
	);
	self->encoder.context->bit_rate = (self->encoder.max_bw_kpbs * 1024);// bps

	self->encoder.context->rc_min_rate = (self->encoder.context->bit_rate >> 3);
	self->encoder.context->rc_max_rate = self->encoder.context->bit_rate;

#if LIBAVCODEC_VERSION_MAJOR <= 53
	self->encoder.context->rc_lookahead = 0;
#endif
	self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
	
#if LIBAVCODEC_VERSION_MAJOR <= 53
    self->encoder.context->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_B8X8;
#endif
    self->encoder.context->me_method = ME_UMH;
	self->encoder.context->me_range = 16;
	self->encoder.context->qmin = 10;
	self->encoder.context->qmax = 51;
#if LIBAVCODEC_VERSION_MAJOR <= 53
    self->encoder.context->mb_qmin = self->encoder.context->qmin;
	self->encoder.context->mb_qmax = self->encoder.context->qmax;
#endif
	/* METROPOLIS = G2J.COM TelePresence client. Check Issue 378: No video when calling "TANDBERG/4129 (X8.1.1)" */
#if !METROPOLIS  && 0
	self->encoder.context->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
    self->encoder.context->flags |= CODEC_FLAG_LOW_DELAY;
	if (self->encoder.context->profile == FF_PROFILE_H264_BASELINE) {
		self->encoder.context->max_b_frames = 0;
	}

	switch(TDAV_CODEC_H264_COMMON(self)->profile){
		case profile_idc_baseline:
		default:
			self->encoder.context->profile = FF_PROFILE_H264_BASELINE;
			self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
			break;
		case profile_idc_main:
			self->encoder.context->profile = FF_PROFILE_H264_MAIN;
			self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
			break;
	} 
	
	/* Comment from libavcodec/libx264.c:
     * Allow x264 to be instructed through AVCodecContext about the maximum
     * size of the RTP payload. For example, this enables the production of
     * payload suitable for the H.264 RTP packetization-mode 0 i.e. single
     * NAL unit per RTP packet.
     */
	self->encoder.context->rtp_payload_size = H264_RTP_PAYLOAD_SIZE;
	self->encoder.context->opaque = tsk_null;
	self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * TDAV_H264_GOP_SIZE_IN_SECONDS);
	
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 35, 0))
    if((ret = av_opt_set_int(self->encoder.context->priv_data, "slice-max-size", H264_RTP_PAYLOAD_SIZE, 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 slice-max-size to %d", H264_RTP_PAYLOAD_SIZE);
	}
    if((ret = av_opt_set(self->encoder.context->priv_data, "profile", (self->encoder.context->profile == FF_PROFILE_H264_BASELINE ? "baseline" : "main"), 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 profile");
	}
    if((ret = av_opt_set(self->encoder.context->priv_data, "preset", "veryfast", 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 preset to veryfast");
	}
    if((ret = av_opt_set_int(self->encoder.context->priv_data, "rc-lookahead", 0, 0)) && (ret = av_opt_set_int(self->encoder.context->priv_data, "rc_lookahead", 0, 0))){
        TSK_DEBUG_ERROR("Failed to set x264 rc_lookahead=0");
    }
	if((ret = av_opt_set(self->encoder.context->priv_data, "tune", "animation+zerolatency", 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 tune to zerolatency");
	}
#endif

	// Picture (YUV 420)
	if(!(self->encoder.picture = avcodec_alloc_frame())){
		TSK_DEBUG_ERROR("Failed to create encoder picture");
		return -2;
	}
	avcodec_get_frame_defaults(self->encoder.picture);
	

	size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
	if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){
		TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
		return -2;
	}

	// Open encoder
	if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0){
		TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
		return ret;
	}
    
    self->encoder.frame_count = 0;

	TSK_DEBUG_INFO("[H.264] bitrate=%d bps", self->encoder.context->bit_rate);

	return ret;
#elif HAVE_H264_PASSTHROUGH
    self->encoder.frame_count = 0;
	return 0;
#endif

	TSK_DEBUG_ERROR("Not expected code called");
	return -1;
}
Exemplo n.º 9
0
static int tdav_codec_h264_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
	tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
	if (param->value_type == tmedia_pvt_int32) {
		if(tsk_striequals(param->key, "action")){
			tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
			switch(action){
				case tmedia_codec_action_encode_idr:
					{
						h264->encoder.force_idr = tsk_true;
						break;
					}
				case tmedia_codec_action_bw_down:
					{
						h264->encoder.quality = TSK_CLAMP(1, (h264->encoder.quality + 1), 31);
#if HAVE_FFMPEG
						if (h264->encoder.context) {
							h264->encoder.context->global_quality = FF_QP2LAMBDA * h264->encoder.quality;
						}
#endif
						break;
					}
				case tmedia_codec_action_bw_up:
					{
						h264->encoder.quality = TSK_CLAMP(1, (h264->encoder.quality - 1), 31);
#if HAVE_FFMPEG
						if (h264->encoder.context) {
							h264->encoder.context->global_quality = FF_QP2LAMBDA * h264->encoder.quality;
						}
#endif
						break;
					}
			}
			return 0;
		}
		else if(tsk_striequals(param->key, "bw_kbps")){
			int32_t max_bw_userdefine = self->bandwidth_max_upload;
			int32_t max_bw_new = *((int32_t*)param->value);
			if (max_bw_userdefine > 0) {
				// do not use more than what the user defined in it's configuration
				h264->encoder.max_bw_kpbs = TSK_MIN(max_bw_new, max_bw_userdefine);
			}
			else {
				h264->encoder.max_bw_kpbs = max_bw_new;
			}
			return 0;
		}
		else if(tsk_striequals(param->key, "bypass-encoding")){
			h264->encoder.passthrough = *((int32_t*)param->value) ? tsk_true : tsk_false;
			TSK_DEBUG_INFO("[H.264] bypass-encoding = %d", h264->encoder.passthrough);
			return 0;
		}
		else if(tsk_striequals(param->key, "bypass-decoding")){
			h264->decoder.passthrough = *((int32_t*)param->value) ? tsk_true : tsk_false;
			TSK_DEBUG_INFO("[H.264] bypass-decoding = %d", h264->decoder.passthrough);
			return 0;
		}
		else if(tsk_striequals(param->key, "rotation")){
			int32_t rotation = *((int32_t*)param->value);
			if(h264->encoder.rotation != rotation){
                h264->encoder.rotation = rotation;
				if (self->opened) {
					int ret;
                    if ((ret = tdav_codec_h264_close_encoder(h264, kResetRotationFalse))) {
                        return ret;
                    }
					if ((ret = tdav_codec_h264_open_encoder(h264))) {
						return ret;
					}
#if 0 // Not working
					if((ret = avcodec_close(h264->encoder.context))){
						TSK_DEBUG_ERROR("Failed to close [%s] codec", TMEDIA_CODEC(h264)->plugin->desc);
						return ret;
					}
					h264->encoder.context->width = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(h264)->out.height : TMEDIA_CODEC_VIDEO(h264)->out.width;
					h264->encoder.context->height = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(h264)->out.width : TMEDIA_CODEC_VIDEO(h264)->out.height;
					if((ret = avcodec_open(h264->encoder.context, h264->encoder.codec)) < 0){
						TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(h264)->plugin->desc);
						return ret;
					}
					h264->encoder.force_idr = tsk_true;
#endif
				}
			}
			return 0;
		}
	}
	return -1;
}
Exemplo n.º 10
0
// RTP/RTCP callback (From the network to the consumer)
static int tdav_session_audio_rtp_cb(const void* callback_data, const struct trtp_rtp_packet_s* packet)
{
	tdav_session_audio_t* audio = (tdav_session_audio_t*)callback_data;
	tdav_session_av_t* base = (tdav_session_av_t*)callback_data;

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

	if(audio->is_started && base->consumer && base->consumer->is_started){
		tsk_size_t out_size = 0;

		// Find the codec to use to decode the RTP payload
		if(!audio->decoder.codec || audio->decoder.payload_type != packet->header->payload_type){
			tsk_istr_t format;
			TSK_OBJECT_SAFE_FREE(audio->decoder.codec);
			tsk_itoa(packet->header->payload_type, &format);
			if(!(audio->decoder.codec = tmedia_codec_find_by_format(TMEDIA_SESSION(audio)->neg_codecs, format)) || !audio->decoder.codec->plugin || !audio->decoder.codec->plugin->decode){
				TSK_DEBUG_ERROR("%s is not a valid payload for this session", format);
				return -2;
			}
			audio->decoder.payload_type = packet->header->payload_type;
		}
		
		// Open codec if not already done
		if(!TMEDIA_CODEC(audio->decoder.codec)->opened){
			int ret;
			tsk_safeobj_lock(base);
			if((ret = tmedia_codec_open(audio->decoder.codec))){
				tsk_safeobj_unlock(base);
				TSK_DEBUG_ERROR("Failed to open [%s] codec", audio->decoder.codec->plugin->desc);
				TSK_OBJECT_SAFE_FREE(audio->decoder.codec);
				return ret;
			}
			tsk_safeobj_unlock(base);
		}
		// Decode data
		out_size = audio->decoder.codec->plugin->decode(audio->decoder.codec, packet->payload.data, packet->payload.size, &audio->decoder.buffer, &audio->decoder.buffer_size, packet->header);
		if(out_size){
			void* buffer = audio->decoder.buffer;
			tsk_size_t size = out_size;

			// resample if needed
			if((base->consumer->audio.out.rate && base->consumer->audio.out.rate != audio->decoder.codec->in.rate) || (base->consumer->audio.out.channels && base->consumer->audio.out.channels != TMEDIA_CODEC_AUDIO(audio->decoder.codec)->in.channels)){
				tsk_size_t resampler_result_size = 0;
				int bytesPerSample = (base->consumer->audio.bits_per_sample >> 3);

				if(!audio->decoder.resampler.instance){
					TSK_DEBUG_INFO("Create audio resampler(%s) for consumer: rate=%d->%d, channels=%d->%d, bytesPerSample=%d", 
						audio->decoder.codec->plugin->desc, 
						audio->decoder.codec->in.rate, base->consumer->audio.out.rate,
						TMEDIA_CODEC_AUDIO(audio->decoder.codec)->in.channels, base->consumer->audio.out.channels,
						bytesPerSample);
					audio->decoder.resampler.instance = _tdav_session_audio_resampler_create(
							bytesPerSample, 
							audio->decoder.codec->in.rate, base->consumer->audio.out.rate, 
							base->consumer->audio.ptime, 
							TMEDIA_CODEC_AUDIO(audio->decoder.codec)->in.channels, base->consumer->audio.out.channels, 
							TDAV_AUDIO_RESAMPLER_DEFAULT_QUALITY, 
							&audio->decoder.resampler.buffer, &audio->decoder.resampler.buffer_size
						);
				}
				if(!audio->decoder.resampler.instance){
					TSK_DEBUG_ERROR("No resampler to handle data");
					return -5;
				}
				if(!(resampler_result_size = tmedia_resampler_process(audio->decoder.resampler.instance, buffer, size/bytesPerSample, audio->decoder.resampler.buffer, audio->decoder.resampler.buffer_size/bytesPerSample))){
					TSK_DEBUG_ERROR("Failed to process audio resampler input buffer");
					return -6;
				}
				
				buffer = audio->decoder.resampler.buffer;
				size = audio->decoder.resampler.buffer_size;
			}

			// adjust the gain
			if(base->consumer->audio.gain){
				_tdav_session_audio_apply_gain(buffer, size, base->consumer->audio.bits_per_sample, base->consumer->audio.gain);
			}
			// consume the frame
			tmedia_consumer_consume(base->consumer, buffer, size, packet->header);
		}
Exemplo n.º 11
0
int tdav_codec_h264_open_encoder(tdav_codec_h264_t* self)
{
#if HAVE_FFMPEG
	int ret;
	tsk_size_t size;
	int32_t max_bw_kpbs;

	if(self->encoder.context){
		TSK_DEBUG_ERROR("Encoder already opened");
		return -1;
	}
    
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 35, 0))
    if((self->encoder.context = avcodec_alloc_context3(self->encoder.codec))){
        avcodec_get_context_defaults3(self->encoder.context, self->encoder.codec);
    }
#else
    if((self->encoder.context = avcodec_alloc_context())){
        avcodec_get_context_defaults(self->encoder.context);
    }
#endif
    
    if(!self->encoder.context){
        TSK_DEBUG_ERROR("Failed to allocate context");
		return -1;
    }

#if TDAV_UNDER_X86 && LIBAVCODEC_VERSION_MAJOR <= 53
	self->encoder.context->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE);
#endif

	self->encoder.context->pix_fmt		= PIX_FMT_YUV420P;
	self->encoder.context->time_base.num  = 1;
	self->encoder.context->time_base.den  = TMEDIA_CODEC_VIDEO(self)->out.fps;
	self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
	self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
	max_bw_kpbs = TSK_CLAMP(
		0,
		tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps), 
		self->encoder.max_bw_kpbs
	);
	self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps

	self->encoder.context->rc_min_rate = (self->encoder.context->bit_rate >> 3);
	self->encoder.context->rc_max_rate = self->encoder.context->bit_rate;

#if LIBAVCODEC_VERSION_MAJOR <= 53
	self->encoder.context->rc_lookahead = 0;
#endif
	self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
	
	self->encoder.context->scenechange_threshold = 0;
    self->encoder.context->me_subpel_quality = 0;
#if LIBAVCODEC_VERSION_MAJOR <= 53
    self->encoder.context->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_B8X8;
#endif
    self->encoder.context->me_method = ME_EPZS;
    self->encoder.context->trellis = 0;

	self->encoder.context->me_range = 16;
	self->encoder.context->qmin = 10;
	self->encoder.context->qmax = 51;
#if LIBAVCODEC_VERSION_MAJOR <= 53
    self->encoder.context->mb_qmin = self->encoder.context->qmin;
	self->encoder.context->mb_qmax = self->encoder.context->qmax;
#endif
	self->encoder.context->qcompress = 0.6f;
	self->encoder.context->mb_decision = FF_MB_DECISION_SIMPLE;
#if LIBAVCODEC_VERSION_MAJOR <= 53
	self->encoder.context->flags2 |= CODEC_FLAG2_FASTPSKIP;
#else 
    self->encoder.context->flags2 |= CODEC_FLAG2_FAST;
#endif
	self->encoder.context->flags |= CODEC_FLAG_LOOP_FILTER;
	self->encoder.context->flags |= CODEC_FLAG_GLOBAL_HEADER;
    self->encoder.context->flags |= CODEC_FLAG_LOW_DELAY;
	self->encoder.context->max_b_frames = 0;
	self->encoder.context->b_frame_strategy = 1;
	self->encoder.context->chromaoffset = 0;

	switch(TDAV_CODEC_H264_COMMON(self)->profile){
		case profile_idc_baseline:
		default:
			self->encoder.context->profile = FF_PROFILE_H264_BASELINE;
			self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
			break;
		case profile_idc_main:
			self->encoder.context->profile = FF_PROFILE_H264_MAIN;
			self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
			break;
	}
	
	self->encoder.context->rtp_payload_size = H264_RTP_PAYLOAD_SIZE;
	self->encoder.context->opaque = tsk_null;
	self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * TDAV_H264_GOP_SIZE_IN_SECONDS);
	
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 35, 0))
    if((ret = av_opt_set_int(self->encoder.context->priv_data, "slice-max-size", H264_RTP_PAYLOAD_SIZE, 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 slice-max-size to %d", H264_RTP_PAYLOAD_SIZE);
	}
    if((ret = av_opt_set(self->encoder.context->priv_data, "profile", (self->encoder.context->profile == FF_PROFILE_H264_BASELINE ? "baseline" : "main"), 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 profile");
	}
    if((ret = av_opt_set(self->encoder.context->priv_data, "preset", "veryfast", 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 preset to veryfast");
	}
    if((ret = av_opt_set_int(self->encoder.context->priv_data, "rc-lookahead", 0, 0)) && (ret = av_opt_set_int(self->encoder.context->priv_data, "rc_lookahead", 0, 0))){
        TSK_DEBUG_ERROR("Failed to set x264 rc_lookahead=0");
    }
	if((ret = av_opt_set(self->encoder.context->priv_data, "tune", "animation+zerolatency", 0))){
	    TSK_DEBUG_ERROR("Failed to set x264 tune to zerolatency");
	}
#endif

	// Picture (YUV 420)
	if(!(self->encoder.picture = avcodec_alloc_frame())){
		TSK_DEBUG_ERROR("Failed to create encoder picture");
		return -2;
	}
	avcodec_get_frame_defaults(self->encoder.picture);
	

	size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
	if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){
		TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
		return -2;
	}

	// Open encoder
	if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0){
		TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
		return ret;
	}

	TSK_DEBUG_INFO("[H.264] bitrate=%d bps", self->encoder.context->bit_rate);

	return ret;
#elif HAVE_H264_PASSTHROUGH
	return 0;
#endif

	TSK_DEBUG_ERROR("Not expected code called");
	return -1;
}