diff options
author | Anton Khirnov <anton@khirnov.net> | 2017-05-01 21:42:54 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2020-04-10 15:52:41 +0200 |
commit | 5e316096fa9ba4493d9dbb48847ad8e0b0e188c3 (patch) | |
tree | c0c6cb248b47ef3b71dbb83bb8f4756d45ac86cd /libavcodec | |
parent | ec7f33a38e341807c0ff9530e4dc7e175a86f437 (diff) |
h264_ps: make the PPS hold a reference to its SPS
It represents the relationship between them more naturally and will be
useful in the following commits.
Allows significantly more frames in fate-h264-attachment-631 to be
decoded.
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/h264_parser.c | 16 | ||||
-rw-r--r-- | libavcodec/h264_ps.c | 30 | ||||
-rw-r--r-- | libavcodec/h264_ps.h | 4 | ||||
-rw-r--r-- | libavcodec/h264_slice.c | 27 | ||||
-rw-r--r-- | libavcodec/h264dec.c | 4 |
5 files changed, 36 insertions, 45 deletions
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index ec1cbc6a66..aacd44cf3b 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -361,26 +361,14 @@ static inline int parse_nal_units(AVCodecParserContext *s, } av_buffer_unref(&p->ps.pps_ref); - av_buffer_unref(&p->ps.sps_ref); p->ps.pps = NULL; p->ps.sps = NULL; p->ps.pps_ref = av_buffer_ref(p->ps.pps_list[pps_id]); if (!p->ps.pps_ref) goto fail; p->ps.pps = (const PPS*)p->ps.pps_ref->data; - - if (!p->ps.sps_list[p->ps.pps->sps_id]) { - av_log(avctx, AV_LOG_ERROR, - "non-existing SPS %u referenced\n", p->ps.pps->sps_id); - goto fail; - } - - p->ps.sps_ref = av_buffer_ref(p->ps.sps_list[p->ps.pps->sps_id]); - if (!p->ps.sps_ref) - goto fail; - p->ps.sps = (const SPS*)p->ps.sps_ref->data; - - sps = p->ps.sps; + p->ps.sps = p->ps.pps->sps; + sps = p->ps.sps; // heuristic to detect non marked keyframes if (p->ps.sps->ref_frame_count <= 1 && p->ps.pps->ref_count[0] <= 1 && s->pict_type == AV_PICTURE_TYPE_I) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index 8df195e0a9..e774929e21 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -324,7 +324,6 @@ void ff_h264_ps_uninit(H264ParamSets *ps) for (i = 0; i < MAX_PPS_COUNT; i++) av_buffer_unref(&ps->pps_list[i]); - av_buffer_unref(&ps->sps_ref); av_buffer_unref(&ps->pps_ref); ps->pps = NULL; @@ -738,6 +737,15 @@ static int more_rbsp_data_in_pps(const SPS *sps, void *logctx) return 1; } +static void pps_free(void *opaque, uint8_t *data) +{ + PPS *pps = (PPS*)data; + + av_buffer_unref(&pps->sps_ref); + + av_freep(&data); +} + int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avctx, H264ParamSets *ps, int bit_length) { @@ -754,10 +762,15 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct return AVERROR_INVALIDDATA; } - pps_buf = av_buffer_allocz(sizeof(*pps)); - if (!pps_buf) + pps = av_mallocz(sizeof(*pps)); + if (!pps) return AVERROR(ENOMEM); - pps = (PPS*)pps_buf->data; + pps_buf = av_buffer_create((uint8_t*)pps, sizeof(*pps), + pps_free, NULL, 0); + if (!pps_buf) { + av_freep(&pps); + return AVERROR(ENOMEM); + } pps->data_size = gb->buffer_end - gb->buffer; if (pps->data_size > sizeof(pps->data)) { @@ -775,7 +788,14 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct ret = AVERROR_INVALIDDATA; goto fail; } - sps = (const SPS*)ps->sps_list[pps->sps_id]->data; + pps->sps_ref = av_buffer_ref(ps->sps_list[pps->sps_id]); + if (!pps->sps_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + pps->sps = (const SPS*)pps->sps_ref->data; + sps = pps->sps; + if (sps->bit_depth_luma > 14) { av_log(avctx, AV_LOG_ERROR, "Invalid luma bit depth=%d\n", diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index d6798ca0ef..3f1ab72e38 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -135,6 +135,9 @@ typedef struct PPS { uint32_t dequant8_buffer[6][QP_MAX_NUM + 1][64]; uint32_t(*dequant4_coeff[6])[16]; uint32_t(*dequant8_coeff[6])[64]; + + AVBufferRef *sps_ref; + const SPS *sps; } PPS; typedef struct H264ParamSets { @@ -142,7 +145,6 @@ typedef struct H264ParamSets { AVBufferRef *pps_list[MAX_PPS_COUNT]; AVBufferRef *pps_ref; - AVBufferRef *sps_ref; /* currently active parameters sets */ const PPS *pps; const SPS *sps; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c6072738d7..5a8a4a7f86 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -333,7 +333,6 @@ int ff_h264_update_thread_context(AVCodecContext *dst, } av_buffer_unref(&h->ps.pps_ref); - av_buffer_unref(&h->ps.sps_ref); h->ps.pps = NULL; h->ps.sps = NULL; if (h1->ps.pps_ref) { @@ -341,12 +340,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, if (!h->ps.pps_ref) return AVERROR(ENOMEM); h->ps.pps = (const PPS*)h->ps.pps_ref->data; - } - if (h1->ps.sps_ref) { - h->ps.sps_ref = av_buffer_ref(h1->ps.sps_ref); - if (!h->ps.sps_ref) - return AVERROR(ENOMEM); - h->ps.sps = (const SPS*)h->ps.sps_ref->data; + h->ps.sps = h->ps.pps->sps; } if (need_reinit || !inited) { @@ -1013,13 +1007,8 @@ static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_sl h->ps.pps = (const PPS*)h->ps.pps_ref->data; } - if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { - av_buffer_unref(&h->ps.sps_ref); - h->ps.sps = NULL; - h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]); - if (!h->ps.sps_ref) - return AVERROR(ENOMEM); - h->ps.sps = (const SPS*)h->ps.sps_ref->data; + if (h->ps.sps != h->ps.pps->sps) { + h->ps.sps = (const SPS*)h->ps.pps->sps; if (h->mb_width != h->ps.sps->mb_width || h->mb_height != h->ps.sps->mb_height || @@ -1779,13 +1768,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, return AVERROR_INVALIDDATA; } pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data; - - if (!h->ps.sps_list[pps->sps_id]) { - av_log(h->avctx, AV_LOG_ERROR, - "non-existing SPS %u referenced\n", pps->sps_id); - return AVERROR_INVALIDDATA; - } - sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data; + sps = pps->sps; sl->frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); if (!first_slice) { @@ -2171,7 +2154,7 @@ int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal) av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); return AVERROR_INVALIDDATA; } - if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { + if (h->ps.sps != pps->sps) { av_log(h->avctx, AV_LOG_ERROR, "SPS changed in the middle of the frame\n"); return AVERROR_INVALIDDATA; diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 8673d5a2c2..b8a1879522 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -764,9 +764,7 @@ end: * past end by one (callers fault) and resync_mb_y != 0 * causes problems for the first MB line, too. */ - if (!FIELD_PICTURE(h) && h->current_slice && - h->ps.sps == (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data && - h->enable_er) { + if (!FIELD_PICTURE(h) && h->current_slice && h->enable_er) { H264SliceContext *sl = h->slice_ctx; int use_last_pic = h->last_pic_for_ec.f->buf[0] && !sl->ref_count[0]; |