Example #1
0
void set_encoding_quality(struct x264lib_ctx *ctx, int pct)
{
	if (ctx->supports_csc_option) {
		int new_colour_sampling = get_x264_colour_sampling(ctx, pct);
		if (ctx->colour_sampling!=new_colour_sampling) {
			//pixel encoding has changed, we must re-init everything:
			//printf("set_encoding_quality(%i) old colour_sampling=%i, new colour_sampling %i\n", pct, ctx->colour_sampling, new_colour_sampling);
			do_clean_encoder(ctx);
			do_init_encoder(ctx, ctx->width , ctx->height, pct, ctx->supports_csc_option);
			return;
		}
	}
	if ((ctx->quality & ~0x1)!=(pct & ~0x1)) {
		float new_quality = get_x264_quality(pct);
		//float old_quality = ctx->x264_quality;
		//printf("set_encoding_quality(%i) was %i, new x264 quality %f was %f\n", pct, ctx->quality, new_quality, old_quality);
		//only f_rf_constant was changed,
		//read new configuration is sufficient
		x264_param_t param;
		// Retrieve current parameters
		x264_encoder_parameters(ctx->encoder, &param);
		ctx->quality = pct;
		ctx->x264_quality = new_quality;
		param.rc.f_rf_constant = new_quality;
		x264_encoder_reconfig(ctx->encoder, &param);
	}
	int old_csc_algo = ctx->csc_algo;
	ctx->csc_algo = get_csc_algo_for_quality(pct);
	if (old_csc_algo!=ctx->csc_algo) {
		ctx->rgb2yuv = init_encoder_csc(ctx);
	}
}
Example #2
0
void H264Encoder::init_(const int wid, const int hei) {
    // 0. building encoder parameters.
    x264_param_default_preset(&x264_opt_, "ultrafast", "zerolatency");

    x264_opt_.i_width = wid;
    x264_opt_.i_height = hei;
    x264_opt_.i_threads = 1;
    x264_opt_.b_repeat_headers = 1;
    x264_opt_.b_intra_refresh = 1;

    x264_opt_.rc.i_rc_method = X264_RC_CQP;
    x264_opt_.rc.i_qp_constant = 24;
    x264_opt_.rc.i_qp_min = 24;
    x264_opt_.rc.i_qp_max = 24;
    //x264_param_default(&opt);
    x264_param_apply_profile(&x264_opt_, "baseline");

    // 1. Prepare the output buffer and target file
    x264_picture_alloc(&x264_picin_,  X264_CSP_NV12, x264_opt_.i_width, x264_opt_.i_height);
    x264_picture_alloc(&x264_picout_, X264_CSP_NV12, x264_opt_.i_width, x264_opt_.i_height);

    // 2. Building the encoder handler
    x264_hdl_ = x264_encoder_open(&x264_opt_);
    x264_encoder_parameters(x264_hdl_, &x264_opt_);
}
Example #3
0
int H264Encoder::Prepare(const MediaDescription& desc) {
    if ( desc.isVideo == false)
        return -1;
    
    int wid = desc.width;
    int hei = desc.height;

    // 0. building a default encoder parameters. 
    x264_param_default_preset(&x264_opt_, "ultrafast", "zerolatency");
    x264_opt_.rc.i_rc_method = X264_RC_CRF;
    x264_opt_.rc.i_bitrate = 512;
    x264_opt_.i_nal_hrd = X264_NAL_HRD_CBR; 
    //x264_param_default(&opt);
    
    // 1. Setting the fields of parameter struct
    x264_opt_.i_width = wid;
    x264_opt_.i_height = hei;
    //opt.i_slice_count = 5;
    //opt.b_intra_refresh = 1;
    
    // 3. Prepare the output buffer and target file
    x264_picture_alloc(&x264_picin_[0], X264_CSP_NV12, x264_opt_.i_width, x264_opt_.i_height);
    x264_picture_alloc(&x264_picin_[1], X264_CSP_NV12, x264_opt_.i_width, x264_opt_.i_height);
    x264_picture_alloc(&x264_picout_, X264_CSP_NV12, x264_opt_.i_width, x264_opt_.i_height);
    ppIndex = -1;

    // 4. Building the encoder handler
    x264_hdl_ = x264_encoder_open(&x264_opt_);
    x264_encoder_parameters(x264_hdl_, &x264_opt_);

    return 0;
}
Example #4
0
void change_encoding_speed(struct x264lib_ctx *ctx, int increase)
{
	x264_param_t param;
	x264_encoder_parameters(ctx->encoder, &param);
	ctx->encoding_preset -= increase;
	if (ctx->encoding_preset < 0)
		ctx->encoding_preset = 0;
	if (ctx->encoding_preset > 5)
		ctx->encoding_preset = 5;
	x264_param_default_preset(&param, x264_preset_names[ctx->encoding_preset], "zerolatency");
	//printf("Setting encoding preset %s %d\n", x264_preset_names[ctx->encoding_preset], ctx->encoding_preset);
	x264_param_apply_profile(&param, "baseline");
	x264_encoder_reconfig(ctx->encoder, &param);
}
Example #5
0
void set_encoding_speed(struct x264lib_ctx *ctx, int pct)
{
	x264_param_t param;
	x264_encoder_parameters(ctx->encoder, &param);
	int new_preset = 7-MAX(0, MIN(7, pct/12.5));
	if (new_preset==ctx->encoding_preset)
		return;
	ctx->encoding_preset = new_preset;
	//"tune" options: film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency
	//Multiple tunings can be used if separated by a delimiter in ",./-+"
	//however multiple psy tunings cannot be used.
	//film, animation, grain, stillimage, psnr, and ssim are psy tunings.
	x264_param_default_preset(&param, x264_preset_names[ctx->encoding_preset], "zerolatency");
	x264_param_apply_profile(&param, "baseline");
	x264_encoder_reconfig(ctx->encoder, &param);
}
Example #6
0
int compress_image(struct x264lib_ctx *ctx, x264_picture_t *pic_in, uint8_t **out, int *outsz, int quality_override)
{
	if (!ctx->encoder || !ctx->rgb2yuv) {
		free_csc_image(pic_in);
		*out = NULL;
		*outsz = 0;
		return 1;
	}
	x264_picture_t pic_out;

	/* Encoding */
	pic_in->i_pts = 1;
	if (quality_override>=0) {
		// Retrieve current parameters and override quality for this frame
		float new_q = get_x264_quality(quality_override);
		if (new_q!=ctx->x264_quality) {
			x264_param_t *param = malloc(sizeof(x264_param_t));
			x264_encoder_parameters(ctx->encoder, param);
			param->rc.f_rf_constant = new_q;
			pic_in->param = param;
			pic_in->param->param_free = free;
		}
	}

	x264_nal_t* nals;
	int i_nals;
	int frame_size = x264_encoder_encode(ctx->encoder, &nals, &i_nals, pic_in, &pic_out);
	if (frame_size < 0) {
		fprintf(stderr, "Problem during x264_encoder_encode: frame_size is invalid!\n");
		free_csc_image(pic_in);
		*out = NULL;
		*outsz = 0;
		return 2;
	}
	free_csc_image(pic_in);
	/* Do not clean that! */
	*out = nals[0].p_payload;
	*outsz = frame_size;
	return 0;
}
jlong Java_com_H264_H264Encoder_CompressBegin(JNIEnv* env,jobject thiz,
												jint width,jint height,
												jint FrameRate,
												jbyteArray filename){
	en = (Encoder *) malloc(sizeof(Encoder));
	en->param = (x264_param_t *) malloc(sizeof(x264_param_t));
	en->picture = (x264_picture_t *) malloc(sizeof(x264_picture_t));

	opt = (cli_opt_t *)malloc(sizeof(cli_opt_t));


	//test
	nalcount=0;
	last_pts = 0;
	i_frame= 0;
	//test

    x264_nal_t *headers;
    int i_nal;

	jbyte * fname = (jbyte*)(*env)->GetByteArrayElements(env, filename, 0);
	mp4_output.open_file( fname, &opt->hout, &output_opt );




 	x264_param_default(en->param); // default param
	 en->param->i_log_level = X264_LOG_NONE;
	 en->param->i_width = width; // frame width
	 en->param->i_height = height; // frame height
	 en->param->rc.i_lookahead =0;
	 en->param->i_bframe=0;
	 en->param->i_fps_num =FrameRate;
	 en->param->i_fps_den = 1;
	 en->param->i_frame_reference=5;
	 en->param->i_bframe_adaptive=1;




 	 en->param->b_vfr_input=1;
 	 en->param->i_timebase_num = 1;
 	 en->param->i_timebase_den = FrameRate;



 	en->param->i_csp =X264_CSP_I420;
 	en->param->analyse.b_psnr = 1;
 	en->param->analyse.b_ssim = 1;


 	int frames = 0;
 	en->param->i_frame_total = 0;

///////

	// Intra refres:
 	en->param->i_keyint_max = 30;
 	en->param->b_intra_refresh = 1;
	//Rate control:
 	en->param->rc.f_rf_constant = 25;
 	en->param->rc.f_rf_constant_max = 35;
	//For streaming:
 	en->param->b_repeat_headers = 0;
 	en->param->b_annexb = 0;


 	///////

 	uv = en->param->i_width * en->param->i_height;

	 if ((en->handle = x264_encoder_open(en->param)) == 0) {
		 return 0;
	 }
	 x264_encoder_parameters( en->handle, en->param );
	 /* Create a new pic */
	 x264_picture_alloc(en->picture, X264_CSP_I420, en->param->i_width,
	 en->param->i_height);

	 mp4_output.set_param(opt->hout,en->param);

	 ticks_per_frame = (int64_t)en->param->i_timebase_den * en->param->i_fps_den / en->param->i_timebase_num / en->param->i_fps_num;
	 ticks_per_frame = X264_MAX( ticks_per_frame, 1 );

	 __android_log_print(ANDROID_LOG_INFO, "H264Encoder native", "ticks_per_frame:%d",ticks_per_frame);

	 if(x264_encoder_headers( en->handle, &headers, &i_nal)<0)
		 ;
	 __android_log_print(ANDROID_LOG_INFO, "H264Encoder native", "encoder header:%d",i_nal);
	 mp4_output.write_headers(opt->hout, headers);
	 (*env)->ReleaseByteArrayElements(env,filename,fname,0);
	 return (jlong) en; 
}
// See https://gist.github.com/roxlu/0f61a499df75e64b764d for an older version of this, with some rate control tests
// @todo - we should check if the supplied settings are valid for the current profile.. e.g. bframes are not supported by the baseline profile
bool VideoEncoder::initializeX264() {
  assert(settings.width > 0);
  assert(settings.height > 0);
  assert(settings.fps > 0);

  int r = 0;
  x264_param_t* p = &params;
  
  std::string preset = (settings.preset.size()) ? settings.preset : "superfast";
  std::string tune = (settings.tune.size()) ? settings.tune : "zerolatency";
  STREAMER_STATUS("x264 using preset: %s and tune: %s\n", preset.c_str(), tune.c_str());

  r = x264_param_default_preset(p, preset.c_str(), tune.c_str());
  if(r != 0) {
    STREAMER_ERROR("error: cannot set the default preset on x264.\n");
    return false;
  }

  p->i_threads = settings.threads;
  p->i_width = settings.width;
  p->i_height = settings.height;
  p->i_fps_num = settings.fps;
  p->i_fps_den = 1;
  p->b_annexb = 0; // flv == no annexb, but strangely, when I disable it the generated flv cannot be played back, for raw h264 you'll need to set annexb to 1 when you want to play it in vlc (vlc isn't properly playing back flv)

  p->rc.i_rc_method = X264_RC_ABR;  // when you're limited to bandwidth you set the vbv_buffer_size and vbv_max_bitrate using the X264_RC_ABR rate control method. The vbv_buffer_size is a decoder option and tells the decoder how much data must be buffered before playback can start. When vbv_max_bitrate == vbv_buffer_size, then it will take one second before the playback might start. when vbv_buffer_size == vbv_max_bitrate * 0.5, it might start in 0.5 sec. 
  p->rc.i_bitrate = settings.bitrate;
  p->rc.i_vbv_buffer_size = (settings.vbv_buffer_size < 0) ? p->rc.i_bitrate : settings.vbv_buffer_size; 
  p->rc.i_vbv_max_bitrate = (settings.vbv_max_bitrate < 0) ? p->rc.i_bitrate : settings.vbv_max_bitrate;;

  if(settings.keyint_max > 0) {
    p->i_keyint_max = settings.keyint_max;
  }
  
  if(settings.bframe > 0) {
    p->i_bframe = settings.bframe;
  }

  if(settings.level_idc > 0) {
    p->i_level_idc = settings.level_idc;
  }

#if !defined(NDEBUG)
  p->i_log_level = X264_LOG_DEBUG;
  p->pf_log = videoencoder_x264_log;
#endif   

  if(settings.profile.size()) {
    r = x264_param_apply_profile(p, settings.profile.c_str());
    if(r != 0) {
      STREAMER_ERROR("error: cannot set the baseline profile on x264.\n");
      return false;
    }
  }

  encoder = x264_encoder_open(p);
  if(!encoder) {
    STREAMER_ERROR("error: cannot create the encoder.\n");
    return false;
  }

  x264_encoder_parameters(encoder, &params);  

  print_x264_params(p);

  return true;
}
Example #9
0
static void *start_encoder( void *ptr )
{
    obe_vid_enc_params_t *enc_params = ptr;
    obe_t *h = enc_params->h;
    obe_encoder_t *encoder = enc_params->encoder;
    x264_t *s = NULL;
    x264_picture_t pic, pic_out;
    x264_nal_t *nal;
    int i_nal, frame_size = 0, user_sar_width, user_sar_height;
    int64_t pts = 0, arrival_time = 0, frame_duration, buffer_duration;
    int64_t *pts2;
    float buffer_fill;
    obe_raw_frame_t *raw_frame;
    obe_coded_frame_t *coded_frame;

    /* TODO: check for width, height changes */

    /* Lock the mutex until we verify and fetch new parameters */
    pthread_mutex_lock( &encoder->encoder_mutex );

    enc_params->avc_param.pf_log = x264_logger;
    s = x264_encoder_open( &enc_params->avc_param );
    if( !s )
    {
        pthread_mutex_unlock( &encoder->encoder_mutex );
        fprintf( stderr, "[x264]: encoder configuration failed\n" );
        goto end;
    }

    x264_encoder_parameters( s, &enc_params->avc_param );

    encoder->encoder_params = malloc( sizeof(enc_params->avc_param) );
    if( !encoder->encoder_params )
    {
        pthread_mutex_unlock( &encoder->encoder_mutex );
        syslog( LOG_ERR, "Malloc failed\n" );
        goto end;
    }
    memcpy( encoder->encoder_params, &enc_params->avc_param, sizeof(enc_params->avc_param) );

    encoder->is_ready = 1;
    /* XXX: This will need fixing for soft pulldown streams */
    frame_duration = av_rescale_q( 1, (AVRational){enc_params->avc_param.i_fps_den, enc_params->avc_param.i_fps_num}, (AVRational){1, OBE_CLOCK} );
    buffer_duration = frame_duration * enc_params->avc_param.sc.i_buffer_size;

    /* Broadcast because input and muxer can be stuck waiting for encoder */
    pthread_cond_broadcast( &encoder->encoder_cv );
    pthread_mutex_unlock( &encoder->encoder_mutex );

    user_sar_width = enc_params->avc_param.vui.i_sar_width;
    user_sar_height = enc_params->avc_param.vui.i_sar_height;

    while( 1 )
    {
        pthread_mutex_lock( &encoder->encoder_mutex );

        if( encoder->cancel_thread )
        {
            pthread_mutex_unlock( &encoder->encoder_mutex );
            break;
        }

        if( !encoder->num_raw_frames )
            pthread_cond_wait( &encoder->encoder_cv, &encoder->encoder_mutex );

        if( encoder->cancel_thread )
        {
            pthread_mutex_unlock( &encoder->encoder_mutex );
            break;
        }

        /* Reset the speedcontrol buffer if the source has dropped frames. Otherwise speedcontrol
         * stays in an underflow state and is locked to the fastest preset */
        pthread_mutex_lock( &h->drop_mutex );
        if( h->encoder_drop )
        {
            pthread_mutex_lock( &h->smoothing_mutex );
            h->smoothing_buffer_complete = 0;
            pthread_mutex_unlock( &h->smoothing_mutex );
            syslog( LOG_INFO, "Speedcontrol reset\n" );
            x264_speedcontrol_sync( s, enc_params->avc_param.sc.i_buffer_size, enc_params->avc_param.sc.f_buffer_init, 0 );
            h->encoder_drop = 0;
        }
        pthread_mutex_unlock( &h->drop_mutex );

        raw_frame = encoder->frames[0];
        pthread_mutex_unlock( &encoder->encoder_mutex );

        if( convert_obe_to_x264_pic( &pic, raw_frame ) < 0 )
        {
            syslog( LOG_ERR, "Malloc failed\n" );
            break;
        }

        /* FIXME: if frames are dropped this might not be true */
        pic.i_pts = pts++;
        pts2 = malloc( sizeof(int64_t) );
        if( !pts2 )
        {
            syslog( LOG_ERR, "Malloc failed\n" );
            break;
        }
        pts2[0] = raw_frame->pts;
        pic.opaque = pts2;

        /* If the AFD has changed, then change the SAR. x264 will write the SAR at the next keyframe
         * TODO: allow user to force keyframes in order to be frame accurate */
        if( raw_frame->sar_width  != enc_params->avc_param.vui.i_sar_width ||
            raw_frame->sar_height != enc_params->avc_param.vui.i_sar_height )
        {
            /* If the frame's SAR has been guessed but the user entered a reasonable SAR, then use it.
             * Otherwise, use the guessed SAR. */
            if( raw_frame->sar_guess && user_sar_width > 0 && user_sar_height > 0 )
            {
                enc_params->avc_param.vui.i_sar_width  = user_sar_width;
                enc_params->avc_param.vui.i_sar_height = user_sar_height;
            }
            else
            {
                enc_params->avc_param.vui.i_sar_width  = raw_frame->sar_width;
                enc_params->avc_param.vui.i_sar_height = raw_frame->sar_height;
            }

            x264_encoder_reconfig( s, &enc_params->avc_param );
        }

        /* Update speedcontrol based on the system state */
        if( h->obe_system == OBE_SYSTEM_TYPE_GENERIC )
        {
            pthread_mutex_lock( &h->smoothing_mutex );
            if( h->smoothing_buffer_complete )
            {
                /* Wait until a frame is sent out. */
                while( !h->smoothing_last_exit_time )
                    pthread_cond_wait( &h->smoothing_out_cv, &h->smoothing_mutex );

                /* time elapsed since last frame was removed */
                int64_t last_frame_delta = get_input_clock_in_mpeg_ticks( h ) - h->smoothing_last_exit_time;

                if( h->num_smoothing_frames )
                {
                    int64_t frame_durations = h->smoothing_frames[h->num_smoothing_frames-1]->real_dts - h->smoothing_frames[0]->real_dts + frame_duration;
                    buffer_fill = (float)(frame_durations - last_frame_delta)/buffer_duration;
                }
                else
                    buffer_fill = (float)(-1 * last_frame_delta)/buffer_duration;

                x264_speedcontrol_sync( s, buffer_fill, enc_params->avc_param.sc.i_buffer_size, 1 );
            }

            pthread_mutex_unlock( &h->smoothing_mutex );
        }

        frame_size = x264_encoder_encode( s, &nal, &i_nal, &pic, &pic_out );

        arrival_time = raw_frame->arrival_time;
        raw_frame->release_data( raw_frame );
        raw_frame->release_frame( raw_frame );
        remove_frame_from_encode_queue( encoder );

        if( frame_size < 0 )
        {
            syslog( LOG_ERR, "x264_encoder_encode failed\n" );
            break;
        }

        if( frame_size )
        {
            coded_frame = new_coded_frame( encoder->stream_id, frame_size );
            if( !coded_frame )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                break;
            }
            memcpy( coded_frame->data, nal[0].p_payload, frame_size );
            coded_frame->is_video = 1;
            coded_frame->len = frame_size;
            coded_frame->cpb_initial_arrival_time = pic_out.hrd_timing.safe_cpb_initial_arrival_time;
            coded_frame->cpb_final_arrival_time = pic_out.hrd_timing.cpb_final_arrival_time;
            coded_frame->real_dts = pic_out.hrd_timing.cpb_removal_time;
            coded_frame->real_pts = pic_out.hrd_timing.dpb_output_time;
            pts2 = pic_out.opaque;
            coded_frame->pts = pts2[0];
            coded_frame->random_access = pic_out.b_keyframe;
            coded_frame->priority = IS_X264_TYPE_I( pic_out.i_type );
            free( pic_out.opaque );

            if( h->obe_system == OBE_SYSTEM_TYPE_LOW_LATENCY )
            {
                coded_frame->arrival_time = arrival_time;
                //printf("\n Encode Latency %"PRIi64" \n", obe_mdate() - coded_frame->arrival_time );
            }

            add_to_smoothing_queue( h, coded_frame );
        }
     }

end:
    if( s )
        x264_encoder_close( s );
    free( enc_params );

    return NULL;
}