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 + -
显示快捷键?