Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * This file is part of FFmpeg. | ||
3 | * | ||
4 | * FFmpeg is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU Lesser General Public | ||
6 | * License as published by the Free Software Foundation; either | ||
7 | * version 2.1 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * FFmpeg is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * Lesser General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Lesser General Public | ||
15 | * License along with FFmpeg; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | |||
19 | #include <inttypes.h> | ||
20 | |||
21 | #include "libavutil/log.h" | ||
22 | |||
23 | #include "bsf.h" | ||
24 | #include "bsf_internal.h" | ||
25 | #include "cbs.h" | ||
26 | #include "cbs_bsf.h" | ||
27 | #include "cbs_h264.h" | ||
28 | #include "codec_id.h" | ||
29 | #include "h264.h" | ||
30 | #include "packet.h" | ||
31 | |||
32 | #define NEW_GLOBAL_PIC_INIT_QP 26 | ||
33 | |||
34 | typedef struct H264RedundantPPSContext { | ||
35 | CBSBSFContext common; | ||
36 | } H264RedundantPPSContext; | ||
37 | |||
38 | |||
39 | 307 | static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, | |
40 | CodedBitstreamUnit *unit) | ||
41 | { | ||
42 | H264RawPPS *pps; | ||
43 | int err; | ||
44 | |||
45 | // The changes we are about to perform affect the parsing process, | ||
46 | // so we must make sure that the PPS is writable, otherwise the | ||
47 | // parsing of future slices will be incorrect and even raise errors. | ||
48 | 307 | err = ff_cbs_make_unit_writable(ctx->common.input, unit); | |
49 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
|
307 | if (err < 0) |
50 | ✗ | return err; | |
51 | 307 | pps = unit->content; | |
52 | |||
53 | // Overwrite pic_init_qp with the global value. | ||
54 | 307 | pps->pic_init_qp_minus26 = NEW_GLOBAL_PIC_INIT_QP - 26; | |
55 | |||
56 | // Some PPSs have this set, so it must be set in all of them. | ||
57 | // (Slices which do not use such a PPS on input will still have | ||
58 | // *_weight_l*flag as zero and therefore write equivalently.) | ||
59 | 307 | pps->weighted_pred_flag = 1; | |
60 | |||
61 | 307 | return 0; | |
62 | } | ||
63 | |||
64 | 516 | static int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx, | |
65 | H264RawSliceHeader *slice) | ||
66 | { | ||
67 | 516 | const CodedBitstreamH264Context *const in = ctx->common.input->priv_data; | |
68 | 516 | const H264RawPPS *const pps = in->pps[slice->pic_parameter_set_id]; | |
69 | |||
70 | // We modified the PPS's qp value, now offset this by applying | ||
71 | // the negative offset to the slices. | ||
72 | 516 | slice->slice_qp_delta += pps->pic_init_qp_minus26 | |
73 | - (NEW_GLOBAL_PIC_INIT_QP - 26); | ||
74 | |||
75 | 516 | return 0; | |
76 | } | ||
77 | |||
78 | 431 | static int h264_redundant_pps_update_fragment(AVBSFContext *bsf, | |
79 | AVPacket *pkt, | ||
80 | CodedBitstreamFragment *au) | ||
81 | { | ||
82 | 431 | H264RedundantPPSContext *ctx = bsf->priv_data; | |
83 | int err, i; | ||
84 | |||
85 |
2/2✓ Branch 0 taken 866 times.
✓ Branch 1 taken 431 times.
|
1297 | for (i = 0; i < au->nb_units; i++) { |
86 | 866 | CodedBitstreamUnit *nal = &au->units[i]; | |
87 | |||
88 |
2/2✓ Branch 0 taken 307 times.
✓ Branch 1 taken 559 times.
|
866 | if (nal->type == H264_NAL_PPS) { |
89 | 307 | err = h264_redundant_pps_fixup_pps(ctx, nal); | |
90 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 307 times.
|
307 | if (err < 0) |
91 | ✗ | return err; | |
92 | } | ||
93 |
2/2✓ Branch 0 taken 371 times.
✓ Branch 1 taken 495 times.
|
866 | if (nal->type == H264_NAL_SLICE || |
94 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 350 times.
|
371 | nal->type == H264_NAL_IDR_SLICE) { |
95 | 516 | H264RawSlice *slice = nal->content; | |
96 | 516 | h264_redundant_pps_fixup_slice(ctx, &slice->header); | |
97 | } | ||
98 | } | ||
99 | |||
100 | 431 | return 0; | |
101 | } | ||
102 | |||
103 | static const CBSBSFType h264_redundant_pps_type = { | ||
104 | .codec_id = AV_CODEC_ID_H264, | ||
105 | .fragment_name = "access unit", | ||
106 | .unit_name = "NAL unit", | ||
107 | .update_fragment = &h264_redundant_pps_update_fragment, | ||
108 | }; | ||
109 | |||
110 | 4 | static int h264_redundant_pps_init(AVBSFContext *bsf) | |
111 | { | ||
112 | 4 | return ff_cbs_bsf_generic_init(bsf, &h264_redundant_pps_type); | |
113 | } | ||
114 | |||
115 | static const enum AVCodecID h264_redundant_pps_codec_ids[] = { | ||
116 | AV_CODEC_ID_H264, AV_CODEC_ID_NONE, | ||
117 | }; | ||
118 | |||
119 | const FFBitStreamFilter ff_h264_redundant_pps_bsf = { | ||
120 | .p.name = "h264_redundant_pps", | ||
121 | .p.codec_ids = h264_redundant_pps_codec_ids, | ||
122 | .priv_data_size = sizeof(H264RedundantPPSContext), | ||
123 | .init = &h264_redundant_pps_init, | ||
124 | .close = &ff_cbs_bsf_generic_close, | ||
125 | .filter = &ff_cbs_bsf_generic_filter, | ||
126 | }; | ||
127 |