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