From 63c690ad154509dcda78d3d3537bd1af9c406241 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 23 Nov 2017 23:47:52 +0000 Subject: [PATCH] vaapi: Add MJPEG decode hwaccel --- Changelog | 2 +- configure | 2 + libavcodec/Makefile | 1 + libavcodec/hwaccels.h | 1 + libavcodec/mjpegdec.c | 6 ++ libavcodec/vaapi_decode.c | 2 + libavcodec/vaapi_mjpeg.c | 159 ++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 libavcodec/vaapi_mjpeg.c diff --git a/Changelog b/Changelog index 56dedd1aea..441ee1cd29 100644 --- a/Changelog +++ b/Changelog @@ -21,7 +21,7 @@ version : - video mix filter - video normalize filter - audio lv2 wrapper filter -- VAAPI VP8 decoding +- VAAPI MJPEG and VP8 decoding - AMD AMF H.264 and HEVC encoders - video fillborders filter - video setrange filter diff --git a/configure b/configure index fa5c530abe..9b2468516a 100755 --- a/configure +++ b/configure @@ -2714,6 +2714,8 @@ hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" hevc_vdpau_hwaccel_select="hevc_decoder" hevc_videotoolbox_hwaccel_deps="videotoolbox" hevc_videotoolbox_hwaccel_select="hevc_decoder" +mjpeg_vaapi_hwaccel_deps="vaapi" +mjpeg_vaapi_hwaccel_select="mjpeg_decoder" mpeg_xvmc_hwaccel_deps="xvmc" mpeg_xvmc_hwaccel_select="mpeg2video_decoder" mpeg1_nvdec_hwaccel_deps="nvdec" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3d4b738e0b..de52bc2094 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -854,6 +854,7 @@ OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o +OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index fcfe4e088e..420e2feeea 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -37,6 +37,7 @@ extern const AVHWAccel ff_hevc_nvdec_hwaccel; extern const AVHWAccel ff_hevc_vaapi_hwaccel; extern const AVHWAccel ff_hevc_vdpau_hwaccel; extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; +extern const AVHWAccel ff_mjpeg_vaapi_hwaccel; extern const AVHWAccel ff_mpeg1_nvdec_hwaccel; extern const AVHWAccel ff_mpeg1_vdpau_hwaccel; extern const AVHWAccel ff_mpeg1_videotoolbox_hwaccel; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 6141f06367..939f2849d0 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -650,6 +650,9 @@ unk_pixfmt: s->avctx->pix_fmt = s->hwaccel_pix_fmt; } else { enum AVPixelFormat pix_fmts[] = { +#if CONFIG_MJPEG_VAAPI_HWACCEL + AV_PIX_FMT_VAAPI, +#endif s->avctx->pix_fmt, AV_PIX_FMT_NONE, }; @@ -2777,6 +2780,9 @@ AVCodec ff_mjpeg_decoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MJPEG_VAAPI_HWACCEL + HWACCEL_VAAPI(mjpeg), +#endif NULL }, }; diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 28c6eeb801..d0a6b5817d 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -379,6 +379,8 @@ static const struct { MAP(HEVC, HEVC_MAIN, HEVCMain ), MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ), #endif + MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT, + JPEGBaseline), MAP(WMV3, VC1_SIMPLE, VC1Simple ), MAP(WMV3, VC1_MAIN, VC1Main ), MAP(WMV3, VC1_COMPLEX, VC1Advanced ), diff --git a/libavcodec/vaapi_mjpeg.c b/libavcodec/vaapi_mjpeg.c new file mode 100644 index 0000000000..14e0206ae1 --- /dev/null +++ b/libavcodec/vaapi_mjpeg.c @@ -0,0 +1,159 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "hwaccel.h" +#include "vaapi_decode.h" +#include "mjpegdec.h" + +static int vaapi_mjpeg_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const MJpegDecodeContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->hwaccel_picture_private; + VAPictureParameterBufferJPEGBaseline pp; + int err, i; + + pic->output_surface = ff_vaapi_get_surface_id(s->picture_ptr); + + pp = (VAPictureParameterBufferJPEGBaseline) { + .picture_width = avctx->width, + .picture_height = avctx->height, + + .num_components = s->nb_components, + }; + + for (i = 0; i < s->nb_components; i++) { + pp.components[i].component_id = s->component_id[i]; + pp.components[i].h_sampling_factor = s->h_count[i]; + pp.components[i].v_sampling_factor = s->v_count[i]; + pp.components[i].quantiser_table_selector = s->quant_index[i]; + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAPictureParameterBufferType, + &pp, sizeof(pp)); + if (err < 0) + goto fail; + + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; +} + +static int vaapi_mjpeg_end_frame(AVCodecContext *avctx) +{ + const MJpegDecodeContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->hwaccel_picture_private; + + return ff_vaapi_decode_issue(avctx, pic); +} + +static int vaapi_mjpeg_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const MJpegDecodeContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->hwaccel_picture_private; + VAHuffmanTableBufferJPEGBaseline huff; + VAIQMatrixBufferJPEGBaseline quant; + VASliceParameterBufferJPEGBaseline sp; + int err, i, j; + + memset(&huff, 0, sizeof(huff)); + for (i = 0; i < 2; i++) { + huff.load_huffman_table[i] = 1; + for (j = 0; j < 16; j++) + huff.huffman_table[i].num_dc_codes[j] = s->raw_huffman_lengths[0][i][j]; + for (j = 0; j < 12; j++) + huff.huffman_table[i].dc_values[j] = s->raw_huffman_values[0][i][j]; + for (j = 0; j < 16; j++) + huff.huffman_table[i].num_ac_codes[j] = s->raw_huffman_lengths[1][i][j]; + for (j = 0; j < 162; j++) + huff.huffman_table[i].ac_values[j] = s->raw_huffman_values[1][i][j]; + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAHuffmanTableBufferType, + &huff, sizeof(huff)); + if (err < 0) + goto fail; + + memset(&quant, 0, sizeof(quant)); + for (i = 0; i < 4; i++) { + quant.load_quantiser_table[i] = 1; + for (j = 0; j < 64; j++) + quant.quantiser_table[i][j] = s->quant_matrixes[i][j]; + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAIQMatrixBufferType, + &quant, sizeof(quant)); + if (err < 0) + goto fail; + + sp = (VASliceParameterBufferJPEGBaseline) { + .slice_data_size = size, + .slice_data_offset = 0, + .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, + + .slice_horizontal_position = 0, + .slice_vertical_position = 0, + + .restart_interval = s->restart_interval, + .num_mcus = s->mb_width * s->mb_height, + }; + + sp.num_components = s->nb_components; + for (i = 0; i < s->nb_components; i++) { + sp.components[i].component_selector = s->component_id[s->comp_index[i]]; + sp.components[i].dc_table_selector = s->dc_index[i]; + sp.components[i].ac_table_selector = s->ac_index[i]; + } + + err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), buffer, size); + if (err) + goto fail; + + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; +} + +const AVHWAccel ff_mjpeg_vaapi_hwaccel = { + .name = "mjpeg_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .pix_fmt = AV_PIX_FMT_VAAPI, + .start_frame = &vaapi_mjpeg_start_frame, + .end_frame = &vaapi_mjpeg_end_frame, + .decode_slice = &vaapi_mjpeg_decode_slice, + .frame_priv_data_size = sizeof(VAAPIDecodePicture), + .init = &ff_vaapi_decode_init, + .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, + .priv_data_size = sizeof(VAAPIDecodeContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index d772f3e48e..3939c4f67a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 12 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \