History

Merge commit '61f168ae348f94f39e7afc6971654455a5de0e4d'

* 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."

Clément Bœsch committed 10 years ago

Commit f512e4a2 parents 0f2654c 61f168a2 files · +138 −125Browse files

Unified · Split

2 files
  1. libavcodec/h264.h +2 −0
  2. libavcodec/h264_slice.c +136 −125
libavcodec/h264.h+2−0
@@ -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
libavcodec/h264_slice.c+136−125
@@ -1004,6 +1004,125 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a) · 1003 unmodified lines
1004 }1004 }
1005}1005}
1006 1006
1007static 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 first1126/* 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 frame1127 * 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
1011static int h264_field_start(H264Context *h, const H264SliceContext *sl)1130static 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) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t