* commit '61f168ae348f94f39e7afc6971654455a5de0e4d': h264: factor out setting the parameter sets for a frame Michael's changes on top of the merge undo parts of the original diff that are not factorization: "The call point is left where it was before. Such a change should be in a separate commit and has multiple issues, one being null pointer dereferences the other is that some safety checks would become conditional. I tried to split the PPS init between the new and old functions similarly to the SPS code."
Unified · Split
| @@ -413,6 +413,8 @@ typedef struct H264SliceContext { · 412 unmodified lines | ||
| 413 | 413 | } ref_modifications[2][32]; |
| 414 | 414 | int nb_ref_modifications[2]; |
| 415 | 415 | |
| 416 | + unsigned int pps_id; | |
| 417 | + | |
| 416 | 418 | const uint8_t *intra_pcm_ptr; |
| 417 | 419 | int16_t *dc_val_base; |
| 418 | 420 | |
| @@ -1004,6 +1004,125 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a) · 1003 unmodified lines | ||
| 1004 | 1004 | } |
| 1005 | 1005 | } |
| 1006 | 1006 | |
| 1007 | +static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_slice) | |
| 1008 | +{ | |
| 1009 | + const SPS *sps; | |
| 1010 | + int needs_reinit = 0, must_reinit, ret; | |
| 1011 | + | |
| 1012 | + if (first_slice) { | |
| 1013 | + av_buffer_unref(&h->ps.pps_ref); | |
| 1014 | + h->ps.pps = NULL; | |
| 1015 | + h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[sl->pps_id]); | |
| 1016 | + if (!h->ps.pps_ref) | |
| 1017 | + return AVERROR(ENOMEM); | |
| 1018 | + h->ps.pps = (const PPS*)h->ps.pps_ref->data; | |
| 1019 | + } | |
| 1020 | + | |
| 1021 | + if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { | |
| 1022 | + av_buffer_unref(&h->ps.sps_ref); | |
| 1023 | + h->ps.sps = NULL; | |
| 1024 | + h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]); | |
| 1025 | + if (!h->ps.sps_ref) | |
| 1026 | + return AVERROR(ENOMEM); | |
| 1027 | + h->ps.sps = (const SPS*)h->ps.sps_ref->data; | |
| 1028 | + | |
| 1029 | + if (h->mb_width != h->ps.sps->mb_width || | |
| 1030 | + h->mb_height != h->ps.sps->mb_height * (2 - h->ps.sps->frame_mbs_only_flag) || | |
| 1031 | + h->cur_bit_depth_luma != h->ps.sps->bit_depth_luma || | |
| 1032 | + h->cur_chroma_format_idc != h->ps.sps->chroma_format_idc | |
| 1033 | + ) | |
| 1034 | + needs_reinit = 1; | |
| 1035 | + | |
| 1036 | + if (h->bit_depth_luma != h->ps.sps->bit_depth_luma || | |
| 1037 | + h->chroma_format_idc != h->ps.sps->chroma_format_idc) | |
| 1038 | + needs_reinit = 1; | |
| 1039 | + } | |
| 1040 | + sps = h->ps.sps; | |
| 1041 | + | |
| 1042 | + must_reinit = (h->context_initialized && | |
| 1043 | + ( 16*sps->mb_width != h->avctx->coded_width | |
| 1044 | + || 16*sps->mb_height * (2 - sps->frame_mbs_only_flag) != h->avctx->coded_height | |
| 1045 | + || h->cur_bit_depth_luma != sps->bit_depth_luma | |
| 1046 | + || h->cur_chroma_format_idc != sps->chroma_format_idc | |
| 1047 | + || h->mb_width != sps->mb_width | |
| 1048 | + || h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag) | |
| 1049 | + )); | |
| 1050 | + if (h->avctx->pix_fmt == AV_PIX_FMT_NONE | |
| 1051 | + || (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0)))) | |
| 1052 | + must_reinit = 1; | |
| 1053 | + | |
| 1054 | + if (first_slice && av_cmp_q(sps->sar, h->avctx->sample_aspect_ratio)) | |
| 1055 | + must_reinit = 1; | |
| 1056 | + | |
| 1057 | + if (!h->setup_finished) { | |
| 1058 | + h->avctx->profile = ff_h264_get_profile(sps); | |
| 1059 | + h->avctx->level = sps->level_idc; | |
| 1060 | + h->avctx->refs = sps->ref_frame_count; | |
| 1061 | + | |
| 1062 | + h->mb_width = sps->mb_width; | |
| 1063 | + h->mb_height = sps->mb_height * (2 - sps->frame_mbs_only_flag); | |
| 1064 | + h->mb_num = h->mb_width * h->mb_height; | |
| 1065 | + h->mb_stride = h->mb_width + 1; | |
| 1066 | + | |
| 1067 | + h->b_stride = h->mb_width * 4; | |
| 1068 | + | |
| 1069 | + h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p | |
| 1070 | + | |
| 1071 | + h->width = 16 * h->mb_width; | |
| 1072 | + h->height = 16 * h->mb_height; | |
| 1073 | + | |
| 1074 | + ret = init_dimensions(h); | |
| 1075 | + if (ret < 0) | |
| 1076 | + return ret; | |
| 1077 | + | |
| 1078 | + if (sps->video_signal_type_present_flag) { | |
| 1079 | + h->avctx->color_range = sps->full_range > 0 ? AVCOL_RANGE_JPEG | |
| 1080 | + : AVCOL_RANGE_MPEG; | |
| 1081 | + if (sps->colour_description_present_flag) { | |
| 1082 | + if (h->avctx->colorspace != sps->colorspace) | |
| 1083 | + needs_reinit = 1; | |
| 1084 | + h->avctx->color_primaries = sps->color_primaries; | |
| 1085 | + h->avctx->color_trc = sps->color_trc; | |
| 1086 | + h->avctx->colorspace = sps->colorspace; | |
| 1087 | + } | |
| 1088 | + } | |
| 1089 | + } | |
| 1090 | + | |
| 1091 | + if (!h->context_initialized || must_reinit || needs_reinit) { | |
| 1092 | + int flush_changes = h->context_initialized; | |
| 1093 | + h->context_initialized = 0; | |
| 1094 | + if (sl != h->slice_ctx) { | |
| 1095 | + av_log(h->avctx, AV_LOG_ERROR, | |
| 1096 | + "changing width %d -> %d / height %d -> %d on " | |
| 1097 | + "slice %d\n", | |
| 1098 | + h->width, h->avctx->coded_width, | |
| 1099 | + h->height, h->avctx->coded_height, | |
| 1100 | + h->current_slice + 1); | |
| 1101 | + return AVERROR_INVALIDDATA; | |
| 1102 | + } | |
| 1103 | + | |
| 1104 | + av_assert1(first_slice); | |
| 1105 | + | |
| 1106 | + if (flush_changes) | |
| 1107 | + ff_h264_flush_change(h); | |
| 1108 | + | |
| 1109 | + if ((ret = get_pixel_format(h, 1)) < 0) | |
| 1110 | + return ret; | |
| 1111 | + h->avctx->pix_fmt = ret; | |
| 1112 | + | |
| 1113 | + av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, " | |
| 1114 | + "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(h->avctx->pix_fmt)); | |
| 1115 | + | |
| 1116 | + if ((ret = h264_slice_header_init(h)) < 0) { | |
| 1117 | + av_log(h->avctx, AV_LOG_ERROR, | |
| 1118 | + "h264_slice_header_init() failed\n"); | |
| 1119 | + return ret; | |
| 1120 | + } | |
| 1121 | + } | |
| 1122 | + | |
| 1123 | + return 0; | |
| 1124 | +} | |
| 1125 | + | |
| 1007 | 1126 | /* This function is called right after decoding the slice header for a first |
| 1008 | 1127 | * slice in a field (or a frame). It decides whether we are decoding a new frame |
| 1009 | 1128 | * or a second field in a pair and does the necessary setup. |
| @@ -1011,10 +1130,12 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a) · 1 unmodified line | ||
| 1011 | 1130 | static int h264_field_start(H264Context *h, const H264SliceContext *sl) |
| 1012 | 1131 | { |
| 1013 | 1132 | int i; |
| 1014 | − const SPS *sps = h->ps.sps; | |
| 1133 | + const SPS *sps; | |
| 1015 | 1134 | |
| 1016 | 1135 | int last_pic_structure, last_pic_droppable, ret; |
| 1017 | 1136 | |
| 1137 | + sps = h->ps.sps; | |
| 1138 | + | |
| 1018 | 1139 | last_pic_droppable = h->droppable; |
| 1019 | 1140 | last_pic_structure = h->picture_structure; |
| 1020 | 1141 | h->droppable = (h->nal_ref_idc == 0); |
| @@ -1205,11 +1326,8 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl) · 184 unmodified lines | ||
| 1205 | 1326 | { |
| 1206 | 1327 | const SPS *sps; |
| 1207 | 1328 | const PPS *pps; |
| 1208 | − unsigned int pps_id; | |
| 1209 | 1329 | int ret; |
| 1210 | 1330 | unsigned int slice_type, tmp, i; |
| 1211 | − int must_reinit; | |
| 1212 | − int needs_reinit = 0; | |
| 1213 | 1331 | int field_pic_flag, bottom_field_flag; |
| 1214 | 1332 | int first_slice = sl == h->slice_ctx && !h->current_slice; |
| 1215 | 1333 | int frame_num, droppable, picture_structure; |
| @@ -1299,152 +1417,45 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl) · 83 unmodified lines | ||
| 1299 | 1417 | } |
| 1300 | 1418 | } |
| 1301 | 1419 | |
| 1302 | − pps_id = get_ue_golomb(&sl->gb); | |
| 1303 | − if (pps_id >= MAX_PPS_COUNT) { | |
| 1304 | − av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id); | |
| 1420 | + sl->pps_id = get_ue_golomb(&sl->gb); | |
| 1421 | + if (sl->pps_id >= MAX_PPS_COUNT) { | |
| 1422 | + av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", sl->pps_id); | |
| 1305 | 1423 | return AVERROR_INVALIDDATA; |
| 1306 | 1424 | } |
| 1307 | − if (!h->ps.pps_list[pps_id]) { | |
| 1425 | + if (!h->ps.pps_list[sl->pps_id]) { | |
| 1308 | 1426 | av_log(h->avctx, AV_LOG_ERROR, |
| 1309 | 1427 | "non-existing PPS %u referenced\n", |
| 1310 | − pps_id); | |
| 1428 | + sl->pps_id); | |
| 1311 | 1429 | return AVERROR_INVALIDDATA; |
| 1312 | 1430 | } |
| 1313 | 1431 | |
| 1314 | − pps = (const PPS*)h->ps.pps_list[pps_id]->data; | |
| 1432 | + pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data; | |
| 1315 | 1433 | |
| 1316 | 1434 | if (!h->ps.sps_list[pps->sps_id]) { |
| 1317 | 1435 | av_log(h->avctx, AV_LOG_ERROR, |
| 1318 | − "non-existing SPS %u referenced\n", | |
| 1319 | − pps->sps_id); | |
| 1436 | + "non-existing SPS %u referenced\n", pps->sps_id); | |
| 1320 | 1437 | return AVERROR_INVALIDDATA; |
| 1321 | 1438 | } |
| 1322 | − | |
| 1323 | − if (first_slice) { | |
| 1324 | − av_buffer_unref(&h->ps.pps_ref); | |
| 1325 | − h->ps.pps = NULL; | |
| 1326 | − h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[pps_id]); | |
| 1327 | − if (!h->ps.pps_ref) | |
| 1328 | − return AVERROR(ENOMEM); | |
| 1329 | − h->ps.pps = (const PPS*)h->ps.pps_ref->data; | |
| 1330 | − } else { | |
| 1439 | + if (!first_slice) { | |
| 1331 | 1440 | if (h->ps.pps->sps_id != pps->sps_id || |
| 1332 | 1441 | h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*|| |
| 1333 | 1442 | (h->setup_finished && h->ps.pps != pps)*/) { |
| 1334 | 1443 | av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); |
| 1335 | 1444 | return AVERROR_INVALIDDATA; |
| 1336 | 1445 | } |
| 1337 | − } | |
| 1338 | − | |
| 1339 | − if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { | |
| 1340 | − if (!first_slice) { | |
| 1446 | + if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { | |
| 1341 | 1447 | av_log(h->avctx, AV_LOG_ERROR, |
| 1342 | 1448 | "SPS changed in the middle of the frame\n"); |
| 1343 | 1449 | return AVERROR_INVALIDDATA; |
| 1344 | 1450 | } |
| 1345 | − | |
| 1346 | − av_buffer_unref(&h->ps.sps_ref); | |
| 1347 | − h->ps.sps = NULL; | |
| 1348 | − h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]); | |
| 1349 | − if (!h->ps.sps_ref) | |
| 1350 | − return AVERROR(ENOMEM); | |
| 1351 | − h->ps.sps = (const SPS*)h->ps.sps_ref->data; | |
| 1352 | − | |
| 1353 | − if (h->mb_width != h->ps.sps->mb_width || | |
| 1354 | − h->mb_height != h->ps.sps->mb_height * (2 - h->ps.sps->frame_mbs_only_flag) || | |
| 1355 | − h->cur_bit_depth_luma != h->ps.sps->bit_depth_luma || | |
| 1356 | − h->cur_chroma_format_idc != h->ps.sps->chroma_format_idc | |
| 1357 | − ) | |
| 1358 | − needs_reinit = 1; | |
| 1359 | − | |
| 1360 | − if (h->bit_depth_luma != h->ps.sps->bit_depth_luma || | |
| 1361 | − h->chroma_format_idc != h->ps.sps->chroma_format_idc) | |
| 1362 | − needs_reinit = 1; | |
| 1363 | 1451 | } |
| 1364 | 1452 | |
| 1365 | − pps = h->ps.pps; | |
| 1366 | − sps = h->ps.sps; | |
| 1367 | − | |
| 1368 | − must_reinit = (h->context_initialized && | |
| 1369 | − ( 16*sps->mb_width != h->avctx->coded_width | |
| 1370 | − || 16*sps->mb_height * (2 - sps->frame_mbs_only_flag) != h->avctx->coded_height | |
| 1371 | − || h->cur_bit_depth_luma != sps->bit_depth_luma | |
| 1372 | − || h->cur_chroma_format_idc != sps->chroma_format_idc | |
| 1373 | − || h->mb_width != sps->mb_width | |
| 1374 | − || h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag) | |
| 1375 | − )); | |
| 1376 | − if (h->avctx->pix_fmt == AV_PIX_FMT_NONE | |
| 1377 | − || (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0)))) | |
| 1378 | − must_reinit = 1; | |
| 1379 | − | |
| 1380 | − if (first_slice && av_cmp_q(sps->sar, h->avctx->sample_aspect_ratio)) | |
| 1381 | − must_reinit = 1; | |
| 1382 | − | |
| 1383 | − if (!h->setup_finished) { | |
| 1384 | − h->avctx->profile = ff_h264_get_profile(sps); | |
| 1385 | − h->avctx->level = sps->level_idc; | |
| 1386 | − h->avctx->refs = sps->ref_frame_count; | |
| 1387 | − | |
| 1388 | − h->mb_width = sps->mb_width; | |
| 1389 | − h->mb_height = sps->mb_height * (2 - sps->frame_mbs_only_flag); | |
| 1390 | − h->mb_num = h->mb_width * h->mb_height; | |
| 1391 | − h->mb_stride = h->mb_width + 1; | |
| 1392 | − | |
| 1393 | − h->b_stride = h->mb_width * 4; | |
| 1394 | − | |
| 1395 | − h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p | |
| 1396 | − | |
| 1397 | − h->width = 16 * h->mb_width; | |
| 1398 | − h->height = 16 * h->mb_height; | |
| 1399 | − | |
| 1400 | − ret = init_dimensions(h); | |
| 1401 | − if (ret < 0) | |
| 1402 | − return ret; | |
| 1403 | − | |
| 1404 | − if (sps->video_signal_type_present_flag) { | |
| 1405 | − h->avctx->color_range = sps->full_range > 0 ? AVCOL_RANGE_JPEG | |
| 1406 | − : AVCOL_RANGE_MPEG; | |
| 1407 | − if (sps->colour_description_present_flag) { | |
| 1408 | − if (h->avctx->colorspace != sps->colorspace) | |
| 1409 | − needs_reinit = 1; | |
| 1410 | − h->avctx->color_primaries = sps->color_primaries; | |
| 1411 | − h->avctx->color_trc = sps->color_trc; | |
| 1412 | − h->avctx->colorspace = sps->colorspace; | |
| 1413 | − } | |
| 1414 | − } | |
| 1415 | − } | |
| 1416 | − | |
| 1417 | − if (!h->context_initialized || must_reinit || needs_reinit) { | |
| 1418 | − int flush_changes = h->context_initialized; | |
| 1419 | − h->context_initialized = 0; | |
| 1420 | − if (sl != h->slice_ctx) { | |
| 1421 | − av_log(h->avctx, AV_LOG_ERROR, | |
| 1422 | − "changing width %d -> %d / height %d -> %d on " | |
| 1423 | − "slice %d\n", | |
| 1424 | − h->width, h->avctx->coded_width, | |
| 1425 | − h->height, h->avctx->coded_height, | |
| 1426 | − h->current_slice + 1); | |
| 1427 | − return AVERROR_INVALIDDATA; | |
| 1428 | − } | |
| 1429 | − | |
| 1430 | − av_assert1(first_slice); | |
| 1431 | − | |
| 1432 | − if(flush_changes) | |
| 1433 | − ff_h264_flush_change(h); | |
| 1434 | − | |
| 1435 | − if ((ret = get_pixel_format(h, 1)) < 0) | |
| 1436 | − return ret; | |
| 1437 | − h->avctx->pix_fmt = ret; | |
| 1438 | − | |
| 1439 | − av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, " | |
| 1440 | − "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(h->avctx->pix_fmt)); | |
| 1453 | + // TODO: should probably be moved to h264_field_start() | |
| 1454 | + ret = h264_init_ps(h, sl, first_slice); | |
| 1455 | + if (ret < 0) | |
| 1456 | + return ret; | |
| 1441 | 1457 | |
| 1442 | − if ((ret = h264_slice_header_init(h)) < 0) { | |
| 1443 | − av_log(h->avctx, AV_LOG_ERROR, | |
| 1444 | − "h264_slice_header_init() failed\n"); | |
| 1445 | − return ret; | |
| 1446 | − } | |
| 1447 | − } | |
| 1458 | + sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data; | |
| 1448 | 1459 | |
| 1449 | 1460 | frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); |
| 1450 | 1461 | if (!first_slice) { |