avcodec/hevcdec: Export Dolby Vision RPUs as side data

Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
This commit is contained in:
Derek Buitenhuis 2021-07-22 22:44:42 +01:00
parent 54e65aa38a
commit bc68fd1050
3 changed files with 42 additions and 1 deletions

View File

@ -2950,6 +2950,14 @@ static int set_side_data(HEVCContext *s)
}
}
if (s->rpu_buf) {
AVFrameSideData *rpu = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DOVI_RPU_BUFFER, s->rpu_buf);
if (!rpu)
return AVERROR(ENOMEM);
s->rpu_buf = NULL;
}
return 0;
}
@ -3223,6 +3231,7 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
break;
case HEVC_NAL_AUD:
case HEVC_NAL_FD_NUT:
case HEVC_NAL_UNSPEC62:
break;
default:
av_log(s->avctx, AV_LOG_INFO,
@ -3269,6 +3278,29 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
}
}
/*
* Check for RPU delimiter.
*
* Dolby Vision RPUs masquerade as unregistered NALs of type 62.
*
* We have to do this check here an create the rpu buffer, since RPUs are appended
* to the end of an AU; they are the last non-EOB/EOS NAL in the AU.
*/
if (s->pkt.nb_nals > 1 && s->pkt.nals[s->pkt.nb_nals - 1].type == HEVC_NAL_UNSPEC62 &&
s->pkt.nals[s->pkt.nb_nals - 1].size > 2 && !s->pkt.nals[s->pkt.nb_nals - 1].nuh_layer_id
&& !s->pkt.nals[s->pkt.nb_nals - 1].temporal_id) {
if (s->rpu_buf) {
av_buffer_unref(&s->rpu_buf);
av_log(s->avctx, AV_LOG_WARNING, "Multiple Dolby Vision RPUs found in one AU. Skipping previous.\n");
}
s->rpu_buf = av_buffer_alloc(s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2);
if (!s->rpu_buf)
return AVERROR(ENOMEM);
memcpy(s->rpu_buf->data, s->pkt.nals[s->pkt.nb_nals - 1].raw_data + 2, s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2);
}
/* decode the NAL units */
for (i = 0; i < s->pkt.nb_nals; i++) {
H2645NAL *nal = &s->pkt.nals[i];
@ -3512,6 +3544,8 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
pic_arrays_free(s);
av_buffer_unref(&s->rpu_buf);
av_freep(&s->md5_ctx);
av_freep(&s->cabac_state);
@ -3698,6 +3732,10 @@ static int hevc_update_thread_context(AVCodecContext *dst,
if (ret < 0)
return ret;
ret = av_buffer_replace(&s->rpu_buf, s0->rpu_buf);
if (ret < 0)
return ret;
s->sei.frame_packing = s0->sei.frame_packing;
s->sei.display_orientation = s0->sei.display_orientation;
s->sei.mastering_display = s0->sei.mastering_display;
@ -3754,6 +3792,7 @@ static void hevc_decode_flush(AVCodecContext *avctx)
HEVCContext *s = avctx->priv_data;
ff_hevc_flush_dpb(s);
ff_hevc_reset_sei(&s->sei);
av_buffer_unref(&s->rpu_buf);
s->max_ra = INT_MAX;
s->eos = 1;
}

View File

@ -572,6 +572,8 @@ typedef struct HEVCContext {
int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4)
int nuh_layer_id;
AVBufferRef *rpu_buf; ///< 0 or 1 Dolby Vision RPUs.
} HEVCContext;
/**

View File

@ -28,7 +28,7 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 59
#define LIBAVCODEC_VERSION_MINOR 12
#define LIBAVCODEC_VERSION_MINOR 13
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \