summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2017-05-01 21:42:54 +0200
committerAnton Khirnov <anton@khirnov.net>2020-04-10 15:52:41 +0200
commit5e316096fa9ba4493d9dbb48847ad8e0b0e188c3 (patch)
treec0c6cb248b47ef3b71dbb83bb8f4756d45ac86cd /libavcodec
parentec7f33a38e341807c0ff9530e4dc7e175a86f437 (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.c16
-rw-r--r--libavcodec/h264_ps.c30
-rw-r--r--libavcodec/h264_ps.h4
-rw-r--r--libavcodec/h264_slice.c27
-rw-r--r--libavcodec/h264dec.c4
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];