Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2019 James Almer <jamrial@gmail.com> | ||
3 | * | ||
4 | * This file is part of FFmpeg. | ||
5 | * | ||
6 | * FFmpeg is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * FFmpeg is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | #include "get_bits.h" | ||
21 | #include "bsf.h" | ||
22 | #include "bsf_internal.h" | ||
23 | |||
24 | #include "evc.h" | ||
25 | #include "evc_parse.h" | ||
26 | #include "evc_ps.h" | ||
27 | |||
28 | // Access unit data | ||
29 | typedef struct AccessUnitBuffer { | ||
30 | uint8_t *data; // the data buffer | ||
31 | size_t data_size; // size of data in bytes | ||
32 | unsigned capacity; // buffer capacity | ||
33 | } AccessUnitBuffer; | ||
34 | |||
35 | typedef struct EVCFMergeContext { | ||
36 | AVPacket *in, *buffer_pkt; | ||
37 | EVCParamSets ps; | ||
38 | EVCParserPoc poc; | ||
39 | AccessUnitBuffer au_buffer; | ||
40 | } EVCFMergeContext; | ||
41 | |||
42 | 300 | static int end_of_access_unit_found(const EVCParamSets *ps, const EVCParserSliceHeader *sh, | |
43 | const EVCParserPoc *poc, enum EVCNALUnitType nalu_type) | ||
44 | { | ||
45 | 300 | EVCParserPPS *pps = ps->pps[sh->slice_pic_parameter_set_id]; | |
46 | 300 | EVCParserSPS *sps = ps->sps[pps->pps_seq_parameter_set_id]; | |
47 | |||
48 |
2/4✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 300 times.
|
300 | av_assert0(sps && pps); |
49 | |||
50 |
1/2✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
|
300 | if (sps->profile_idc == 0) { // BASELINE profile |
51 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
300 | if (nalu_type == EVC_NOIDR_NUT || nalu_type == EVC_IDR_NUT) |
52 | 300 | return 1; | |
53 | } else { // MAIN profile | ||
54 | ✗ | if (nalu_type == EVC_NOIDR_NUT) { | |
55 | ✗ | if (poc->PicOrderCntVal != poc->prevPicOrderCntVal) | |
56 | ✗ | return 1; | |
57 | ✗ | } else if (nalu_type == EVC_IDR_NUT) | |
58 | ✗ | return 1; | |
59 | } | ||
60 | ✗ | return 0; | |
61 | } | ||
62 | |||
63 | ✗ | static void evc_frame_merge_flush(AVBSFContext *bsf) | |
64 | { | ||
65 | ✗ | EVCFMergeContext *ctx = bsf->priv_data; | |
66 | |||
67 | ✗ | ff_evc_ps_free(&ctx->ps); | |
68 | ✗ | av_packet_unref(ctx->in); | |
69 | ✗ | av_packet_unref(ctx->buffer_pkt); | |
70 | ✗ | ctx->au_buffer.data_size = 0; | |
71 | ✗ | } | |
72 | |||
73 | 303 | static int parse_nal_unit(AVBSFContext *bsf, const uint8_t *buf, int buf_size) | |
74 | { | ||
75 | 303 | EVCFMergeContext *ctx = bsf->priv_data; | |
76 | GetBitContext gb; | ||
77 | enum EVCNALUnitType nalu_type; | ||
78 | int tid, err; | ||
79 | |||
80 | 303 | err = init_get_bits8(&gb, buf, buf_size); | |
81 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (err < 0) |
82 | ✗ | return err; | |
83 | |||
84 | // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes) | ||
85 | // @see enum EVCNALUnitType in evc.h | ||
86 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 303 times.
|
303 | if (get_bits1(&gb)) {// forbidden_zero_bit |
87 | ✗ | av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit header\n"); | |
88 | ✗ | return AVERROR_INVALIDDATA; | |
89 | } | ||
90 | |||
91 | 303 | nalu_type = get_bits(&gb, 6) - 1; | |
92 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { |
93 | ✗ | av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); | |
94 | ✗ | return AVERROR_INVALIDDATA; | |
95 | } | ||
96 | |||
97 | 303 | tid = get_bits(&gb, 3); | |
98 | 303 | skip_bits(&gb, 5); // nuh_reserved_zero_5bits | |
99 | 303 | skip_bits1(&gb); // nuh_extension_flag | |
100 | |||
101 |
4/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 300 times.
✓ Branch 3 taken 1 times.
|
303 | switch (nalu_type) { |
102 | 1 | case EVC_SPS_NUT: | |
103 | 1 | err = ff_evc_parse_sps(&gb, &ctx->ps); | |
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) { |
105 | ✗ | av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n"); | |
106 | ✗ | return err; | |
107 | } | ||
108 | 1 | break; | |
109 | 1 | case EVC_PPS_NUT: | |
110 | 1 | err = ff_evc_parse_pps(&gb, &ctx->ps); | |
111 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) { |
112 | ✗ | av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n"); | |
113 | ✗ | return err; | |
114 | } | ||
115 | 1 | break; | |
116 | 300 | case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture | |
117 | case EVC_NOIDR_NUT: { | ||
118 | EVCParserSliceHeader sh; | ||
119 | |||
120 | 300 | err = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type); | |
121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | if (err < 0) { |
122 | ✗ | av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n"); | |
123 | ✗ | return err; | |
124 | } | ||
125 | |||
126 | // POC (picture order count of the current picture) derivation | ||
127 | // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count | ||
128 | 300 | err = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid); | |
129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | if (err < 0) |
130 | ✗ | return err; | |
131 | |||
132 | 300 | return end_of_access_unit_found(&ctx->ps, &sh, &ctx->poc, nalu_type); | |
133 | |||
134 | break; | ||
135 | } | ||
136 | 1 | case EVC_SEI_NUT: // Supplemental Enhancement Information | |
137 | case EVC_APS_NUT: // Adaptation parameter set | ||
138 | case EVC_FD_NUT: // Filler data | ||
139 | default: | ||
140 | 1 | break; | |
141 | } | ||
142 | |||
143 | 3 | return 0; | |
144 | } | ||
145 | |||
146 | 303 | static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) | |
147 | { | ||
148 | 303 | EVCFMergeContext *ctx = bsf->priv_data; | |
149 | 303 | AVPacket *in = ctx->in, *buffer_pkt = ctx->buffer_pkt; | |
150 | size_t data_size; | ||
151 | 303 | int au_end_found = 0, err; | |
152 | |||
153 |
2/2✓ Branch 0 taken 306 times.
✓ Branch 1 taken 300 times.
|
606 | while (!au_end_found) { |
154 | uint8_t *buffer; | ||
155 | uint32_t nalu_size; | ||
156 | |||
157 |
1/2✓ Branch 0 taken 306 times.
✗ Branch 1 not taken.
|
306 | if (!in->size) { |
158 | 306 | av_packet_unref(in); | |
159 | 306 | err = ff_bsf_get_packet_ref(bsf, in); | |
160 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 303 times.
|
306 | if (err < 0) { |
161 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | if (err == AVERROR_EOF && ctx->au_buffer.data_size > 0) |
162 | ✗ | break; | |
163 | 3 | return err; | |
164 | } | ||
165 | /* Buffer packets with timestamps (there should be at most one per AU) | ||
166 | * or any packet if buffer_pkt is empty. The latter is needed to | ||
167 | * passthrough positions in case there are no timestamps like with | ||
168 | * the raw EVC demuxer. */ | ||
169 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 300 times.
|
303 | if (!buffer_pkt->data || |
170 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | in->pts != AV_NOPTS_VALUE && buffer_pkt->pts == AV_NOPTS_VALUE) { |
171 | 300 | err = av_packet_ref(buffer_pkt, in); | |
172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | if (err < 0) |
173 | ✗ | goto end; | |
174 | } | ||
175 | } | ||
176 | |||
177 | // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length) | ||
178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (in->size < EVC_NALU_LENGTH_PREFIX_SIZE) |
179 | ✗ | return AVERROR_INVALIDDATA; | |
180 | |||
181 | 303 | nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf); | |
182 |
2/4✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 303 times.
|
303 | if (!nalu_size || nalu_size > INT_MAX) { |
183 | ✗ | av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%u)\n", nalu_size); | |
184 | ✗ | err = AVERROR_INVALIDDATA; | |
185 | ✗ | goto end; | |
186 | } | ||
187 | |||
188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (in->size < nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE) { |
189 | ✗ | err = AVERROR_INVALIDDATA; | |
190 | ✗ | goto end; | |
191 | } | ||
192 | |||
193 | 303 | err = parse_nal_unit(bsf, in->data + EVC_NALU_LENGTH_PREFIX_SIZE, nalu_size); | |
194 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (err < 0) { |
195 | ✗ | av_log(bsf, AV_LOG_ERROR, "Parsing of NAL unit failed\n"); | |
196 | ✗ | goto end; | |
197 | } | ||
198 | 303 | au_end_found = err; | |
199 | |||
200 | 303 | nalu_size += EVC_NALU_LENGTH_PREFIX_SIZE; | |
201 | |||
202 | 303 | data_size = ctx->au_buffer.data_size + nalu_size; | |
203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (data_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { |
204 | ✗ | av_log(bsf, AV_LOG_ERROR, "Assembled packet is too big\n"); | |
205 | ✗ | err = AVERROR(ERANGE); | |
206 | ✗ | goto end; | |
207 | } | ||
208 | |||
209 | 303 | buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity, | |
210 | data_size); | ||
211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (!buffer) { |
212 | ✗ | av_freep(&ctx->au_buffer.data); | |
213 | ✗ | err = AVERROR_INVALIDDATA; | |
214 | ✗ | goto end; | |
215 | } | ||
216 | |||
217 | 303 | ctx->au_buffer.data = buffer; | |
218 | 303 | memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size); | |
219 | |||
220 | 303 | ctx->au_buffer.data_size = data_size; | |
221 | |||
222 | 303 | in->data += nalu_size; | |
223 | 303 | in->size -= nalu_size; | |
224 | } | ||
225 | |||
226 | 300 | av_packet_unref(in); | |
227 | 300 | data_size = ctx->au_buffer.data_size; | |
228 | |||
229 | 300 | ctx->au_buffer.data_size = 0; | |
230 | // drop the data in buffer_pkt, if any, but keep the props | ||
231 | 300 | av_buffer_unref(&buffer_pkt->buf); | |
232 | 300 | err = av_buffer_realloc(&buffer_pkt->buf, data_size + AV_INPUT_BUFFER_PADDING_SIZE); | |
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | if (err < 0) |
234 | ✗ | goto end; | |
235 | |||
236 | 300 | buffer_pkt->data = buffer_pkt->buf->data; | |
237 | 300 | buffer_pkt->size = data_size; | |
238 | 300 | av_packet_move_ref(out, buffer_pkt); | |
239 | 300 | memcpy(out->data, ctx->au_buffer.data, data_size); | |
240 | 300 | memset(out->data + data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
241 | |||
242 | 300 | err = 0; | |
243 | 300 | end: | |
244 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | if (err < 0) { |
245 | ✗ | av_packet_unref(in); | |
246 | ✗ | av_packet_unref(buffer_pkt); | |
247 | ✗ | ctx->au_buffer.data_size = 0; | |
248 | } | ||
249 | 300 | return err; | |
250 | } | ||
251 | |||
252 | 1 | static int evc_frame_merge_init(AVBSFContext *bsf) | |
253 | { | ||
254 | 1 | EVCFMergeContext *ctx = bsf->priv_data; | |
255 | |||
256 | 1 | ctx->in = av_packet_alloc(); | |
257 | 1 | ctx->buffer_pkt = av_packet_alloc(); | |
258 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!ctx->in || !ctx->buffer_pkt) |
259 | ✗ | return AVERROR(ENOMEM); | |
260 | |||
261 | 1 | return 0; | |
262 | } | ||
263 | |||
264 | 1 | static void evc_frame_merge_close(AVBSFContext *bsf) | |
265 | { | ||
266 | 1 | EVCFMergeContext *ctx = bsf->priv_data; | |
267 | |||
268 | 1 | av_packet_free(&ctx->in); | |
269 | 1 | av_packet_free(&ctx->buffer_pkt); | |
270 | 1 | ff_evc_ps_free(&ctx->ps); | |
271 | |||
272 | 1 | ctx->au_buffer.capacity = 0; | |
273 | 1 | av_freep(&ctx->au_buffer.data); | |
274 | 1 | ctx->au_buffer.data_size = 0; | |
275 | 1 | } | |
276 | |||
277 | static const enum AVCodecID evc_frame_merge_codec_ids[] = { | ||
278 | AV_CODEC_ID_EVC, AV_CODEC_ID_NONE, | ||
279 | }; | ||
280 | |||
281 | const FFBitStreamFilter ff_evc_frame_merge_bsf = { | ||
282 | .p.name = "evc_frame_merge", | ||
283 | .p.codec_ids = evc_frame_merge_codec_ids, | ||
284 | .priv_data_size = sizeof(EVCFMergeContext), | ||
285 | .init = evc_frame_merge_init, | ||
286 | .flush = evc_frame_merge_flush, | ||
287 | .close = evc_frame_merge_close, | ||
288 | .filter = evc_frame_merge_filter, | ||
289 | }; | ||
290 |