vd_ffmpeg.c

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

C
1,079
字号
    case mmioFOURCC('R', 'V', '3', '0'):    case mmioFOURCC('R', 'V', '4', '0'):        if(sh->bih->biSize<sizeof(*sh->bih)+8){            /* only 1 packet per frame & sub_id from fourcc */            avctx->extradata_size= 8;            avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);	    ((uint32_t*)avctx->extradata)[0] = 0;	    ((uint32_t*)avctx->extradata)[1] =        	(sh->format == mmioFOURCC('R', 'V', '1', '3')) ? 0x10003001 : 0x10000000;        } else {	    /* has extra slice header (demux_rm or rm->avi streamcopy) */	    avctx->extradata_size = sh->bih->biSize-sizeof(BITMAPINFOHEADER);	    avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);	    memcpy(avctx->extradata, sh->bih+1, avctx->extradata_size);	}	avctx->sub_id= AV_RB32(avctx->extradata+4);//        printf("%X %X %d %d\n", extrahdr[0], extrahdr[1]);        break;    default:	if (!sh->bih || sh->bih->biSize <= sizeof(BITMAPINFOHEADER))	    break;	avctx->extradata_size = sh->bih->biSize-sizeof(BITMAPINFOHEADER);	avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);	memcpy(avctx->extradata, sh->bih+1, avctx->extradata_size);	break;    }    /* Pass palette to codec */    if (sh->bih && (sh->bih->biBitCount <= 8)) {        avctx->palctrl = calloc(1,sizeof(AVPaletteControl));        avctx->palctrl->palette_changed = 1;        if (sh->bih->biSize-sizeof(BITMAPINFOHEADER))            /* Palette size in biSize */            memcpy(avctx->palctrl->palette, sh->bih+1,                   FFMIN(sh->bih->biSize-sizeof(BITMAPINFOHEADER), AVPALETTE_SIZE));        else            /* Palette size in biClrUsed */            memcpy(avctx->palctrl->palette, sh->bih+1,                   FFMIN(sh->bih->biClrUsed * 4, AVPALETTE_SIZE));	}    if(sh->bih)	avctx->bits_per_sample= sh->bih->biBitCount;    if(lavc_param_threads > 1)        avcodec_thread_init(avctx, lavc_param_threads);    /* open it */    if (avcodec_open(avctx, lavc_codec) < 0) {        mp_msg(MSGT_DECVIDEO,MSGL_ERR, MSGTR_CantOpenCodec);        uninit(sh);        return 0;    }    mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: libavcodec init OK!\n");    return 1; //mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YV12);}// uninit driverstatic void uninit(sh_video_t *sh){    vd_ffmpeg_ctx *ctx = sh->context;    AVCodecContext *avctx = ctx->avctx;        if(lavc_param_vstats){        int i;        for(i=1; i<32; i++){            mp_msg(MSGT_DECVIDEO, MSGL_INFO,"QP: %d, count: %d\n", i, ctx->qp_stat[i]);        }        mp_msg(MSGT_DECVIDEO, MSGL_INFO,MSGTR_MPCODECS_ArithmeticMeanOfQP,             ctx->qp_sum / avctx->coded_frame->coded_picture_number,            1.0/(ctx->inv_qp_sum / avctx->coded_frame->coded_picture_number)            );    }    if (avctx) {        if (avctx->codec && avcodec_close(avctx) < 0)            mp_msg(MSGT_DECVIDEO,MSGL_ERR, MSGTR_CantCloseCodec);        av_freep(&avctx->extradata);        av_freep(&avctx->palctrl);        av_freep(&avctx->slice_offset);    }    av_freep(&avctx);    av_freep(&ctx->pic);    if (ctx)	free(ctx);	avcodec_inited=0;}static void draw_slice(struct AVCodecContext *s,                	AVFrame *src, int offset[4],                	int y, int type, int height){    sh_video_t * sh = s->opaque;    uint8_t *source[3]= {src->data[0] + offset[0], src->data[1] + offset[1], src->data[2] + offset[2]};#if 0    int start=0, i;    int width= s->width;    int skip_stride= ((width<<lavc_param_lowres)+15)>>4;    uint8_t *skip= &s->coded_frame->mbskip_table[(y>>4)*skip_stride];    int threshold= s->coded_frame->age;    if(s->pict_type!=B_TYPE){        for(i=0; i*16<width+16; i++){             if(i*16>=width || skip[i]>=threshold){                if(start==i) start++;                else{                    uint8_t *src2[3]= {src[0] + start*16,                                      src[1] + start*8,                                      src[2] + start*8};//printf("%2d-%2d x %d\n", start, i, y);                    mpcodecs_draw_slice (sh,src2, stride, (i-start)*16, height, start*16, y);                    start= i+1;                }            }               }    }else#endif    if (y < sh->disp_h) {        mpcodecs_draw_slice (sh, source, src->linesize, sh->disp_w, (y+height)<=sh->disp_h?height:sh->disp_h-y, 0, y);    }}static int init_vo(sh_video_t *sh, enum PixelFormat pix_fmt){    vd_ffmpeg_ctx *ctx = sh->context;    AVCodecContext *avctx = ctx->avctx;    float aspect= av_q2d(avctx->sample_aspect_ratio) * avctx->width / avctx->height;    int width, height;    width = avctx->width;    height = avctx->height;    // HACK!    // if sh->ImageDesc is non-NULL, it means we decode QuickTime(tm) video.    // use dimensions from BIH to avoid black borders at the right and bottom.    if (sh->bih && sh->ImageDesc) {	width = sh->bih->biWidth>>lavc_param_lowres;	height = sh->bih->biHeight>>lavc_param_lowres;    }         // it is possible another vo buffers to be used after vo config()     // lavc reset its buffers on width/heigh change but not on aspect change!!!    if (av_cmp_q(avctx->sample_aspect_ratio, ctx->last_sample_aspect_ratio) ||	width != sh->disp_w  ||	height != sh->disp_h ||	pix_fmt != ctx->pix_fmt ||	!ctx->vo_inited)    {	mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] aspect_ratio: %f\n", aspect);	if (sh->aspect == 0 ||	    av_cmp_q(avctx->sample_aspect_ratio, 	             ctx->last_sample_aspect_ratio))	    sh->aspect = aspect;	ctx->last_sample_aspect_ratio = avctx->sample_aspect_ratio;	sh->disp_w = width;	sh->disp_h = height;	ctx->pix_fmt = pix_fmt;	switch(pix_fmt){	// YUVJ are YUV formats that use the full Y range and not just	// 16 - 235 (see colorspaces.txt).	// Currently they are all treated the same way.	case PIX_FMT_YUV410P: ctx->best_csp=IMGFMT_YVU9;break; //svq1	case PIX_FMT_YUVJ420P:	case PIX_FMT_YUV420P: ctx->best_csp=IMGFMT_YV12;break; //mpegs	case PIX_FMT_YUVJ422P:	case PIX_FMT_YUV422P: ctx->best_csp=IMGFMT_422P;break; //mjpeg / huffyuv	case PIX_FMT_YUVJ444P:	case PIX_FMT_YUV444P: ctx->best_csp=IMGFMT_444P;break; //photo jpeg	case PIX_FMT_YUV411P: ctx->best_csp=IMGFMT_411P;break; //dv ntsc	case PIX_FMT_YUYV422: ctx->best_csp=IMGFMT_YUY2;break; //huffyuv perhaps in the future	case PIX_FMT_RGB24 :  ctx->best_csp=IMGFMT_RGB24;break; //qtrle	case PIX_FMT_RGB32:   ctx->best_csp=IMGFMT_BGR32;break; //huffyuv / mjpeg	case PIX_FMT_BGR24 :  ctx->best_csp=IMGFMT_BGR24;break; //8bps	case PIX_FMT_RGB555:  ctx->best_csp=IMGFMT_BGR15;break; //rpza,cram	case PIX_FMT_RGB565:  ctx->best_csp=IMGFMT_BGR16;break; //4xm	case PIX_FMT_GRAY8:   ctx->best_csp=IMGFMT_Y800;break; // gray jpeg	case PIX_FMT_PAL8:    ctx->best_csp=IMGFMT_BGR8;break; //8bps,mrle,cram#ifdef HAVE_XVMC        case PIX_FMT_XVMC_MPEG2_MC:ctx->best_csp=IMGFMT_XVMC_MOCO_MPEG2;break;        case PIX_FMT_XVMC_MPEG2_IDCT:ctx->best_csp=IMGFMT_XVMC_IDCT_MPEG2;break;#endif	default:	    ctx->best_csp=0;	}    	if (!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h, ctx->best_csp))    		return -1;	ctx->vo_inited = 1;    }    return 0;}static int get_buffer(AVCodecContext *avctx, AVFrame *pic){    sh_video_t * sh = avctx->opaque;    vd_ffmpeg_ctx *ctx = sh->context;    mp_image_t* mpi=NULL;    int flags= MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE;    int type= MP_IMGTYPE_IPB;    int width= avctx->width;    int height= avctx->height;    int align=15;//printf("get_buffer %d %d %d\n", pic->reference, ctx->ip_count, ctx->b_count);    if(avctx->pix_fmt == PIX_FMT_YUV410P)        align=63; //yes seriously, its really needed (16x16 chroma blocks in SVQ1 -> 64x64)  if (pic->buffer_hints) {    mp_msg(MSGT_DECVIDEO,MSGL_DBG2, "Buffer hints: %u\n", pic->buffer_hints);    type = MP_IMGTYPE_TEMP;    if (pic->buffer_hints & FF_BUFFER_HINTS_READABLE)        flags |= MP_IMGFLAG_READABLE;    if (pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) {        type = MP_IMGTYPE_STATIC;        flags |= MP_IMGFLAG_PRESERVE;    }    if (pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) {        type = MP_IMGTYPE_STATIC;        flags |= MP_IMGFLAG_PRESERVE;    }    flags|=(!avctx->hurry_up && ctx->do_slices) ?            MP_IMGFLAG_DRAW_CALLBACK:0;    mp_msg(MSGT_DECVIDEO,MSGL_DBG2, type == MP_IMGTYPE_STATIC ? "using STATIC\n" : "using TEMP\n");  } else {    if(!pic->reference){        ctx->b_count++;        flags|=(!avctx->hurry_up && ctx->do_slices) ?                MP_IMGFLAG_DRAW_CALLBACK:0;    }else{        ctx->ip_count++;        flags|= MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE                | (ctx->do_slices ? MP_IMGFLAG_DRAW_CALLBACK : 0);    }  }    if(init_vo(sh,avctx->pix_fmt) < 0){        avctx->release_buffer= avcodec_default_release_buffer;        avctx->get_buffer= avcodec_default_get_buffer;        return avctx->get_buffer(avctx, pic);    }  if (!pic->buffer_hints) {    if(ctx->b_count>1 || ctx->ip_count>2){        mp_msg(MSGT_DECVIDEO, MSGL_WARN, MSGTR_MPCODECS_DRIFailure);        ctx->do_dr1=0; //FIXME        avctx->get_buffer= avcodec_default_get_buffer;        return avctx->get_buffer(avctx, pic);    }    if(avctx->has_b_frames){        type= MP_IMGTYPE_IPB;    }else{        type= MP_IMGTYPE_IP;    }    mp_msg(MSGT_DECVIDEO,MSGL_DBG2, type== MP_IMGTYPE_IPB ? "using IPB\n" : "using IP\n");  }    mpi= mpcodecs_get_image(sh,type, flags,			(width+align)&(~align), (height+align)&(~align));    // ok, let's see what did we get:    if(  mpi->flags&MP_IMGFLAG_DRAW_CALLBACK &&       !(mpi->flags&MP_IMGFLAG_DIRECT)){	// nice, filter/vo likes draw_callback :)	avctx->draw_horiz_band= draw_slice;    } else	avctx->draw_horiz_band= NULL;	// Palette support: libavcodec copies palette to *data[1]	if (mpi->bpp == 8)		mpi->planes[1] = av_malloc(AVPALETTE_SIZE);    pic->data[0]= mpi->planes[0];    pic->data[1]= mpi->planes[1];    pic->data[2]= mpi->planes[2];#if 0        assert(mpi->width >= ((width +align)&(~align)));    assert(mpi->height >= ((height+align)&(~align)));    assert(mpi->stride[0] >= mpi->width);    if(mpi->imgfmt==IMGFMT_I420 || mpi->imgfmt==IMGFMT_YV12 || mpi->imgfmt==IMGFMT_IYUV){        const int y_size= mpi->stride[0] * (mpi->h-1) + mpi->w;        const int c_size= mpi->stride[1] * ((mpi->h>>1)-1) + (mpi->w>>1);                assert(mpi->planes[0] > mpi->planes[1] || mpi->planes[0] + y_size <= mpi->planes[1]);        assert(mpi->planes[0] > mpi->planes[2] || mpi->planes[0] + y_size <= mpi->planes[2]);        assert(mpi->planes[1] > mpi->planes[0] || mpi->planes[1] + c_size <= mpi->planes[0]);        assert(mpi->planes[1] > mpi->planes[2] || mpi->planes[1] + c_size <= mpi->planes[2]);        assert(mpi->planes[2] > mpi->planes[0] || mpi->planes[2] + c_size <= mpi->planes[0]);        assert(mpi->planes[2] > mpi->planes[1] || mpi->planes[2] + c_size <= mpi->planes[1]);    }#endif    /* 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;//printf("%X\n", (int)mpi->planes[0]);#if 0if(mpi->flags&MP_IMGFLAG_DIRECT)    printf("D");else if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)    printf("S");else    printf(".");#endif    if(pic->reference){        pic->age= ctx->ip_age[0];                ctx->ip_age[0]= ctx->ip_age[1]+1;        ctx->ip_age[1]= 1;        ctx->b_age++;    }else{        pic->age= ctx->b_age;            ctx->ip_age[0]++;        ctx->ip_age[1]++;        ctx->b_age=1;    }    pic->type= FF_BUFFER_TYPE_USER;    return 0;}static void release_buffer(struct AVCodecContext *avctx, AVFrame *pic){    mp_image_t* mpi= pic->opaque;    sh_video_t * sh = avctx->opaque;    vd_ffmpeg_ctx *ctx = sh->context;    int i;//printf("release buffer %d %d %d\n", mpi ? mpi->flags&MP_IMGFLAG_PRESERVE : -99, ctx->ip_count, ctx->b_count);   if(ctx->ip_count <= 2 && ctx->b_count<=1){    if(mpi->flags&MP_IMGFLAG_PRESERVE)        ctx->ip_count--;    else        ctx->b_count--;  }	// Palette support: free palette buffer allocated in get_buffer	if ( mpi && (mpi->bpp == 8))		av_freep(&mpi->planes[1]);    if(pic->type!=FF_BUFFER_TYPE_USER){        avcodec_default_release_buffer(avctx, pic);        return;    }    for(i=0; i<4; i++){        pic->data[i]= NULL;    }//printf("R%X %X\n", pic->linesize[0], pic->data[0]);}// copypaste from demux_real.c - it should match to get it working!//FIXME put into some headertypedef struct dp_hdr_s {    uint32_t chunks;	// number of chunks    uint32_t timestamp; // timestamp from packet header    uint32_t len;	// length of actual data

⌨️ 快捷键说明

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