Signed-off-by: softworkz <softwo...@hotmail.com> --- libavcodec/qsvdec.c | 210 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+)
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 8bce9f2cf0..62f3e65455 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -45,6 +45,12 @@ #include "hwconfig.h" #include "qsv.h" #include "qsv_internal.h" +#include "h264dec.h" +#include "h264_sei.h" +#include "hevcdec.h" +#include "hevc_ps.h" +#include "hevc_sei.h" +#include "mpeg12.h" static const AVRational mfx_tb = { 1, 90000 }; @@ -92,6 +98,8 @@ typedef struct QSVContext { mfxExtBuffer **ext_buffers; int nb_ext_buffers; + + Mpeg1Context mpeg_ctx; } QSVContext; static const AVCodecHWConfigInternal *const qsv_hw_configs[] = { @@ -498,6 +506,185 @@ static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf) return NULL; } +static int find_start_offset(mfxU8 data[1024]) +{ + if (data[0] == 0 && data[1] == 0 && data[2] == 1) + return 3; + + if (data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 1) + return 4; + + return 0; +} + +static int parse_sei_h264(AVCodecContext* avctx, QSVContext* q, AVFrame* out) +{ + H264SEIContext sei = { 0 }; + GetBitContext gb = { 0 }; + mfxU8 data[1024] = { 0 }; + mfxPayload payload = { 0, .Data = &data[0], .BufSize = sizeof(data) }; + mfxU64 ts; + int ret; + + while (1) { + int start; + memset(&data[0], 0, sizeof(data)); + + ret = MFXVideoDECODE_GetPayload(q->session, &ts, &payload); + if (ret != MFX_ERR_NONE) { + av_log(avctx, AV_LOG_WARNING, "error getting SEI payload: %d \n", ret); + return ret; + } + + if (payload.NumBit == 0 || payload.NumBit >= sizeof(data) * 8) { + break; + } + + start = find_start_offset(data); + + switch (payload.Type) { + case SEI_TYPE_BUFFERING_PERIOD: + case SEI_TYPE_PIC_TIMING: + continue; + } + + if (init_get_bits(&gb, &data[start], payload.NumBit - start * 8) < 0) + av_log(avctx, AV_LOG_ERROR, "Error initializing bitstream reader"); + else + ret = ff_h264_sei_decode(&sei, &gb, NULL, avctx); + + if (ret < 0) + av_log(avctx, AV_LOG_WARNING, "Error parsing SEI type: %d Numbits %d error: %d\n", payload.Type, payload.NumBit, ret); + else + av_log(avctx, AV_LOG_DEBUG, "mfxPayload Type: %d Numbits %d\n", payload.Type, payload.NumBit); + } + + if (out) + return ff_h264_export_frame_props(avctx, &sei, NULL, out); + + return 0; +} + +static int parse_sei_hevc(AVCodecContext* avctx, QSVContext* q, AVFrame* out) +{ + HEVCSEI sei = { 0 }; + HEVCParamSets ps = { 0 }; + GetBitContext gb = { 0 }; + mfxU8 data[1024] = { 0 }; + mfxPayload payload = { 0, .Data = &data[0], .BufSize = sizeof(data) }; + mfxU64 ts; + int ret; + + while (1) { + int start; + memset(&data[0], 0, sizeof(data)); + + ret = MFXVideoDECODE_GetPayload(q->session, &ts, &payload); + if (ret != MFX_ERR_NONE) { + av_log(avctx, AV_LOG_WARNING, "error getting SEI payload: %d \n", ret); + return ret; + } + + if (payload.NumBit == 0 || payload.NumBit >= sizeof(data) * 8) { + break; + } + + start = find_start_offset(data); + + switch (payload.Type) { + case SEI_TYPE_BUFFERING_PERIOD: + case SEI_TYPE_PIC_TIMING: + continue; + case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: + case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: + // There seems to be a bug in MSDK for these + payload.NumBit -= 8; + break; + } + + if (init_get_bits(&gb, &data[start], payload.NumBit - start * 8) < 0) + av_log(avctx, AV_LOG_ERROR, "Error initializing bitstream reader"); + else + ret = ff_hevc_decode_nal_sei(&gb, avctx, &sei, &ps, HEVC_NAL_SEI_PREFIX); + + if (ret < 0) + av_log(avctx, AV_LOG_WARNING, "error parsing SEI type: %d Numbits %d error: %d\n", payload.Type, payload.NumBit, ret); + else + av_log(avctx, AV_LOG_DEBUG, "mfxPayload Type: %d Numbits %d\n", payload.Type, payload.NumBit); + } + + if (out) + return ff_set_side_data(avctx, &sei, NULL, out); + + return 0; +} + +static int parse_sei_mpeg12(AVCodecContext* avctx, QSVContext* q, AVFrame* out) +{ + Mpeg1Context *mpeg_ctx = &q->mpeg_ctx; + mfxU8 data[1024] = { 0 }; + mfxPayload payload = { 0, .Data = &data[0], .BufSize = sizeof(data) }; + mfxU64 ts; + int ret; + + while (1) { + int start; + + memset(&data[0], 0, sizeof(data)); + ret = MFXVideoDECODE_GetPayload(q->session, &ts, &payload); + if (ret != MFX_ERR_NONE) { + av_log(avctx, AV_LOG_WARNING, "error getting SEI payload: %d \n", ret); + return ret; + } + + if (payload.NumBit == 0 || payload.NumBit >= sizeof(data) * 8) { + break; + } + + start = find_start_offset(data); + + start++; + + ff_mpeg_decode_user_data(avctx, mpeg_ctx, &data[start], (int)((payload.NumBit + 7) / 8) - start); + + if (ret < 0) + av_log(avctx, AV_LOG_WARNING, "error parsing SEI type: %d Numbits %d error: %d\n", payload.Type, payload.NumBit, ret); + else + av_log(avctx, AV_LOG_DEBUG, "mfxPayload Type: %d Numbits %d start %d -> %.s\n", payload.Type, payload.NumBit, start, (char *)(&data[start])); + } + + if (!out) + return 0; + + if (mpeg_ctx->a53_buf_ref) { + + AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_A53_CC, mpeg_ctx->a53_buf_ref); + if (!sd) + av_buffer_unref(&mpeg_ctx->a53_buf_ref); + mpeg_ctx->a53_buf_ref = NULL; + } + + if (mpeg_ctx->has_stereo3d) { + AVStereo3D *stereo = av_stereo3d_create_side_data(out); + if (!stereo) + return AVERROR(ENOMEM); + + *stereo = mpeg_ctx->stereo3d; + mpeg_ctx->has_stereo3d = 0; + } + + if (mpeg_ctx->has_afd) { + AVFrameSideData *sd = av_frame_new_side_data(out, AV_FRAME_DATA_AFD, 1); + if (!sd) + return AVERROR(ENOMEM); + + *sd->data = mpeg_ctx->afd; + mpeg_ctx->has_afd = 0; + } + + return 0; +} + static int qsv_decode(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, const AVPacket *avpkt) @@ -535,6 +722,8 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, insurf, &outsurf, sync); if (ret == MFX_WRN_DEVICE_BUSY) av_usleep(500); + else if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO || avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO) + parse_sei_mpeg12(avctx, q, NULL); } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); @@ -570,6 +759,27 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, return AVERROR_BUG; } + switch (avctx->codec_id) { + case AV_CODEC_ID_MPEG1VIDEO: + case AV_CODEC_ID_MPEG2VIDEO: + ret = parse_sei_mpeg12(avctx, q, out_frame->frame); + break; + case AV_CODEC_ID_H264: + ret = parse_sei_h264(avctx, q, out_frame->frame); + break; + case AV_CODEC_ID_HEVC: + ret = parse_sei_hevc(avctx, q, out_frame->frame); + break; + default: + ret = 0; + } + + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing SEI data\n"); + av_freep(&sync); + return ret; + } +# out_frame->queued = 1; av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); -- 2.30.2.windows.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".