@@ -35,6 +35,8 @@ public ConcurrentQueue<VideoFrame>
3535
3636 // Hardware & Software_Handled (Y_UV | Y_U_V)
3737 Texture2DDescription textDesc , textDescUV ;
38+ ID3D11Texture2D textureFFmpeg ;
39+ AVCodecContext_get_format getHWformat ;
3840
3941 // Software_Sws (RGBA)
4042 const AVPixelFormat VOutPixelFormat = AVPixelFormat . AV_PIX_FMT_RGBA ;
@@ -107,9 +109,15 @@ public void DisposeVA()
107109 {
108110 if ( Renderer == null ) return ;
109111
110- fixed( AVBufferRef * * ptr = & hw_device_ctx ) av_buffer_unref ( ptr ) ;
111- hw_device_ctx = null ;
112+ if ( hw_device_ctx != null )
113+ fixed( AVBufferRef * * ptr = & hw_device_ctx ) av_buffer_unref ( ptr ) ;
114+
115+ if ( hwframes != null )
116+ fixed( AVBufferRef * * ptr = & hwframes ) av_buffer_unref ( ptr ) ;
112117
118+ hw_device_ctx = null ;
119+ hwframes = null ;
120+
113121 Renderer . Dispose ( ) ;
114122 }
115123 public void Swap ( VideoDecoder videoDecoder )
@@ -170,10 +178,96 @@ public void Swap(VideoDecoder videoDecoder)
170178
171179 public VideoDecoder ( Config config , Control control = null , int uniqueId = - 1 , bool initVA = true ) : base ( config , uniqueId )
172180 {
181+ getHWformat = new AVCodecContext_get_format ( get_format ) ;
182+
173183 if ( initVA )
174184 InitVA ( control ) ;
175185 }
176186
187+ AVBufferRef * hwframes ;
188+ private unsafe AVPixelFormat get_format ( AVCodecContext * avctx , AVPixelFormat * pix_fmts )
189+ {
190+ Log ( "get_format" ) ;
191+
192+ //if (codecCtx->hw_frames_ctx == null)
193+ // return AVPixelFormat.AV_PIX_FMT_NONE;
194+
195+ if ( AllocateHWFrames ( ) != 0 )
196+ Log ( "Hmmm..." ) ;
197+
198+ return AVPixelFormat . AV_PIX_FMT_D3D11 ;
199+ }
200+
201+ private bool ShouldAllocateNew ( )
202+ {
203+ if ( hwframes == null )
204+ return true ;
205+
206+ var t2 = ( AVHWFramesContext * ) hwframes ->data ;
207+
208+ if ( codecCtx ->width != t2 ->width )
209+ return true ;
210+
211+ if ( codecCtx ->height != t2 ->height )
212+ return true ;
213+
214+ var fmt = codecCtx ->sw_pix_fmt == AVPixelFormat . AV_PIX_FMT_YUV420P10LE ? AVPixelFormat . AV_PIX_FMT_P010LE : AVPixelFormat . AV_PIX_FMT_NV12 ;
215+ if ( fmt != t2 ->sw_format )
216+ return true ;
217+
218+ return false ;
219+ }
220+ private int AllocateHWFrames ( )
221+ {
222+ if ( ! ShouldAllocateNew ( ) )
223+ {
224+ if ( hwframes != null && codecCtx ->hw_frames_ctx == null )
225+ {
226+ codecCtx ->hw_frames_ctx = av_buffer_ref ( hwframes ) ;
227+ Log ( "Already allocated 1" ) ;
228+ }
229+ else
230+ Log ( "Already allocated 2" ) ;
231+
232+ textDesc . Format = textureFFmpeg . Description . Format ;
233+ return 0 ;
234+ }
235+
236+ Log ( "Allocating ..." ) ;
237+
238+ if ( hwframes != null )
239+ fixed( AVBufferRef * * ptr = & hwframes ) av_buffer_unref ( ptr ) ;
240+
241+ codecCtx ->hw_frames_ctx = av_hwframe_ctx_alloc ( codecCtx ->hw_device_ctx ) ;
242+ if ( codecCtx ->hw_frames_ctx == null )
243+ return - 1 ;
244+
245+ codecCtx ->hwaccel_context = null ;
246+ codecCtx ->hwaccel_flags |= 2 ; //AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX
247+
248+ var t2 = ( AVHWFramesContext * ) ( codecCtx ->hw_frames_ctx ->data ) ;
249+ t2 ->format = AVPixelFormat . AV_PIX_FMT_D3D11 ;
250+ t2 ->sw_format = codecCtx ->sw_pix_fmt == AVPixelFormat . AV_PIX_FMT_YUV420P10LE ? AVPixelFormat . AV_PIX_FMT_P010LE : AVPixelFormat . AV_PIX_FMT_NV12 ;
251+ t2 ->width = codecCtx ->width ;
252+ t2 ->height = codecCtx ->height ;
253+ t2 ->initial_pool_size = 20 ;
254+
255+ AVD3D11VAFramesContext * t3 = ( AVD3D11VAFramesContext * ) t2 ->hwctx ;
256+ t3 ->texture = null ;
257+ t3 ->BindFlags |= ( uint ) BindFlags . Decoder ;
258+
259+ hwframes = av_buffer_ref ( codecCtx ->hw_frames_ctx ) ;
260+
261+ int ret = av_hwframe_ctx_init ( codecCtx ->hw_frames_ctx ) ;
262+ if ( ret == 0 )
263+ {
264+ textureFFmpeg = new ID3D11Texture2D ( ( IntPtr ) t3 ->texture ) ;
265+ textDesc . Format = textureFFmpeg . Description . Format ;
266+ }
267+
268+ return ret ;
269+ }
270+
177271 protected override int Setup ( AVCodec * codec )
178272 {
179273 VideoAccelerated = false ;
@@ -200,6 +294,12 @@ protected override int Setup(AVCodec* codec)
200294 codecCtx ->thread_count = Math . Min ( Config . Decoder . VideoThreads , codecCtx ->codec_id == AV_CODEC_ID_HEVC ? 32 : 16 ) ;
201295 codecCtx ->thread_type = 0 ;
202296
297+ if ( VideoAccelerated )
298+ {
299+ codecCtx ->pix_fmt = AVPixelFormat . AV_PIX_FMT_D3D11 ;
300+ codecCtx ->get_format = getHWformat ;
301+ }
302+
203303 int bits = VideoStream . PixelFormatDesc ->comp . ToArray ( ) [ 0 ] . depth ;
204304
205305 textDesc = new Texture2DDescription ( )
@@ -647,11 +747,12 @@ internal VideoFrame ProcessVideoFrame(AVFrame* frame)
647747 VideoAccelerated = false ;
648748 Renderer ? . FrameResized ( ) ;
649749 CodecChanged ? . Invoke ( this ) ;
750+ codecCtx ->get_format = null ;
751+
650752 return ProcessVideoFrame ( frame ) ;
651753 }
652-
653- ID3D11Texture2D textureFFmpeg = new ID3D11Texture2D ( ( IntPtr ) frame ->data . ToArray ( ) [ 0 ] ) ;
654- textDesc . Format = textureFFmpeg . Description . Format ;
754+
755+ //Log($"{(IntPtr) frame->data.ToArray()[0]} | {(int) frame->data.ToArray()[1]} | {(IntPtr) (((AVD3D11VAFramesContext *)((AVHWFramesContext*)(codecCtx->hw_frames_ctx->data))->hwctx)->texture)}");
655756 mFrame . textures = new ID3D11Texture2D [ 1 ] ;
656757 mFrame . textures [ 0 ] = Renderer . Device . CreateTexture2D ( textDesc ) ;
657758 Renderer . Device . ImmediateContext . CopySubresourceRegion ( mFrame . textures [ 0 ] , 0 , 0 , 0 , 0 , textureFFmpeg , ( int ) frame ->data . ToArray ( ) [ 1 ] , new Vortice . Mathematics . Box ( 0 , 0 , 0 , mFrame . textures [ 0 ] . Description . Width , mFrame . textures [ 0 ] . Description . Height , 1 ) ) ;
0 commit comments