X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fhevc.c;h=607a8da95e555a93c19372c8c8e6b21f78353bbb;hb=79307ae56374b35cf12563a7c8e3e759658f847e;hp=764e0938bbd4e6370dcb6fd838ba8f819fa12401;hpb=edb4c445119501070cb00be1696d47c6d6462e2a;p=ffmpeg diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index 764e0938bbd..607a8da95e5 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -2973,10 +2973,84 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) return 0; } +static int hevc_decode_extradata(HEVCContext *s, uint8_t *buf, int length) +{ + AVCodecContext *avctx = s->avctx; + GetByteContext gb; + int ret, i; + + bytestream2_init(&gb, buf, length); + + if (length > 3 && (buf[0] || buf[1] || buf[2] > 1)) { + /* It seems the extradata is encoded as hvcC format. + * Temporarily, we support configurationVersion==0 until 14496-15 3rd + * is finalized. When finalized, configurationVersion will be 1 and we + * can recognize hvcC by checking if avctx->extradata[0]==1 or not. */ + int i, j, num_arrays, nal_len_size; + + s->is_nalff = 1; + + bytestream2_skip(&gb, 21); + nal_len_size = (bytestream2_get_byte(&gb) & 3) + 1; + num_arrays = bytestream2_get_byte(&gb); + + /* nal units in the hvcC always have length coded with 2 bytes, + * so put a fake nal_length_size = 2 while parsing them */ + s->nal_length_size = 2; + + /* Decode nal units from hvcC. */ + for (i = 0; i < num_arrays; i++) { + int type = bytestream2_get_byte(&gb) & 0x3f; + int cnt = bytestream2_get_be16(&gb); + + for (j = 0; j < cnt; j++) { + // +2 for the nal size field + int nalsize = bytestream2_peek_be16(&gb) + 2; + if (bytestream2_get_bytes_left(&gb) < nalsize) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid NAL unit size in extradata.\n"); + return AVERROR_INVALIDDATA; + } + + ret = decode_nal_units(s, gb.buffer, nalsize); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Decoding nal unit %d %d from hvcC failed\n", + type, i); + return ret; + } + bytestream2_skip(&gb, nalsize); + } + } + + /* Now store right nal length size, that will be used to parse + * all other nals */ + s->nal_length_size = nal_len_size; + } else { + s->is_nalff = 0; + ret = decode_nal_units(s, buf, length); + if (ret < 0) + return ret; + } + + /* export stream parameters from the first SPS */ + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { + if (s->ps.sps_list[i]) { + const HEVCSPS *sps = (const HEVCSPS*)s->ps.sps_list[i]->data; + export_stream_params(s->avctx, &s->ps, sps); + break; + } + } + + return 0; +} + static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, AVPacket *avpkt) { int ret; + int new_extradata_size; + uint8_t *new_extradata; HEVCContext *s = avctx->priv_data; if (!avpkt->size) { @@ -2988,6 +3062,14 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, return 0; } + new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, + &new_extradata_size); + if (new_extradata && new_extradata_size > 0) { + ret = hevc_decode_extradata(s, new_extradata, new_extradata_size); + if (ret < 0) + return ret; + } + s->ref = NULL; ret = decode_nal_units(s, avpkt->data, avpkt->size); if (ret < 0) @@ -3243,80 +3325,6 @@ static int hevc_update_thread_context(AVCodecContext *dst, return 0; } -static int hevc_decode_extradata(HEVCContext *s) -{ - AVCodecContext *avctx = s->avctx; - GetByteContext gb; - int ret, i; - - bytestream2_init(&gb, avctx->extradata, avctx->extradata_size); - - if (avctx->extradata_size > 3 && - (avctx->extradata[0] || avctx->extradata[1] || - avctx->extradata[2] > 1)) { - /* It seems the extradata is encoded as hvcC format. - * Temporarily, we support configurationVersion==0 until 14496-15 3rd - * is finalized. When finalized, configurationVersion will be 1 and we - * can recognize hvcC by checking if avctx->extradata[0]==1 or not. */ - int i, j, num_arrays, nal_len_size; - - s->is_nalff = 1; - - bytestream2_skip(&gb, 21); - nal_len_size = (bytestream2_get_byte(&gb) & 3) + 1; - num_arrays = bytestream2_get_byte(&gb); - - /* nal units in the hvcC always have length coded with 2 bytes, - * so put a fake nal_length_size = 2 while parsing them */ - s->nal_length_size = 2; - - /* Decode nal units from hvcC. */ - for (i = 0; i < num_arrays; i++) { - int type = bytestream2_get_byte(&gb) & 0x3f; - int cnt = bytestream2_get_be16(&gb); - - for (j = 0; j < cnt; j++) { - // +2 for the nal size field - int nalsize = bytestream2_peek_be16(&gb) + 2; - if (bytestream2_get_bytes_left(&gb) < nalsize) { - av_log(s->avctx, AV_LOG_ERROR, - "Invalid NAL unit size in extradata.\n"); - return AVERROR_INVALIDDATA; - } - - ret = decode_nal_units(s, gb.buffer, nalsize); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, - "Decoding nal unit %d %d from hvcC failed\n", - type, i); - return ret; - } - bytestream2_skip(&gb, nalsize); - } - } - - /* Now store right nal length size, that will be used to parse - * all other nals */ - s->nal_length_size = nal_len_size; - } else { - s->is_nalff = 0; - ret = decode_nal_units(s, avctx->extradata, avctx->extradata_size); - if (ret < 0) - return ret; - } - - /* export stream parameters from the first SPS */ - for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { - if (s->ps.sps_list[i]) { - const HEVCSPS *sps = (const HEVCSPS*)s->ps.sps_list[i]->data; - export_stream_params(s->avctx, &s->ps, sps); - break; - } - } - - return 0; -} - static av_cold int hevc_decode_init(AVCodecContext *avctx) { HEVCContext *s = avctx->priv_data; @@ -3338,7 +3346,7 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx) s->threads_number = 1; if (avctx->extradata_size > 0 && avctx->extradata) { - ret = hevc_decode_extradata(s); + ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size); if (ret < 0) { hevc_decode_free(avctx); return ret; @@ -3408,5 +3416,6 @@ AVCodec ff_hevc_decoder = { .init_thread_copy = hevc_init_thread_copy, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), };