Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * H.266 / VVC parser | ||
3 | * | ||
4 | * Copyright (C) 2021 Nuo Mi <nuomi2021@gmail.com> | ||
5 | * | ||
6 | * This file is part of FFmpeg. | ||
7 | * | ||
8 | * FFmpeg is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public | ||
10 | * License as published by the Free Software Foundation; either | ||
11 | * version 2.1 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * FFmpeg is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with FFmpeg; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include "libavutil/mem.h" | ||
24 | #include "cbs.h" | ||
25 | #include "cbs_h266.h" | ||
26 | #include "parser.h" | ||
27 | |||
28 | #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes | ||
29 | #define IS_IDR(nut) (nut == VVC_IDR_W_RADL || nut == VVC_IDR_N_LP) | ||
30 | #define IS_H266_SLICE(nut) (nut <= VVC_RASL_NUT || (nut >= VVC_IDR_W_RADL && nut <= VVC_GDR_NUT)) | ||
31 | |||
32 | typedef struct PuInfo { | ||
33 | const H266RawPPS *pps; | ||
34 | const H266RawSPS *sps; | ||
35 | const H266RawPictureHeader *ph; | ||
36 | const H266RawSlice *slice; | ||
37 | int pic_type; | ||
38 | } PuInfo; | ||
39 | |||
40 | typedef struct AuDetector { | ||
41 | uint8_t prev_layer_id; | ||
42 | int prev_tid0_poc; | ||
43 | int prev_poc; | ||
44 | } AuDetector; | ||
45 | |||
46 | typedef struct VVCParserContext { | ||
47 | ParseContext pc; | ||
48 | CodedBitstreamContext *cbc; | ||
49 | |||
50 | CodedBitstreamFragment picture_unit; | ||
51 | |||
52 | AVPacket au; | ||
53 | AVPacket last_au; | ||
54 | |||
55 | AuDetector au_detector; | ||
56 | |||
57 | int parsed_extradata; | ||
58 | } VVCParserContext; | ||
59 | |||
60 | static const enum AVPixelFormat pix_fmts_8bit[] = { | ||
61 | AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P, | ||
62 | AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P | ||
63 | }; | ||
64 | |||
65 | static const enum AVPixelFormat pix_fmts_10bit[] = { | ||
66 | AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P10, | ||
67 | AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10 | ||
68 | }; | ||
69 | |||
70 | 2951 | static int get_format(const H266RawSPS *sps) | |
71 | { | ||
72 |
2/3✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2947 times.
✗ Branch 2 not taken.
|
2951 | switch (sps->sps_bitdepth_minus8) { |
73 | 4 | case 0: | |
74 | 4 | return pix_fmts_8bit[sps->sps_chroma_format_idc]; | |
75 | 2947 | case 2: | |
76 | 2947 | return pix_fmts_10bit[sps->sps_chroma_format_idc]; | |
77 | } | ||
78 | ✗ | return AV_PIX_FMT_NONE; | |
79 | } | ||
80 | |||
81 | /** | ||
82 | * Find the end of the current frame in the bitstream. | ||
83 | * @return the position of the first byte of the next frame, or END_NOT_FOUND | ||
84 | */ | ||
85 | 9966 | static int find_frame_end(AVCodecParserContext *s, const uint8_t *buf, | |
86 | int buf_size) | ||
87 | { | ||
88 | 9966 | VVCParserContext *ctx = s->priv_data; | |
89 | 9966 | ParseContext *pc = &ctx->pc; | |
90 | int i; | ||
91 | |||
92 |
2/2✓ Branch 0 taken 7101415 times.
✓ Branch 1 taken 7040 times.
|
7108455 | for (i = 0; i < buf_size; i++) { |
93 | int nut, code_len; | ||
94 | |||
95 | 7101415 | pc->state64 = (pc->state64 << 8) | buf[i]; | |
96 | |||
97 |
2/2✓ Branch 0 taken 7089881 times.
✓ Branch 1 taken 11534 times.
|
7101415 | if (((pc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE) |
98 | 7089881 | continue; | |
99 | |||
100 |
2/2✓ Branch 0 taken 6383 times.
✓ Branch 1 taken 5151 times.
|
11534 | code_len = ((pc->state64 >> 3 * 8) & 0xFFFFFFFF) == 0x01 ? 4 : 3; |
101 | |||
102 | 11534 | nut = (pc->state64 >> (8 + 3)) & 0x1F; | |
103 | // 7.4.2.4.3 and 7.4.2.4.4 | ||
104 |
5/6✓ Branch 0 taken 5252 times.
✓ Branch 1 taken 6282 times.
✓ Branch 2 taken 1971 times.
✓ Branch 3 taken 3281 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1971 times.
|
11534 | if ((nut >= VVC_OPI_NUT && nut <= VVC_PREFIX_APS_NUT && |
105 |
2/2✓ Branch 0 taken 9521 times.
✓ Branch 1 taken 42 times.
|
9563 | nut != VVC_PH_NUT) || nut == VVC_AUD_NUT |
106 |
4/4✓ Branch 0 taken 124 times.
✓ Branch 1 taken 9397 times.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 8 times.
|
9521 | || (nut == VVC_PREFIX_SEI_NUT && !pc->frame_start_found) |
107 |
2/4✓ Branch 0 taken 9513 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9513 times.
✗ Branch 3 not taken.
|
9513 | || nut == VVC_RSV_NVCL_26 || nut == VVC_UNSPEC_28 |
108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9513 times.
|
9513 | || nut == VVC_UNSPEC_29) { |
109 |
2/2✓ Branch 0 taken 705 times.
✓ Branch 1 taken 1316 times.
|
2021 | if (pc->frame_start_found) { |
110 | 705 | pc->frame_start_found = 0; | |
111 | 705 | return i - (code_len + 2); | |
112 | } | ||
113 |
7/8✓ Branch 0 taken 9371 times.
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 3674 times.
✓ Branch 3 taken 5697 times.
✓ Branch 4 taken 3674 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 585 times.
✓ Branch 7 taken 3089 times.
|
9513 | } else if (nut == VVC_PH_NUT || IS_H266_SLICE(nut)) { |
114 | 6424 | int sh_picture_header_in_slice_header_flag = buf[i] >> 7; | |
115 | |||
116 |
4/4✓ Branch 0 taken 6282 times.
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 5056 times.
✓ Branch 3 taken 1226 times.
|
6424 | if (nut == VVC_PH_NUT || sh_picture_header_in_slice_header_flag) { |
117 |
2/2✓ Branch 0 taken 2977 times.
✓ Branch 1 taken 2221 times.
|
5198 | if (!pc->frame_start_found) { |
118 | 2977 | pc->frame_start_found = 1; | |
119 | } else { // First slice of next frame found | ||
120 | 2221 | pc->frame_start_found = 0; | |
121 | 2221 | return i - (code_len + 2); | |
122 | } | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | 7040 | return END_NOT_FOUND; | |
127 | } | ||
128 | |||
129 | 2977 | static int get_pict_type(const CodedBitstreamFragment *pu) | |
130 | { | ||
131 | 2977 | int has_p = 0; | |
132 |
2/2✓ Branch 0 taken 6033 times.
✓ Branch 1 taken 1417 times.
|
7450 | for (int i = 0; i < pu->nb_units; i++) { |
133 | 6033 | CodedBitstreamUnit *unit = &pu->units[i]; | |
134 |
5/6✓ Branch 0 taken 3406 times.
✓ Branch 1 taken 2627 times.
✓ Branch 2 taken 3406 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585 times.
✓ Branch 5 taken 2821 times.
|
6033 | if (IS_H266_SLICE(unit->type)) { |
135 | 3212 | const H266RawSlice *slice = unit->content; | |
136 | 3212 | uint8_t type = slice->header.sh_slice_type; | |
137 |
2/2✓ Branch 0 taken 1560 times.
✓ Branch 1 taken 1652 times.
|
3212 | if (type == VVC_SLICE_TYPE_B) { |
138 | 1560 | return AV_PICTURE_TYPE_B; | |
139 | } | ||
140 |
2/2✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 584 times.
|
1652 | if (type == VVC_SLICE_TYPE_P) { |
141 | 1068 | has_p = 1; | |
142 | } | ||
143 | } | ||
144 | } | ||
145 |
2/2✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 349 times.
|
1417 | return has_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; |
146 | } | ||
147 | |||
148 | 2951 | static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx, | |
149 | const PuInfo *pu) | ||
150 | { | ||
151 | static const uint8_t h266_sub_width_c[] = { | ||
152 | 1, 2, 2, 1 | ||
153 | }; | ||
154 | static const uint8_t h266_sub_height_c[] = { | ||
155 | 1, 2, 1, 1 | ||
156 | }; | ||
157 | 2951 | const H266RawSPS *sps = pu->sps; | |
158 | 2951 | const H266RawPPS *pps = pu->pps; | |
159 | 2951 | const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header; | |
160 | |||
161 | 2951 | s->pict_type = pu->pic_type; | |
162 | 2951 | s->format = get_format(sps); | |
163 | 2951 | s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; | |
164 | |||
165 | 8847 | s->key_frame = nal->nal_unit_type == VVC_IDR_W_RADL || | |
166 |
2/2✓ Branch 0 taken 2623 times.
✓ Branch 1 taken 322 times.
|
2945 | nal->nal_unit_type == VVC_IDR_N_LP || |
167 |
4/4✓ Branch 0 taken 2945 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2605 times.
✓ Branch 3 taken 18 times.
|
8501 | nal->nal_unit_type == VVC_CRA_NUT || |
168 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2603 times.
|
2605 | nal->nal_unit_type == VVC_GDR_NUT; |
169 | |||
170 | 2951 | s->coded_width = pps->pps_pic_width_in_luma_samples; | |
171 | 2951 | s->coded_height = pps->pps_pic_height_in_luma_samples; | |
172 | 2951 | s->width = pps->pps_pic_width_in_luma_samples - | |
173 | 2951 | (pps->pps_conf_win_left_offset + pps->pps_conf_win_right_offset) * | |
174 | 2951 | h266_sub_width_c[sps->sps_chroma_format_idc]; | |
175 | 2951 | s->height = pps->pps_pic_height_in_luma_samples - | |
176 | 2951 | (pps->pps_conf_win_top_offset + pps->pps_conf_win_bottom_offset) * | |
177 | 2951 | h266_sub_height_c[sps->sps_chroma_format_idc]; | |
178 | |||
179 | 2951 | avctx->profile = sps->profile_tier_level.general_profile_idc; | |
180 | 2951 | avctx->level = sps->profile_tier_level.general_level_idc; | |
181 | |||
182 | 2951 | avctx->colorspace = (enum AVColorSpace) sps->vui.vui_matrix_coeffs; | |
183 | 2951 | avctx->color_primaries = (enum AVColorPrimaries) sps->vui.vui_colour_primaries; | |
184 | 2951 | avctx->color_trc = (enum AVColorTransferCharacteristic) sps->vui.vui_transfer_characteristics; | |
185 | 2951 | avctx->color_range = | |
186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2951 times.
|
2951 | sps->vui.vui_full_range_flag ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; |
187 | |||
188 | 2951 | avctx->has_b_frames = | |
189 | 2951 | sps->sps_dpb_params.dpb_max_num_reorder_pics[sps->sps_max_sublayers_minus1]; | |
190 | |||
191 |
1/2✓ Branch 0 taken 2951 times.
✗ Branch 1 not taken.
|
2951 | if (sps->sps_ptl_dpb_hrd_params_present_flag && |
192 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 2831 times.
|
2951 | sps->sps_timing_hrd_params_present_flag) { |
193 | 120 | uint32_t num = sps->sps_general_timing_hrd_parameters.num_units_in_tick; | |
194 | 120 | uint32_t den = sps->sps_general_timing_hrd_parameters.time_scale; | |
195 | |||
196 |
2/4✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
|
120 | if (num != 0 && den != 0) |
197 | 120 | av_reduce(&avctx->framerate.den, &avctx->framerate.num, | |
198 | num, den, 1 << 30); | ||
199 | } | ||
200 | 2951 | } | |
201 | |||
202 | //8.3.1 Decoding process for picture order count. | ||
203 | //VTM did not follow the spec, and it's much simpler than spec. | ||
204 | //We follow the VTM. | ||
205 | 2977 | static void get_slice_poc(VVCParserContext *s, int *poc, | |
206 | const H266RawSPS *sps, | ||
207 | const H266RawPictureHeader *ph, | ||
208 | const H266RawSliceHeader *slice, void *log_ctx) | ||
209 | { | ||
210 | int poc_msb, max_poc_lsb, poc_lsb; | ||
211 | 2977 | AuDetector *d = &s->au_detector; | |
212 | 2977 | max_poc_lsb = 1 << (sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4); | |
213 | 2977 | poc_lsb = ph->ph_pic_order_cnt_lsb; | |
214 |
4/4✓ Branch 0 taken 2971 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 2647 times.
|
2977 | if (IS_IDR(slice->nal_unit_header.nal_unit_type)) { |
215 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
|
330 | if (ph->ph_poc_msb_cycle_present_flag) |
216 | ✗ | poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb; | |
217 | else | ||
218 | 330 | poc_msb = 0; | |
219 | } else { | ||
220 | 2647 | int prev_poc = d->prev_tid0_poc; | |
221 | 2647 | int prev_poc_lsb = prev_poc & (max_poc_lsb - 1); | |
222 | 2647 | int prev_poc_msb = prev_poc - prev_poc_lsb; | |
223 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2647 times.
|
2647 | if (ph->ph_poc_msb_cycle_present_flag) { |
224 | ✗ | poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb; | |
225 | } else { | ||
226 |
2/2✓ Branch 0 taken 1041 times.
✓ Branch 1 taken 1606 times.
|
2647 | if ((poc_lsb < prev_poc_lsb) && ((prev_poc_lsb - poc_lsb) >= |
227 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1037 times.
|
1041 | (max_poc_lsb / 2))) |
228 | 4 | poc_msb = prev_poc_msb + (unsigned)max_poc_lsb; | |
229 |
2/2✓ Branch 0 taken 1597 times.
✓ Branch 1 taken 1046 times.
|
2643 | else if ((poc_lsb > prev_poc_lsb) && ((poc_lsb - prev_poc_lsb) > |
230 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1597 times.
|
1597 | (max_poc_lsb / 2))) |
231 | ✗ | poc_msb = prev_poc_msb - (unsigned)max_poc_lsb; | |
232 | else | ||
233 | 2643 | poc_msb = prev_poc_msb; | |
234 | } | ||
235 | } | ||
236 | |||
237 | 2977 | *poc = poc_msb + poc_lsb; | |
238 | 2977 | } | |
239 | |||
240 | 51 | static void au_detector_init(AuDetector *d) | |
241 | { | ||
242 | 51 | d->prev_layer_id = UINT8_MAX; | |
243 | 51 | d->prev_poc = INT_MAX; | |
244 | 51 | d->prev_tid0_poc = INT_MAX; | |
245 | 51 | } | |
246 | |||
247 | 2977 | static int is_au_start(VVCParserContext *s, const PuInfo *pu, void *log_ctx) | |
248 | { | ||
249 | //7.4.2.4.3 | ||
250 | 2977 | AuDetector *d = &s->au_detector; | |
251 | 2977 | const H266RawSPS *sps = pu->sps; | |
252 | 2977 | const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header; | |
253 | 2977 | const H266RawPictureHeader *ph = pu->ph; | |
254 | 2977 | const H266RawSlice *slice = pu->slice; | |
255 | int ret, poc, nut; | ||
256 | |||
257 | 2977 | get_slice_poc(s, &poc, sps, ph, &slice->header, log_ctx); | |
258 | |||
259 |
3/4✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2951 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
|
2977 | ret = (nal->nuh_layer_id <= d->prev_layer_id) || (poc != d->prev_poc); |
260 | |||
261 | 2977 | nut = nal->nal_unit_type; | |
262 | 2977 | d->prev_layer_id = nal->nuh_layer_id; | |
263 | 2977 | d->prev_poc = poc; | |
264 |
2/2✓ Branch 0 taken 1551 times.
✓ Branch 1 taken 1426 times.
|
2977 | if (nal->nuh_temporal_id_plus1 == 1 && |
265 |
2/4✓ Branch 0 taken 1551 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1551 times.
✗ Branch 3 not taken.
|
1551 | !ph->ph_non_ref_pic_flag && nut != VVC_RADL_NUT |
266 |
1/2✓ Branch 0 taken 1551 times.
✗ Branch 1 not taken.
|
1551 | && nut != VVC_RASL_NUT) { |
267 | 1551 | d->prev_tid0_poc = poc; | |
268 | } | ||
269 | 2977 | return ret; | |
270 | } | ||
271 | |||
272 | 2977 | static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266, | |
273 | const CodedBitstreamFragment *pu, void *logctx) | ||
274 | { | ||
275 | const H266RawNALUnitHeader *nal; | ||
276 | int ret; | ||
277 | |||
278 | 2977 | memset(info, 0, sizeof(*info)); | |
279 |
1/2✓ Branch 0 taken 4379 times.
✗ Branch 1 not taken.
|
4379 | for (int i = 0; i < pu->nb_units; i++) { |
280 | 4379 | nal = pu->units[i].content; | |
281 |
2/2✓ Branch 0 taken 464 times.
✓ Branch 1 taken 3915 times.
|
4379 | if (!nal) |
282 | 464 | continue; | |
283 |
2/2✓ Branch 0 taken 86 times.
✓ Branch 1 taken 3829 times.
|
3915 | if ( nal->nal_unit_type == VVC_PH_NUT ) { |
284 | 86 | const H266RawPH *ph = pu->units[i].content; | |
285 | 86 | info->ph = &ph->ph_picture_header; | |
286 |
5/6✓ Branch 0 taken 1202 times.
✓ Branch 1 taken 2627 times.
✓ Branch 2 taken 1202 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 350 times.
✓ Branch 5 taken 852 times.
|
3829 | } else if (IS_H266_SLICE(nal->nal_unit_type)) { |
287 | 2977 | info->slice = pu->units[i].content; | |
288 |
2/2✓ Branch 0 taken 2891 times.
✓ Branch 1 taken 86 times.
|
2977 | if (info->slice->header.sh_picture_header_in_slice_header_flag) |
289 | 2891 | info->ph = &info->slice->header.sh_picture_header; | |
290 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2977 times.
|
2977 | if (!info->ph) { |
291 | ✗ | av_log(logctx, AV_LOG_ERROR, | |
292 | "can't find picture header in picture unit.\n"); | ||
293 | ✗ | ret = AVERROR_INVALIDDATA; | |
294 | ✗ | goto error; | |
295 | } | ||
296 | 2977 | break; | |
297 | } | ||
298 | } | ||
299 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2977 times.
|
2977 | if (!info->slice) { |
300 | ✗ | av_log(logctx, AV_LOG_ERROR, "can't find slice in picture unit.\n"); | |
301 | ✗ | ret = AVERROR_INVALIDDATA; | |
302 | ✗ | goto error; | |
303 | } | ||
304 | 2977 | info->pps = h266->pps[info->ph->ph_pic_parameter_set_id]; | |
305 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2977 times.
|
2977 | if (!info->pps) { |
306 | ✗ | av_log(logctx, AV_LOG_ERROR, "PPS id %d is not avaliable.\n", | |
307 | ✗ | info->ph->ph_pic_parameter_set_id); | |
308 | ✗ | ret = AVERROR_INVALIDDATA; | |
309 | ✗ | goto error; | |
310 | } | ||
311 | 2977 | info->sps = h266->sps[info->pps->pps_seq_parameter_set_id]; | |
312 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2977 times.
|
2977 | if (!info->sps) { |
313 | ✗ | av_log(logctx, AV_LOG_ERROR, "SPS id %d is not avaliable.\n", | |
314 | ✗ | info->pps->pps_seq_parameter_set_id); | |
315 | ✗ | ret = AVERROR_INVALIDDATA; | |
316 | ✗ | goto error; | |
317 | } | ||
318 | 2977 | info->pic_type = get_pict_type(pu); | |
319 | 2977 | return 0; | |
320 | ✗ | error: | |
321 | ✗ | memset(info, 0, sizeof(*info)); | |
322 | ✗ | return ret; | |
323 | } | ||
324 | |||
325 | 2977 | static int append_au(AVPacket *pkt, const uint8_t *buf, int buf_size) | |
326 | { | ||
327 | 2977 | int offset = pkt->size; | |
328 | int ret; | ||
329 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2977 times.
|
2977 | if ((ret = av_grow_packet(pkt, buf_size)) < 0) |
330 | ✗ | goto end; | |
331 | 2977 | memcpy(pkt->data + offset, buf, buf_size); | |
332 | 2977 | end: | |
333 | 2977 | return ret; | |
334 | } | ||
335 | |||
336 | /** | ||
337 | * Parse NAL units of found picture and decode some basic information. | ||
338 | * | ||
339 | * @param s parser context. | ||
340 | * @param avctx codec context. | ||
341 | * @param buf buffer with field/frame data. | ||
342 | * @param buf_size size of the buffer. | ||
343 | * @return < 0 for error, == 0 for a complete au, > 0 is not a completed au. | ||
344 | */ | ||
345 | 2979 | static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, | |
346 | int buf_size, AVCodecContext *avctx) | ||
347 | { | ||
348 | 2979 | VVCParserContext *ctx = s->priv_data; | |
349 | 2979 | const CodedBitstreamH266Context *h266 = ctx->cbc->priv_data; | |
350 | |||
351 | 2979 | CodedBitstreamFragment *pu = &ctx->picture_unit; | |
352 | int ret; | ||
353 | PuInfo info; | ||
354 | |||
355 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2977 times.
|
2979 | if (!buf_size) { |
356 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (ctx->au.size) { |
357 | 2 | av_packet_move_ref(&ctx->last_au, &ctx->au); | |
358 | 2 | return 0; | |
359 | } | ||
360 | ✗ | return 1; | |
361 | } | ||
362 | |||
363 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2977 times.
|
2977 | if ((ret = ff_cbs_read(ctx->cbc, pu, buf, buf_size)) < 0) { |
364 | ✗ | av_log(avctx, AV_LOG_ERROR, "Failed to parse picture unit.\n"); | |
365 | ✗ | goto end; | |
366 | } | ||
367 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2977 times.
|
2977 | if ((ret = get_pu_info(&info, h266, pu, avctx)) < 0) |
368 | ✗ | goto end; | |
369 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2977 times.
|
2977 | if (append_au(&ctx->au, buf, buf_size) < 0) { |
370 | ✗ | ret = AVERROR(ENOMEM); | |
371 | ✗ | goto end; | |
372 | } | ||
373 |
2/2✓ Branch 1 taken 2951 times.
✓ Branch 2 taken 26 times.
|
2977 | if (is_au_start(ctx, &info, avctx)) { |
374 | 2951 | set_parser_ctx(s, avctx, &info); | |
375 | 2951 | av_packet_move_ref(&ctx->last_au, &ctx->au); | |
376 | } else { | ||
377 | 26 | ret = 1; //not a completed au | |
378 | } | ||
379 | 2977 | end: | |
380 | 2977 | ff_cbs_fragment_reset(pu); | |
381 | 2977 | return ret; | |
382 | } | ||
383 | |||
384 | /** | ||
385 | * Combine PU to AU | ||
386 | * | ||
387 | * @param s parser context. | ||
388 | * @param avctx codec context. | ||
389 | * @param buf buffer to a PU. | ||
390 | * @param buf_size size of the buffer. | ||
391 | * @return < 0 for error, == 0 a complete au, > 0 not a completed au. | ||
392 | */ | ||
393 | 2979 | static int combine_au(AVCodecParserContext *s, AVCodecContext *avctx, | |
394 | const uint8_t **buf, int *buf_size) | ||
395 | { | ||
396 | 2979 | VVCParserContext *ctx = s->priv_data; | |
397 | int ret; | ||
398 | |||
399 | 2979 | ctx->cbc->log_ctx = avctx; | |
400 | |||
401 | 2979 | av_packet_unref(&ctx->last_au); | |
402 | 2979 | ret = parse_nal_units(s, *buf, *buf_size, avctx); | |
403 |
2/2✓ Branch 0 taken 2953 times.
✓ Branch 1 taken 26 times.
|
2979 | if (ret == 0) { |
404 |
1/2✓ Branch 0 taken 2953 times.
✗ Branch 1 not taken.
|
2953 | if (ctx->last_au.size) { |
405 | 2953 | *buf = ctx->last_au.data; | |
406 | 2953 | *buf_size = ctx->last_au.size; | |
407 | } else { | ||
408 | ✗ | ret = 1; //no output | |
409 | } | ||
410 | } | ||
411 | 2979 | ctx->cbc->log_ctx = NULL; | |
412 | 2979 | return ret; | |
413 | } | ||
414 | |||
415 | 9966 | static int vvc_parser_parse(AVCodecParserContext *s, AVCodecContext *avctx, | |
416 | const uint8_t **poutbuf, int *poutbuf_size, | ||
417 | const uint8_t *buf, int buf_size) | ||
418 | { | ||
419 | int next, ret; | ||
420 | 9966 | VVCParserContext *ctx = s->priv_data; | |
421 | 9966 | ParseContext *pc = &ctx->pc; | |
422 | 9966 | CodedBitstreamFragment *pu = &ctx->picture_unit; | |
423 | |||
424 | 9966 | int is_dummy_buf = !buf_size; | |
425 | 9966 | int flush = !buf_size; | |
426 | 9966 | const uint8_t *dummy_buf = buf; | |
427 | |||
428 | 9966 | *poutbuf = NULL; | |
429 | 9966 | *poutbuf_size = 0; | |
430 | |||
431 |
4/4✓ Branch 0 taken 7800 times.
✓ Branch 1 taken 2166 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 7749 times.
|
9966 | if (avctx->extradata_size && !ctx->parsed_extradata) { |
432 | 51 | ctx->parsed_extradata = 1; | |
433 | |||
434 | 51 | ret = ff_cbs_read_extradata_from_codec(ctx->cbc, pu, avctx); | |
435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
|
51 | if (ret < 0) |
436 | ✗ | av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata.\n"); | |
437 | |||
438 | 51 | ff_cbs_fragment_reset(pu); | |
439 | } | ||
440 | |||
441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9966 times.
|
9966 | if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { |
442 | ✗ | next = buf_size; | |
443 | } else { | ||
444 | 9966 | next = find_frame_end(s, buf, buf_size); | |
445 |
2/2✓ Branch 1 taken 6938 times.
✓ Branch 2 taken 3028 times.
|
9966 | if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) |
446 | 6938 | return buf_size; | |
447 | } | ||
448 | |||
449 | 3028 | is_dummy_buf &= (dummy_buf == buf); | |
450 | |||
451 |
2/2✓ Branch 0 taken 2977 times.
✓ Branch 1 taken 51 times.
|
3028 | if (!is_dummy_buf) { |
452 | 2977 | ret = combine_au(s, avctx, &buf, &buf_size); | |
453 |
4/4✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2951 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 24 times.
|
2977 | if (ret > 0 && flush) { |
454 | 2 | buf_size = 0; | |
455 | 2 | ret = combine_au(s, avctx, &buf, &buf_size); | |
456 | } | ||
457 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2953 times.
|
2977 | if (ret != 0) |
458 | 24 | return next; | |
459 | } | ||
460 | |||
461 | 3004 | *poutbuf = buf; | |
462 | 3004 | *poutbuf_size = buf_size; | |
463 | |||
464 | 3004 | return next; | |
465 | } | ||
466 | |||
467 | static const CodedBitstreamUnitType decompose_unit_types[] = { | ||
468 | VVC_TRAIL_NUT, | ||
469 | VVC_STSA_NUT, | ||
470 | VVC_RADL_NUT, | ||
471 | VVC_RASL_NUT, | ||
472 | VVC_IDR_W_RADL, | ||
473 | VVC_IDR_N_LP, | ||
474 | VVC_CRA_NUT, | ||
475 | VVC_GDR_NUT, | ||
476 | VVC_VPS_NUT, | ||
477 | VVC_SPS_NUT, | ||
478 | VVC_PPS_NUT, | ||
479 | VVC_PH_NUT, | ||
480 | VVC_AUD_NUT, | ||
481 | }; | ||
482 | |||
483 | 51 | static av_cold int vvc_parser_init(AVCodecParserContext *s) | |
484 | { | ||
485 | 51 | VVCParserContext *ctx = s->priv_data; | |
486 | int ret; | ||
487 | |||
488 | 51 | ret = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VVC, NULL); | |
489 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
|
51 | if (ret < 0) |
490 | ✗ | return ret; | |
491 | 51 | au_detector_init(&ctx->au_detector); | |
492 | |||
493 | 51 | ctx->cbc->decompose_unit_types = decompose_unit_types; | |
494 | 51 | ctx->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types); | |
495 | |||
496 | 51 | return ret; | |
497 | } | ||
498 | |||
499 | 51 | static av_cold void vvc_parser_close(AVCodecParserContext *s) | |
500 | { | ||
501 | 51 | VVCParserContext *ctx = s->priv_data; | |
502 | |||
503 | 51 | av_packet_unref(&ctx->au); | |
504 | 51 | av_packet_unref(&ctx->last_au); | |
505 | 51 | ff_cbs_fragment_free(&ctx->picture_unit); | |
506 | |||
507 | 51 | ff_cbs_close(&ctx->cbc); | |
508 | 51 | av_freep(&ctx->pc.buffer); | |
509 | 51 | } | |
510 | |||
511 | const AVCodecParser ff_vvc_parser = { | ||
512 | .codec_ids = { AV_CODEC_ID_VVC }, | ||
513 | .priv_data_size = sizeof(VVCParserContext), | ||
514 | .parser_init = vvc_parser_init, | ||
515 | .parser_close = vvc_parser_close, | ||
516 | .parser_parse = vvc_parser_parse, | ||
517 | }; | ||
518 |