vd_ffmpeg.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,079 行 · 第 1/3 页

C
1,079
字号
    uint32_t chunktab;	// offset to chunk offset array} dp_hdr_t;void swap_palette(void *pal) {    int i;    uint32_t *p = pal;    for (i = 0; i < AVPALETTE_COUNT; i++)        p[i] = le2me_32(p[i]);}// decode a framestatic mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){    int got_picture=0;    int ret;    vd_ffmpeg_ctx *ctx = sh->context;    AVFrame *pic= ctx->pic;    AVCodecContext *avctx = ctx->avctx;    mp_image_t* mpi=NULL;    int dr1= ctx->do_dr1;	    if(len<=0) return NULL; // skipped frame	if(flags == 1)		flags = 2;  // by  dsqiu	//ffmpeg interlace (mpeg2) bug have been fixed. no need of -noslices    if (!dr1)    avctx->draw_horiz_band=NULL;    avctx->opaque=sh;    if(ctx->vo_inited && !(flags&3) && !dr1){	mpi=mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, MP_IMGFLAG_PRESERVE |	    (ctx->do_slices?MP_IMGFLAG_DRAW_CALLBACK:0),	    sh->disp_w, sh->disp_h);	if(mpi && mpi->flags&MP_IMGFLAG_DRAW_CALLBACK){	    // vd core likes slices!	    avctx->draw_horiz_band=draw_slice;	}    }    avctx->hurry_up=(flags&3)?((flags&2)?2:1):0;    if(sh->ds->demuxer->type != DEMUXER_TYPE_LAVF)    if(   sh->format == mmioFOURCC('R', 'V', '1', '0')       || sh->format == mmioFOURCC('R', 'V', '1', '3')       || sh->format == mmioFOURCC('R', 'V', '2', '0')       || sh->format == mmioFOURCC('R', 'V', '3', '0')       || sh->format == mmioFOURCC('R', 'V', '4', '0'))    if(sh->bih->biSize>=sizeof(*sh->bih)+8){        int i;        dp_hdr_t *hdr= (dp_hdr_t*)data;        uint32_t *offsets = (uint32_t*)(data + hdr->chunktab) + 1;        char *end = data + len;        if(avctx->slice_offset==NULL)             avctx->slice_offset= av_malloc(sizeof(int)*1000);        //        for(i=0; i<25; i++) printf("%02X ", ((uint8_t*)data)[i]);                avctx->slice_count= FFMIN(hdr->chunks+1, 1000);        for(i=0; i<avctx->slice_count && end >= &offsets[2*i+1]; i++)            avctx->slice_offset[i]= offsets[2*i];	len=hdr->len;        data+= sizeof(dp_hdr_t);    }    mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "vd_ffmpeg data: %04x, %04x, %04x, %04x\n",           ((int *)data)[0], ((int *)data)[1], ((int *)data)[2], ((int *)data)[3]);    ret = avcodec_decode_video(avctx, pic,	     &got_picture, data, len);    dr1= ctx->do_dr1;    if(ret<0) mp_msg(MSGT_DECVIDEO,MSGL_WARN, "Error while decoding frame!\n");//printf("repeat: %d\n", pic->repeat_pict);//-- vstats generation    while(lavc_param_vstats){ // always one time loop        static FILE *fvstats=NULL;        char filename[20];        static long long int all_len=0;        static int frame_number=0;        static double all_frametime=0.0;        AVFrame *pic= avctx->coded_frame;	double quality=0.0;        if(!fvstats) {            time_t today2;            struct tm *today;            today2 = time(NULL);            today = localtime(&today2);            sprintf(filename, "vstats_%02d%02d%02d.log", today->tm_hour,                today->tm_min, today->tm_sec);            fvstats = fopen(filename,"w");            if(!fvstats) {                perror("fopen");                lavc_param_vstats=0; // disable block                break;                /*exit(1);*/            }        }	// average MB quantizer	{	    int x, y;	    int w = ((avctx->width  << lavc_param_lowres)+15) >> 4;	    int h = ((avctx->height << lavc_param_lowres)+15) >> 4;	    int8_t *q = pic->qscale_table;	    for( y = 0; y < h; y++ ) {		for( x = 0; x < w; x++ )		    quality += (double)*(q+x);		q += pic->qstride;	    }	    quality /= w * h;	}        all_len+=len;        all_frametime+=sh->frametime;        fprintf(fvstats, "frame= %5d q= %2.2f f_size= %6d s_size= %8.0fkB ",            ++frame_number, quality, len, (double)all_len/1024);        fprintf(fvstats, "time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",           all_frametime, (double)(len*8)/sh->frametime/1000.0,           (double)(all_len*8)/all_frametime/1000.0);	switch(pic->pict_type){	case FF_I_TYPE:            fprintf(fvstats, "type= I\n");	    break;	case FF_P_TYPE:            fprintf(fvstats, "type= P\n");	    break;	case FF_S_TYPE:            fprintf(fvstats, "type= S\n");	    break;	case FF_B_TYPE:            fprintf(fvstats, "type= B\n");	    break;	default:            fprintf(fvstats, "type= ? (%d)\n", pic->pict_type);	    break;	}                ctx->qp_stat[(int)(quality+0.5)]++;        ctx->qp_sum += quality;        ctx->inv_qp_sum += 1.0/(double)quality;                break;    }//--    if(!got_picture) return NULL;	// skipped image    if(init_vo(sh,avctx->pix_fmt) < 0) return NULL;    if(dr1 && pic->opaque){        mpi= (mp_image_t*)pic->opaque;    }            if(!mpi)    mpi=mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, MP_IMGFLAG_PRESERVE,	avctx->width, avctx->height);    if(!mpi){	// temporary!	mp_msg(MSGT_DECVIDEO, MSGL_WARN, MSGTR_MPCODECS_CouldntAllocateImageForCodec);	return NULL;    }        if(!dr1){        mpi->planes[0]=pic->data[0];        mpi->planes[1]=pic->data[1];        mpi->planes[2]=pic->data[2];        mpi->stride[0]=pic->linesize[0];        mpi->stride[1]=pic->linesize[1];        mpi->stride[2]=pic->linesize[2];    }        if (!mpi->planes[0])	return NULL;    if(avctx->pix_fmt==PIX_FMT_YUV422P && mpi->chroma_y_shift==1){	// we have 422p but user wants 420p	mpi->stride[1]*=2;	mpi->stride[2]*=2;    }    #ifdef WORDS_BIGENDIAN    // FIXME: this might cause problems for buffers with FF_BUFFER_HINTS_PRESERVE    if (mpi->bpp == 8)        swap_palette(mpi->planes[1]);#endif/* to comfirm with newer lavc style */    mpi->qscale =pic->qscale_table;    mpi->qstride=pic->qstride;    mpi->pict_type=pic->pict_type;    mpi->qscale_type= pic->qscale_type;    mpi->fields = MP_IMGFIELD_ORDERED;    if(pic->interlaced_frame) mpi->fields |= MP_IMGFIELD_INTERLACED;    if(pic->top_field_first ) mpi->fields |= MP_IMGFIELD_TOP_FIRST;        if(pic->repeat_pict == 1) mpi->fields |= MP_IMGFIELD_REPEAT_FIRST;    return mpi;}#ifdef HAVE_XVMCstatic enum PixelFormat get_format(struct AVCodecContext * avctx,                                     const enum PixelFormat * fmt){sh_video_t * sh = avctx->opaque;int i;    if(avctx->xvmc_acceleration){        vd_ffmpeg_ctx *ctx = sh->context;        avctx->get_buffer= mc_get_buffer;        avctx->release_buffer= mc_release_buffer;        avctx->draw_horiz_band = mc_render_slice;        mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCAcceleratedMPEG2);        assert(ctx->do_dr1);//these are must to!        assert(ctx->do_slices); //it is (vo_)ffmpeg bug if this fails        avctx->flags|= CODEC_FLAG_EMU_EDGE;//do i need that??!!        avctx->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;    }    for(i=0;fmt[i]!=-1;i++){        mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_TryingPixfmt,i);        if( init_vo(sh,fmt[i]) >= 0)	    return fmt[i];    }    return fmt[0];}static int mc_get_buffer(AVCodecContext *avctx, AVFrame *pic){    sh_video_t * sh = avctx->opaque;    vd_ffmpeg_ctx *ctx = sh->context;    mp_image_t* mpi=NULL;    xvmc_render_state_t * render;    int flags= MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE|                MP_IMGFLAG_DRAW_CALLBACK;    //  printf("vd_ffmpeg::mc_get_buffer (xvmc) %d %d %d\n", pic->reference, ctx->ip_count, ctx->b_count);    if(!avctx->xvmc_acceleration){        mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_McGetBufferShouldWorkOnlyWithXVMC);        assert(0);        exit(1);//        return -1;//!!fixme check error conditions    }    assert(avctx->draw_horiz_band == mc_render_slice);    assert(avctx->release_buffer == mc_release_buffer);    if( mp_msg_test(MSGT_DECVIDEO,MSGL_DBG5) )        mp_msg(MSGT_DECVIDEO, MSGL_DBG5, "vd_ffmpeg::mc_get_buffer\n");    if(init_vo(sh,avctx->pix_fmt) < 0){        mp_msg(MSGT_DECVIDEO, MSGL_WARN, MSGTR_MPCODECS_UnexpectedInitVoError);        exit(1);//        return -1;//!!fixme check error conditions    }    if(!pic->reference){        ctx->b_count++;    }else{        ctx->ip_count++;        flags|= MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE;    }    mpi= mpcodecs_get_image(sh, MP_IMGTYPE_IPB,flags ,                            avctx->width, avctx->height);    if(mpi==NULL){        mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_MPCODECS_UnrecoverableErrorRenderBuffersNotTaken);        assert(0);        exit(1);//        return -1;//!!fixme check error conditions in ffmpeg    };        if( (mpi->flags & MP_IMGFLAG_DIRECT) == 0){        mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_MPCODECS_OnlyBuffersAllocatedByVoXvmcAllowed);        assert(0);        exit(1);//        return -1;//!!fixme check error conditions in ffmpeg    }        pic->data[0]= mpi->planes[0];    pic->data[1]= mpi->planes[1];    pic->data[2]= mpi->planes[2];    /* Note, some (many) codecs in libavcodec must have stride1==stride2 && no changes between frames     * lavc will check that and die with an error message, if its not true     */    pic->linesize[0]= mpi->stride[0];    pic->linesize[1]= mpi->stride[1];    pic->linesize[2]= mpi->stride[2];    pic->opaque = mpi;    if(pic->reference){    //I or P frame        pic->age= ctx->ip_age[0];                ctx->ip_age[0]= ctx->ip_age[1]+1;        ctx->ip_age[1]= 1;        ctx->b_age++;    }else{    //B frame        pic->age= ctx->b_age;            ctx->ip_age[0]++;        ctx->ip_age[1]++;        ctx->b_age=1;    }    pic->type= FF_BUFFER_TYPE_USER;    render=(xvmc_render_state_t*)mpi->priv;//same as data[2]    if( mp_msg_test(MSGT_DECVIDEO,MSGL_DBG5) )        mp_msg(MSGT_DECVIDEO, MSGL_DBG5, "vd_ffmpeg::mc_get_buffer (render=%p)\n",render);    assert(render != 0);    assert(render->magic == MP_XVMC_RENDER_MAGIC);    render->state |= MP_XVMC_STATE_PREDICTION;    return 0;}static void mc_release_buffer(AVCodecContext *avctx, AVFrame *pic){    mp_image_t* mpi= pic->opaque;    sh_video_t * sh = avctx->opaque;    vd_ffmpeg_ctx *ctx = sh->context;    xvmc_render_state_t * render;    int i;    if(ctx->ip_count <= 2 && ctx->b_count<=1){        if(mpi->flags&MP_IMGFLAG_PRESERVE)            ctx->ip_count--;        else            ctx->b_count--;    }//printf("R%X %X\n", pic->linesize[0], pic->data[0]);//mark the surface as not requared for prediction    render=(xvmc_render_state_t*)pic->data[2];//same as mpi->priv    if( mp_msg_test(MSGT_DECVIDEO,MSGL_DBG5) )        mp_msg(MSGT_DECVIDEO, MSGL_DBG5, "vd_ffmpeg::mc_release_buffer (render=%p)\n",render);    assert(render!=NULL);    assert(render->magic==MP_XVMC_RENDER_MAGIC);    render->state&=~MP_XVMC_STATE_PREDICTION;    for(i=0; i<4; i++){        pic->data[i]= NULL;    }}static void mc_render_slice(struct AVCodecContext *s,                	AVFrame *src, int offset[4],                	int y, int type, int height){int width= s->width;sh_video_t * sh = s->opaque;uint8_t *source[3]= {src->data[0], src->data[1], src->data[2]};        assert(src->linesize[0]==0 && src->linesize[1]==0 && src->linesize[2]==0);    assert(offset[0]==0 && offset[1]==0 && offset[2]==0);        mpcodecs_draw_slice (sh, source, src->linesize, width, height, 0, y);}#endif // HAVE_XVMC

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?