Closed 4714407 closed 3 years ago
Normally we just need to set the codec, like FFmpegFrameGrabber.setVideoCodecName("h264_dxva2")
.
/cc @n-kai-cj
setVideoCodecName or setVideoCodec? I use the following method to view all codecs, without this codec Pointer pointer = new Pointer((Pointer)null); while ((c = av_codec_iterate(pointer)) != null) { if (av_codec_is_decoder(c)>0) logger.debug("{}:{} ", c.name().getString(),c.type()); }
Then your system doesn't support DXVA2, I guess...
I have no problem using the following command line:
./ffmpeg -hwaccel dxva2 -c:v h264 -threads 0 -i d:\ test.mp4 -f null - -benchmark
I checked with the following code and found no problem AVCodecHWConfig avCodecHWConfig=null; for (int i = 0;; i++) { avCodecHWConfig= avcodec_get_hw_config(codec, i); if (avCodecHWConfig == null) { logger.debug("codec{} not support hw",codec.name().getString()); break; }else{ if ((avCodecHWConfig.methods() & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)>0 && avCodecHWConfig.device_type() == hwdevice) { logger.debug("codec{} support{}",codec.name().getString(),av_hwdevice_get_type_name(hwdevice).getString()); break; } } } when hwdevice=AV_HWDEVICE_TYPE_DXVA2 print support
I added the following code to the decoding logic( FFmpegFrameGrabber.java 1322 row), but AV hwframe transfer_ Data caused a JVM crash
int len = avcodec_decode_video2(video_c, picture, got_frame, pkt);
// Did we get a video frame?
if (len >= 0 && got_frame[0] != 0
&& (!keyFrames || picture.pict_type() == AV_PICTURE_TYPE_I)) {
long pts = av_frame_get_best_effort_timestamp(picture);
AVRational time_base = video_st.time_base();
timestamp = 1000000L * pts * time_base.num() / time_base.den();
// best guess, AVCodecContext.frame_number = number of decoded frames...
frameNumber = (int)Math.round(timestamp * getFrameRate() / 1000000L);
frame.image = image_buf;
if (picture.format() == AV_PIX_FMT_DXVA2_VLD) {
/* retrieve data from GPU to CPU */
AVFrame hwframe = null;
if ((hwframe = av_frame_alloc()) == null) {
throw new Exception("av_frame_alloc() error: Could not allocate raw hwframe.");
}
if ((av_hwframe_transfer_data(hwframe, picture, 0)) < 0) {
throw new Exception("Error transferring the data to system memory");
}
}
We probably need to allocate memory for that frame...
When I use the API method "avcodec_receive_frame" recommended by ffmpeg, everything is normal. If you have time, you can consider rewriting the decoding logic and replacing the deprecated method "avcodec_decode_video2".
@deprecated Use avcodec_send_packet() and avcodec_receive_frame().
Yes, that's on the to-do list, see issue #1498. If you'd like to work on that, it would be great!
We probably need to allocate memory for that frame...
what frame?
I have successfully used hwaccel to turn on dxva2 acceleration (refer to ffmpeg code).
You need to make sure the pixel format of images from FFmpeg and Java 2D is the same.
When I use the API method "avcodec_receive_frame" recommended by ffmpeg, everything is normal. If you have time, you can consider rewriting the decoding logic and replacing the deprecated method "avcodec_decode_video2".
@deprecated Use avcodec_send_packet() and avcodec_receive_frame().
I've switched to that new API in commit https://github.com/bytedeco/javacv/commit/c952a23cc33ace29688ce577ce116d65bb1146b4. Please give it a try with the snapshots: http://bytedeco.org/builds/
I have successfully used hwaccel to turn on dxva2 acceleration (refer to ffmpeg code).
@4714407 ,hello, I wonder if you can give me the demo of how to use the hwaccel to turn on dxva2 acceleration by javacv,. if not, can you tell me how to use the method "get_format" by javacv. many thanks
The following code doesn't seem to work
AVBufferRef hw_context=av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DXVA2); if ((ret=av_hwdevice_ctx_create(hw_context,AV_HWDEVICE_TYPE_DXVA2,(String)null,null,0))<0){ releaseUnsafe(); throw new Exception("av_hwdevice_ctx_create() error " + ret + ": Could not create hwdevice context."); } if (video_c.hwaccel_context(av_buffer_ref(hw_context))==null){ releaseUnsafe(); throw new Exception("hwaccel_context() error : Could not set hwaccel "+av_hwdevice_get_type_name(AV_HWDEVICE_TYPE_DXVA2).getString()+" ."); }