* 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 | } ref_modifications[2][32]; | 413 | } ref_modifications[2][32]; |
| 414 | int nb_ref_modifications[2]; | 414 | int nb_ref_modifications[2]; |
| 415 | 415 | ||
| 416 | unsigned int pps_id; | ||
| 417 | |||
| 416 | const uint8_t *intra_pcm_ptr; | 418 | const uint8_t *intra_pcm_ptr; |
| 417 | int16_t *dc_val_base; | 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 | /* This function is called right after decoding the slice header for a first | 1126 | /* This function is called right after decoding the slice header for a first |
| 1008 | * slice in a field (or a frame). It decides whether we are decoding a new frame | 1127 | * slice in a field (or a frame). It decides whether we are decoding a new frame |
| 1009 | * or a second field in a pair and does the necessary setup. | 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 | static int h264_field_start(H264Context *h, const H264SliceContext *sl) | 1130 | static int h264_field_start(H264Context *h, const H264SliceContext *sl) |
| 1012 | { | 1131 | { |
| 1013 | int i; | 1132 | int i; |
| 1014 | const SPS *sps = h->ps.sps; | 1133 | const SPS *sps; |
| 1015 | 1134 | ||
| 1016 | int last_pic_structure, last_pic_droppable, ret; | 1135 | int last_pic_structure, last_pic_droppable, ret; |
| 1017 | 1136 | ||
| 1137 | sps = h->ps.sps; | ||
| 1138 | |||
| 1018 | last_pic_droppable = h->droppable; | 1139 | last_pic_droppable = h->droppable; |
| 1019 | last_pic_structure = h->picture_structure; | 1140 | last_pic_structure = h->picture_structure; |
| 1020 | h->droppable = (h->nal_ref_idc == 0); | 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 | const SPS *sps; | 1327 | const SPS *sps; |
| 1207 | const PPS *pps; | 1328 | const PPS *pps; |
| 1208 | unsigned int pps_id; | ||
| 1209 | int ret; | 1329 | int ret; |
| 1210 | unsigned int slice_type, tmp, i; | 1330 | unsigned int slice_type, tmp, i; |
| 1211 | int must_reinit; | ||
| 1212 | int needs_reinit = 0; | ||
| 1213 | int field_pic_flag, bottom_field_flag; | 1331 | int field_pic_flag, bottom_field_flag; |
| 1214 | int first_slice = sl == h->slice_ctx && !h->current_slice; | 1332 | int first_slice = sl == h->slice_ctx && !h->current_slice; |
| 1215 | int frame_num, droppable, picture_structure; | 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); | 1420 | sl->pps_id = get_ue_golomb(&sl->gb); |
| 1303 | if (pps_id >= MAX_PPS_COUNT) { | 1421 | if (sl->pps_id >= MAX_PPS_COUNT) { |
| 1304 | av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id); | 1422 | av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", sl->pps_id); |
| 1305 | return AVERROR_INVALIDDATA; | 1423 | return AVERROR_INVALIDDATA; |
| 1306 | } | 1424 | } |
| 1307 | if (!h->ps.pps_list[pps_id]) { | 1425 | if (!h->ps.pps_list[sl->pps_id]) { |
| 1308 | av_log(h->avctx, AV_LOG_ERROR, | 1426 | av_log(h->avctx, AV_LOG_ERROR, |
| 1309 | "non-existing PPS %u referenced\n", | 1427 | "non-existing PPS %u referenced\n", |
| 1310 | pps_id); | 1428 | sl->pps_id); |
| 1311 | return AVERROR_INVALIDDATA; | 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 | if (!h->ps.sps_list[pps->sps_id]) { | 1434 | if (!h->ps.sps_list[pps->sps_id]) { |
| 1317 | av_log(h->avctx, AV_LOG_ERROR, | 1435 | av_log(h->avctx, AV_LOG_ERROR, |
| 1318 | "non-existing SPS %u referenced\n", | 1436 | "non-existing SPS %u referenced\n", pps->sps_id); |
| 1319 | pps->sps_id); | ||
| 1320 | return AVERROR_INVALIDDATA; | 1437 | return AVERROR_INVALIDDATA; |
| 1321 | } | 1438 | } |
| 1322 | 1439 | if (!first_slice) { | |
| 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 { | ||
| 1331 | if (h->ps.pps->sps_id != pps->sps_id || | 1440 | if (h->ps.pps->sps_id != pps->sps_id || |
| 1332 | h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*|| | 1441 | h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*|| |
| 1333 | (h->setup_finished && h->ps.pps != pps)*/) { | 1442 | (h->setup_finished && h->ps.pps != pps)*/) { |
| 1334 | av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); | 1443 | av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); |
| 1335 | return AVERROR_INVALIDDATA; | 1444 | return AVERROR_INVALIDDATA; |
| 1336 | } | 1445 | } |
| 1337 | } | 1446 | if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { |
| 1338 | |||
| 1339 | if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { | ||
| 1340 | if (!first_slice) { | ||
| 1341 | av_log(h->avctx, AV_LOG_ERROR, | 1447 | av_log(h->avctx, AV_LOG_ERROR, |
| 1342 | "SPS changed in the middle of the frame\n"); | 1448 | "SPS changed in the middle of the frame\n"); |
| 1343 | return AVERROR_INVALIDDATA; | 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; | 1453 | // TODO: should probably be moved to h264_field_start() |
| 1366 | sps = h->ps.sps; | 1454 | ret = h264_init_ps(h, sl, first_slice); |
| 1367 | 1455 | if (ret < 0) | |
| 1368 | must_reinit = (h->context_initialized && | 1456 | return ret; |
| 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)); | ||
| 1441 | 1457 | ||
| 1442 | if ((ret = h264_slice_header_init(h)) < 0) { | 1458 | sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data; |
| 1443 | av_log(h->avctx, AV_LOG_ERROR, | ||
| 1444 | "h264_slice_header_init() failed\n"); | ||
| 1445 | return ret; | ||
| 1446 | } | ||
| 1447 | } | ||
| 1448 | 1459 | ||
| 1449 | frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); | 1460 | frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); |
| 1450 | if (!first_slice) { | 1461 | if (!first_slice) { |