X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fh264.c;h=a225f5b5e263f54190f02dabbd17944190af6f4e;hb=bf52f773913cf74bdf0d2c8c2cb4473fa1b7801e;hp=a5f64b27671090252c5bf125df842a12c9623fcb;hpb=7d8154edd594981e7891d57de91f2260f8a62939;p=ffmpeg diff --git a/libavcodec/h264.c b/libavcodec/h264.c index a5f64b27671..a225f5b5e26 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -28,6 +28,7 @@ #include "libavutil/avassert.h" #include "libavutil/display.h" #include "libavutil/imgutils.h" +#include "libavutil/opt.h" #include "libavutil/stereo3d.h" #include "libavutil/timer.h" #include "internal.h" @@ -56,32 +57,33 @@ static void h264_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, int mb_x, int mb_y, int mb_intra, int mb_skipped) { H264Context *h = opaque; + H264SliceContext *sl = &h->slice_ctx[0]; - h->mb_x = mb_x; - h->mb_y = mb_y; - h->mb_xy = mb_x + mb_y * h->mb_stride; - memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache)); + sl->mb_x = mb_x; + sl->mb_y = mb_y; + sl->mb_xy = mb_x + mb_y * h->mb_stride; + memset(sl->non_zero_count_cache, 0, sizeof(sl->non_zero_count_cache)); assert(ref >= 0); /* FIXME: It is possible albeit uncommon that slice references * differ between slices. We take the easy approach and ignore * it for now. If this turns out to have any relevance in * practice then correct remapping should be added. */ - if (ref >= h->ref_count[0]) + if (ref >= sl->ref_count[0]) ref = 0; - fill_rectangle(&h->cur_pic.ref_index[0][4 * h->mb_xy], + fill_rectangle(&h->cur_pic.ref_index[0][4 * sl->mb_xy], 2, 2, 2, ref, 1); - fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); - fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, + fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); + fill_rectangle(sl->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32((*mv)[0][0][0], (*mv)[0][0][1]), 4); assert(!FRAME_MBAFF(h)); ff_h264_hl_decode_mb(h, &h->slice_ctx[0]); } -void ff_h264_draw_horiz_band(H264Context *h, int y, int height) +void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, + int y, int height) { AVCodecContext *avctx = h->avctx; - AVFrame *cur = &h->cur_pic.f; - AVFrame *last = h->ref_list[0][0].f.data[0] ? &h->ref_list[0][0].f : NULL; + const AVFrame *src = h->cur_pic.f; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); int vshift = desc->log2_chroma_h; const int field_pic = h->picture_structure != PICT_FRAME; @@ -96,18 +98,9 @@ void ff_h264_draw_horiz_band(H264Context *h, int y, int height) return; if (avctx->draw_horiz_band) { - AVFrame *src; int offset[AV_NUM_DATA_POINTERS]; int i; - if (cur->pict_type == AV_PICTURE_TYPE_B || h->low_delay || - (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) - src = cur; - else if (last) - src = last; - else - return; - offset[0] = y * src->linesize[0]; offset[1] = offset[2] = (y >> vshift) * src->linesize[1]; @@ -125,7 +118,7 @@ void ff_h264_draw_horiz_band(H264Context *h, int y, int height) * Check if the top & left blocks are available if needed and * change the dc mode so it only uses the available blocks. */ -int ff_h264_check_intra4x4_pred_mode(H264Context *h, H264SliceContext *sl) +int ff_h264_check_intra4x4_pred_mode(const H264Context *h, H264SliceContext *sl) { static const int8_t top[12] = { -1, 0, LEFT_DC_PRED, -1, -1, -1, -1, -1, 0 @@ -135,13 +128,13 @@ int ff_h264_check_intra4x4_pred_mode(H264Context *h, H264SliceContext *sl) }; int i; - if (!(h->top_samples_available & 0x8000)) { + if (!(sl->top_samples_available & 0x8000)) { for (i = 0; i < 4; i++) { int status = top[sl->intra4x4_pred_mode_cache[scan8[0] + i]]; if (status < 0) { av_log(h->avctx, AV_LOG_ERROR, "top block unavailable for requested intra4x4 mode %d at %d %d\n", - status, h->mb_x, h->mb_y); + status, sl->mb_x, sl->mb_y); return AVERROR_INVALIDDATA; } else if (status) { sl->intra4x4_pred_mode_cache[scan8[0] + i] = status; @@ -149,15 +142,15 @@ int ff_h264_check_intra4x4_pred_mode(H264Context *h, H264SliceContext *sl) } } - if ((h->left_samples_available & 0x8888) != 0x8888) { + if ((sl->left_samples_available & 0x8888) != 0x8888) { static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 }; for (i = 0; i < 4; i++) - if (!(h->left_samples_available & mask[i])) { + if (!(sl->left_samples_available & mask[i])) { int status = left[sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i]]; if (status < 0) { av_log(h->avctx, AV_LOG_ERROR, "left block unavailable for requested intra4x4 mode %d at %d %d\n", - status, h->mb_x, h->mb_y); + status, sl->mb_x, sl->mb_y); return AVERROR_INVALIDDATA; } else if (status) { sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i] = status; @@ -172,7 +165,8 @@ int ff_h264_check_intra4x4_pred_mode(H264Context *h, H264SliceContext *sl) * Check if the top & left blocks are available if needed and * change the dc mode so it only uses the available blocks. */ -int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma) +int ff_h264_check_intra_pred_mode(const H264Context *h, H264SliceContext *sl, + int mode, int is_chroma) { static const int8_t top[4] = { LEFT_DC_PRED8x8, 1, -1, -1 }; static const int8_t left[5] = { TOP_DC_PRED8x8, -1, 2, -1, DC_128_PRED8x8 }; @@ -180,32 +174,32 @@ int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma) if (mode > 3U) { av_log(h->avctx, AV_LOG_ERROR, "out of range intra chroma pred mode at %d %d\n", - h->mb_x, h->mb_y); + sl->mb_x, sl->mb_y); return AVERROR_INVALIDDATA; } - if (!(h->top_samples_available & 0x8000)) { + if (!(sl->top_samples_available & 0x8000)) { mode = top[mode]; if (mode < 0) { av_log(h->avctx, AV_LOG_ERROR, "top block unavailable for requested intra mode at %d %d\n", - h->mb_x, h->mb_y); + sl->mb_x, sl->mb_y); return AVERROR_INVALIDDATA; } } - if ((h->left_samples_available & 0x8080) != 0x8080) { + if ((sl->left_samples_available & 0x8080) != 0x8080) { mode = left[mode]; - if (is_chroma && (h->left_samples_available & 0x8080)) { + if (is_chroma && (sl->left_samples_available & 0x8080)) { // mad cow disease mode, aka MBAFF + constrained_intra_pred mode = ALZHEIMER_DC_L0T_PRED8x8 + - (!(h->left_samples_available & 0x8000)) + + (!(sl->left_samples_available & 0x8000)) + 2 * (mode == DC_128_PRED8x8); } if (mode < 0) { av_log(h->avctx, AV_LOG_ERROR, "left block unavailable for requested intra mode at %d %d\n", - h->mb_x, h->mb_y); + sl->mb_x, sl->mb_y); return AVERROR_INVALIDDATA; } } @@ -213,12 +207,12 @@ int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma) return mode; } -const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, +const uint8_t *ff_h264_decode_nal(H264Context *h, H264SliceContext *sl, + const uint8_t *src, int *dst_length, int *consumed, int length) { int i, si, di; uint8_t *dst; - int bufidx; // src[0]&0x80; // forbidden bit h->nal_ref_idc = src[0] >> 5; @@ -280,11 +274,9 @@ const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, return src; } - // use second escape buffer for inter data - bufidx = h->nal_unit_type == NAL_DPC ? 1 : 0; - av_fast_malloc(&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], + av_fast_malloc(&sl->rbsp_buffer, &sl->rbsp_buffer_size, length + FF_INPUT_BUFFER_PADDING_SIZE); - dst = h->rbsp_buffer[bufidx]; + dst = sl->rbsp_buffer; if (!dst) return NULL; @@ -330,7 +322,7 @@ static int decode_rbsp_trailing(H264Context *h, const uint8_t *src) int v = *src; int r; - tprintf(h->avctx, "rbsp trailing %X\n", v); + ff_tlog(h->avctx, "rbsp trailing %X\n", v); for (r = 1; r < 9; r++) { if (v & 1) @@ -340,10 +332,9 @@ static int decode_rbsp_trailing(H264Context *h, const uint8_t *src) return 0; } -void ff_h264_free_tables(H264Context *h, int free_rbsp) +void ff_h264_free_tables(H264Context *h) { int i; - H264Context *hx; av_freep(&h->intra4x4_pred_mode); av_freep(&h->chroma_pred_mode_table); @@ -364,40 +355,23 @@ void ff_h264_free_tables(H264Context *h, int free_rbsp) av_buffer_pool_uninit(&h->motion_val_pool); av_buffer_pool_uninit(&h->ref_index_pool); - if (free_rbsp && h->DPB) { - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - ff_h264_unref_picture(h, &h->DPB[i]); - av_freep(&h->DPB); - } else if (h->DPB) { - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - h->DPB[i].needs_realloc = 1; - } + for (i = 0; i < h->nb_slice_ctx; i++) { + H264SliceContext *sl = &h->slice_ctx[i]; - h->cur_pic_ptr = NULL; + av_freep(&sl->dc_val_base); + av_freep(&sl->er.mb_index2xy); + av_freep(&sl->er.error_status_table); + av_freep(&sl->er.er_temp_buffer); - for (i = 0; i < H264_MAX_THREADS; i++) { - hx = h->thread_context[i]; - if (!hx) - continue; - av_freep(&hx->top_borders[1]); - av_freep(&hx->top_borders[0]); - av_freep(&hx->bipred_scratchpad); - av_freep(&hx->edge_emu_buffer); - av_freep(&hx->dc_val_base); - av_freep(&hx->er.mb_index2xy); - av_freep(&hx->er.error_status_table); - av_freep(&hx->er.er_temp_buffer); - av_freep(&hx->er.mbintra_table); - av_freep(&hx->er.mbskip_table); - - if (free_rbsp) { - av_freep(&hx->rbsp_buffer[1]); - av_freep(&hx->rbsp_buffer[0]); - hx->rbsp_buffer_size[0] = 0; - hx->rbsp_buffer_size[1] = 0; - } - if (i) - av_freep(&h->thread_context[i]); + av_freep(&sl->bipred_scratchpad); + av_freep(&sl->edge_emu_buffer); + av_freep(&sl->top_borders[0]); + av_freep(&sl->top_borders[1]); + + sl->bipred_scratchpad_allocated = 0; + sl->edge_emu_buffer_allocated = 0; + sl->top_borders_allocated[0] = 0; + sl->top_borders_allocated[1] = 0; } } @@ -405,7 +379,7 @@ int ff_h264_alloc_tables(H264Context *h) { const int big_mb_num = h->mb_stride * (h->mb_height + 1); const int row_mb_num = h->mb_stride * 2 * h->avctx->thread_count; - int x, y, i; + int x, y; FF_ALLOCZ_OR_GOTO(h->avctx, h->intra4x4_pred_mode, row_mb_num * 8 * sizeof(uint8_t), fail) @@ -423,6 +397,9 @@ int ff_h264_alloc_tables(H264Context *h) 16 * row_mb_num * sizeof(uint8_t), fail); FF_ALLOCZ_OR_GOTO(h->avctx, h->mvd_table[1], 16 * row_mb_num * sizeof(uint8_t), fail); + h->slice_ctx[0].mvd_table[0] = h->mvd_table[0]; + h->slice_ctx[0].mvd_table[1] = h->mvd_table[1]; + FF_ALLOCZ_OR_GOTO(h->avctx, h->direct_table, 4 * big_mb_num * sizeof(uint8_t), fail); FF_ALLOCZ_OR_GOTO(h->avctx, h->list_counts, @@ -448,19 +425,10 @@ int ff_h264_alloc_tables(H264Context *h) if (!h->dequant4_coeff[0]) h264_init_dequant_tables(h); - if (!h->DPB) { - h->DPB = av_mallocz_array(H264_MAX_PICTURE_COUNT, sizeof(*h->DPB)); - if (!h->DPB) - goto fail; - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - av_frame_unref(&h->DPB[i].f); - av_frame_unref(&h->cur_pic.f); - } - return 0; fail: - ff_h264_free_tables(h, 1); + ff_h264_free_tables(h); return AVERROR(ENOMEM); } @@ -468,26 +436,21 @@ fail: * Init context * Allocate buffers which are not shared amongst multiple threads. */ -int ff_h264_context_init(H264Context *h) +int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl) { - ERContext *er = &h->er; + ERContext *er = &sl->er; int mb_array_size = h->mb_height * h->mb_stride; int y_size = (2 * h->mb_width + 1) * (2 * h->mb_height + 1); int c_size = h->mb_stride * (h->mb_height + 1); int yc_size = y_size + 2 * c_size; int x, y, i; - FF_ALLOCZ_OR_GOTO(h->avctx, h->top_borders[0], - h->mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->top_borders[1], - h->mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail) - - h->ref_cache[0][scan8[5] + 1] = - h->ref_cache[0][scan8[7] + 1] = - h->ref_cache[0][scan8[13] + 1] = - h->ref_cache[1][scan8[5] + 1] = - h->ref_cache[1][scan8[7] + 1] = - h->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE; + sl->ref_cache[0][scan8[5] + 1] = + sl->ref_cache[0][scan8[7] + 1] = + sl->ref_cache[0][scan8[13] + 1] = + sl->ref_cache[1][scan8[5] + 1] = + sl->ref_cache[1][scan8[7] + 1] = + sl->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE; if (CONFIG_ERROR_RESILIENCE) { /* init ER */ @@ -516,21 +479,16 @@ int ff_h264_context_init(H264Context *h) FF_ALLOCZ_OR_GOTO(h->avctx, er->error_status_table, mb_array_size * sizeof(uint8_t), fail); - FF_ALLOC_OR_GOTO(h->avctx, er->mbintra_table, mb_array_size, fail); - memset(er->mbintra_table, 1, mb_array_size); - - FF_ALLOCZ_OR_GOTO(h->avctx, er->mbskip_table, mb_array_size + 2, fail); - FF_ALLOC_OR_GOTO(h->avctx, er->er_temp_buffer, h->mb_height * h->mb_stride, fail); - FF_ALLOCZ_OR_GOTO(h->avctx, h->dc_val_base, + FF_ALLOCZ_OR_GOTO(h->avctx, sl->dc_val_base, yc_size * sizeof(int16_t), fail); - er->dc_val[0] = h->dc_val_base + h->mb_width * 2 + 2; - er->dc_val[1] = h->dc_val_base + y_size + h->mb_stride + 1; + er->dc_val[0] = sl->dc_val_base + h->mb_width * 2 + 2; + er->dc_val[1] = sl->dc_val_base + y_size + h->mb_stride + 1; er->dc_val[2] = er->dc_val[1] + c_size; for (i = 0; i < yc_size; i++) - h->dc_val_base[i] = 1024; + sl->dc_val_base[i] = 1024; } return 0; @@ -601,49 +559,30 @@ int ff_h264_decode_extradata(H264Context *h) return 0; } -av_cold int ff_h264_decode_init(AVCodecContext *avctx) +static int h264_init_context(AVCodecContext *avctx, H264Context *h) { - H264Context *h = avctx->priv_data; int i; - int ret; - - h->avctx = avctx; - - h->bit_depth_luma = 8; - h->chroma_format_idc = 1; - - ff_h264dsp_init(&h->h264dsp, 8, 1); - ff_h264chroma_init(&h->h264chroma, h->sps.bit_depth_chroma); - ff_h264qpel_init(&h->h264qpel, 8); - ff_h264_pred_init(&h->hpc, h->avctx->codec_id, 8, 1); - h->dequant_coeff_pps = -1; + h->avctx = avctx; + h->dequant_coeff_pps = -1; - /* needed so that IDCT permutation is known early */ - ff_videodsp_init(&h->vdsp, 8); + h->picture_structure = PICT_FRAME; + h->slice_context_count = 1; + h->workaround_bugs = avctx->workaround_bugs; + h->flags = avctx->flags; + h->prev_poc_msb = 1 << 16; + h->x264_build = -1; + h->recovery_frame = -1; + h->frame_recovered = 0; - memset(h->pps.scaling_matrix4, 16, 6 * 16 * sizeof(uint8_t)); - memset(h->pps.scaling_matrix8, 16, 2 * 64 * sizeof(uint8_t)); - - h->picture_structure = PICT_FRAME; - h->slice_context_count = 1; - h->workaround_bugs = avctx->workaround_bugs; - h->flags = avctx->flags; + h->next_outputed_poc = INT_MIN; + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + h->last_pocs[i] = INT_MIN; - /* set defaults */ - // s->decode_mb = ff_h263_decode_mb; - if (!avctx->has_b_frames) - h->low_delay = 1; + ff_h264_reset_sei(h); avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; - ff_h264_decode_init_vlc(); - - ff_init_cabac_states(); - - h->pixel_shift = 0; - h->sps.bit_depth_luma = avctx->bits_per_raw_sample = 8; - h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ? H264_MAX_THREADS : 1; h->slice_ctx = av_mallocz_array(h->nb_slice_ctx, sizeof(*h->slice_ctx)); if (!h->slice_ctx) { @@ -651,18 +590,39 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - h->thread_context[0] = h; + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { + h->DPB[i].f = av_frame_alloc(); + if (!h->DPB[i].f) + return AVERROR(ENOMEM); + } + + h->cur_pic.f = av_frame_alloc(); + if (!h->cur_pic.f) + return AVERROR(ENOMEM); + for (i = 0; i < h->nb_slice_ctx; i++) - h->slice_ctx[i].h264 = h->thread_context[0]; + h->slice_ctx[i].h264 = h; + + return 0; +} + +av_cold int ff_h264_decode_init(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int ret; + + ret = h264_init_context(avctx, h); + if (ret < 0) + return ret; + + /* set defaults */ + if (!avctx->has_b_frames) + h->low_delay = 1; + + ff_h264_decode_init_vlc(); + + ff_init_cabac_states(); - h->outputed_poc = h->next_outputed_poc = INT_MIN; - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) - h->last_pocs[i] = INT_MIN; - h->prev_poc_msb = 1 << 16; - h->x264_build = -1; - ff_h264_reset_sei(h); - h->recovery_frame = -1; - h->frame_recovered = 0; if (avctx->codec_id == AV_CODEC_ID_H264) { if (avctx->ticks_per_frame == 1) h->avctx->framerate.num *= 2; @@ -685,34 +645,29 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) avctx->internal->allocate_progress = 1; + if (h->enable_er) { + av_log(avctx, AV_LOG_WARNING, + "Error resilience is enabled. It is unsafe and unsupported and may crash. " + "Use it at your own risk\n"); + } + return 0; } static int decode_init_thread_copy(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; - int i; + int ret; if (!avctx->internal->is_copy) return 0; - memset(h->sps_buffers, 0, sizeof(h->sps_buffers)); - memset(h->pps_buffers, 0, sizeof(h->pps_buffers)); - h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ? H264_MAX_THREADS : 1; - h->slice_ctx = av_mallocz_array(h->nb_slice_ctx, sizeof(*h->slice_ctx)); - if (!h->slice_ctx) { - h->nb_slice_ctx = 0; - return AVERROR(ENOMEM); - } + memset(h, 0, sizeof(*h)); - for (i = 0; i < h->nb_slice_ctx; i++) - h->slice_ctx[i].h264 = h; + ret = h264_init_context(avctx, h); + if (ret < 0) + return ret; - h->avctx = avctx; - h->rbsp_buffer[0] = NULL; - h->rbsp_buffer[1] = NULL; - h->rbsp_buffer_size[0] = 0; - h->rbsp_buffer_size[1] = 0; h->context_initialized = 0; return 0; @@ -733,7 +688,7 @@ static void decode_postinit(H264Context *h, int setup_finished) int i, pics, out_of_order, out_idx; int invalid = 0, cnt = 0; - h->cur_pic_ptr->f.pict_type = h->pict_type; + h->cur_pic_ptr->f->pict_type = h->pict_type; if (h->next_output_pic) return; @@ -748,8 +703,8 @@ static void decode_postinit(H264Context *h, int setup_finished) return; } - cur->f.interlaced_frame = 0; - cur->f.repeat_pict = 0; + cur->f->interlaced_frame = 0; + cur->f->repeat_pict = 0; /* Signal interlacing information externally. */ /* Prioritize picture timing SEI information over used @@ -761,55 +716,55 @@ static void decode_postinit(H264Context *h, int setup_finished) break; case SEI_PIC_STRUCT_TOP_FIELD: case SEI_PIC_STRUCT_BOTTOM_FIELD: - cur->f.interlaced_frame = 1; + cur->f->interlaced_frame = 1; break; case SEI_PIC_STRUCT_TOP_BOTTOM: case SEI_PIC_STRUCT_BOTTOM_TOP: if (FIELD_OR_MBAFF_PICTURE(h)) - cur->f.interlaced_frame = 1; + cur->f->interlaced_frame = 1; else // try to flag soft telecine progressive - cur->f.interlaced_frame = h->prev_interlaced_frame; + cur->f->interlaced_frame = h->prev_interlaced_frame; break; case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: /* Signal the possibility of telecined film externally * (pic_struct 5,6). From these hints, let the applications * decide if they apply deinterlacing. */ - cur->f.repeat_pict = 1; + cur->f->repeat_pict = 1; break; case SEI_PIC_STRUCT_FRAME_DOUBLING: - cur->f.repeat_pict = 2; + cur->f->repeat_pict = 2; break; case SEI_PIC_STRUCT_FRAME_TRIPLING: - cur->f.repeat_pict = 4; + cur->f->repeat_pict = 4; break; } if ((h->sei_ct_type & 3) && h->sei_pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP) - cur->f.interlaced_frame = (h->sei_ct_type & (1 << 1)) != 0; + cur->f->interlaced_frame = (h->sei_ct_type & (1 << 1)) != 0; } else { /* Derive interlacing flag from used decoding process. */ - cur->f.interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); + cur->f->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); } - h->prev_interlaced_frame = cur->f.interlaced_frame; + h->prev_interlaced_frame = cur->f->interlaced_frame; if (cur->field_poc[0] != cur->field_poc[1]) { /* Derive top_field_first from field pocs. */ - cur->f.top_field_first = cur->field_poc[0] < cur->field_poc[1]; + cur->f->top_field_first = cur->field_poc[0] < cur->field_poc[1]; } else { - if (cur->f.interlaced_frame || h->sps.pic_struct_present_flag) { + if (cur->f->interlaced_frame || h->sps.pic_struct_present_flag) { /* Use picture timing SEI information. Even if it is a * information of a past frame, better than nothing. */ if (h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM || h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP) - cur->f.top_field_first = 1; + cur->f->top_field_first = 1; else - cur->f.top_field_first = 0; + cur->f->top_field_first = 0; } else { /* Most likely progressive */ - cur->f.top_field_first = 0; + cur->f->top_field_first = 0; } } @@ -818,7 +773,7 @@ static void decode_postinit(H264Context *h, int setup_finished) h->frame_packing_arrangement_type <= 6 && h->content_interpretation_type > 0 && h->content_interpretation_type < 3) { - AVStereo3D *stereo = av_stereo3d_create_side_data(&cur->f); + AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f); if (!stereo) return; @@ -856,7 +811,7 @@ static void decode_postinit(H264Context *h, int setup_finished) if (h->sei_display_orientation_present && (h->sei_anticlockwise_rotation || h->sei_hflip || h->sei_vflip)) { double angle = h->sei_anticlockwise_rotation * 360 / (double) (1 << 16); - AVFrameSideData *rotation = av_frame_new_side_data(&cur->f, + AVFrameSideData *rotation = av_frame_new_side_data(cur->f, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (!rotation) @@ -867,6 +822,28 @@ static void decode_postinit(H264Context *h, int setup_finished) h->sei_hflip, h->sei_vflip); } + if (h->sei_reguserdata_afd_present) { + AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_AFD, + sizeof(uint8_t)); + if (!sd) + return; + + *sd->data = h->active_format_description; + h->sei_reguserdata_afd_present = 0; + } + + if (h->a53_caption) { + AVFrameSideData *sd = av_frame_new_side_data(cur->f, + AV_FRAME_DATA_A53_CC, + h->a53_caption_size); + if (!sd) + return; + + memcpy(sd->data, h->a53_caption, h->a53_caption_size); + av_freep(&h->a53_caption); + h->a53_caption_size = 0; + } + // FIXME do something with unavailable reference frames /* Sort B-frames into display order */ @@ -910,13 +887,13 @@ static void decode_postinit(H264Context *h, int setup_finished) cnt += out->poc < h->last_pocs[i]; invalid += out->poc == INT_MIN; } - if (!h->mmco_reset && !cur->f.key_frame && + if (!h->mmco_reset && !cur->f->key_frame && cnt + invalid == MAX_DELAYED_PIC_COUNT && cnt > 0) { h->mmco_reset = 2; if (pics > 1) h->delayed_pic[pics - 2]->mmco_reset = 2; } - if (h->mmco_reset || cur->f.key_frame) { + if (h->mmco_reset || cur->f->key_frame) { for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) h->last_pocs[i] = INT_MIN; cnt = 0; @@ -927,16 +904,16 @@ static void decode_postinit(H264Context *h, int setup_finished) for (i = 1; i < MAX_DELAYED_PIC_COUNT && h->delayed_pic[i] && !h->delayed_pic[i - 1]->mmco_reset && - !h->delayed_pic[i]->f.key_frame; + !h->delayed_pic[i]->f->key_frame; i++) if (h->delayed_pic[i]->poc < out->poc) { out = h->delayed_pic[i]; out_idx = i; } if (h->avctx->has_b_frames == 0 && - (h->delayed_pic[0]->f.key_frame || h->mmco_reset)) + (h->delayed_pic[0]->f->key_frame || h->mmco_reset)) h->next_outputed_poc = INT_MIN; - out_of_order = !out->f.key_frame && !h->mmco_reset && + out_of_order = !out->f->key_frame && !h->mmco_reset && (out->poc < h->next_outputed_poc); if (h->sps.bitstream_restriction_flag && @@ -950,7 +927,7 @@ static void decode_postinit(H264Context *h, int setup_finished) } else if (h->low_delay && ((h->next_outputed_poc != INT_MIN && out->poc > h->next_outputed_poc + 2) || - cur->f.pict_type == AV_PICTURE_TYPE_B)) { + cur->f->pict_type == AV_PICTURE_TYPE_B)) { h->low_delay = 0; h->avctx->has_b_frames++; } @@ -975,7 +952,7 @@ static void decode_postinit(H264Context *h, int setup_finished) h->next_outputed_poc = INT_MIN; } } else { - if (out_idx == 0 && pics > 1 && h->delayed_pic[0]->f.key_frame) { + if (out_idx == 0 && pics > 1 && h->delayed_pic[0]->f->key_frame) { h->next_outputed_poc = INT_MIN; } else { h->next_outputed_poc = out->poc; @@ -995,8 +972,12 @@ static void decode_postinit(H264Context *h, int setup_finished) h->next_output_pic->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_SEI); } - if (setup_finished && !h->avctx->hwaccel) + if (setup_finished && !h->avctx->hwaccel) { ff_thread_finish_setup(h->avctx); + + if (h->avctx->active_thread_type & FF_THREAD_FRAME) + h->setup_finished = 1; + } } int ff_pred_weight_table(H264Context *h, H264SliceContext *sl) @@ -1006,22 +987,22 @@ int ff_pred_weight_table(H264Context *h, H264SliceContext *sl) sl->use_weight = 0; sl->use_weight_chroma = 0; - sl->luma_log2_weight_denom = get_ue_golomb(&h->gb); + sl->luma_log2_weight_denom = get_ue_golomb(&sl->gb); if (h->sps.chroma_format_idc) - sl->chroma_log2_weight_denom = get_ue_golomb(&h->gb); + sl->chroma_log2_weight_denom = get_ue_golomb(&sl->gb); luma_def = 1 << sl->luma_log2_weight_denom; chroma_def = 1 << sl->chroma_log2_weight_denom; for (list = 0; list < 2; list++) { sl->luma_weight_flag[list] = 0; sl->chroma_weight_flag[list] = 0; - for (i = 0; i < h->ref_count[list]; i++) { + for (i = 0; i < sl->ref_count[list]; i++) { int luma_weight_flag, chroma_weight_flag; - luma_weight_flag = get_bits1(&h->gb); + luma_weight_flag = get_bits1(&sl->gb); if (luma_weight_flag) { - sl->luma_weight[i][list][0] = get_se_golomb(&h->gb); - sl->luma_weight[i][list][1] = get_se_golomb(&h->gb); + sl->luma_weight[i][list][0] = get_se_golomb(&sl->gb); + sl->luma_weight[i][list][1] = get_se_golomb(&sl->gb); if (sl->luma_weight[i][list][0] != luma_def || sl->luma_weight[i][list][1] != 0) { sl->use_weight = 1; @@ -1033,12 +1014,12 @@ int ff_pred_weight_table(H264Context *h, H264SliceContext *sl) } if (h->sps.chroma_format_idc) { - chroma_weight_flag = get_bits1(&h->gb); + chroma_weight_flag = get_bits1(&sl->gb); if (chroma_weight_flag) { int j; for (j = 0; j < 2; j++) { - sl->chroma_weight[i][list][j][0] = get_se_golomb(&h->gb); - sl->chroma_weight[i][list][j][1] = get_se_golomb(&h->gb); + sl->chroma_weight[i][list][j][0] = get_se_golomb(&sl->gb); + sl->chroma_weight[i][list][j][1] = get_se_golomb(&sl->gb); if (sl->chroma_weight[i][list][j][0] != chroma_def || sl->chroma_weight[i][list][j][1] != 0) { sl->use_weight_chroma = 1; @@ -1054,7 +1035,7 @@ int ff_pred_weight_table(H264Context *h, H264SliceContext *sl) } } } - if (h->slice_type_nos != AV_PICTURE_TYPE_B) + if (sl->slice_type_nos != AV_PICTURE_TYPE_B) break; } sl->use_weight = sl->use_weight || sl->use_weight_chroma; @@ -1079,7 +1060,7 @@ void ff_h264_flush_change(H264Context *h) int i; for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) h->last_pocs[i] = INT_MIN; - h->outputed_poc = h->next_outputed_poc = INT_MIN; + h->next_outputed_poc = INT_MIN; h->prev_interlaced_frame = 1; idr(h); if (h->cur_pic_ptr) @@ -1100,15 +1081,14 @@ static void flush_dpb(AVCodecContext *avctx) ff_h264_flush_change(h); - if (h->DPB) - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - ff_h264_unref_picture(h, &h->DPB[i]); + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) + ff_h264_unref_picture(h, &h->DPB[i]); h->cur_pic_ptr = NULL; ff_h264_unref_picture(h, &h->cur_pic); - h->mb_x = h->mb_y = 0; + h->mb_y = 0; - ff_h264_free_tables(h, 1); + ff_h264_free_tables(h); h->context_initialized = 0; } @@ -1217,45 +1197,7 @@ int ff_h264_get_profile(SPS *sps) return profile; } -int ff_h264_set_parameter_from_sps(H264Context *h) -{ - if (h->flags & CODEC_FLAG_LOW_DELAY || - (h->sps.bitstream_restriction_flag && - !h->sps.num_reorder_frames)) { - if (h->avctx->has_b_frames > 1 || h->delayed_pic[0]) - av_log(h->avctx, AV_LOG_WARNING, "Delayed frames seen. " - "Reenabling low delay requires a codec flush.\n"); - else - h->low_delay = 1; - } - - if (h->avctx->has_b_frames < 2) - h->avctx->has_b_frames = !h->low_delay; - - if (h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || - h->cur_chroma_format_idc != h->sps.chroma_format_idc) { - if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10) { - h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; - h->cur_chroma_format_idc = h->sps.chroma_format_idc; - h->pixel_shift = h->sps.bit_depth_luma > 8; - - ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, - h->sps.chroma_format_idc); - ff_h264chroma_init(&h->h264chroma, h->sps.bit_depth_chroma); - ff_h264qpel_init(&h->h264qpel, h->sps.bit_depth_luma); - ff_h264_pred_init(&h->hpc, h->avctx->codec_id, h->sps.bit_depth_luma, - h->sps.chroma_format_idc); - ff_videodsp_init(&h->vdsp, h->sps.bit_depth_luma); - } else { - av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth %d\n", - h->sps.bit_depth_luma); - return AVERROR_INVALIDDATA; - } - } - return 0; -} - -int ff_set_ref_count(H264Context *h) +int ff_set_ref_count(H264Context *h, H264SliceContext *sl) { int ref_count[2], list_count; int num_ref_idx_active_override_flag, max_refs; @@ -1264,23 +1206,23 @@ int ff_set_ref_count(H264Context *h) ref_count[0] = h->pps.ref_count[0]; ref_count[1] = h->pps.ref_count[1]; - if (h->slice_type_nos != AV_PICTURE_TYPE_I) { - if (h->slice_type_nos == AV_PICTURE_TYPE_B) - h->direct_spatial_mv_pred = get_bits1(&h->gb); - num_ref_idx_active_override_flag = get_bits1(&h->gb); + if (sl->slice_type_nos != AV_PICTURE_TYPE_I) { + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) + sl->direct_spatial_mv_pred = get_bits1(&sl->gb); + num_ref_idx_active_override_flag = get_bits1(&sl->gb); if (num_ref_idx_active_override_flag) { - ref_count[0] = get_ue_golomb(&h->gb) + 1; + ref_count[0] = get_ue_golomb(&sl->gb) + 1; if (ref_count[0] < 1) return AVERROR_INVALIDDATA; - if (h->slice_type_nos == AV_PICTURE_TYPE_B) { - ref_count[1] = get_ue_golomb(&h->gb) + 1; + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { + ref_count[1] = get_ue_golomb(&sl->gb) + 1; if (ref_count[1] < 1) return AVERROR_INVALIDDATA; } } - if (h->slice_type_nos == AV_PICTURE_TYPE_B) + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) list_count = 2; else list_count = 1; @@ -1293,16 +1235,16 @@ int ff_set_ref_count(H264Context *h) if (ref_count[0] > max_refs || ref_count[1] > max_refs) { av_log(h->avctx, AV_LOG_ERROR, "reference overflow\n"); - h->ref_count[0] = h->ref_count[1] = 0; + sl->ref_count[0] = sl->ref_count[1] = 0; return AVERROR_INVALIDDATA; } - if (list_count != h->list_count || - ref_count[0] != h->ref_count[0] || - ref_count[1] != h->ref_count[1]) { - h->ref_count[0] = ref_count[0]; - h->ref_count[1] = ref_count[1]; - h->list_count = list_count; + if (list_count != sl->list_count || + ref_count[0] != sl->ref_count[0] || + ref_count[1] != sl->ref_count[1]) { + sl->ref_count[0] = ref_count[0]; + sl->ref_count[1] = ref_count[1]; + sl->list_count = list_count; return 1; } @@ -1371,6 +1313,7 @@ static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int buf_size) int nals_needed = 0; while(1) { + GetBitContext gb; int nalsize = 0; int dst_length, bit_length, consumed; const uint8_t *ptr; @@ -1386,7 +1329,7 @@ static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int buf_size) break; } - ptr = ff_h264_decode_nal(h, buf + buf_index, &dst_length, &consumed, + ptr = ff_h264_decode_nal(h, &h->slice_ctx[0], buf + buf_index, &dst_length, &consumed, next_avc - buf_index); if (!ptr || dst_length < 0) @@ -1410,8 +1353,8 @@ static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int buf_size) case NAL_DPA: case NAL_IDR_SLICE: case NAL_SLICE: - init_get_bits(&h->gb, ptr, bit_length); - if (!get_ue_golomb(&h->gb)) + init_get_bits(&gb, ptr, bit_length); + if (!get_ue_golomb(&gb)) nals_needed = nal_index; } } @@ -1423,7 +1366,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, int parse_extradata) { AVCodecContext *const avctx = h->avctx; - H264Context *hx; ///< thread context H264SliceContext *sl; int buf_index; unsigned context_count; @@ -1469,10 +1411,9 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, continue; } - hx = h->thread_context[context_count]; sl = &h->slice_ctx[context_count]; - ptr = ff_h264_decode_nal(hx, buf + buf_index, &dst_length, + ptr = ff_h264_decode_nal(h, sl, buf + buf_index, &dst_length, &consumed, next_avc - buf_index); if (!ptr || dst_length < 0) { ret = -1; @@ -1485,7 +1426,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, if (h->avctx->debug & FF_DEBUG_STARTCODE) av_log(h->avctx, AV_LOG_DEBUG, "NAL %d at %d/%d length %d\n", - hx->nal_unit_type, buf_index, buf_size, dst_length); + h->nal_unit_type, buf_index, buf_size, dst_length); if (h->is_avc && (nalsize != consumed) && nalsize) av_log(h->avctx, AV_LOG_DEBUG, @@ -1506,17 +1447,17 @@ again: * with frame-mt */ if (parse_extradata && HAVE_THREADS && (h->avctx->active_thread_type & FF_THREAD_FRAME) && - (hx->nal_unit_type != NAL_PPS && - hx->nal_unit_type != NAL_SPS)) { - if (hx->nal_unit_type < NAL_AUD || - hx->nal_unit_type > NAL_AUXILIARY_SLICE) + (h->nal_unit_type != NAL_PPS && + h->nal_unit_type != NAL_SPS)) { + if (h->nal_unit_type < NAL_AUD || + h->nal_unit_type > NAL_AUXILIARY_SLICE) av_log(avctx, AV_LOG_INFO, "Ignoring NAL unit %d during extradata parsing\n", - hx->nal_unit_type); - hx->nal_unit_type = NAL_FF_IGNORE; + h->nal_unit_type); + h->nal_unit_type = NAL_FF_IGNORE; } err = 0; - switch (hx->nal_unit_type) { + switch (h->nal_unit_type) { case NAL_IDR_SLICE: if (h->nal_unit_type != NAL_IDR_SLICE) { av_log(h->avctx, AV_LOG_ERROR, @@ -1526,11 +1467,9 @@ again: } idr(h); // FIXME ensure we don't lose some frames if there is reordering case NAL_SLICE: - init_get_bits(&hx->gb, ptr, bit_length); - hx->intra_gb_ptr = - hx->inter_gb_ptr = &hx->gb; + init_get_bits(&sl->gb, ptr, bit_length); - if ((err = ff_h264_decode_slice_header(hx, sl, h))) + if ((err = ff_h264_decode_slice_header(h, sl))) break; if (h->sei_recovery_frame_cnt >= 0 && h->recovery_frame < 0) { @@ -1538,18 +1477,18 @@ again: ((1 << h->sps.log2_max_frame_num) - 1); } - h->cur_pic_ptr->f.key_frame |= - (hx->nal_unit_type == NAL_IDR_SLICE) || + h->cur_pic_ptr->f->key_frame |= + (h->nal_unit_type == NAL_IDR_SLICE) || (h->sei_recovery_frame_cnt >= 0); - if (hx->nal_unit_type == NAL_IDR_SLICE || + if (h->nal_unit_type == NAL_IDR_SLICE || h->recovery_frame == h->frame_num) { h->recovery_frame = -1; h->cur_pic_ptr->recovered = 1; } // If we have an IDR, all frames after it in decoded order are // "recovered". - if (hx->nal_unit_type == NAL_IDR_SLICE) + if (h->nal_unit_type == NAL_IDR_SLICE) h->frame_recovered |= FRAME_RECOVERED_IDR; h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR); @@ -1562,13 +1501,13 @@ again: return ret; } - if (hx->redundant_pic_count == 0 && + if (sl->redundant_pic_count == 0 && (avctx->skip_frame < AVDISCARD_NONREF || - hx->nal_ref_idc) && + h->nal_ref_idc) && (avctx->skip_frame < AVDISCARD_BIDIR || - hx->slice_type_nos != AV_PICTURE_TYPE_B) && + sl->slice_type_nos != AV_PICTURE_TYPE_B) && (avctx->skip_frame < AVDISCARD_NONKEY || - hx->slice_type_nos == AV_PICTURE_TYPE_I) && + sl->slice_type_nos == AV_PICTURE_TYPE_I) && avctx->skip_frame < AVDISCARD_ALL) { if (avctx->hwaccel) { ret = avctx->hwaccel->decode_slice(avctx, @@ -1604,10 +1543,6 @@ again: ff_h264_decode_seq_parameter_set(h); } - ret = ff_h264_set_parameter_from_sps(h); - if (ret < 0) - goto end; - break; case NAL_PPS: init_get_bits(&h->gb, ptr, bit_length); @@ -1626,7 +1561,7 @@ again: break; default: av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n", - hx->nal_unit_type, bit_length); + h->nal_unit_type, bit_length); } if (context_count == h->max_contexts) { @@ -1638,15 +1573,11 @@ again: if (err < 0) { av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n"); - h->ref_count[0] = h->ref_count[1] = h->list_count = 0; + sl->ref_count[0] = sl->ref_count[1] = sl->list_count = 0; } else if (err == 1) { - /* Slice could not be decoded in parallel mode, copy down - * NAL unit stuff to context 0 and restart. Note that - * rbsp_buffer is not transferred, but since we no longer + /* Slice could not be decoded in parallel mode, restart. Note + * that rbsp_buffer is not transferred, but since we no longer * run in parallel mode this should not be an issue. */ - h->nal_unit_type = hx->nal_unit_type; - h->nal_ref_idc = hx->nal_ref_idc; - hx = h; sl = &h->slice_ctx[0]; goto again; } @@ -1713,6 +1644,7 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data, int ret; h->flags = avctx->flags; + h->setup_finished = 0; /* end of stream, output what is still in the buffers */ out: @@ -1727,7 +1659,7 @@ out: out_idx = 0; for (i = 1; h->delayed_pic[i] && - !h->delayed_pic[i]->f.key_frame && + !h->delayed_pic[i]->f->key_frame && !h->delayed_pic[i]->mmco_reset; i++) if (h->delayed_pic[i]->poc < out->poc) { @@ -1739,7 +1671,7 @@ out: h->delayed_pic[i] = h->delayed_pic[i + 1]; if (out) { - ret = output_frame(h, pict, &out->f); + ret = output_frame(h, pict, out->f); if (ret < 0) return ret; *got_frame = 1; @@ -1769,15 +1701,15 @@ out: if (avctx->flags2 & CODEC_FLAG2_CHUNKS) decode_postinit(h, 1); - ff_h264_field_end(h, 0); + ff_h264_field_end(h, &h->slice_ctx[0], 0); *got_frame = 0; if (h->next_output_pic && ((avctx->flags & CODEC_FLAG_OUTPUT_CORRUPT) || h->next_output_pic->recovered)) { if (!h->next_output_pic->recovered) - h->next_output_pic->f.flags |= AV_FRAME_FLAG_CORRUPT; + h->next_output_pic->f->flags |= AV_FRAME_FLAG_CORRUPT; - ret = output_frame(h, pict, &h->next_output_pic->f); + ret = output_frame(h, pict, h->next_output_pic->f); if (ret < 0) return ret; *got_frame = 1; @@ -1793,8 +1725,17 @@ av_cold void ff_h264_free_context(H264Context *h) { int i; - ff_h264_free_tables(h, 1); // FIXME cleanup init stuff perhaps + ff_h264_free_tables(h); + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { + ff_h264_unref_picture(h, &h->DPB[i]); + av_frame_free(&h->DPB[i].f); + } + + h->cur_pic_ptr = NULL; + + for (i = 0; i < h->nb_slice_ctx; i++) + av_freep(&h->slice_ctx[i].rbsp_buffer); av_freep(&h->slice_ctx); h->nb_slice_ctx = 0; @@ -1812,10 +1753,25 @@ static av_cold int h264_decode_end(AVCodecContext *avctx) ff_h264_free_context(h); ff_h264_unref_picture(h, &h->cur_pic); + av_frame_free(&h->cur_pic.f); return 0; } +#define OFFSET(x) offsetof(H264Context, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption h264_options[] = { + { "enable_er", "Enable error resilience on damaged frames (unsafe)", OFFSET(enable_er), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD }, + { NULL }, +}; + +static const AVClass h264_class = { + .class_name = "h264", + .item_name = av_default_item_name, + .option = h264_options, + .version = LIBAVUTIL_VERSION_INT, +}; + static const AVProfile profiles[] = { { FF_PROFILE_H264_BASELINE, "Baseline" }, { FF_PROFILE_H264_CONSTRAINED_BASELINE, "Constrained Baseline" }, @@ -1849,4 +1805,5 @@ AVCodec ff_h264_decoder = { .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context), .profiles = NULL_IF_CONFIG_SMALL(profiles), + .priv_class = &h264_class, };