int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal)

{

    H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued;

    int first_slice = sl == h->slice_ctx && !h->current_slice;

    int ret;



    sl->gb = nal->gb;



    ret = h264_slice_header_parse(h, sl, nal);

    if (ret < 0)

        return ret;



    // discard redundant pictures

    if (sl->redundant_pic_count > 0)

        return 0;



    if (sl->first_mb_addr == 0 || !h->current_slice) {

        if (h->setup_finished) {

            av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n");

            return AVERROR_INVALIDDATA;

        }

    }



    if (sl->first_mb_addr == 0) { // FIXME better field boundary detection

        if (h->current_slice) {

            // this slice starts a new field

            // first decode any pending queued slices

            if (h->nb_slice_ctx_queued) {

                H264SliceContext tmp_ctx;



                ret = ff_h264_execute_decode_slices(h);

                if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))

                    return ret;



                memcpy(&tmp_ctx, h->slice_ctx, sizeof(tmp_ctx));

                memcpy(h->slice_ctx, sl, sizeof(tmp_ctx));

                memcpy(sl, &tmp_ctx, sizeof(tmp_ctx));

                sl = h->slice_ctx;

            }



            if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {

                ret = ff_h264_field_end(h, h->slice_ctx, 1);

                if (ret < 0)

                    return ret;

            } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type  == H264_NAL_IDR_SLICE) {

                av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n");

                ret = ff_h264_field_end(h, h->slice_ctx, 1);

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);

                h->cur_pic_ptr = NULL;

                if (ret < 0)

                    return ret;

            } else

                return AVERROR_INVALIDDATA;

        }



        if (!h->first_field) {

            if (h->cur_pic_ptr && !h->droppable) {

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,

                                          h->picture_structure == PICT_BOTTOM_FIELD);

            }

            h->cur_pic_ptr = NULL;

        }

    }



    if (!h->current_slice)

        av_assert0(sl == h->slice_ctx);



    if (h->current_slice == 0 && !h->first_field) {

        if (

            (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) ||

            (h->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||

            (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||

            (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != H264_NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) ||

            h->avctx->skip_frame >= AVDISCARD_ALL) {

            return 0;

        }

    }



    if (!first_slice) {

        const PPS *pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;



        if (h->ps.pps->sps_id != pps->sps_id ||

            h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*||

            (h->setup_finished && h->ps.pps != pps)*/) {

            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) {

            av_log(h->avctx, AV_LOG_ERROR,

               "SPS changed in the middle of the frame\n");

            return AVERROR_INVALIDDATA;

        }

    }



    if (h->current_slice == 0) {

        ret = h264_field_start(h, sl, nal, first_slice);

        if (ret < 0)

            return ret;

    } else {

        if (h->picture_structure != sl->picture_structure ||

            h->droppable         != (nal->ref_idc == 0)) {

            av_log(h->avctx, AV_LOG_ERROR,

                   "Changing field mode (%d -> %d) between slices is not allowed\n",

                   h->picture_structure, sl->picture_structure);

            return AVERROR_INVALIDDATA;

        } else if (!h->cur_pic_ptr) {

            av_log(h->avctx, AV_LOG_ERROR,

                   "unset cur_pic_ptr on slice %d\n",

                   h->current_slice + 1);

            return AVERROR_INVALIDDATA;

        }

    }



    ret = h264_slice_init(h, sl, nal);

    if (ret < 0)

        return ret;



    h->nb_slice_ctx_queued++;



    return 0;

}

int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal)

{

    H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued;

    int first_slice = sl == h->slice_ctx && !h->current_slice;

    int ret;



    sl->gb = nal->gb;



    ret = h264_slice_header_parse(h, sl, nal);

    if (ret < 0)

        return ret;



    

    if (sl->redundant_pic_count > 0)

        return 0;



    if (sl->first_mb_addr == 0 || !h->current_slice) {

        if (h->setup_finished) {

            av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n");

            return AVERROR_INVALIDDATA;

        }

    }



    if (sl->first_mb_addr == 0) { 

        if (h->current_slice) {

            

            

            if (h->nb_slice_ctx_queued) {

                H264SliceContext tmp_ctx;



                ret = ff_h264_execute_decode_slices(h);

                if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))

                    return ret;



                memcpy(&tmp_ctx, h->slice_ctx, sizeof(tmp_ctx));

                memcpy(h->slice_ctx, sl, sizeof(tmp_ctx));

                memcpy(sl, &tmp_ctx, sizeof(tmp_ctx));

                sl = h->slice_ctx;

            }



            if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {

                ret = ff_h264_field_end(h, h->slice_ctx, 1);

                if (ret < 0)

                    return ret;

            } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type  == H264_NAL_IDR_SLICE) {

                av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n");

                ret = ff_h264_field_end(h, h->slice_ctx, 1);

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);

                h->cur_pic_ptr = NULL;

                if (ret < 0)

                    return ret;

            } else

                return AVERROR_INVALIDDATA;

        }



        if (!h->first_field) {

            if (h->cur_pic_ptr && !h->droppable) {

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,

                                          h->picture_structure == PICT_BOTTOM_FIELD);

            }

            h->cur_pic_ptr = NULL;

        }

    }



    if (!h->current_slice)

        av_assert0(sl == h->slice_ctx);



    if (h->current_slice == 0 && !h->first_field) {

        if (

            (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) ||

            (h->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||

            (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||

            (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != H264_NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) ||

            h->avctx->skip_frame >= AVDISCARD_ALL) {

            return 0;

        }

    }



    if (!first_slice) {

        const PPS *pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;



        if (h->ps.pps->sps_id != pps->sps_id ||

            h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode 

) {

            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) {

            av_log(h->avctx, AV_LOG_ERROR,

               "SPS changed in the middle of the frame\n");

            return AVERROR_INVALIDDATA;

        }

    }



    if (h->current_slice == 0) {

        ret = h264_field_start(h, sl, nal, first_slice);

        if (ret < 0)

            return ret;

    } else {

        if (h->picture_structure != sl->picture_structure ||

            h->droppable         != (nal->ref_idc == 0)) {

            av_log(h->avctx, AV_LOG_ERROR,

                   "Changing field mode (%d -> %d) between slices is not allowed\n",

                   h->picture_structure, sl->picture_structure);

            return AVERROR_INVALIDDATA;

        } else if (!h->cur_pic_ptr) {

            av_log(h->avctx, AV_LOG_ERROR,

                   "unset cur_pic_ptr on slice %d\n",

                   h->current_slice + 1);

            return AVERROR_INVALIDDATA;

        }

    }



    ret = h264_slice_init(h, sl, nal);

    if (ret < 0)

        return ret;



    h->nb_slice_ctx_queued++;



    return 0;

}

    if (sl->redundant_pic_count > 0)
int FUNC_0(H264Context *VAR_0, const H2645NAL *VAR_1)

{

    H264SliceContext *sl = VAR_0->slice_ctx + VAR_0->nb_slice_ctx_queued;

    int VAR_2 = sl == VAR_0->slice_ctx && !VAR_0->current_slice;

    int VAR_3;



    sl->gb = VAR_1->gb;



    VAR_3 = h264_slice_header_parse(VAR_0, sl, VAR_1);

    if (VAR_3 < 0)

        return VAR_3;



    

    if (sl->redundant_pic_count > 0)

        return 0;



    if (sl->first_mb_addr == 0 || !VAR_0->current_slice) {

        if (VAR_0->setup_finished) {

            av_log(VAR_0->avctx, AV_LOG_ERROR, "Too many fields\n");

            return AVERROR_INVALIDDATA;

        }

    }



    if (sl->first_mb_addr == 0) { 

        if (VAR_0->current_slice) {

            

            

            if (VAR_0->nb_slice_ctx_queued) {

                H264SliceContext tmp_ctx;



                VAR_3 = ff_h264_execute_decode_slices(VAR_0);

                if (VAR_3 < 0 && (VAR_0->avctx->err_recognition & AV_EF_EXPLODE))

                    return VAR_3;



                memcpy(&tmp_ctx, VAR_0->slice_ctx, sizeof(tmp_ctx));

                memcpy(VAR_0->slice_ctx, sl, sizeof(tmp_ctx));

                memcpy(sl, &tmp_ctx, sizeof(tmp_ctx));

                sl = VAR_0->slice_ctx;

            }



            if (VAR_0->cur_pic_ptr && FIELD_PICTURE(VAR_0) && VAR_0->first_field) {

                VAR_3 = ff_h264_field_end(VAR_0, VAR_0->slice_ctx, 1);

                if (VAR_3 < 0)

                    return VAR_3;

            } else if (VAR_0->cur_pic_ptr && !FIELD_PICTURE(VAR_0) && !VAR_0->first_field && VAR_0->nal_unit_type  == H264_NAL_IDR_SLICE) {

                av_log(VAR_0, AV_LOG_WARNING, "Broken frame packetizing\n");

                VAR_3 = ff_h264_field_end(VAR_0, VAR_0->slice_ctx, 1);

                ff_thread_report_progress(&VAR_0->cur_pic_ptr->tf, INT_MAX, 0);

                ff_thread_report_progress(&VAR_0->cur_pic_ptr->tf, INT_MAX, 1);

                VAR_0->cur_pic_ptr = NULL;

                if (VAR_3 < 0)

                    return VAR_3;

            } else

                return AVERROR_INVALIDDATA;

        }



        if (!VAR_0->first_field) {

            if (VAR_0->cur_pic_ptr && !VAR_0->droppable) {

                ff_thread_report_progress(&VAR_0->cur_pic_ptr->tf, INT_MAX,

                                          VAR_0->picture_structure == PICT_BOTTOM_FIELD);

            }

            VAR_0->cur_pic_ptr = NULL;

        }

    }



    if (!VAR_0->current_slice)

        av_assert0(sl == VAR_0->slice_ctx);



    if (VAR_0->current_slice == 0 && !VAR_0->first_field) {

        if (

            (VAR_0->avctx->skip_frame >= AVDISCARD_NONREF && !VAR_0->nal_ref_idc) ||

            (VAR_0->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||

            (VAR_0->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||

            (VAR_0->avctx->skip_frame >= AVDISCARD_NONKEY && VAR_0->nal_unit_type != H264_NAL_IDR_SLICE && VAR_0->sei.recovery_point.recovery_frame_cnt < 0) ||

            VAR_0->avctx->skip_frame >= AVDISCARD_ALL) {

            return 0;

        }

    }



    if (!VAR_2) {

        const PPS *VAR_4 = (const PPS*)VAR_0->ps.pps_list[sl->pps_id]->data;



        if (VAR_0->ps.VAR_4->sps_id != VAR_4->sps_id ||

            VAR_0->ps.VAR_4->transform_8x8_mode != VAR_4->transform_8x8_mode 

) {

            av_log(VAR_0->avctx, AV_LOG_ERROR, "PPS changed between slices\n");

            return AVERROR_INVALIDDATA;

        }

        if (VAR_0->ps.sps != (const SPS*)VAR_0->ps.sps_list[VAR_0->ps.VAR_4->sps_id]->data) {

            av_log(VAR_0->avctx, AV_LOG_ERROR,

               "SPS changed in the middle of the frame\n");

            return AVERROR_INVALIDDATA;

        }

    }



    if (VAR_0->current_slice == 0) {

        VAR_3 = h264_field_start(VAR_0, sl, VAR_1, VAR_2);

        if (VAR_3 < 0)

            return VAR_3;

    } else {

        if (VAR_0->picture_structure != sl->picture_structure ||

            VAR_0->droppable         != (VAR_1->ref_idc == 0)) {

            av_log(VAR_0->avctx, AV_LOG_ERROR,

                   "Changing field mode (%d -> %d) between slices is not allowed\n",

                   VAR_0->picture_structure, sl->picture_structure);

            return AVERROR_INVALIDDATA;

        } else if (!VAR_0->cur_pic_ptr) {

            av_log(VAR_0->avctx, AV_LOG_ERROR,

                   "unset cur_pic_ptr on slice %d\n",

                   VAR_0->current_slice + 1);

            return AVERROR_INVALIDDATA;

        }

    }



    VAR_3 = h264_slice_init(VAR_0, sl, VAR_1);

    if (VAR_3 < 0)

        return VAR_3;



    VAR_0->nb_slice_ctx_queued++;



    return 0;

}

int FUNC_0(H264Context *VAR_0, const H2645NAL *VAR_1)
{ H264SliceContext *sl = VAR_0->slice_ctx + VAR_0->nb_slice_ctx_queued; int VAR_2 = sl == VAR_0->slice_ctx && !VAR_0->current_slice; int VAR_3; sl->gb = VAR_1->gb; VAR_3 = h264_slice_header_parse(VAR_0, sl, VAR_1); if (VAR_3 < 0)
return VAR_3; if (sl->redundant_pic_count > 0)
return 0; if (sl->first_mb_addr == 0 || !VAR_0->current_slice) { if (VAR_0->setup_finished) { av_log(VAR_0->avctx, AV_LOG_ERROR, "Too many fields\n"); return AVERROR_INVALIDDATA; } } if (sl->first_mb_addr == 0) { if (VAR_0->current_slice) { if (VAR_0->nb_slice_ctx_queued) { H264SliceContext tmp_ctx; VAR_3 = ff_h264_execute_decode_slices(VAR_0); if (VAR_3 < 0 && (VAR_0->avctx->err_recognition & AV_EF_EXPLODE))
return VAR_3; memcpy(&tmp_ctx, VAR_0->slice_ctx, sizeof(tmp_ctx)); memcpy(VAR_0->slice_ctx, sl, sizeof(tmp_ctx)); memcpy(sl, &tmp_ctx, sizeof(tmp_ctx)); sl = VAR_0->slice_ctx; } if (VAR_0->cur_pic_ptr && FIELD_PICTURE(VAR_0) && VAR_0->first_field) { VAR_3 = ff_h264_field_end(VAR_0, VAR_0->slice_ctx, 1); if (VAR_3 < 0)
return VAR_3; } else if (VAR_0->cur_pic_ptr && !FIELD_PICTURE(VAR_0) && !VAR_0->first_field && VAR_0->nal_unit_type  == H264_NAL_IDR_SLICE) { av_log(VAR_0, AV_LOG_WARNING, "Broken frame packetizing\n"); VAR_3 = ff_h264_field_end(VAR_0, VAR_0->slice_ctx, 1); ff_thread_report_progress(&VAR_0->cur_pic_ptr->tf, INT_MAX, 0); ff_thread_report_progress(&VAR_0->cur_pic_ptr->tf, INT_MAX, 1); VAR_0->cur_pic_ptr = NULL; if (VAR_3 < 0)
return VAR_3; } else return AVERROR_INVALIDDATA; } if (!VAR_0->first_field) { if (VAR_0->cur_pic_ptr && !VAR_0->droppable) { ff_thread_report_progress(&VAR_0->cur_pic_ptr->tf, INT_MAX,
VAR_0->picture_structure == PICT_BOTTOM_FIELD); } VAR_0->cur_pic_ptr = NULL; } } if (!VAR_0->current_slice)
av_assert0(sl == VAR_0->slice_ctx); if (VAR_0->current_slice == 0 && !VAR_0->first_field) { if (
(VAR_0->avctx->skip_frame >= AVDISCARD_NONREF && !VAR_0->nal_ref_idc) ||
(VAR_0->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||
(VAR_0->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||
(VAR_0->avctx->skip_frame >= AVDISCARD_NONKEY && VAR_0->nal_unit_type != H264_NAL_IDR_SLICE && VAR_0->sei.recovery_point.recovery_frame_cnt < 0) ||
VAR_0->avctx->skip_frame >= AVDISCARD_ALL) { return 0; } } if (!VAR_2) { const PPS *VAR_4 = (const PPS*)VAR_0->ps.pps_list[sl->pps_id]->data; if (VAR_0->ps.VAR_4->sps_id != VAR_4->sps_id ||
VAR_0->ps.VAR_4->transform_8x8_mode != VAR_4->transform_8x8_mode
) { av_log(VAR_0->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); return AVERROR_INVALIDDATA; } if (VAR_0->ps.sps != (const SPS*)VAR_0->ps.sps_list[VAR_0->ps.VAR_4->sps_id]->data) { av_log(VAR_0->avctx, AV_LOG_ERROR,
"SPS changed in the middle of the frame\n"); return AVERROR_INVALIDDATA; } } if (VAR_0->current_slice == 0) { VAR_3 = h264_field_start(VAR_0, sl, VAR_1, VAR_2); if (VAR_3 < 0)
return VAR_3; } else { if (VAR_0->picture_structure != sl->picture_structure ||
VAR_0->droppable         != (VAR_1->ref_idc == 0)) { av_log(VAR_0->avctx, AV_LOG_ERROR,
"Changing field mode (%d -> %d) between slices is not allowed\n",
VAR_0->picture_structure, sl->picture_structure); return AVERROR_INVALIDDATA; } else if (!VAR_0->cur_pic_ptr) { av_log(VAR_0->avctx, AV_LOG_ERROR,
"unset cur_pic_ptr on slice %d\n",
VAR_0->current_slice + 1); return AVERROR_INVALIDDATA; } } VAR_3 = h264_slice_init(VAR_0, sl, VAR_1); if (VAR_3 < 0)
return VAR_3; VAR_0->nb_slice_ctx_queued++; return 0; }