<pre>On Sat, 13 Oct 2007, ½¯Ð˲ý wrote:<br><br>><i> I'm a newbie of x264 and tried to encode yuv sequences on multi-core<br></i>><i> platforms.<br></i>
And x264's builtin threading doesn't suffice?
---------------------------------------------<div>yes, when I tried 4—16 threads(and I also changed the maxium number of threads defined in common.h),the cpus are</div><div>all less than 50% usage. maybe the slice/frame level parallelisms are not enouth.
<br><br>><i> first I pinned some GOP task on each logical CPUs, and then read a gop<br></i>><i> for every gop task, when the encoding process is done, the main thread<br></i>><i> re-order the out-of-order data encoded by the GOP tasks.
<br><br></i>><i> the result is fine, but when I playback the bitstream, there will be<br></i>><i> some error information displayed on the information window of videolan<br></i>><i> client:<br></i>><i><br>
</i>
><i> ffmpeg warning: error while decoding MB 14 13, bytestream (-7)<br></i>><i> (<a href="http://mailman.videolan.org/listinfo/x264-devel" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">h264 at 00CEB3C0
</a>)<br></i>><i> ffmpeg debug: concealing 145 DC, 145 AC, 145 MV errors<br><br></i>><i> (<a href="http://mailman.videolan.org/listinfo/x264-devel" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">
h264 at 00CEB3C0</a>)<br></i>><i><br></i>><i> any sugestion will be appreciated.<br></i><br>There's nothing in the bitstream format that would prevent arbitrary <br><br>concatenation of GOPs. So it's a bug in your code. And since you haven't
<br>posted your code, no one can possibly help.</div><div>---------------------------------------------------</div><div>I only changed the <br>x264.c & encoder/encoder.c:</div>/*x264.c*/<br>#define CPUNUM 3 <br>#define GOPSIZE 125
<br>#define BUFSIZE 10<br>#define INVGOP BUFSIZE<br>x264_picture_t* g_Pic[CPUNUM];<br>int g_count[CPUNUM];<br>int g_progress;<br>sem_t sem[CPUNUM];<br>sem_t resem[CPUNUM];<br>sem_t g_sem;<br>int g_flush;<br><br>typedef struct para
<br>{<br>        int cpuno;<br>        x264_param_t *param;<br>}Para;<br><br>typedef struct data<br>{<br>        unsigned char * pdata;<br>        int length;<br>}Data;<br><br>Data * result[BUFSIZE];<br>int g_ready;<br>int g_curgop[CPUNUM];<br>int complete=0;
<br>x264_t *encoder[CPUNUM];<br><br>static int Encode_frame( x264_t *h, unsigned char **pdata, x264_picture_t *pic,int* gop)<br>{<br> x264_picture_t pic_out;<br> x264_nal_t *nal;<br> int i_nal, i;<br> int i_file = 0;
<br><br> *pdata = (unsigned char *)malloc(1024*1024);<br> <br> if( x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out,gop) < 0 )<br> {<br> fprintf( stderr, "x264_encoder_encode failed\n" );
<br> }<br><br> for( i = 0; i < i_nal; i++ )<br> {<br> int i_size;<br> int i_data;<br><br> i_data = DATA_MAX;<br> if( ( i_size = x264_nal_encode( data, &i_data, 1, &nal[i] ) ) > 0 )
<br> {<br>         memcpy(*pdata+i_file,data,i_size);<br>         i_file += i_size;<br> }<br> else if( i_size < 0 )<br> {<br> fprintf( stderr, "need to increase buffer size (size=%d)\n", -i_size );
<br> }<br> }<br> return i_file;<br>}<br><br>void * GOP_Thread(void * gop_data)<br>{<br>         x264_picture_t *pics;<br>         Para * para = (Para *)gop_data;<br>         sem_t *cursem = &sem[para->cpuno-1];<br>
        sem_t *curresem = &resem[para->cpuno-1];<br>        int ret;<br>        pid_t p = 0;<br>        unsigned long new_mask=1<<para->cpuno;<br>        unsigned long cur_mask;<br>        int i;<br>        x264_t * h;<br>        int count=0;<br>        int i_file=0;<br>
        int gop=0;<br>        int cpu = para->cpuno;<br>        Data * dest;<br> <br>        ret = sched_getaffinity(p,sizeof(new_mask),&cur_mask);<br>        ret = sched_setaffinity(p,sizeof(new_mask),&new_mask);<br><br>        h = encoder[para->cpuno-1];
<br><br>        while(1)<br>        {<br>         if(complete)<br>         return NULL;<br><br>         if(!(ret=sem_trywait(cursem)))<br>         {<br>         unsigned char * ret;<br>         int length;<br>         int start_frame;<br>                <br>         i_file = 0;
<br>         count = g_count[cpu-1];<br>         gop = g_curgop[cpu-1];<br>         dest = (Data *)malloc(sizeof(Data));<br>         dest->pdata = (unsigned char *)malloc(5*1024*1024);<br>                        <br> h->frames.i_last_idr
= (gop-1)*GOPSIZE;<br>         h->frames.i_input = gop*GOPSIZE;<br>                h->i_frame_num = 0;<br>                h->frames.last_nonb = NULL;<br>                h->i_frame = gop*GOPSIZE;<br>                h->i_idr_pic_id = gop;<br>                start_frame = gop * GOPSIZE;
<br>                <br>                for(i=0;i<count;i++)<br>                {<br>                 pics = g_Pic[cpu-1]+i;<br>                 length = Encode_frame( h, &ret, pics,&start_frame);<br>                 if(length>0)<br>                 {<br>                  memcpy(dest->pdata+i_file,ret,length);
<br>                 i_file += length;<br>          }<br>         free(ret);<br>         }<br>                        <br>                do{<br>                 length=Encode_frame(h, &ret, NULL,NULL);<br>                 if(length>0)<br>                 {<br>                 memcpy(dest->pdata+i_file,ret,length);
<br>                 i_file += length;<br>                 }<br>                 free(ret);<br>                }while(length);<br>                        <br>                dest->length=i_file;<br>                result[gop%BUFSIZE]=dest;<br>                g_ready ++;<br>                g_progress --;<br>                sem_post(curresem);<br>         }
<br>        }<br>}<br><br><br>/*****************************************************************************<br> * Encode:<br> *****************************************************************************/<br>static int Encode( x264_param_t *param, cli_opt_t *opt )
<br>{<br> x264_picture_t *pic;<br> int i_frame, i_frame_total;<br> int64_t i_start, i_end;<br> int64_t i_file;<br> int i_progress;<br> int ret;<br> unsigned long new_mask=1;<br> unsigned long cur_mask;
<br> int g_flush=0;<br> int gop_number=0;<br> int i,j;<br> Para para[CPUNUM];<br> pid_t p=0;<br> pthread_t handles[CPUNUM];<br> <br> sched_getaffinity(p,sizeof(new_mask),&cur_mask);<br> ret = sched_setaffinity(p,sizeof(new_mask),&new_mask);
<br><br> g_progress=0;<br> g_ready=0;<br> <br> for(i=0;i<CPUNUM;i++)<br> {<br> if( ( encoder[i] = x264_encoder_open( param ) ) == NULL )<br> {<br>          fprintf( stderr, "x264_encoder_open failed\n" );
<br>          return -1;        <br> }<br> }<br><br> for(i=0;i<CPUNUM;i++)<br> {<br>         para[i].cpuno = i+1;<br>         para[i].param = param;<br>         sem_init(&sem[i],0,0);<br>         sem_init(&resem[i],0,1);<br>         g_count[i]=0;
<br>         g_curgop[i]=INVGOP;<br>         pthread_create(&handles[i],NULL,GOP_Thread,&para[i]);<br> }<br><br> sem_init(&g_sem,0,1);<br><br> for(i=0;i<BUFSIZE;i++)<br>         result[i] = NULL;<br><br> i_frame_total = p_get_frame_total( opt->hin, param->i_width, param->i_height );
<br><br> for(i=0;i<CPUNUM;i++)<br> {<br>        g_Pic[i]=(x264_picture_t *)malloc(GOPSIZE*sizeof(x264_picture_t));<br>        for(j=0;j<GOPSIZE;j++)<br>          x264_picture_alloc( g_Pic[i]+j, X264_CSP_I420, param->i_width, param->i_height );
<br> }<br><br> i_start = x264_mdate();<br> i_frame_total -= opt->i_seek;<br> if( opt->i_maxframes > 0 && opt->i_maxframes < i_frame_total )<br> i_frame_total = opt->i_maxframes;
<br> <br> if( set_param_bsf( opt->hout, param ) )<br> {<br>        fprintf( stderr, "x264 [error]: can't set outfile param\n" );<br>        close_file_yuv( opt->hin );<br>        close_file_bsf( opt->hout );<br>
        return -1;<br> }<br><br> for(i_frame=0,i_file=0,i_progress=0; b_ctrl_c==0&&(i_frame<i_frame_total||i_frame_total==0);)<br> {<br>        complete=0;<br>        for(i=0;i<CPUNUM;i++)<br>        {<br>         if((sem_trywait(&resem[i])==0)&&(!complete))
<br>                break;<br>         else <br>         {<br>                if(i>=CPUNUM-1)<br>                {<br>                 if(result[g_flush])<br>                 {<br>                        i_file += write_nalu_bsf( opt->hout, result[g_flush]->pdata, result[g_flush]->length );<br>                        g_ready --;
<br>                        free(result[g_flush]->pdata);<br>                        free(result[g_flush]);<br>                        result[g_flush]=NULL;<br>                        g_flush=(g_flush+1)%BUFSIZE;<br>                 }<br><br>                 i=-1;<br>                  continue;<br>                }<br>         }<br>        }<br>        <br>        j=0;<br>
while((j<GOPSIZE)&&(!p_read_frame(g_Pic[i]+j,opt->hin,i_frame+opt->i_seek,param->i_width,param->i_height))&&(i_frame<i_frame_total))<br>        {<br>         pic = g_Pic[i]+j;<br> pic->i_pts = i_frame * param->i_fps_den;
<br>         pic->i_type = X264_TYPE_AUTO;<br>         pic->i_qpplus1 = 0;<br>         j++;<br>         i_frame++;<br>        }<br><br>        g_count[i]=j;<br>        g_curgop[i]=gop_number;<br>        gop_number=gop_number+1;<br>        g_progress ++;<br>        sem_post(&sem[i]);
<br> }<br><br> while(g_progress||g_ready)<br> {<br>        if(result[g_flush])<br>        {<br>         i_file += write_nalu_bsf( opt->hout, result[g_flush]->pdata, result[g_flush]->length );<br>         g_ready --;<br>         free(result[g_flush]->pdata);
<br>         free(result[g_flush]);<br> result[g_flush]=NULL;<br> g_flush=(g_flush+1)%BUFSIZE;<br> }<br> }<br><br> complete=1;<br> <br> for(i=0;i<CPUNUM;i++)<br>         pthread_join(handles[i],NULL);
<br><br> <br> for(i=0;i<CPUNUM;i++)<br> x264_encoder_close(encoder[i]);<br><br> i_end = x264_mdate();<br> fprintf( stderr, "\n" );<br><br> if( b_ctrl_c )<br> fprintf( stderr, "aborted at input frame %d\n", opt->i_seek + i_frame );
<br><br> p_close_infile( opt->hin );<br> p_close_outfile( opt->hout );<br><br> if( i_frame > 0 )<br> {<br> double fps = (double)i_frame * (double)1000000 /<br> (double)( i_end - i_start );
<br><br> fprintf( stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame, fps,<br> (double) i_file * 8 * param->i_fps_num / ( param->i_fps_den * i_frame * 1000 ) );<br> }<br>
<br> return 0;<div><p>}</p><p>/*encoder/encoder.c, I only added the start frame number parameter to x264_encoder_encode function*/ <br></p><p>int x264_encoder_encode( x264_t *h,<br> x264_nal_t **pp_nal, int *pi_nal,
<br> x264_picture_t *pic_in,<br> x264_picture_t *pic_out,<br>                         int* gop)<br>{<br> x264_frame_t *frame_psnr = h->fdec; /* just to keep the current decoded frame for psnr calculation */
<br> int i_nal_type;<br> int i_nal_ref_idc;<br> int i_slice_type;<br> int i_frame_size;<br><br> int i;<br><br> int i_global_qp;<br><br> char psz_message[80];<br><br> /* no data out */
<br> *pi_nal = 0;<br> *pp_nal = NULL;<br><br><br> /* ------------------- Setup new frame from picture -------------------- */<br> TIMER_START( i_mtime_encode_frame );<br> if( pic_in != NULL )<br> {<br> /* 1: Copy the picture to a frame and move it to a buffer */
<br> x264_frame_t *fenc = x264_frame_get( h->frames.unused );<br><br> x264_frame_copy_picture( h, fenc, pic_in );<br><br> fenc->i_frame = h->frames.i_input++;<br><br> x264_frame_put( h->
frames.next, fenc );<br><br> x264_frame_init_lowres( h->param.cpu, fenc );<br><br> if( h->frames.i_input <= h->frames.i_delay + *gop)<br> {<br>         /* Nothing yet to encode */<br> /* waiting for filling bframe buffer */
<br> pic_out->i_type = X264_TYPE_AUTO;<br> return 0;<br> }<br> }</p><p>...........</p><br><p><br></p><p>Thanks!<br></p></div></pre>