Re: [libav-devel] [PATCH 1/6] qsvenc_hevc: Replace ad-hoc VPS writing with CBS implementation
if tested - LGTM On Mon, Dec 11, 2017 at 1:44 AM, Mark Thompsonwrote: > This copies more information which should be present from the SPS. > It also fixes the value of vps_temporal_id_nesting_flag, which was > previously incorrect for a single-layer stream (the standard states > that it must be 1, and the reference decoder barfs if it isn't). > --- > configure| 2 +- > libavcodec/Makefile | 3 +- > libavcodec/qsvenc_hevc.c | 190 +++--- > - > 3 files changed, 111 insertions(+), 84 deletions(-) > > diff --git a/configure b/configure > index 7f320fee1..3aa61abb8 100755 > --- a/configure > +++ b/configure > @@ -2267,7 +2267,7 @@ h264_vaapi_encoder_deps=" > VAEncPictureParameterBufferH264" > h264_vaapi_encoder_select="cbs_h264 vaapi_encode" > hevc_nvenc_encoder_deps="nvenc" > hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser > hevc_qsv_hwaccel qsvdec" > -hevc_qsv_encoder_select="hevcparse qsvenc" > +hevc_qsv_encoder_select="cbs_h265 qsvenc" > hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" > hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" > mjpeg_qsv_encoder_deps="libmfx" > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index d04902be0..9a1a6fec6 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -284,8 +284,7 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o > hevc_mvs.o hevc_sei.o \ >hevcdsp.o hevc_filter.o > hevc_data.o > OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o > OBJS-$(CONFIG_HEVC_QSV_DECODER)+= qsvdec_h2645.o > -OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o hevc_ps_enc.o >\ > - hevc_data.o > +OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o > OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o > OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o > OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o > hq_hqadsp.o \ > diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c > index dbb55e2f1..92066dcb7 100644 > --- a/libavcodec/qsvenc_hevc.c > +++ b/libavcodec/qsvenc_hevc.c > @@ -28,11 +28,11 @@ > #include "libavutil/opt.h" > > #include "avcodec.h" > -#include "bytestream.h" > +#include "cbs.h" > +#include "cbs_h265.h" > #include "get_bits.h" > #include "hevc.h" > #include "hevcdec.h" > -#include "h2645_parse.h" > #include "internal.h" > #include "qsv.h" > #include "qsv_internal.h" > @@ -52,107 +52,135 @@ typedef struct QSVHEVCEncContext { > > static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) > { > -GetByteContext gbc; > -PutByteContext pbc; > - > -GetBitContext gb; > -H2645NAL sps_nal = { NULL }; > -HEVCSPS sps = { 0 }; > -HEVCVPS vps = { 0 }; > -uint8_t vps_buf[128], vps_rbsp_buf[128]; > -uint8_t *new_extradata; > -unsigned int sps_id; > -int ret, i, type, vps_size; > +CodedBitstreamContext cbc; > +CodedBitstreamFragment ps; > +const H265RawSPS *sps; > +H265RawVPS vps; > +uint8_t *data = NULL; > +size_t data_size; > +int err, sps_pos, i; > > if (!avctx->extradata_size) { > -av_log(avctx, AV_LOG_ERROR, "No extradata returned from > libmfx\n"); > +av_log(avctx, AV_LOG_ERROR, > + "No parameter sets returned by libmfx.\n"); > return AVERROR_UNKNOWN; > } > > -/* parse the SPS */ > -ret = ff_h2645_extract_rbsp(avctx->extradata + 4, > avctx->extradata_size - 4, _nal); > -if (ret < 0) { > -av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n"); > -return ret; > -} > +err = ff_cbs_init(, AV_CODEC_ID_HEVC, avctx); > +if (err < 0) > +return err; > > -ret = init_get_bits8(, sps_nal.data, sps_nal.size); > -if (ret < 0) { > -av_freep(_nal.rbsp_buffer); > -return ret; > +err = ff_cbs_read(, , avctx->extradata, avctx->extradata_size); > +if (err < 0) { > +av_log(avctx, AV_LOG_ERROR, > + "Error reading parameter sets returned by libmfx.\n"); > +ff_cbs_close(); > +return err; > } > > -get_bits(, 1); > -type = get_bits(, 6); > -if (type != HEVC_NAL_SPS) { > -av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the > extradata: %d\n", > - type); > -av_freep(_nal.rbsp_buffer); > -return AVERROR_INVALIDDATA; > +sps = NULL; > +for (sps_pos = 0; sps_pos < ps.nb_units; sps_pos++) { > +if (ps.units[sps_pos].type == HEVC_NAL_SPS) { > +sps = ps.units[sps_pos].content; > +break; > +} > } > -get_bits(, 9); > - > -ret = ff_hevc_parse_sps(, , _id, 0, NULL, avctx); > -av_freep(_nal.rbsp_buffer); > -if (ret < 0) { > -av_log(avctx, AV_LOG_ERROR, "Error parsing the SPS\n"); > -return ret; > +if (!sps) { > +
[libav-devel] [PATCH 1/6] qsvenc_hevc: Replace ad-hoc VPS writing with CBS implementation
This copies more information which should be present from the SPS. It also fixes the value of vps_temporal_id_nesting_flag, which was previously incorrect for a single-layer stream (the standard states that it must be 1, and the reference decoder barfs if it isn't). --- configure| 2 +- libavcodec/Makefile | 3 +- libavcodec/qsvenc_hevc.c | 190 +++ 3 files changed, 111 insertions(+), 84 deletions(-) diff --git a/configure b/configure index 7f320fee1..3aa61abb8 100755 --- a/configure +++ b/configure @@ -2267,7 +2267,7 @@ h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" hevc_nvenc_encoder_deps="nvenc" hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvdec" -hevc_qsv_encoder_select="hevcparse qsvenc" +hevc_qsv_encoder_select="cbs_h265 qsvenc" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" mjpeg_qsv_encoder_deps="libmfx" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index d04902be0..9a1a6fec6 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -284,8 +284,7 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o hevc_sei.o \ hevcdsp.o hevc_filter.o hevc_data.o OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o OBJS-$(CONFIG_HEVC_QSV_DECODER)+= qsvdec_h2645.o -OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o hevc_ps_enc.o \ - hevc_data.o +OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index dbb55e2f1..92066dcb7 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -28,11 +28,11 @@ #include "libavutil/opt.h" #include "avcodec.h" -#include "bytestream.h" +#include "cbs.h" +#include "cbs_h265.h" #include "get_bits.h" #include "hevc.h" #include "hevcdec.h" -#include "h2645_parse.h" #include "internal.h" #include "qsv.h" #include "qsv_internal.h" @@ -52,107 +52,135 @@ typedef struct QSVHEVCEncContext { static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) { -GetByteContext gbc; -PutByteContext pbc; - -GetBitContext gb; -H2645NAL sps_nal = { NULL }; -HEVCSPS sps = { 0 }; -HEVCVPS vps = { 0 }; -uint8_t vps_buf[128], vps_rbsp_buf[128]; -uint8_t *new_extradata; -unsigned int sps_id; -int ret, i, type, vps_size; +CodedBitstreamContext cbc; +CodedBitstreamFragment ps; +const H265RawSPS *sps; +H265RawVPS vps; +uint8_t *data = NULL; +size_t data_size; +int err, sps_pos, i; if (!avctx->extradata_size) { -av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx\n"); +av_log(avctx, AV_LOG_ERROR, + "No parameter sets returned by libmfx.\n"); return AVERROR_UNKNOWN; } -/* parse the SPS */ -ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, _nal); -if (ret < 0) { -av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n"); -return ret; -} +err = ff_cbs_init(, AV_CODEC_ID_HEVC, avctx); +if (err < 0) +return err; -ret = init_get_bits8(, sps_nal.data, sps_nal.size); -if (ret < 0) { -av_freep(_nal.rbsp_buffer); -return ret; +err = ff_cbs_read(, , avctx->extradata, avctx->extradata_size); +if (err < 0) { +av_log(avctx, AV_LOG_ERROR, + "Error reading parameter sets returned by libmfx.\n"); +ff_cbs_close(); +return err; } -get_bits(, 1); -type = get_bits(, 6); -if (type != HEVC_NAL_SPS) { -av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the extradata: %d\n", - type); -av_freep(_nal.rbsp_buffer); -return AVERROR_INVALIDDATA; +sps = NULL; +for (sps_pos = 0; sps_pos < ps.nb_units; sps_pos++) { +if (ps.units[sps_pos].type == HEVC_NAL_SPS) { +sps = ps.units[sps_pos].content; +break; +} } -get_bits(, 9); - -ret = ff_hevc_parse_sps(, , _id, 0, NULL, avctx); -av_freep(_nal.rbsp_buffer); -if (ret < 0) { -av_log(avctx, AV_LOG_ERROR, "Error parsing the SPS\n"); -return ret; +if (!sps) { +av_log(avctx, AV_LOG_ERROR, "No SPS returned by libmfx.\n"); +goto fail; } -/* generate the VPS */ -vps.vps_max_layers = 1; -vps.vps_max_sub_layers = sps.max_sub_layers; -memcpy(, , sizeof(vps.ptl)); -vps.vps_sub_layer_ordering_info_present_flag = 1; +vps = (H265RawVPS) { +.nal_unit_header = { +