static void load_headers(struct obs_x264 *obsx264)
{
	x264_nal_t      *nals;
	int             nal_count;
	DARRAY(uint8_t) header;
	DARRAY(uint8_t) sei;

	da_init(header);
	da_init(sei);

	x264_encoder_headers(obsx264->context, &nals, &nal_count);

	for (int i = 0; i < nal_count; i++) {
		x264_nal_t *nal = nals+i;

		if (nal->i_type == NAL_SEI)
			da_push_back_array(sei, nal->p_payload, nal->i_payload);
		else
			da_push_back_array(header, nal->p_payload,
					nal->i_payload);
	}

	obsx264->extra_data      = header.array;
	obsx264->extra_data_size = header.num;
	obsx264->sei             = sei.array;
	obsx264->sei_size        = sei.num;
}
Exemple #2
0
void encode_spspps()
{
	int i = 0;
	int i_nal = 0;
	x264_nal_t* p_nal = NULL;

	if (x264_encoder_headers(x264_encode.handle, &p_nal, &i_nal) < 0)
		CAP_DBG_EXIT("x264_encoder_headers error!\n");

	for (i = 0; i < i_nal; i++) {
		if (p_nal[i].i_type == 7) {	//sps
			spslen = p_nal[i].i_payload - 4;
			memcpy(sps, p_nal[i].p_payload + 4, spslen);
		} else if (p_nal[i].i_type == 8) {	//pps
			ppslen = p_nal[i].i_payload - 4;
			memcpy(pps, p_nal[i].p_payload + 4, ppslen);
		}
	}

	// ricann debug
	CAP_DBG("sps = %s, len = %d\n", sps, spslen);
	CAP_DBG("pps = %s, len = %d\n", sps, ppslen);

	// ricann todo
	//write(fd_write, sps, spslen);
	//write(fd_write, pps, ppslen);
}
Exemple #3
0
uint8_t* video_encoder_get_headers(VideoEncoder *enc, int *bytesRead){

    x264_nal_t *nal_scoop;
    int n_nal;
    int nbytes = x264_encoder_headers(enc->encoder,&nal_scoop,&n_nal);

    if(nbytes < 0){
        fprintf(stderr,"x264_encoder_get_headers returns %d\n",nbytes);
        return NULL;
    }
    if(nbytes > enc->output_buffer_size){
	fprintf(
		stderr,
		"buffer overflow: x264_encoder_get_headers returns %d bytes, greater than %d buffer size\n",
		nbytes,enc->output_buffer_size);
	return NULL;
    }
    int i;
    int read = 0;
    for(i=0; i < n_nal ; i++){
        memcpy(
               &enc->output_buffer[read],
               nal_scoop[i].p_payload,
               nal_scoop[i].i_payload
               );

        read += nal_scoop[i].i_payload;
    }

    *bytesRead = read;
    return enc->output_buffer;
}
Exemple #4
0
static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt) {
    h264_module_t *mod=(h264_module_t*)vf->priv;

    if(parse_error)
        return 0;

    mod->mux->bih->biWidth = width;
    mod->mux->bih->biHeight = height;
    mod->mux->bih->biSizeImage = width * height * 3;
    mod->mux->aspect = (float)d_width/d_height;

    // make sure param is initialized
    x264enc_set_param(NULL, "");
    param.i_width = width;
    param.i_height = height;
    param.i_fps_num = mod->mux->h.dwRate;
    param.i_fps_den = mod->mux->h.dwScale;
    param.b_vfr_input = 0;
    param.vui.i_sar_width = d_width*height;
    param.vui.i_sar_height = d_height*width;

    x264_param_parse(&param, "stats", passtmpfile);

    switch(outfmt) {
    case IMGFMT_I420:
        param.i_csp = X264_CSP_I420;
        break;
    case IMGFMT_YV12:
        param.i_csp = X264_CSP_YV12;
        break;
    default:
        mp_msg(MSGT_MENCODER, MSGL_ERR, "Wrong colorspace.\n");
        return 0;
    }

    mod->x264 = x264_encoder_open(&param);
    if(!mod->x264) {
        mp_msg(MSGT_MENCODER, MSGL_ERR, "x264_encoder_open failed.\n");
        return 0;
    }

    if(!param.b_repeat_headers){
        x264_nal_t *nal;
        int extradata_size, nnal;

        extradata_size = x264_encoder_headers(mod->x264, &nal, &nnal);

        mod->mux->bih= realloc(mod->mux->bih, sizeof(*mod->mux->bih) + extradata_size);
        memcpy(mod->mux->bih + 1, nal->p_payload, extradata_size);
        mod->mux->bih->biSize= sizeof(*mod->mux->bih) + extradata_size;
    }

    if (param.i_bframe > 1 && param.i_bframe_pyramid)
        mod->mux->decoder_delay = 2;
    else
        mod->mux->decoder_delay = param.i_bframe ? 1 : 0;

    return 1;
}
bool x264Encoder::createHeader (void)
{

    x264_nal_t *nal;
    int        nalCount;

    extraDataLen = x264_encoder_headers(handle, &nal, &nalCount);
    extraData = new uint8_t[extraDataLen];
    extraDataLen = encodeNals(extraData, extraDataLen, nal, nalCount, true);

    return 1;
}
x264_t* msx264::msx264_encoder_open()
{
    int iResult;
    pX264Handle = x264_encoder_open(&params);
	assert(pX264Handle);

	iResult = x264_encoder_headers(pX264Handle, &pNals, &iNal);
	assert(iResult >= 0);

//* 获取整个流的PPS和SPS,不需要可以不调用.
	iResult = x264_encoder_headers(pX264Handle, &pNals, &iNal);
	assert(iResult >= 0);
//* PPS SPS 总共只有36B,如何解析出来呢?
	for (int i = 0; i < iNal; ++i) {
		switch (pNals[i].i_type) {
		case NAL_SPS:
			break;
		case NAL_PPS:
			break;
		default:
			break;
		}
	}
}
Exemple #7
0
void CH264Encoder::GetSPSAndPPS(unsigned char*sps,long&spslen,unsigned char*pps,long&ppslen)
{
	if (m_hx264!=NULL)
	{
		int i_nal=0;
		x264_nal_t*tnal=NULL;
		x264_encoder_headers(m_hx264,&tnal,&i_nal);
		spslen=tnal[0].i_payload-4;
		memcpy(sps,tnal[0].p_payload+4,spslen);
		ppslen=tnal[1].i_payload-4;
		memcpy(pps,tnal[1].p_payload+4,ppslen);
	}else
	{
		spslen=0;
		ppslen=0;
	}
}
Exemple #8
0
int init_head(x264_t * x264_handle, char * header, int hlen)
{
    x264_nal_t * nal_;
    int nal_size = 0;
    
    x264_encoder_headers(x264_handle, &nal_, &nal_size);
    
    for (int i = 0; i < nal_size; i++) {
        x264_nal_t & nal = nal_[i];
        switch (nal.i_type) {
            case NAL_SPS:
                printb(nal.p_payload, nal.i_payload);
                break;
            case NAL_PPS:
                printb(nal.p_payload, nal.i_payload);
                break;
        }
    }
}
Exemple #9
0
    void GetHeaders(DataPacket &packet)
    {
        if(!HeaderPacket.Num())
        {
            x264_nal_t *nalOut;
            int nalNum;

            x264_encoder_headers(x264, &nalOut, &nalNum);

            for(int i=0; i<nalNum; i++)
            {
                x264_nal_t &nal = nalOut[i];

                if(nal.i_type == NAL_SPS)
                {
                    BufferOutputSerializer headerOut(HeaderPacket);

                    headerOut.OutputByte(0x17);
                    headerOut.OutputByte(0);
                    headerOut.OutputByte(0);
                    headerOut.OutputByte(0);
                    headerOut.OutputByte(0);
                    headerOut.OutputByte(1);
                    headerOut.Serialize(nal.p_payload+5, 3);
                    headerOut.OutputByte(0xff);
                    headerOut.OutputByte(0xe1);
                    headerOut.OutputWord(htons(nal.i_payload-4));
                    headerOut.Serialize(nal.p_payload+4, nal.i_payload-4);

                    x264_nal_t &pps = nalOut[i+1]; //the PPS always comes after the SPS

                    headerOut.OutputByte(1);
                    headerOut.OutputWord(htons(pps.i_payload-4));
                    headerOut.Serialize(pps.p_payload+4, pps.i_payload-4);
                }
            }
        }

        packet.lpPacket = HeaderPacket.Array();
        packet.size     = HeaderPacket.Num();
    }
bool VideoEncoder::createDecoderConfigurationRecord(AVCDecoderConfigurationRecord& rec) {
  assert(encoder);

  int num_nals = 0;
  x264_nal_t* nals = NULL;

  x264_encoder_headers(encoder, &nals, &num_nals);

  if(!nals) {
    STREAMER_ERROR("error: cannot get encoder headers from x264.\n");
    return false;
  }

  if(num_nals != 3) {
    STREAMER_WARNING("warning: we expect number of nals from x264_encoder_headers to be 3.\n");
    return false;
  }

  int sps_size = nals[0].i_payload;
  int pps_size = nals[1].i_payload;
  int sei_size = nals[2].i_payload;
  uint8_t* sps = nals[0].p_payload + 4;
  uint8_t* pps = nals[1].p_payload + 4;
  uint8_t* sei = nals[2].p_payload + 4;

  rec.configuration_version = 1;
  rec.avc_profile_indication = sps[1];
  rec.profile_compatibility = sps[2];
  rec.avc_level_indication = sps[3];

  std::copy(sps, sps+(sps_size-4), std::back_inserter(rec.sps));
  std::copy(pps, pps+(pps_size-4), std::back_inserter(rec.pps));
  std::copy(sei, sei+(sei_size-4), std::back_inserter(rec.sei));

  STREAMER_VERBOSE("nals[0].i_payload: %d, sps_size: %d, profile: %d\n", nals[0].i_payload, sps_size, sps[1]);
  STREAMER_VERBOSE("nals[1].i_payload: %d, pps_size: %d\n", nals[1].i_payload, pps_size);
  STREAMER_VERBOSE("nals[2].i_payload: %d, sei_size: %d / %ld\n", nals[2].i_payload, sei_size, rec.sei.size());

  return true;
} 
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; 
}
Exemple #12
0
/*****************************************************************************
 * Open: probe the encoder
 *****************************************************************************/
static int  Open ( vlc_object_t *p_this )
{
    encoder_t     *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;
    int i_val;
    char *psz_val;
    int i_qmin = 0, i_qmax = 0;
    x264_nal_t    *nal;
    int i, i_nal;

    if( p_enc->fmt_out.i_codec != VLC_CODEC_H264 &&
        !p_enc->b_force )
    {
        return VLC_EGENERIC;
    }
    /* X264_POINTVER or X264_VERSION are not available */
    msg_Dbg ( p_enc, "version x264 0.%d.X", X264_BUILD );

    config_ChainParse( p_enc, SOUT_CFG_PREFIX, ppsz_sout_options, p_enc->p_cfg );

    p_enc->fmt_out.i_cat = VIDEO_ES;
    p_enc->fmt_out.i_codec = VLC_CODEC_H264;
    p_enc->fmt_in.i_codec = VLC_CODEC_I420;

    p_enc->pf_encode_video = Encode;
    p_enc->pf_encode_audio = NULL;
    p_enc->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;
    p_sys->i_interpolated_dts = 0;
    p_sys->psz_stat_name = NULL;
    p_sys->p_buffer = NULL;

    x264_param_default( &p_sys->param );
    p_sys->param.i_width  = p_enc->fmt_in.video.i_width;
    p_sys->param.i_height = p_enc->fmt_in.video.i_height;

    p_sys->param.rc.f_qcompress = var_GetFloat( p_enc, SOUT_CFG_PREFIX "qcomp" );

    /* transcode-default bitrate is 0,
     * set more to ABR if user specifies bitrate */
    if( p_enc->fmt_out.i_bitrate > 0 )
    {
        p_sys->param.rc.i_bitrate = p_enc->fmt_out.i_bitrate / 1000;
        p_sys->param.rc.i_rc_method = X264_RC_ABR;
    }
    else /* Set default to CRF */
    {
        i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "crf" );
        if( i_val > 0 && i_val <= 51 )
        {
            p_sys->param.rc.f_rf_constant = i_val;
            p_sys->param.rc.i_rc_method = X264_RC_CRF;
        }
    }

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "qpstep" );
    if( i_val >= 0 && i_val <= 51 ) p_sys->param.rc.i_qp_step = i_val;

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "qpmin" );
    if( i_val >= 0 && i_val <= 51 )
    {
        i_qmin = i_val;
        p_sys->param.rc.i_qp_min = i_qmin;
    }
    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "qpmax" );
    if( i_val >= 0 && i_val <= 51 )
    {
        i_qmax = i_val;
        p_sys->param.rc.i_qp_max = i_qmax;
    }

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "qp" );
    if( i_val >= 0 && i_val <= 51 )
    {
        if( i_qmin > i_val ) i_qmin = i_val;
        if( i_qmax < i_val ) i_qmax = i_val;

        /* User defined QP-value, so change ratecontrol method */
        p_sys->param.rc.i_rc_method = X264_RC_CQP;
        p_sys->param.rc.i_qp_constant = i_val;
        p_sys->param.rc.i_qp_min = i_qmin;
        p_sys->param.rc.i_qp_max = i_qmax;
    }


    p_sys->param.rc.f_rate_tolerance = var_GetFloat( p_enc,
                            SOUT_CFG_PREFIX "ratetol" );
    p_sys->param.rc.f_vbv_buffer_init = var_GetFloat( p_enc,
                            SOUT_CFG_PREFIX "vbv-init" );
    p_sys->param.rc.i_vbv_buffer_size = var_GetInteger( p_enc,
                            SOUT_CFG_PREFIX "vbv-bufsize" );

    /* max bitrate = average bitrate -> CBR */
    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "vbv-maxrate" );

    if( !i_val && p_sys->param.rc.i_rc_method == X264_RC_ABR )
        p_sys->param.rc.i_vbv_max_bitrate = p_sys->param.rc.i_bitrate;
    else if ( i_val )
        p_sys->param.rc.i_vbv_max_bitrate = i_val;

    p_sys->param.b_cabac = var_GetBool( p_enc, SOUT_CFG_PREFIX "cabac" );

    /* disable deblocking when nf (no loop filter) is enabled */
    p_sys->param.b_deblocking_filter = !var_GetBool( p_enc, SOUT_CFG_PREFIX "nf" );

    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "deblock" );
    if( psz_val )
    {
        char *p = strchr( psz_val, ':' );
        p_sys->param.i_deblocking_filter_alphac0 = atoi( psz_val );
        p_sys->param.i_deblocking_filter_beta = p ?
                    atoi( p+1 ) : p_sys->param.i_deblocking_filter_alphac0;
        free( psz_val );
    }

    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "psy-rd" );
    if( psz_val )
    {
        char *p = strchr( psz_val, ':' );
        p_sys->param.analyse.f_psy_rd = us_atof( psz_val );
        p_sys->param.analyse.f_psy_trellis = p ? us_atof( p+1 ) : 0;
        free( psz_val );
    }

    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "level" );
    if( psz_val )
    {
        if( us_atof (psz_val) < 6 )
            p_sys->param.i_level_idc = (int) (10 * us_atof (psz_val)
                                              + .5);
        else
            p_sys->param.i_level_idc = atoi (psz_val);
        free( psz_val );
    }

    p_sys->param.b_interlaced = var_GetBool( p_enc, SOUT_CFG_PREFIX "interlaced" );
    p_sys->param.rc.f_ip_factor = var_GetFloat( p_enc, SOUT_CFG_PREFIX "ipratio" );
    p_sys->param.rc.f_pb_factor = var_GetFloat( p_enc, SOUT_CFG_PREFIX "pbratio" );
    p_sys->param.rc.f_complexity_blur = var_GetFloat( p_enc, SOUT_CFG_PREFIX "cplxblur" );
    p_sys->param.rc.f_qblur = var_GetFloat( p_enc, SOUT_CFG_PREFIX "qblur" );
    p_sys->param.rc.i_aq_mode = var_GetInteger( p_enc, SOUT_CFG_PREFIX "aq-mode" );
    p_sys->param.rc.f_aq_strength = var_GetFloat( p_enc, SOUT_CFG_PREFIX "aq-strength" );

    if( var_GetBool( p_enc, SOUT_CFG_PREFIX "verbose" ) )
        p_sys->param.i_log_level = X264_LOG_DEBUG;

    if( var_GetBool( p_enc, SOUT_CFG_PREFIX "quiet" ) )
        p_sys->param.i_log_level = X264_LOG_NONE;

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "sps-id" );
    if( i_val >= 0 ) p_sys->param.i_sps_id = i_val;

    if( var_GetBool( p_enc, SOUT_CFG_PREFIX "aud" ) )
        p_sys->param.b_aud = true;

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "keyint" );
    if( i_val > 0 ) p_sys->param.i_keyint_max = i_val;

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "min-keyint" );
    if( i_val > 0 ) p_sys->param.i_keyint_min = i_val;

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "bframes" );
    if( i_val >= 0 && i_val <= 16 )
        p_sys->param.i_bframe = i_val;

#if X264_BUILD >= 78
    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "bpyramid" );
    p_sys->param.i_bframe_pyramid = X264_B_PYRAMID_NONE;
    if( !strcmp( psz_val, "none" ) )
    {
       p_sys->param.i_bframe_pyramid = X264_B_PYRAMID_NONE;
    } else if ( !strcmp( psz_val, "strict" ) )
    {
       p_sys->param.i_bframe_pyramid = X264_B_PYRAMID_STRICT;
    } else if ( !strcmp( psz_val, "normal" ) )
    {
       p_sys->param.i_bframe_pyramid = X264_B_PYRAMID_NORMAL;
    }
    free( psz_val );
#else
    p_sys->param.b_bframe_pyramid = var_GetBool( p_enc, SOUT_CFG_PREFIX "bpyramid" );
 #endif

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "ref" );
    if( i_val > 0 && i_val <= 15 )
        p_sys->param.i_frame_reference = i_val;

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "scenecut" );
    if( i_val >= -1 && i_val <= 100 )
        p_sys->param.i_scenecut_threshold = i_val;

    p_sys->param.b_deterministic = var_GetBool( p_enc,
                        SOUT_CFG_PREFIX "non-deterministic" );

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "subme" );
    if( i_val >= 1 && i_val <= SUBME_MAX )
        p_sys->param.analyse.i_subpel_refine = i_val;

    //TODO: psz_val == NULL ?
    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "me" );
    if( !strcmp( psz_val, "dia" ) )
    {
        p_sys->param.analyse.i_me_method = X264_ME_DIA;
    }
    else if( !strcmp( psz_val, "hex" ) )
    {
        p_sys->param.analyse.i_me_method = X264_ME_HEX;
    }
    else if( !strcmp( psz_val, "umh" ) )
    {
        p_sys->param.analyse.i_me_method = X264_ME_UMH;
    }
    else if( !strcmp( psz_val, "esa" ) )
    {
        p_sys->param.analyse.i_me_method = X264_ME_ESA;
    }
    else if( !strcmp( psz_val, "tesa" ) )
    {
        p_sys->param.analyse.i_me_method = X264_ME_TESA;
    }
    free( psz_val );

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "merange" );
    if( i_val >= 0 && i_val <= 64 )
        p_sys->param.analyse.i_me_range = i_val;

    p_sys->param.analyse.i_mv_range = var_GetInteger( p_enc,
                                    SOUT_CFG_PREFIX "mvrange" );
    p_sys->param.analyse.i_mv_range_thread = var_GetInteger( p_enc,
                                    SOUT_CFG_PREFIX "mvrange-thread" );

    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "direct" );
    if( !strcmp( psz_val, "none" ) )
    {
        p_sys->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_NONE;
    }
    else if( !strcmp( psz_val, "spatial" ) )
    {
        p_sys->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
    }
    else if( !strcmp( psz_val, "temporal" ) )
    {
        p_sys->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_TEMPORAL;
    }
    else if( !strcmp( psz_val, "auto" ) )
    {
        p_sys->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
    }
    free( psz_val );

    p_sys->param.analyse.b_psnr = var_GetBool( p_enc, SOUT_CFG_PREFIX "psnr" );
    p_sys->param.analyse.b_ssim = var_GetBool( p_enc, SOUT_CFG_PREFIX "ssim" );
    p_sys->param.analyse.b_weighted_bipred = var_GetBool( p_enc,
                                    SOUT_CFG_PREFIX "weightb" );
    p_sys->param.i_bframe_adaptive = var_GetInteger( p_enc,
                                    SOUT_CFG_PREFIX "b-adapt" );

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "b-bias" );
    if( i_val >= -100 && i_val <= 100 )
        p_sys->param.i_bframe_bias = i_val;

    p_sys->param.analyse.b_chroma_me = var_GetBool( p_enc,
                                    SOUT_CFG_PREFIX "chroma-me" );
    p_sys->param.analyse.i_chroma_qp_offset = var_GetInteger( p_enc,
                                    SOUT_CFG_PREFIX "chroma-qp-offset" );
    p_sys->param.analyse.b_mixed_references = var_GetBool( p_enc,
                                    SOUT_CFG_PREFIX "mixed-refs" );

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "trellis" );
    if( i_val >= 0 && i_val <= 2 )
        p_sys->param.analyse.i_trellis = i_val;

    p_sys->param.analyse.b_fast_pskip = var_GetBool( p_enc,
                                    SOUT_CFG_PREFIX "fast-pskip" );

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "nr" );
    if( i_val >= 0 && i_val <= 1000 )
        p_sys->param.analyse.i_noise_reduction = i_val;

    p_sys->param.analyse.b_dct_decimate = var_GetBool( p_enc,
                                    SOUT_CFG_PREFIX "dct-decimate" );

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "deadzone-inter" );
    if( i_val >= 0 && i_val <= 32 )
        p_sys->param.analyse.i_luma_deadzone[0] = i_val;

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "deadzone-intra" );
    if( i_val >= 0 && i_val <= 32 )
        p_sys->param.analyse.i_luma_deadzone[1] = i_val;

    if( !var_GetBool( p_enc, SOUT_CFG_PREFIX "asm" ) )
        p_sys->param.cpu = 0;

#ifndef X264_ANALYSE_BSUB16x16
#   define X264_ANALYSE_BSUB16x16 0
#endif
    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "partitions" );
    if( !strcmp( psz_val, "none" ) )
    {
        p_sys->param.analyse.inter = 0;
    }
    else if( !strcmp( psz_val, "fast" ) )
    {
        p_sys->param.analyse.inter = X264_ANALYSE_I4x4;
    }
    else if( !strcmp( psz_val, "normal" ) )
    {
        p_sys->param.analyse.inter =
            X264_ANALYSE_I4x4 |
            X264_ANALYSE_PSUB16x16;
#ifdef X264_ANALYSE_I8x8
        p_sys->param.analyse.inter |= X264_ANALYSE_I8x8;
#endif
    }
    else if( !strcmp( psz_val, "slow" ) )
    {
        p_sys->param.analyse.inter =
            X264_ANALYSE_I4x4 |
            X264_ANALYSE_PSUB16x16 |
            X264_ANALYSE_BSUB16x16;
#ifdef X264_ANALYSE_I8x8
        p_sys->param.analyse.inter |= X264_ANALYSE_I8x8;
#endif
    }
    else if( !strcmp( psz_val, "all" ) )
    {
        p_sys->param.analyse.inter = ~0;
    }
    free( psz_val );

    p_sys->param.analyse.b_transform_8x8 = var_GetBool( p_enc,
                                    SOUT_CFG_PREFIX "8x8dct" );

    if( p_enc->fmt_in.video.i_aspect > 0 )
    {
        int64_t i_num, i_den;
        unsigned int i_dst_num, i_dst_den;

        i_num = p_enc->fmt_in.video.i_aspect *
            (int64_t)p_enc->fmt_in.video.i_height;
        i_den = VOUT_ASPECT_FACTOR * p_enc->fmt_in.video.i_width;
        vlc_ureduce( &i_dst_num, &i_dst_den, i_num, i_den, 0 );

        p_sys->param.vui.i_sar_width = i_dst_num;
        p_sys->param.vui.i_sar_height = i_dst_den;
    }

    if( p_enc->fmt_in.video.i_frame_rate_base > 0 )
    {
        p_sys->param.i_fps_num = p_enc->fmt_in.video.i_frame_rate;
        p_sys->param.i_fps_den = p_enc->fmt_in.video.i_frame_rate_base;
    }

    /* x264 vbv-bufsize = 0 (default). if not provided set period
       in seconds for local maximum bitrate (cache/bufsize) based
       on average bitrate when use has told bitrate.
       vbv-buffer size is set to bitrate * secods between keyframes */
    if( !p_sys->param.rc.i_vbv_buffer_size &&
         p_sys->param.rc.i_rc_method == X264_RC_ABR &&
         p_sys->param.i_fps_num )
    {
        p_sys->param.rc.i_vbv_buffer_size = p_sys->param.rc.i_bitrate *
            p_sys->param.i_fps_den;
        p_sys->param.rc.i_vbv_buffer_size *= p_sys->param.i_keyint_max;
        p_sys->param.rc.i_vbv_buffer_size /= p_sys->param.i_fps_num;
    }

    /* Check if user has given some profile (baseline,main,high) to limit
     * settings, and apply those*/
    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "profile" );
    if( psz_val )
    {
        if( !strcasecmp( psz_val, "baseline" ) )
        {
            msg_Dbg( p_enc, "Limiting to baseline profile");
            p_sys->param.analyse.b_transform_8x8 = 0;
            p_sys->param.b_cabac = 0;
            p_sys->param.i_bframe = 0;
        }
        else if (!strcasecmp( psz_val, "main" ) )
        {
            msg_Dbg( p_enc, "Limiting to main-profile");
            p_sys->param.analyse.b_transform_8x8 = 0;
        }
        /* high profile don't restrict stuff*/
    }
    free( psz_val );


    unsigned i_cpu = vlc_CPU();
    if( !(i_cpu & CPU_CAPABILITY_MMX) )
    {
        p_sys->param.cpu &= ~X264_CPU_MMX;
    }
    if( !(i_cpu & CPU_CAPABILITY_MMXEXT) )
    {
        p_sys->param.cpu &= ~X264_CPU_MMXEXT;
    }
    if( !(i_cpu & CPU_CAPABILITY_SSE) )
    {
        p_sys->param.cpu &= ~X264_CPU_SSE;
    }
    if( !(i_cpu & CPU_CAPABILITY_SSE2) )
    {
        p_sys->param.cpu &= ~X264_CPU_SSE2;
    }

    /* BUILD 29 adds support for multi-threaded encoding while BUILD 49 (r543)
       also adds support for threads = 0 for automatically selecting an optimal
       value (cores * 1.5) based on detected CPUs. Default behavior for x264 is
       threads = 1, however VLC usage differs and uses threads = 0 (auto) by
       default unless ofcourse transcode threads is explicitly specified.. */
    p_sys->param.i_threads = p_enc->i_threads;

    psz_val = var_GetString( p_enc, SOUT_CFG_PREFIX "stats" );
    if( psz_val )
    {
        p_sys->param.rc.psz_stat_in  =
        p_sys->param.rc.psz_stat_out =
        p_sys->psz_stat_name         = psz_val;
    }

    i_val = var_GetInteger( p_enc, SOUT_CFG_PREFIX "pass" );
    if( i_val > 0 && i_val <= 3 )
    {
        p_sys->param.rc.b_stat_write = i_val & 1;
        p_sys->param.rc.b_stat_read = i_val & 2;
    }

    /* We need to initialize pthreadw32 before we open the encoder,
       but only once for the whole application. Since pthreadw32
       doesn't keep a refcount, do it ourselves. */
#ifdef PTW32_STATIC_LIB
    vlc_value_t lock, count;

    var_Create( p_enc->p_libvlc, "pthread_win32_mutex", VLC_VAR_MUTEX );
    var_Get( p_enc->p_libvlc, "pthread_win32_mutex", &lock );
    vlc_mutex_lock( lock.p_address );

    var_Create( p_enc->p_libvlc, "pthread_win32_count", VLC_VAR_INTEGER );
    var_Get( p_enc->p_libvlc, "pthread_win32_count", &count );

    if( count.i_int == 0 )
    {
        msg_Dbg( p_enc, "initializing pthread-win32" );
        if( !pthread_win32_process_attach_np() || !pthread_win32_thread_attach_np() )
        {
            msg_Warn( p_enc, "pthread Win32 Initialization failed" );
            vlc_mutex_unlock( lock.p_address );
            return VLC_EGENERIC;
        }
    }

    count.i_int++;
    var_Set( p_enc->p_libvlc, "pthread_win32_count", count );
    vlc_mutex_unlock( lock.p_address );

#endif

    /* Set lookahead value to lower than default,
     * as rtp-output without mux doesn't handle
     * difference that well yet*/
    p_sys->param.rc.i_lookahead=5;

    /* Open the encoder */
    p_sys->h = x264_encoder_open( &p_sys->param );

    if( p_sys->h == NULL )
    {
        msg_Err( p_enc, "cannot open x264 encoder" );
        Close( VLC_OBJECT(p_enc) );
        return VLC_EGENERIC;
    }

    /* alloc mem */
    p_sys->i_buffer = 4 * p_enc->fmt_in.video.i_width *
        p_enc->fmt_in.video.i_height + 1000;
    p_sys->p_buffer = malloc( p_sys->i_buffer );
    if( !p_sys->p_buffer )
    {
        Close( VLC_OBJECT(p_enc) );
        return VLC_ENOMEM;
    }

    /* get the globals headers */
    p_enc->fmt_out.i_extra = 0;
    p_enc->fmt_out.p_extra = NULL;

    p_enc->fmt_out.i_extra = x264_encoder_headers( p_sys->h, &nal, &i_nal );
    p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
    if( !p_enc->fmt_out.p_extra )
    {
        Close( VLC_OBJECT(p_enc) );
        return VLC_ENOMEM;
    }
    void *p_tmp = p_enc->fmt_out.p_extra;
    for( i = 0; i < i_nal; i++ )
    {
        memcpy( p_tmp, nal[i].p_payload, nal[i].i_payload );
        p_tmp += nal[i].i_payload;
    }

    return VLC_SUCCESS;
}
Exemple #13
0
bool CX264VideoEncoder::GetEsConfig (uint8_t **ppEsConfig, 
				     uint32_t *pEsConfigLen)
{
#ifdef DEBUG_H264
  debug_message("Getting es config for x264");
#endif
  CHECK_AND_FREE(Profile()->m_videoMpeg4Config);
  Profile()->m_videoMpeg4ConfigLength = 0;

  x264_nal_t *nal;
  int nal_num;
  if (x264_encoder_headers(m_h, &nal, &nal_num) != 0) {
    error_message("x264 - can't create headers");
    StopEncoder();
    return false;
  }
  
  uint8_t *seqptr = m_vopBuffer;
  uint8_t *picptr = m_vopBuffer;
  uint32_t seqlen = 0, piclen = 0;
  bool found_seq = false, found_pic = false;
  if (m_vopBuffer == NULL) {
    m_vopBuffer = (u_int8_t*)malloc(Profile()->m_videoMaxVopSize);
  }
  uint8_t *vopBuffer = m_vopBuffer;
  int vopBufferLen = Profile()->m_videoMaxVopSize;

  for (int ix = 0; ix < nal_num; ix++) {
    int i_size;
    i_size = x264_nal_encode(vopBuffer, &vopBufferLen, 1, &nal[ix]);
    if (i_size > 0) {
      bool useit = false;
      uint header_size = 0;
      if (h264_is_start_code(vopBuffer)) {
	header_size = vopBuffer[2] == 1 ? 3 : 4;
      }
      if (nal[ix].i_type == H264_NAL_TYPE_SEQ_PARAM) {
	found_seq = true;
	seqlen = i_size - header_size;
	seqptr = vopBuffer + header_size;
	useit = true;
      } else if (nal[ix].i_type == H264_NAL_TYPE_PIC_PARAM) {
	found_pic = true;
	piclen = i_size - header_size;
	picptr = vopBuffer + header_size;
	useit = true;
      }
      if (useit) {
	vopBuffer += i_size;
	vopBufferLen -= i_size;
      }
    }
  }
	  
  if (found_seq == false) {
    error_message("Can't find seq pointer in x264 header");
    StopEncoder();
    return false;
  }
  if (found_pic == false) {
    error_message("Can't find pic pointer in x264 header");
    StopEncoder();
    return false;
  }

  uint8_t *p = seqptr;
  
  if (*p == 0 && p[1] == 0 && 
      (p[2] == 1 || (p[2] == 0 && p[3] == 1))) {
    if (p[2] == 0) p += 4;
    else p += 3;
  }
  Profile()->m_videoMpeg4ProfileId = p[1] << 16 |
    p[2] << 8 |
    p[3];

  debug_message("profile id %x", Profile()->m_videoMpeg4ProfileId);
  
  char *sprop = NULL;
  char *base64;
  base64 = MP4BinaryToBase64(seqptr, seqlen);
  sprop = strdup(base64);
  free(base64);
  base64 = MP4BinaryToBase64(picptr, piclen);
  sprop = (char *)realloc(sprop, strlen(sprop) + strlen(base64) + 1 + 1);
  strcat(sprop, ",");
  strcat(sprop, base64);
  free(base64);

  debug_message("sprop %s", sprop);
  Profile()->m_videoMpeg4Config = (uint8_t *)sprop;
  Profile()->m_videoMpeg4ConfigLength = strlen(sprop) + 1;
  StopEncoder();
  return true;
}
bool X264Encoder::openX264Encoder()
{
    this->closeX264Encoder();
    if(!pParameter)
    {
        pParameter = (x264_param_t *)malloc(sizeof(x264_param_t));
        if (!pParameter) {
            this->closeX264Encoder();
            return false;
        }
        memset(pParameter, 0, sizeof(x264_param_t));
    }
    int ret = x264_param_default_preset(pParameter, "ultrafast", "zerolatency");
    if (ret != 0) {
        this->closeX264Encoder();
        return false;
    }
    pParameter->i_threads = 1;
    pParameter->b_sliced_threads = 0;
    pParameter->i_sync_lookahead = X264_SYNC_LOOKAHEAD_AUTO;
    pParameter->i_width = width;
	pParameter->i_height = height;
	pParameter->i_frame_total = 0;
	pParameter->b_deterministic = 1;
	pParameter->i_frame_reference = 4;
	pParameter->i_bframe = 0;
	pParameter->i_bframe_pyramid = 0;
	pParameter->i_bframe_adaptive = 0;
	pParameter->b_intra_refresh = 0;
	pParameter->i_csp = X264_CSP_I420;
    pParameter->i_level_idc = 9;
    pParameter->i_keyint_min = 10;
    pParameter->i_keyint_max = 30;
    pParameter->b_repeat_headers = 1;
    pParameter->b_interlaced = 0;
    pParameter->i_cqm_preset = X264_CQM_FLAT;
    pParameter->psz_cqm_file = NULL;
    pParameter->b_aud = 0;
	pParameter->i_nal_hrd = X264_NAL_HRD_NONE;
	pParameter->i_scenecut_threshold  = 40;
	pParameter->i_bframe_bias = 0;
    pParameter->i_fps_num = i_fps;
    pParameter->i_fps_den = 1;
    pParameter->i_timebase_num = 1;
    pParameter->i_timebase_den = 1000000;

    pParameter->analyse.i_weighted_pred = 0;
    pParameter->analyse.b_weighted_bipred = 0;
	pParameter->analyse.b_chroma_me = 1;
	pParameter->analyse.i_trellis = 1;
	pParameter->analyse.i_subpel_refine = 4;
	pParameter->analyse.b_transform_8x8 = 1;
	pParameter->analyse.i_me_range = 8;
	pParameter->analyse.i_me_method = X264_ME_UMH; //2
    pParameter->analyse.i_direct_mv_pred = X264_DIRECT_PRED_TEMPORAL; //2
    pParameter->analyse.intra = 0;
    pParameter->analyse.inter = 0;

    pParameter->b_cabac = 0;
    pParameter->b_vfr_input = 0;

    pParameter->rc.i_rc_method = X264_RC_ABR;//X264_RC_CQP;
    pParameter->rc.f_qcompress = 0.6f;  // 0.0 => cbr, 1.0 => constant qp
    pParameter->rc.i_lookahead = 0;
    pParameter->rc.b_mb_tree = 0;
    pParameter->rc.i_qp_min = 10;
    pParameter->rc.i_qp_max = 51;
    pParameter->rc.i_qp_step = 3;
    pParameter->rc.i_qp_constant = 10;
    pParameter->rc.f_rf_constant = 10;		  // 1pass VBR, nominal QP
    pParameter->rc.i_bitrate = 300;
    pParameter->rc.i_vbv_max_bitrate = 300;
    pParameter->rc.i_vbv_buffer_size = 300;
    pParameter->rc.f_vbv_buffer_init = 0.6f;
    pParameter->rc.f_rate_tolerance = 10 / 100.0f; // In CRF mode,maximum CRF as caused by VBV

    if(x264_param_apply_profile(pParameter, "baseline"))
    {
        this->closeX264Encoder();
        return false;
    }

    if (!x264EncoderHandle) {
        x264EncoderHandle = x264_encoder_open(pParameter);
        assert(x264EncoderHandle != NULL);
    }

    int	nal_count = 0;
	x264_nal_t* nals = NULL;
    x264_encoder_headers(x264EncoderHandle, &nals, &nal_count);
    assert(nal_count > 0);

    for (int index = 0; index < nal_count; ++index)
    {
		if (nals[index].i_type == NAL_SPS) {
			spslen = createNalBuffer(sps, nals[index].p_payload, nals[index].i_payload);
		}
		if (nals[index].i_type == NAL_PPS) {
			ppslen = createNalBuffer(pps, nals[index].p_payload, nals[index].i_payload);
		}
	}

    assert(spslen != 0);
    assert(ppslen != 0);

    if (!pOutput) {
        pOutput = (x264_picture_t *)malloc(sizeof(x264_picture_t));
        if (!pOutput) {
            this->closeX264Encoder();
            return false;
        }
    }
    memset(pOutput, 0, sizeof(x264_picture_t));
    return true;
}
int BleX264Encoder::init()
{
    MOption *option = MOption::instance();

    QString presetName  = option->option("preset", "x264").toString();
    QString tuneName    = option->option("tune", "x264").toString();
    QString profileName = option->option("profile", "x264").toString();
    int fps = option->option("fps", "encoder").toInt();
    int kbps = option->option("bitrate", "encoder").toInt();

    QSize wh = option->option("res", "encoder").toSize();
    int width = wh.width();
    int height = wh.height();

    int maxBitRate = kbps;
    int bufferSize = maxBitRate;
    bool bUseCBR = (option->option("BitrateMode", "x264").toString() == "CBR");
    int quality = option->option("quality", "x264").toInt();
    int KeyFrameInterval = option->option("KeyFrameInterval", "x264").toInt();
    int threadCount = option->option(Key_Thread_Count, Group_X264).toInt();
    bool enableBFrame = option->option(Key_Enable_B_Frame, Group_X264).toString() == "true" ? true : false;
    int B_frame_count = option->option(Key_B_Frame_Count, Group_X264).toInt();

    m_x264Param = new x264_param_t;

    if (tuneName == "Default" || tuneName.isEmpty()) {
        x264_param_default_preset(m_x264Param , presetName.toStdString().c_str(), NULL);
        log_trace("libx264 preset set to %s, tune set to NULL"
                  , presetName.toStdString().c_str());
    } else {
        x264_param_default_preset(m_x264Param , presetName.toStdString().c_str(), tuneName.toStdString().c_str());
        log_trace("libx264 preset set to %s, tune set to %s"\
                  , presetName.toStdString().c_str(), tuneName.toStdString().c_str());
    }

    if (profileName != "Default") {
        x264_param_apply_profile(m_x264Param, profileName.toStdString().c_str());
        log_trace("libx264 profile set to %s", profileName.toStdString().c_str());
    } else {
        log_trace("libx264 profile set to Default");
    }

    if(bUseCBR)
    {
        m_x264Param->rc.i_bitrate          = maxBitRate;
        m_x264Param->rc.i_vbv_max_bitrate  = maxBitRate; // vbv-maxrate
        m_x264Param->rc.i_vbv_buffer_size  = bufferSize; // vbv-bufsize
        m_x264Param->i_nal_hrd             = X264_NAL_HRD_CBR;
        m_x264Param->rc.i_rc_method        = X264_RC_ABR;
        m_x264Param->rc.f_rf_constant      = 0.0f;
    }
    else
    {
        m_x264Param->rc.i_vbv_max_bitrate  = maxBitRate;  // vbv-maxrate
        m_x264Param->rc.i_vbv_buffer_size  = bufferSize;  // vbv-bufsize
        m_x264Param->rc.i_rc_method        = X264_RC_CRF; // X264_RC_CRF;
        m_x264Param->rc.f_rf_constant      = 10.0f + float(20 - quality);

        log_trace("libx264 quality set to %d", quality);
    }

    m_x264Param->b_vfr_input           = 1;
    m_x264Param->i_keyint_max          = fps * KeyFrameInterval;
    m_x264Param->i_width               = width;
    m_x264Param->i_height              = height;
    m_x264Param->vui.b_fullrange       = 0;          //specify full range input levels

    // For some codecs, the time base is closer to the field rate than the frame rate.
    // Most notably, H.264 and MPEG-2 specify time_base as half of frame duration
    // if no telecine is used ...
    // Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2.
    // @see ffmpeg: AVodecContex::ticks_per_frame
    // never use timebase = 1000, because vlc will show 1000 fps !!
    int ticks_per_frame = 2;
    m_x264Param->i_timebase_num = 1;
    m_x264Param->i_timebase_den = fps;

    m_x264Param->i_fps_num = m_x264Param->i_timebase_den;
    m_x264Param->i_fps_den = m_x264Param->i_timebase_num * ticks_per_frame;

    // disable start code 00 00 00 01 before NAL
    // instead of nalu size
    m_x264Param->b_repeat_headers = 0;
    m_x264Param->b_annexb = 0;

    m_x264Param->i_frame_reference = 5;
    if (enableBFrame) {
        m_x264Param->i_bframe = B_frame_count;
        m_x264Param->i_bframe_bias = 100;
        m_x264Param->i_bframe_adaptive = 1;
        if (B_frame_count >= 2)
            m_x264Param->i_bframe_pyramid = 1;
    }
    else
        m_x264Param->i_bframe = 0;

    if (threadCount > 0)
        m_x264Param->i_threads = threadCount;

    // @note
    // never use cpu capabilities.
    // let libx264 to choose.
#if 0
    m_x264Param->cpu = 0;
    m_x264Param->cpu |=X264_CPU_MMX;
    m_x264Param->cpu |=X264_CPU_MMXEXT;
    m_x264Param->cpu |=X264_CPU_SSE;
#endif

    m_x264Encoder = x264_encoder_open(m_x264Param);

    // update video sh
    x264_nal_t *nalOut;
    int nalNum;
    x264_encoder_headers(m_x264Encoder, &nalOut, &nalNum);

    for (int i = 0; i < nalNum; ++i) {
        x264_nal_t &nal = nalOut[i];
        if (nal.i_type == NAL_SPS) {
            BleVideoPacket *pkt = new BleVideoPacket(Video_Type_H264);
            pkt->dts = 0;

            MStream &body = pkt->data;

            // SPS Serialize
            body.write1Bytes(0x17);
            body.write1Bytes(0x00);
            body.write3Bytes(0x00);
            body.write1Bytes(0x01);
            body.writeString((char*)nal.p_payload + 5, 3);
            body.write1Bytes(0xff);
            body.write1Bytes(0xe1);
            body.write2Bytes(nal.i_payload - 4);
            body.writeString((char*)nal.p_payload + 4, nal.i_payload - 4);

            //the PPS always comes after the SPS
            x264_nal_t &pps = nalOut[++i];

            // PPS Serialize
            body.write1Bytes(0x01);
            body.write2Bytes(pps.i_payload - 4);
            body.writeString(MString((char*)pps.p_payload + 4, pps.i_payload - 4));

            appCtx->setVideoSh(pkt);
        } else if (nal.i_type == NAL_SEI) {
            BleVideoPacket *seiPkt = new BleVideoPacket(Video_Type_H264);
            seiPkt->dts = 0;
            seiPkt->has_encoded = true;

            MStream &seiBody = seiPkt->data;
            int skipBytes = 4;
            int newPayloadSize = (nal.i_payload - skipBytes);

            unsigned char flshFrameType = 0x17;
            seiBody.write1Bytes(flshFrameType);
            seiBody.write1Bytes(0x01);
            seiBody.write3Bytes(0x00);
            seiBody.write4Bytes(newPayloadSize);
            seiBody.writeString((char*)nal.p_payload + skipBytes, newPayloadSize);

            BleAVQueue::instance()->enqueue(seiPkt);
        }
    }

    m_pictureIn = new x264_picture_t;
    m_pictureIn->i_pts = 0;

    return BLE_SUCESS;
}
Exemple #16
0
sc_streamer sc_streamer_init_video(const char* stream_host, const char* room_name, sc_frame_rect capture_rect, sc_time start_time_stamp){
    sc_streamer_setup_windows();
	x264_param_t param;
    
    char *stream_uri = (char *) malloc (100);
    sprintf(stream_uri, "rtmp://%s/screenshare/%s", stream_host, room_name);
    
    sc_streamer streamer = {.start_time_stamp = start_time_stamp,
        .stream_uri = stream_uri,
        .room_name = room_name,
        .capture_rect = capture_rect,
        .frames = 0,
        .rtmpt = 0};

    streamer.flv_out_handle = open_flv_buffer();
    streamer.rtmp = open_RTMP_stream( stream_uri );
    
    if(!RTMP_IsConnected(streamer.rtmp) || RTMP_IsTimedout(streamer.rtmp)) {
        printf("Using rtmpt \n");
        streamer.rtmpt = 1;
        free(stream_uri);
        char *stream_uri = (char *) malloc (100);
        sprintf(stream_uri, "rtmpt://%s/screenshare/%s", stream_host, room_name);
        streamer.rtmp = open_RTMP_stream( stream_uri );
    }
    
    write_RTMP_header(streamer.flv_out_handle, streamer.rtmp);
    
    x264_param_default_preset(&param, "veryfast", "zerolatency");
    
    param.i_log_level  = X264_LOG_ERROR;
    //param.psz_dump_yuv = (char *)"/tmp/dump.y4m";
    
    param.b_vfr_input = 1;
    param.i_keyint_max = 30;
    
    param.i_width = capture_rect.width;
    param.i_height = capture_rect.height;
    param.i_timebase_num   = 1.0;
    param.i_timebase_den   = SC_TimeBase;
    //Rate control/quality
    param.rc.i_rc_method = X264_RC_CRF;
    
    param.i_slice_max_size = 1024;
    param.rc.i_vbv_max_bitrate = 1024;
    param.rc.i_vbv_buffer_size = 2000;
    param.rc.f_rf_constant = 23;
    param.b_sliced_threads = 0;
    param.b_intra_refresh = 0;
    param.b_repeat_headers = 1;
    param.b_annexb = 0;
    
    x264_param_apply_profile(&param, "main");
    
    streamer.encoder = x264_encoder_open(&param);
    
    set_RTMP_param( streamer.flv_out_handle, &param );
    
    x264_nal_t *headers;
    int i_nal;
    
    x264_encoder_headers( streamer.encoder, &headers, &i_nal );
    write_RTMP_headers( streamer.flv_out_handle, streamer.rtmp, headers );
    
    headers = NULL;
    free(headers);
    
    streamer.rtmp_setup = 1;
    streamer.reconnect_tries = 0;
    
    return streamer;
}

sc_streamer sc_streamer_init_cursor(const char* stream_host, const char* room_name, sc_time start_time_stamp){
	sc_streamer_setup_windows();

    char *so_name = (char *) malloc (100);
    sprintf(so_name, "SC.SS.%s.Cursor", room_name);
    
    char *stream_uri = (char *) malloc (100);
    sprintf(stream_uri, "rtmp://%s/screenshare/%s-cursor", stream_host, room_name);
    
    sc_streamer streamer = {.start_time_stamp = start_time_stamp,
        .stream_uri = stream_uri,
        .room_name = room_name,
        .so_name = so_name,
        .rtmpt = 0,
        .have_inital_SO = 0};
    
    streamer.flv_out_handle = open_flv_buffer();
    streamer.rtmp = open_RTMP_stream( stream_uri );
    
    if(!RTMP_IsConnected(streamer.rtmp) || RTMP_IsTimedout(streamer.rtmp)) {
        streamer.rtmpt = 1;
        free(stream_uri);
        char *stream_uri = (char *) malloc (100);
        sprintf(stream_uri, "rtmpt://%s/screenshare/%s-cursor", stream_host, room_name);
        streamer.rtmp = open_RTMP_stream( stream_uri );
    }
    
    setup_shared_object(streamer.so_name, streamer.rtmp);
    
    streamer.rtmp_setup = 1;
    streamer.so_version = 0;
    streamer.reconnect_tries = 0;
    
    return streamer;
}

void sc_streamer_send_frame(sc_streamer *streamer, sc_frame *frame, sc_time frame_time_stamp) {
    x264_picture_t pic_in, pic_out;
  
	x264_picture_alloc(&pic_in, X264_CSP_I420, streamer->capture_rect.width, streamer->capture_rect.height);
    
    const size_t image_size = (streamer->capture_rect.width * streamer->capture_rect.height);
  
    x264_free(pic_in.img.plane[0]);
	
    pic_in.img.plane[0] = frame->framePtr;
    pic_in.img.plane[1] = frame->framePtr + image_size;
    pic_in.img.plane[2] = frame->framePtr + image_size + image_size / 4;
    

    pic_in.i_pts = floor((frame_time_stamp - streamer->start_time_stamp));
    
    
    x264_nal_t* nals;
    int i_nals;
    int frame_size = x264_encoder_encode(streamer->encoder, &nals, &i_nals, &pic_in, &pic_out);
	
    if(frame_size > 0) {
        write_RTMP_frame( streamer->flv_out_handle, streamer->rtmp, nals[0].p_payload, frame_size, &pic_out );
		streamer->frames++;
    }
    
	
    nals = NULL;
    free(nals);
    
	//x264_picture_clean(&pic_in);
}
Exemple #17
0
int main(int argc, char* argv[])
{
	if (argc != 5)
	{
		printf("usage : app [input] [width] [height] [output]\n");
		return 0;
	}

	const char* input = argv[1];
	const char* out264 = argv[4];
	const int width = atoi(argv[2]);
	const int height = atoi(argv[3]);

	FILE *fin = 0, *fout = 0;
	fopen_s(&fin, input, "rb");
	fopen_s(&fout, out264, "wb");

	if (fin == 0 || fout == 0)
	{
		printf("openf file failed\n");
		return -1;
	}

	x264_param_t param;
	x264_param_default_preset(&param, "fast", "zerolatency");
	//x264_param_default(&param);

	param.i_width = width;
	param.i_height = height;
	param.i_bframe = 0;
	param.i_threads = 1;
	param.i_sync_lookahead = 0;
	//	param.b_deblocking_filter = 1;
	param.b_cabac = 1;
	param.i_fps_num = 25;
	param.i_fps_den = 1;
	param.i_level_idc = 30;
	param.i_keyint_min = param.i_fps_num;
	param.i_keyint_max = param.i_fps_num * 2;

	param.analyse.i_subpel_refine = 5;
	param.analyse.i_me_method = X264_ME_HEX;
	param.analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8 | X264_ANALYSE_PSUB16x16 | X264_ANALYSE_BSUB16x16;
	param.analyse.intra = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8;

	if ((param.analyse.inter | param.analyse.intra) & X264_ANALYSE_I8x8)
	{
		param.analyse.b_transform_8x8 = 1;
	}

	param.rc.i_lookahead = 0;
	param.rc.i_bitrate = 500;
	param.rc.i_vbv_max_bitrate = param.rc.i_bitrate;
	param.rc.i_vbv_buffer_size = param.rc.i_bitrate;
	param.rc.f_vbv_buffer_init = 0.7f;
	param.rc.b_mb_tree = 0;
	//	param.rc.i_qp_min = 2;
	//	param.rc.i_qp_max = 31;
	//	param.rc.f_qcompress = 0.5f;
	//	param.rc.i_qp_constant = 0;
	param.rc.i_rc_method = X264_RC_ABR;
	param.rc.f_rf_constant = 8.5f;
	param.rc.f_rf_constant_max = 20.0f;
	param.rc.f_rate_tolerance = 0.1f;
	param.rc.i_aq_mode = X264_AQ_AUTOVARIANCE;
	param.rc.f_aq_strength = 0.5f;
	param.b_repeat_headers = 0;
	//	param.b_annexb = 0;
#ifdef _DEBUG
	//	param.analyse.b_psnr = true;
	//	param.analyse.b_ssim = true;
	param.i_log_level = X264_LOG_INFO;
#endif

	x264_t* h264 = x264_encoder_open(&param);
	if (h264 == NULL)
	{
		printf("x264 open failed\n");
		return -1;
	}

	x264_picture_t pic_in;
	x264_picture_t pic_out;

	x264_picture_alloc(&pic_in, X264_CSP_I420, width, height);
	x264_picture_init(&pic_out);

	int bufferSize = width * height * 3 / 2;
	uchar* buffer = (uchar*)malloc(bufferSize);

	pic_in.img.i_csp = X264_CSP_I420;
	pic_in.img.i_plane = 3;
	pic_in.img.plane[0] = buffer;
	pic_in.img.plane[1] = buffer + width * height;
	pic_in.img.plane[2] = buffer + width * height * 5 / 4;
	pic_in.img.i_stride[0] = width;
	pic_in.img.i_stride[1] = width / 2;
	pic_in.img.i_stride[2] = width / 2;
	pic_in.i_pts = 0;

	int frameCount = 0;
	int encodeFrameCount = 0;
	int frameSize = 0;
	int i_nal = 0;
	x264_nal_t* p_nal = NULL;

	//从头部信息里面获取PPS、SPS等
	x264_encoder_headers(h264, &p_nal, &i_nal);

	for (int i = 0; i < i_nal; i++)
	{
		fwrite(p_nal[i].p_payload, 1, p_nal[i].i_payload, fout);
	}

	while (!feof(fin))
	{
		int bytes = fread(buffer, 1, bufferSize, fin);
		if (bytes != bufferSize)
		{
			break;
		}

		if (frameCount++ % 8 == 0)
		{
			pic_in.i_type = X264_TYPE_IDR;
		}
		else
		{
			pic_in.i_type = X264_TYPE_AUTO;
		}

		frameSize = x264_encoder_encode(h264, &p_nal, &i_nal, &pic_in, &pic_out);

		if (frameSize < 0)
		{
			printf("x264 encode failed\n");
			break;
		}

		if (frameSize > 0)
		{
			for (int i = 0; i < i_nal; i++)
			{
				fwrite(p_nal[i].p_payload, 1, p_nal[i].i_payload, fout);
			}

			encodeFrameCount++;
		}

		pic_in.i_pts++;
	}

	while (frameSize = x264_encoder_encode(h264, &p_nal, &i_nal, NULL, &pic_out))
	{
		for (int i = 0; i < i_nal; i++)
		{
			fwrite(p_nal[i].p_payload, 1, p_nal[i].i_payload, fout);
		}

		encodeFrameCount++;
	}

	free(buffer);
	x264_encoder_close(h264);
	fclose(fin);
	fclose(fout);

	printf("read video frame = %d\n", frameCount);
	printf("encode video frame = %d\n", encodeFrameCount);

	system("pause");
	return 0;
}