+ return 0;
+}
+
+/**
+ * Decode a slice header.
+ * This will (re)initialize the decoder and call h264_frame_start() as needed.
+ *
+ * @param h h264context
+ *
+ * @return 0 if okay, <0 if an error occurred
+ */
+int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
+ const H2645NAL *nal)
+{
+ int i, j, ret = 0;
+
+ ret = h264_slice_header_parse(h, sl, nal);
+ if (ret < 0)
+ return ret;
+
+ if (!h->setup_finished) {
+ if (sl->first_mb_addr == 0) { // FIXME better field boundary detection
+ if (h->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) {
+ ff_h264_field_end(h, sl, 1);
+ }
+
+ h->current_slice = 0;
+ 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 == 0) {
+ ret = h264_field_start(h, sl, nal);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ if (h->current_slice > 0) {
+ if (h->ps.pps != (const PPS*)h->ps.pps_list[sl->pps_id]->data) {
+ av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ 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;
+ }
+ }
+
+ assert(h->mb_num == h->mb_width * h->mb_height);
+ if (sl->first_mb_addr << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num ||
+ sl->first_mb_addr >= h->mb_num) {
+ av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n");
+ return AVERROR_INVALIDDATA;
+ }
+ sl->resync_mb_x = sl->mb_x = sl->first_mb_addr % h->mb_width;
+ sl->resync_mb_y = sl->mb_y = (sl->first_mb_addr / h->mb_width) <<
+ FIELD_OR_MBAFF_PICTURE(h);
+ if (h->picture_structure == PICT_BOTTOM_FIELD)
+ sl->resync_mb_y = sl->mb_y = sl->mb_y + 1;
+ assert(sl->mb_y < h->mb_height);
+
+ ret = ff_h264_build_ref_list(h, sl);
+ if (ret < 0)
+ return ret;
+
+ if (h->ps.pps->weighted_bipred_idc == 2 &&
+ sl->slice_type_nos == AV_PICTURE_TYPE_B) {
+ implicit_weight_table(h, sl, -1);
+ if (FRAME_MBAFF(h)) {
+ implicit_weight_table(h, sl, 0);
+ implicit_weight_table(h, sl, 1);
+ }
+ }
+
+ if (sl->slice_type_nos == AV_PICTURE_TYPE_B && !sl->direct_spatial_mv_pred)
+ ff_h264_direct_dist_scale_factor(h, sl);
+ ff_h264_direct_ref_list_init(h, sl);
+