comparison libmpcodecs/vd_ffmpeg.c @ 10362:8e3e884ec8a4

xvmc support
author iive
date Tue, 01 Jul 2003 22:05:46 +0000
parents ee2fabf561ed
children 27cbf1fb9ad8
comparison
equal deleted inserted replaced
10361:9f97e3bd0e04 10362:8e3e884ec8a4
43 #endif 43 #endif
44 44
45 #if LIBAVCODEC_BUILD < 4654 45 #if LIBAVCODEC_BUILD < 4654
46 #define PIX_FMT_RGB24 PIX_FMT_BGR24 46 #define PIX_FMT_RGB24 PIX_FMT_BGR24
47 #define PIX_FMT_RGBA32 PIX_FMT_BGRA32 47 #define PIX_FMT_RGBA32 PIX_FMT_BGRA32
48 #endif
49
50 //!!TODO!! when ffmpeg is patched set correct version number
51 #if LIBAVCODEC_BUILD < 4669
52 #undef HAVE_XVMC
53 #endif
54
55 #ifdef HAVE_XVMC
56 #include "xvmc_render.h"
48 #endif 57 #endif
49 58
50 int avcodec_inited=0; 59 int avcodec_inited=0;
51 60
52 #if defined(FF_POSTPROCESS) && defined(MBR) 61 #if defined(FF_POSTPROCESS) && defined(MBR)
77 #include "cfgparser.h" 86 #include "cfgparser.h"
78 87
79 static int get_buffer(AVCodecContext *avctx, AVFrame *pic); 88 static int get_buffer(AVCodecContext *avctx, AVFrame *pic);
80 static void release_buffer(AVCodecContext *avctx, AVFrame *pic); 89 static void release_buffer(AVCodecContext *avctx, AVFrame *pic);
81 90
91 #ifdef HAVE_XVMC
92 static int mc_get_buffer(AVCodecContext *avctx, AVFrame *pic);
93 static void mc_release_buffer(AVCodecContext *avctx, AVFrame *pic);
94 static void mc_render_slice(struct AVCodecContext *s,
95 uint8_t **src, int linesize,
96 int y, int width, int height);
97 #endif
98
82 static int lavc_param_workaround_bugs= FF_BUG_AUTODETECT; 99 static int lavc_param_workaround_bugs= FF_BUG_AUTODETECT;
83 static int lavc_param_error_resilience=2; 100 static int lavc_param_error_resilience=2;
84 static int lavc_param_error_concealment=3; 101 static int lavc_param_error_concealment=3;
85 static int lavc_param_gray=0; 102 static int lavc_param_gray=0;
86 static int lavc_param_vstats=0; 103 static int lavc_param_vstats=0;
104 static int control(sh_video_t *sh,int cmd,void* arg,...){ 121 static int control(sh_video_t *sh,int cmd,void* arg,...){
105 vd_ffmpeg_ctx *ctx = sh->context; 122 vd_ffmpeg_ctx *ctx = sh->context;
106 AVCodecContext *avctx = ctx->avctx; 123 AVCodecContext *avctx = ctx->avctx;
107 switch(cmd){ 124 switch(cmd){
108 case VDCTRL_QUERY_FORMAT: 125 case VDCTRL_QUERY_FORMAT:
109 if( (*((int*)arg)) == ctx->best_csp ) return CONTROL_TRUE;//supported 126 {
127 int format =(*((int*)arg));
128 if( format == ctx->best_csp ) return CONTROL_TRUE;//supported
129 #ifdef HAVE_XVMC
130 if( (avctx->pix_fmt == PIX_FMT_XVMC) && IMGFMT_IS_XVMC(format) )
131 return CONTROL_TRUE;
132 #endif
110 // possible conversions: 133 // possible conversions:
111 switch( (*((int*)arg)) ){ 134 switch( format ){
112 case IMGFMT_YV12: 135 case IMGFMT_YV12:
113 case IMGFMT_IYUV: 136 case IMGFMT_IYUV:
114 case IMGFMT_I420: 137 case IMGFMT_I420:
115 // "converted" using pointer/stride modification 138 // "converted" using pointer/stride modification
116 if(avctx->pix_fmt==PIX_FMT_YUV420P) return CONTROL_TRUE;// u/v swap 139 if(avctx->pix_fmt==PIX_FMT_YUV420P) return CONTROL_TRUE;// u/v swap
117 if(avctx->pix_fmt==PIX_FMT_YUV422P) return CONTROL_TRUE;// half stride 140 if(avctx->pix_fmt==PIX_FMT_YUV422P) return CONTROL_TRUE;// half stride
118 break; 141 break;
119 } 142 }
120 return CONTROL_FALSE; 143 return CONTROL_FALSE;
144 }
121 } 145 }
122 return CONTROL_UNKNOWN; 146 return CONTROL_UNKNOWN;
123 } 147 }
124 148
125 // init driver 149 // init driver
162 ctx->pic = avcodec_alloc_picture(); 186 ctx->pic = avcodec_alloc_picture();
163 #endif 187 #endif
164 ctx->avctx = avcodec_alloc_context(); 188 ctx->avctx = avcodec_alloc_context();
165 avctx = ctx->avctx; 189 avctx = ctx->avctx;
166 190
191 #ifdef HAVE_XVMC
192 if(lavc_codec->id == CODEC_ID_MPEG2VIDEO_XVMC){
193 printf("vd_ffmpeg: XVMC accelerated MPEG2\n");
194 assert(ctx->do_dr1);//these are must to!
195 assert(ctx->do_slices); //it is (vo_)ffmpeg bug if this fails
196 avctx->flags|= CODEC_FLAG_EMU_EDGE;//do i need that??!!
197 avctx->get_buffer= mc_get_buffer;
198 avctx->release_buffer= mc_release_buffer;
199 avctx->draw_horiz_band = mc_render_slice;
200 }else
201 #endif
167 if(ctx->do_dr1){ 202 if(ctx->do_dr1){
168 avctx->flags|= CODEC_FLAG_EMU_EDGE; 203 avctx->flags|= CODEC_FLAG_EMU_EDGE;
169 avctx->get_buffer= get_buffer; 204 avctx->get_buffer= get_buffer;
170 avctx->release_buffer= release_buffer; 205 avctx->release_buffer= release_buffer;
171 } 206 }
357 case PIX_FMT_YUV444P: ctx->best_csp=IMGFMT_444P;break; //photo jpeg 392 case PIX_FMT_YUV444P: ctx->best_csp=IMGFMT_444P;break; //photo jpeg
358 case PIX_FMT_YUV411P: ctx->best_csp=IMGFMT_411P;break; //dv ntsc 393 case PIX_FMT_YUV411P: ctx->best_csp=IMGFMT_411P;break; //dv ntsc
359 case PIX_FMT_YUV422: ctx->best_csp=IMGFMT_YUY2;break; //huffyuv perhaps in the future 394 case PIX_FMT_YUV422: ctx->best_csp=IMGFMT_YUY2;break; //huffyuv perhaps in the future
360 case PIX_FMT_RGB24 : ctx->best_csp=IMGFMT_BGR24;break; //huffyuv 395 case PIX_FMT_RGB24 : ctx->best_csp=IMGFMT_BGR24;break; //huffyuv
361 case PIX_FMT_RGBA32: ctx->best_csp=IMGFMT_BGR32;break; //huffyuv 396 case PIX_FMT_RGBA32: ctx->best_csp=IMGFMT_BGR32;break; //huffyuv
397 #ifdef HAVE_XVMC
398 case PIX_FMT_XVMC: //ctx->best_csp=IMGFMT_XVMC_MPEG2;
399 ctx->best_csp=sh->codec->outfmt[sh->outfmtidx];//!!maybe!!??
400 break;
401 #endif
362 default: 402 default:
363 ctx->best_csp=0; 403 ctx->best_csp=0;
364 } 404 }
365 if (!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h, ctx->best_csp)) 405 if (!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h, ctx->best_csp))
366 return -1; 406 return -1;
525 mp_image_t* mpi=NULL; 565 mp_image_t* mpi=NULL;
526 int dr1= ctx->do_dr1; 566 int dr1= ctx->do_dr1;
527 567
528 if(len<=0) return NULL; // skipped frame 568 if(len<=0) return NULL; // skipped frame
529 569
570 #ifdef HAVE_XVMC
571 // in fact if(!dr1) should be the only condition, but this way we hide an
572 //ffmpeg interlace (mpeg2) bug. use -noslices to avoid it.
573 if( (avctx->pix_fmt != PIX_FMT_XVMC) )// && (!dr1) )
574 #endif
530 avctx->draw_horiz_band=NULL; 575 avctx->draw_horiz_band=NULL;
531 avctx->opaque=sh; 576 avctx->opaque=sh;
532 if(ctx->vo_inited && !(flags&3) && !dr1){ 577 if(ctx->vo_inited && !(flags&3) && !dr1){
533 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, MP_IMGFLAG_PRESERVE | 578 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, MP_IMGFLAG_PRESERVE |
534 (ctx->do_slices?MP_IMGFLAG_DRAW_CALLBACK:0), 579 (ctx->do_slices?MP_IMGFLAG_DRAW_CALLBACK:0),
681 #endif 726 #endif
682 727
683 return mpi; 728 return mpi;
684 } 729 }
685 730
686 #endif 731 #ifdef HAVE_XVMC
732 static int mc_get_buffer(AVCodecContext *avctx, AVFrame *pic){
733 sh_video_t * sh = avctx->opaque;
734 vd_ffmpeg_ctx *ctx = sh->context;
735 mp_image_t* mpi=NULL;
736 xvmc_render_state_t * render;
737 int flags= MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE|
738 MP_IMGFLAG_DRAW_CALLBACK;
739
740 // printf("vd_ffmpeg::mc_get_buffer (xvmc) %d %d %d\n", pic->reference, ctx->ip_count, ctx->b_count);
741 if(avctx->pix_fmt != PIX_FMT_XVMC){
742 printf("vd_ffmpeg::mc_get_buffer should work only with XVMC format!!!");
743 assert(0);
744 exit(1);
745 }
746 assert(avctx->draw_horiz_band == mc_render_slice);
747 assert(avctx->release_buffer == mc_release_buffer);
748 if(verbose > 4)
749 printf("vd_ffmpeg::mc_get_buffer\n");
750 if(init_vo(sh)<0){
751 printf("vd_ffmpeg: Unexpected init_vo error\n");
752 exit(1);
753 }
754
755
756
757 if(!pic->reference){
758 ctx->b_count++;
759 }else{
760 ctx->ip_count++;
761 flags|= MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE;
762 }
763
764 mpi= mpcodecs_get_image(sh, MP_IMGTYPE_IPB,flags ,
765 avctx->width, avctx->height);
766 if(mpi==NULL){
767 printf("Unrecoverable error, render buffers not taken\n");
768 assert(0);
769 exit(1);
770 };
771
772 if( (mpi->flags & MP_IMGFLAG_DIRECT) == 0){
773 printf("Only buffers allocated by vo_xvmc allowed\n");
774 assert(0);
775 exit(1);
776 }
777
778 pic->data[0]= mpi->planes[0];
779 pic->data[1]= mpi->planes[1];
780 pic->data[2]= mpi->planes[2];
781
782
783 /* Note, some (many) codecs in libavcodec must have stride1==stride2 && no changes between frames
784 * lavc will check that and die with an error message, if its not true
785 */
786 pic->linesize[0]= mpi->stride[0];
787 pic->linesize[1]= mpi->stride[1];
788 pic->linesize[2]= mpi->stride[2];
789
790 pic->opaque = mpi;
791
792 if(pic->reference){
793 //I or P frame
794 pic->age= ctx->ip_age[0];
795
796 ctx->ip_age[0]= ctx->ip_age[1]+1;
797 ctx->ip_age[1]= 1;
798 ctx->b_age++;
799 }else{
800 //B frame
801 pic->age= ctx->b_age;
802
803 ctx->ip_age[0]++;
804 ctx->ip_age[1]++;
805 ctx->b_age=1;
806 }
807 #if LIBAVCODEC_BUILD >= 4644
808 pic->type= FF_BUFFER_TYPE_USER;
809 #endif
810 render=(xvmc_render_state_t*)mpi->priv;//same as data[2]
811 assert(render != 0);
812 assert(render->magic == MP_XVMC_RENDER_MAGIC);
813 render->state |= MP_XVMC_STATE_PREDICTION;
814 return 0;
815 }
816
817
818 static void mc_release_buffer(AVCodecContext *avctx, AVFrame *pic){
819 mp_image_t* mpi= pic->opaque;
820 sh_video_t * sh = avctx->opaque;
821 vd_ffmpeg_ctx *ctx = sh->context;
822 xvmc_render_state_t * render;
823 int i;
824
825
826 if(ctx->ip_count <= 2 && ctx->b_count<=1){
827 if(mpi->flags&MP_IMGFLAG_PRESERVE)
828 ctx->ip_count--;
829 else
830 ctx->b_count--;
831 }
832
833 //printf("R%X %X\n", pic->linesize[0], pic->data[0]);
834 //mark the surface as not requared for prediction
835 render=(xvmc_render_state_t*)pic->data[2];//same as mpi->priv
836 assert(render!=NULL);
837 assert(render->magic==MP_XVMC_RENDER_MAGIC);
838 render->state&=~MP_XVMC_STATE_PREDICTION;
839 if(verbose > 4)
840 printf("vd_ffmpeg::mc_release buffer (render=%p)\n",render);
841 for(i=0; i<4; i++){
842 pic->data[i]= NULL;
843 }
844 }
845
846 static void mc_render_slice(struct AVCodecContext *s,
847 uint8_t **src, int linesize,
848 int y, int width, int height){
849
850 sh_video_t * sh = s->opaque;
851 int stride[3];
852
853 assert(linesize==0);
854
855 stride[0]=stride[1]=stride[2]=linesize;
856 mpcodecs_draw_slice (sh,src, stride, width, height, 0, y);
857
858 }
859
860 #endif // HAVE_XVMC
861
862 #endif