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