Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Yacine Mathurin Boubacar Aziakou
6 : * Samir Mustapha
7 : * Copyright (c) Telecom ParisTech 2019-2021
8 : * All rights reserved
9 : *
10 : * This file is part of GPAC / HEVC tile split and rewrite filter
11 : *
12 : * GPAC is free software; you can redistribute it and/or modify
13 : * it under the terms of the GNU Lesser General Public License as published by
14 : * the Free Software Foundation; either version 2, or (at your option)
15 : * any later version.
16 : *
17 : * GPAC is distributed in the hope that it will be useful,
18 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : * GNU Lesser General Public License for more details.
21 : *
22 : * You should have received a copy of the GNU Lesser General Public
23 : * License along with this library; see the file COPYING. If not, write to
24 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25 : *
26 : */
27 :
28 : #include <gpac/bitstream.h>
29 : #include <gpac/filters.h>
30 : #include <gpac/avparse.h>
31 : #include <gpac/constants.h>
32 : #include <gpac/internal/media_dev.h>
33 :
34 : #if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS)
35 :
36 : typedef struct
37 : {
38 : GF_FilterPid *opid;
39 : u32 width, height, orig_x, orig_y;
40 : GF_FilterPacket *cur_pck;
41 : } HEVCTilePid;
42 :
43 : typedef struct
44 : {
45 : GF_FilterPid *ipid;
46 : GF_List *outputs;
47 : u32 num_tiles, got_p;
48 : HEVCState hevc_state;
49 : u32 hevc_nalu_size_length, cfg_crc, nb_pck;
50 :
51 : //static read/write objects to avoid allocs
52 : GF_BitStream *bs_au_in;
53 : GF_BitStream *bs_nal_in;
54 : GF_BitStream *bs_nal_out;
55 :
56 : //buffer where we will store the rewritten slice with EPB
57 : u8 *buffer_nal;
58 : u32 buffer_nal_alloc;
59 :
60 : //buffer where we will store the rewritten slice or nal (sps, pps) without EPB
61 : u8 *output_no_epb;
62 : u32 output_no_epb_alloc;
63 :
64 : //buffer where we will store the input slice without EPB - we cannot use EPB removal functions from bitstream object since
65 : //we don't have gf_bs_read_data support in this mode
66 : u8 *input_no_epb;
67 : u32 input_no_epb_alloc;
68 : } GF_HEVCSplitCtx;
69 :
70 : //get tiles coordinates in as index in grid
71 13500 : static u32 hevcsplit_get_slice_tile_index(HEVCState *hevc)
72 : {
73 : u32 tile_x, tile_y;
74 :
75 13500 : HEVCSliceInfo si = hevc->s_info;
76 : u32 i, tbX = 0, tbY = 0, slX, slY, PicWidthInCtbsY, PicHeightInCtbsX;
77 :
78 13500 : PicWidthInCtbsY = (si.sps->width + si.sps->max_CU_width - 1) / si.sps->max_CU_width;
79 13500 : PicHeightInCtbsX = (si.sps->height + si.sps->max_CU_height - 1) / si.sps->max_CU_height;
80 :
81 13500 : slY = si.slice_segment_address % PicWidthInCtbsY;
82 13500 : slX = si.slice_segment_address / PicWidthInCtbsY;
83 : tile_x = 0;
84 : tile_y = 0;
85 13500 : if (si.pps->tiles_enabled_flag) {
86 : u32 valX, valY;
87 13500 : if (si.pps->uniform_spacing_flag) {
88 13500 : for (i = 0; i < si.pps->num_tile_rows; i++) {
89 27000 : if (i < si.pps->num_tile_rows - 1)
90 22500 : valX = (i + 1) * PicHeightInCtbsX / si.pps->num_tile_rows - i * PicHeightInCtbsX / si.pps->num_tile_rows;
91 : else
92 4500 : valX = PicHeightInCtbsX - tbX;
93 :
94 27000 : if (slX < tbX + valX) {
95 : tile_x = i;
96 : break;
97 : }
98 :
99 : tbX += valX;
100 : }
101 27000 : for (i = 0; i < si.pps->num_tile_columns; i++) {
102 27000 : if (i < si.pps->num_tile_columns - 1)
103 22500 : valY = (i + 1) * PicWidthInCtbsY / si.pps->num_tile_columns - i * PicWidthInCtbsY / si.pps->num_tile_columns;
104 : else
105 4500 : valY = PicWidthInCtbsY - tbY;
106 27000 : if (slY < tbY + valY) {
107 : tile_y = i;
108 : break;
109 : }
110 :
111 : tbY += valY;
112 : }
113 : } else {
114 0 : for (i = 0; i < si.pps->num_tile_rows; i++) {
115 0 : if (i < si.pps->num_tile_rows - 1)
116 0 : valX = si.pps->row_height[i];
117 : else
118 0 : valX = PicHeightInCtbsX - tbX;
119 0 : if (slX < tbX + valX) {
120 : tile_x = i;
121 : break;
122 : }
123 :
124 : tbX += valX;
125 : }
126 :
127 0 : for (i = 0; i < si.pps->num_tile_columns; i++) {
128 0 : if (i < si.pps->num_tile_columns - 1)
129 0 : valY = si.pps->column_width[i];
130 : else
131 0 : valY = PicWidthInCtbsY - tbY;
132 :
133 0 : if (slY < tbY + valY) {
134 : tile_y = i;
135 : break;
136 : }
137 : tbY += valY;
138 : }
139 : }
140 : }
141 13500 : return tile_x * hevc->s_info.pps->num_tile_columns + tile_y;
142 : }
143 :
144 : //get the width and the height of the tile in pixel
145 18 : static void hevcsplit_get_tile_pixel_coords(HEVCState *hevc, u32 index_row, u32 index_col, u32 pps_id, u32 *width, u32 *height, u32 *tx, u32 *ty)
146 : {
147 : u32 i, sps_id, tbX = 0, tbY = 0, PicWidthInCtbsY, PicHeightInCtbsX, max_CU_width, max_CU_height;
148 :
149 18 : sps_id = hevc->pps[pps_id].sps_id;
150 18 : max_CU_width = hevc->sps[sps_id].max_CU_width;
151 18 : max_CU_height = hevc->sps[sps_id].max_CU_height;
152 18 : PicWidthInCtbsY = (hevc->sps[sps_id].width + max_CU_width - 1) / max_CU_width;
153 18 : PicHeightInCtbsX = (hevc->sps[sps_id].height + max_CU_height - 1) / max_CU_height;
154 :
155 18 : *tx = 0;
156 18 : *ty = 0;
157 :
158 18 : if (!hevc->pps[pps_id].tiles_enabled_flag) {
159 0 : *width = hevc->sps[sps_id].width;
160 0 : *height = hevc->sps[sps_id].height;
161 0 : return;
162 : }
163 :
164 18 : if (hevc->pps[pps_id].uniform_spacing_flag) {
165 18 : if (index_row < hevc->pps[pps_id].num_tile_rows - 1) {
166 18 : for (i = 0; i < index_row; i++)
167 6 : tbX += ((i + 1) * PicHeightInCtbsX / hevc->pps[pps_id].num_tile_rows - i * PicHeightInCtbsX / hevc->pps[pps_id].num_tile_rows);
168 :
169 12 : *height = (index_row + 1) * PicHeightInCtbsX / hevc->pps[pps_id].num_tile_rows - index_row * PicHeightInCtbsX / hevc->pps[pps_id].num_tile_rows;
170 : } else {
171 18 : for (i = 0; i < hevc->pps[pps_id].num_tile_rows - 1; i++)
172 12 : tbX += ((i + 1) * PicHeightInCtbsX / hevc->pps[pps_id].num_tile_rows - i * PicHeightInCtbsX / hevc->pps[pps_id].num_tile_rows);
173 6 : *height = PicHeightInCtbsX - tbX;
174 : }
175 :
176 18 : if (index_col < hevc->pps[pps_id].num_tile_columns - 1) {
177 18 : for (i = 0; i < index_col; i++)
178 6 : tbY += ((i + 1) * PicWidthInCtbsY / hevc->pps[pps_id].num_tile_columns - i * PicWidthInCtbsY / hevc->pps[pps_id].num_tile_columns);
179 12 : *width = (index_col + 1) * PicWidthInCtbsY / hevc->pps[pps_id].num_tile_columns - index_col * PicWidthInCtbsY / hevc->pps[pps_id].num_tile_columns;
180 : } else {
181 18 : for (i = 0; i < hevc->pps[pps_id].num_tile_columns - 1; i++)
182 12 : tbY += ((i + 1) * PicWidthInCtbsY / hevc->pps[pps_id].num_tile_columns - i * PicWidthInCtbsY / hevc->pps[pps_id].num_tile_columns);
183 6 : *width = PicWidthInCtbsY - tbY;
184 : }
185 : } else {
186 0 : if (index_row < hevc->pps[pps_id].num_tile_rows - 1) {
187 :
188 0 : for (i = 0; i < index_row; i++)
189 0 : tbX += hevc->pps[pps_id].row_height[i];
190 :
191 0 : *height = hevc->pps[pps_id].row_height[index_row];
192 : } else {
193 0 : for (i = 0; i < hevc->pps[pps_id].num_tile_rows - 1; i++)
194 0 : tbX += hevc->pps[pps_id].row_height[i];
195 0 : *height = PicHeightInCtbsX - tbX;
196 : }
197 :
198 0 : if (index_col < hevc->pps[pps_id].num_tile_columns - 1) {
199 0 : *width = hevc->pps[pps_id].column_width[index_col];
200 :
201 0 : for (i = 0; i < index_col; i++)
202 0 : tbY += hevc->pps[pps_id].column_width[i];
203 : } else {
204 0 : for (i = 0; i < hevc->pps[pps_id].num_tile_columns - 1; i++)
205 0 : tbY += hevc->pps[pps_id].column_width[i];
206 0 : *width = PicWidthInCtbsY - tbY;
207 : }
208 : }
209 :
210 18 : *width = *width * max_CU_width;
211 18 : *height = *height * max_CU_height;
212 18 : *ty = tbX * max_CU_height;
213 18 : *tx = tbY * max_CU_width;
214 :
215 18 : if (*tx + *width > hevc->sps[sps_id].width)
216 0 : *width = hevc->sps[sps_id].width - *tx;
217 18 : if (*ty + *height > hevc->sps[sps_id].height)
218 6 : *height = hevc->sps[sps_id].height - *ty;
219 : }
220 :
221 : //rewrite the profile and level
222 43 : static void hevc_write_profile_tier_level(GF_BitStream *bs_in, GF_BitStream *bs_out, Bool ProfilePresentFlag, u8 MaxNumSubLayersMinus1)
223 : {
224 : u8 j;
225 : Bool sub_layer_profile_present_flag[8], sub_layer_level_present_flag[8];
226 43 : if (ProfilePresentFlag) {
227 43 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 8), 8);
228 43 : gf_bs_write_long_int(bs_out, gf_bs_read_long_int(bs_in, 32), 32);
229 43 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 4), 4);
230 43 : gf_bs_write_long_int(bs_out, gf_bs_read_long_int(bs_in, 44), 44);
231 : }
232 43 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 8), 8);
233 :
234 43 : for (j = 0; j < MaxNumSubLayersMinus1; j++) {
235 0 : sub_layer_profile_present_flag[j] = gf_bs_read_int(bs_in, 1);
236 0 : gf_bs_write_int(bs_out, sub_layer_profile_present_flag[j], 1);
237 0 : sub_layer_level_present_flag[j] = gf_bs_read_int(bs_in, 1);
238 0 : gf_bs_write_int(bs_out, sub_layer_level_present_flag[j], 1);
239 : }
240 43 : if (MaxNumSubLayersMinus1 > 0)
241 0 : for (j = MaxNumSubLayersMinus1; j < 8; j++)
242 0 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 2), 2);
243 :
244 :
245 0 : for (j = 0; j < MaxNumSubLayersMinus1; j++) {
246 0 : if (sub_layer_profile_present_flag[j]) {
247 0 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 8), 8);
248 0 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 32), 32);
249 0 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 4), 4);
250 0 : gf_bs_write_long_int(bs_out, gf_bs_read_long_int(bs_in, 44), 44);
251 : }
252 0 : if (sub_layer_level_present_flag[j])
253 0 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 8), 8);
254 : }
255 43 : }
256 :
257 : //also used by HEVCmerge, don't use context bitstream objects
258 43 : void hevc_rewrite_sps(char *in_SPS, u32 in_SPS_length, u32 width, u32 height, char **out_SPS, u32 *out_SPS_length)
259 : {
260 : GF_BitStream *bs_in, *bs_out;
261 : u64 length_no_use = 4096;
262 43 : u8 *data_without_emulation_bytes = NULL;
263 43 : u32 data_without_emulation_bytes_size = 0, sps_ext_or_max_sub_layers_minus1;
264 : u8 max_sub_layers_minus1 = 0, layer_id;
265 : Bool conformance_window_flag, multiLayerExtSpsFlag;
266 : u32 chroma_format_idc;
267 :
268 43 : bs_in = gf_bs_new(in_SPS, in_SPS_length, GF_BITSTREAM_READ);
269 43 : gf_bs_enable_emulation_byte_removal(bs_in, GF_TRUE);
270 43 : bs_out = gf_bs_new(NULL, length_no_use, GF_BITSTREAM_WRITE);
271 43 : /*dst_buffer_size =*/ gf_bs_get_size(bs_out);
272 43 : if (!bs_in) goto exit;
273 :
274 : //copy NAL Header
275 43 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 7), 7);
276 43 : layer_id = gf_bs_read_int(bs_in, 6);
277 43 : gf_bs_write_int(bs_out, layer_id, 6);
278 43 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 3), 3);
279 :
280 43 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 4), 4); //copy vps_id
281 :
282 43 : if (layer_id == 0)
283 : {
284 43 : max_sub_layers_minus1 = gf_bs_read_int(bs_in, 3);
285 43 : gf_bs_write_int(bs_out, max_sub_layers_minus1, 3);
286 : }
287 : else
288 : {
289 0 : sps_ext_or_max_sub_layers_minus1 = gf_bs_read_int(bs_in, 3);
290 0 : gf_bs_write_int(bs_out, sps_ext_or_max_sub_layers_minus1, 3);
291 : }
292 43 : multiLayerExtSpsFlag = (layer_id != 0) && (sps_ext_or_max_sub_layers_minus1 == 7);
293 43 : if (!multiLayerExtSpsFlag) {
294 43 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 1), 1);
295 43 : hevc_write_profile_tier_level(bs_in, bs_out, 1, max_sub_layers_minus1);
296 : }
297 :
298 43 : gf_bs_write_ue(bs_out, gf_bs_read_ue(bs_in)); //copy sps_id
299 :
300 43 : if (multiLayerExtSpsFlag) {
301 0 : u8 update_rep_format_flag = gf_bs_read_int(bs_in, 1);
302 0 : gf_bs_write_int(bs_out, update_rep_format_flag, 1);
303 0 : if (update_rep_format_flag) {
304 0 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 8), 8);
305 : }
306 : }
307 : else {
308 43 : chroma_format_idc = gf_bs_read_ue(bs_in);
309 43 : gf_bs_write_ue(bs_out, chroma_format_idc);
310 43 : if (chroma_format_idc == 3)
311 0 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 1), 1); // copy separate_colour_plane_flag
312 43 : /*w =*/ gf_bs_read_ue(bs_in); //skip width bits in input bitstream
313 43 : /*h =*/ gf_bs_read_ue(bs_in); //skip height bits in input bitstream
314 :
315 : //Copy the new width and height in output bitstream
316 43 : gf_bs_write_ue(bs_out, width);
317 43 : gf_bs_write_ue(bs_out, height);
318 :
319 : //Get rid of the bit conformance_window_flag
320 43 : conformance_window_flag = gf_bs_read_int(bs_in, 1);
321 : //put the new conformance flag to zero
322 43 : gf_bs_write_int(bs_out, 0, 1);
323 :
324 : //Skip the bits related to conformance_window_offset
325 43 : if (conformance_window_flag)
326 : {
327 0 : gf_bs_read_ue(bs_in);
328 0 : gf_bs_read_ue(bs_in);
329 0 : gf_bs_read_ue(bs_in);
330 0 : gf_bs_read_ue(bs_in);
331 : }
332 : }
333 :
334 : //copy and write the rest of the bits in the byte
335 254 : while (gf_bs_get_bit_position(bs_in) != 8) {
336 211 : gf_bs_write_int(bs_out, gf_bs_read_int(bs_in, 1), 1);
337 : }
338 :
339 : //copy and write the rest of the bytes
340 668 : while (gf_bs_get_size(bs_in) != gf_bs_get_position(bs_in)) {
341 625 : gf_bs_write_int(bs_out, gf_bs_read_u8(bs_in), 8); //watchout, not aligned in destination bitstream
342 : }
343 :
344 :
345 43 : gf_bs_align(bs_out); //align
346 :
347 43 : gf_free(data_without_emulation_bytes);
348 43 : data_without_emulation_bytes = NULL;
349 43 : data_without_emulation_bytes_size = 0;
350 :
351 43 : gf_bs_get_content(bs_out, &data_without_emulation_bytes, &data_without_emulation_bytes_size);
352 :
353 43 : *out_SPS_length = data_without_emulation_bytes_size + gf_media_nalu_emulation_bytes_add_count(data_without_emulation_bytes, data_without_emulation_bytes_size);
354 43 : *out_SPS = gf_malloc(*out_SPS_length);
355 43 : *out_SPS_length = gf_media_nalu_add_emulation_bytes(data_without_emulation_bytes, *out_SPS, data_without_emulation_bytes_size);
356 :
357 43 : exit:
358 43 : gf_bs_del(bs_in);
359 43 : gf_bs_del(bs_out);
360 43 : gf_free(data_without_emulation_bytes);
361 43 : }
362 :
363 :
364 18 : static void hevcsplit_rewrite_pps_no_grid(GF_HEVCSplitCtx *ctx, char *in_PPS, u32 in_PPS_length, char **out_PPS, u32 *out_PPS_length)
365 : {
366 : u32 i, out_size_no_epb;
367 : u8 cu_qp_delta_enabled_flag, tiles_enabled_flag, loop_filter_across_slices_enabled_flag;
368 :
369 18 : gf_bs_reassign_buffer(ctx->bs_nal_in, in_PPS, in_PPS_length);
370 18 : gf_bs_enable_emulation_byte_removal(ctx->bs_nal_in, GF_TRUE);
371 :
372 :
373 18 : if (!ctx->bs_nal_out) ctx->bs_nal_out = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
374 16 : else gf_bs_reassign_buffer(ctx->bs_nal_out, ctx->output_no_epb, ctx->output_no_epb_alloc);
375 :
376 : //Read and write NAL header bits
377 18 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 16), 16);
378 18 : gf_bs_write_ue(ctx->bs_nal_out, gf_bs_read_ue(ctx->bs_nal_in)); //pps_pic_parameter_set_id
379 18 : gf_bs_write_ue(ctx->bs_nal_out, gf_bs_read_ue(ctx->bs_nal_in)); //pps_seq_parameter_set_id
380 18 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 7), 7); //from dependent_slice_segments_enabled_flag to cabac_init_present_flag
381 18 : gf_bs_write_ue(ctx->bs_nal_out, gf_bs_read_ue(ctx->bs_nal_in)); //num_ref_idx_l0_default_active_minus1
382 18 : gf_bs_write_ue(ctx->bs_nal_out, gf_bs_read_ue(ctx->bs_nal_in)); //num_ref_idx_l1_default_active_minus1
383 18 : gf_bs_write_se(ctx->bs_nal_out, gf_bs_read_se(ctx->bs_nal_in)); //init_qp_minus26
384 18 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 2), 2); //from constrained_intra_pred_flag to transform_skip_enabled_flag
385 18 : cu_qp_delta_enabled_flag = gf_bs_read_int(ctx->bs_nal_in, 1); //cu_qp_delta_enabled_flag
386 18 : gf_bs_write_int(ctx->bs_nal_out, cu_qp_delta_enabled_flag, 1); //
387 18 : if (cu_qp_delta_enabled_flag)
388 0 : gf_bs_write_ue(ctx->bs_nal_out, gf_bs_read_ue(ctx->bs_nal_in)); // diff_cu_qp_delta_depth
389 18 : gf_bs_write_se(ctx->bs_nal_out, gf_bs_read_se(ctx->bs_nal_in)); // pps_cb_qp_offset
390 18 : gf_bs_write_se(ctx->bs_nal_out, gf_bs_read_se(ctx->bs_nal_in)); // pps_cr_qp_offset
391 18 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 4), 4); // from pps_slice_chroma_qp_offsets_present_flag to transquant_bypass_enabled_flag
392 :
393 18 : tiles_enabled_flag = gf_bs_read_int(ctx->bs_nal_in, 1); // tiles_enabled_flag
394 18 : gf_bs_write_int(ctx->bs_nal_out, 0, 1); //discard tile enable in dest
395 :
396 18 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 1), 1); // entropy_coding_sync_enabled_flag
397 :
398 : //read tile info from source
399 18 : if (tiles_enabled_flag) {
400 18 : u32 num_tile_columns_minus1 = gf_bs_read_ue(ctx->bs_nal_in);
401 18 : u32 num_tile_rows_minus1 = gf_bs_read_ue(ctx->bs_nal_in);
402 18 : u8 uniform_spacing_flag = gf_bs_read_int(ctx->bs_nal_in, 1);
403 :
404 18 : if (!uniform_spacing_flag) {
405 0 : for (i = 0; i < num_tile_columns_minus1; i++)
406 0 : gf_bs_read_ue(ctx->bs_nal_in);
407 0 : for (i = 0; i < num_tile_rows_minus1; i++)
408 0 : gf_bs_read_ue(ctx->bs_nal_in);
409 : }
410 18 : gf_bs_read_int(ctx->bs_nal_in, 1);
411 : }
412 :
413 18 : loop_filter_across_slices_enabled_flag = gf_bs_read_int(ctx->bs_nal_in, 1);
414 18 : gf_bs_write_int(ctx->bs_nal_out, loop_filter_across_slices_enabled_flag, 1);
415 :
416 : //copy and write the rest of the bits in the byte
417 72 : while (gf_bs_get_bit_position(ctx->bs_nal_in) != 8) {
418 36 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 1), 1);
419 : }
420 :
421 : //copy and write the rest of the bytes
422 54 : while (gf_bs_get_size(ctx->bs_nal_in) != gf_bs_get_position(ctx->bs_nal_in)) {
423 36 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_u8(ctx->bs_nal_in), 8); //watchout, not aligned in destination bitstream
424 : }
425 :
426 : //align
427 18 : gf_bs_align(ctx->bs_nal_out);
428 :
429 18 : gf_bs_get_content_no_truncate(ctx->bs_nal_out, &ctx->output_no_epb, &out_size_no_epb, &ctx->output_no_epb_alloc);
430 :
431 18 : *out_PPS_length = out_size_no_epb + gf_media_nalu_emulation_bytes_add_count(ctx->output_no_epb, out_size_no_epb);
432 18 : *out_PPS = gf_malloc(*out_PPS_length);
433 18 : gf_media_nalu_add_emulation_bytes(ctx->output_no_epb, *out_PPS, out_size_no_epb);
434 18 : }
435 :
436 : //return the new size slice - slice data is stored in ctx->buffer_nal
437 13500 : static u32 hevcsplit_remove_slice_address(GF_HEVCSplitCtx *ctx, u8 *in_slice, u32 in_slice_length)
438 : {
439 : u32 inslice_size_no_epb, outslice_size_epb;
440 : u64 header_end;
441 : u32 num_entry_point_start;
442 : u32 pps_id;
443 : Bool RapPicFlag = GF_FALSE;
444 : HEVC_PPS *pps;
445 : HEVC_SPS *sps;
446 : u32 al, slice_size, slice_offset_orig, slice_offset_dst;
447 : u32 first_slice_segment_in_pic_flag;
448 : //u32 dependent_slice_segment_flag;
449 : u8 nal_unit_type;
450 : HEVCState *hevc = &ctx->hevc_state;
451 :
452 13500 : if (ctx->input_no_epb_alloc < in_slice_length) {
453 14 : ctx->input_no_epb = gf_realloc(ctx->input_no_epb, in_slice_length);
454 14 : ctx->input_no_epb_alloc = in_slice_length;
455 : }
456 13500 : inslice_size_no_epb = gf_media_nalu_remove_emulation_bytes(in_slice, ctx->input_no_epb, in_slice_length);
457 :
458 13500 : gf_bs_reassign_buffer(ctx->bs_nal_in, ctx->input_no_epb, inslice_size_no_epb);
459 13500 : gf_bs_enable_emulation_byte_removal(ctx->bs_nal_in, GF_FALSE);
460 :
461 13500 : if (!ctx->bs_nal_out) ctx->bs_nal_out = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
462 13500 : else gf_bs_reassign_buffer(ctx->bs_nal_out, ctx->output_no_epb, ctx->output_no_epb_alloc);
463 :
464 :
465 : assert(hevc->s_info.header_size_bits >= 0);
466 : assert(hevc->s_info.entry_point_start_bits >= 0);
467 13500 : header_end = (u64) hevc->s_info.header_size_bits;
468 :
469 13500 : num_entry_point_start = (u32) hevc->s_info.entry_point_start_bits;
470 :
471 : // nal_unit_header
472 13500 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 1), 1);
473 13500 : nal_unit_type = gf_bs_read_int(ctx->bs_nal_in, 6);
474 13500 : gf_bs_write_int(ctx->bs_nal_out, nal_unit_type, 6);
475 13500 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 9), 9);
476 :
477 13500 : first_slice_segment_in_pic_flag = gf_bs_read_int(ctx->bs_nal_in, 1); //first_slice_segment_in_pic_flag
478 13500 : gf_bs_write_int(ctx->bs_nal_out, 1, 1);
479 :
480 13500 : switch (nal_unit_type) {
481 : case GF_HEVC_NALU_SLICE_IDR_W_DLP:
482 : case GF_HEVC_NALU_SLICE_IDR_N_LP:
483 : RapPicFlag = GF_TRUE;
484 : break;
485 : case GF_HEVC_NALU_SLICE_BLA_W_LP:
486 : case GF_HEVC_NALU_SLICE_BLA_W_DLP:
487 : case GF_HEVC_NALU_SLICE_BLA_N_LP:
488 : case GF_HEVC_NALU_SLICE_CRA:
489 : RapPicFlag = GF_TRUE;
490 : break;
491 : }
492 :
493 : if (RapPicFlag) {
494 : //no_output_of_prior_pics_flag
495 540 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 1), 1);
496 : }
497 :
498 13500 : pps_id = gf_bs_read_ue(ctx->bs_nal_in); //pps_id
499 13500 : gf_bs_write_ue(ctx->bs_nal_out, pps_id);
500 :
501 : pps = &hevc->pps[pps_id];
502 13500 : sps = &hevc->sps[pps->sps_id];
503 :
504 : //dependent_slice_segment_flag = 0;
505 13500 : if (!first_slice_segment_in_pic_flag && pps->dependent_slice_segments_enabled_flag) {
506 0 : /*dependent_slice_segment_flag =*/ gf_bs_read_int(ctx->bs_nal_in, 1);
507 : // } else {
508 : // dependent_slice_segment_flag = GF_FALSE;
509 : }
510 :
511 13500 : if (!first_slice_segment_in_pic_flag) {
512 12000 : gf_bs_read_int(ctx->bs_nal_in, sps->bitsSliceSegmentAddress);
513 : }
514 : //else original slice segment address = 0
515 :
516 : //nothing to write for slice address, we remove the address
517 :
518 : //copy over until num_entry_points
519 321300 : while (num_entry_point_start != (gf_bs_get_position(ctx->bs_nal_in) - 1) * 8 + gf_bs_get_bit_position(ctx->bs_nal_in)) {
520 307800 : gf_bs_write_int(ctx->bs_nal_out, gf_bs_read_int(ctx->bs_nal_in, 1), 1);
521 : }
522 :
523 : //no tilin, don't write num_entry_points
524 :
525 : //write slice extension to 0
526 13500 : if (pps->slice_segment_header_extension_present_flag)
527 0 : gf_bs_write_int(ctx->bs_nal_out, 0, 1);
528 :
529 : //we may have unparsed data in the source bitstream (slice header) due to entry points or slice segment extensions
530 : //TODO: we might want to copy over the slice extension header bits
531 27000 : while (header_end != (gf_bs_get_position(ctx->bs_nal_in) - 1) * 8 + gf_bs_get_bit_position(ctx->bs_nal_in))
532 13500 : gf_bs_read_int(ctx->bs_nal_in, 1);
533 :
534 : //read byte_alignment() is bit=1 + x bit=0
535 13500 : al = gf_bs_read_int(ctx->bs_nal_in, 1);
536 13500 : if (al != 1) {
537 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[HEVCTileSplit] source slice header not properly aligned\n"));
538 : }
539 :
540 : //write byte_alignment() is bit=1 + x bit=0
541 13500 : gf_bs_write_int(ctx->bs_nal_out, 1, 1);
542 13500 : gf_bs_align(ctx->bs_nal_out); //align
543 :
544 : /* get output slice header*/
545 : u32 outslice_size_no_epb;
546 13500 : gf_bs_get_content_no_truncate(ctx->bs_nal_out, &ctx->output_no_epb, &outslice_size_no_epb, &ctx->output_no_epb_alloc);
547 : /* slice_size: the rest of the slice after the header (no_emulation_bytes in it) in source.*/
548 13500 : slice_size = (u32) gf_bs_available(ctx->bs_nal_in);
549 : /* slice_offset_orig: Immediate next byte after header_end (start of the slice_payload) */
550 13500 : slice_offset_orig = (u32) gf_bs_get_position(ctx->bs_nal_in);
551 : /* slice_offset_dst: end of header in dest (=dst_buf_size since we have not copied slice data yet)*/
552 13500 : slice_offset_dst = outslice_size_no_epb;
553 : /*final slice size: add source slice size */
554 13500 : outslice_size_no_epb += slice_size;
555 13500 : if (ctx->output_no_epb_alloc < outslice_size_no_epb) {
556 8 : ctx->output_no_epb = gf_realloc(ctx->output_no_epb, outslice_size_no_epb);
557 8 : ctx->output_no_epb_alloc = outslice_size_no_epb;
558 : }
559 13500 : memcpy(ctx->output_no_epb + slice_offset_dst, ctx->input_no_epb + slice_offset_orig, sizeof(char) * slice_size);
560 :
561 13500 : outslice_size_epb = outslice_size_no_epb + gf_media_nalu_emulation_bytes_add_count(ctx->output_no_epb, outslice_size_no_epb);
562 :
563 13500 : if (ctx->buffer_nal_alloc < outslice_size_epb) {
564 14 : ctx->buffer_nal = gf_realloc(ctx->buffer_nal, outslice_size_epb);
565 14 : ctx->buffer_nal_alloc = outslice_size_epb;
566 : }
567 13500 : gf_media_nalu_add_emulation_bytes(ctx->output_no_epb, ctx->buffer_nal, outslice_size_no_epb);
568 13500 : return outslice_size_epb;
569 : }
570 :
571 15002 : static char *hevcsplit_rewrite_nal(GF_Filter *filter, GF_HEVCSplitCtx *ctx, char *in_nal, u32 in_nal_size, u32 *out_tile_index, u32 *out_nal_size)
572 : {
573 : u8 nal_unit_type, temporal_id, layer_id;
574 : u32 buf_size;
575 15002 : HEVCState *hevc = &ctx->hevc_state;
576 :
577 15002 : gf_hevc_parse_nalu(in_nal, in_nal_size, hevc, &nal_unit_type, &temporal_id, &layer_id);
578 15002 : switch (nal_unit_type) {
579 : //all VCL nal, remove slice address
580 13500 : case GF_HEVC_NALU_SLICE_TRAIL_N:
581 : case GF_HEVC_NALU_SLICE_TRAIL_R:
582 : case GF_HEVC_NALU_SLICE_TSA_N:
583 : case GF_HEVC_NALU_SLICE_TSA_R:
584 : case GF_HEVC_NALU_SLICE_STSA_N:
585 : case GF_HEVC_NALU_SLICE_STSA_R:
586 : case GF_HEVC_NALU_SLICE_RADL_N:
587 : case GF_HEVC_NALU_SLICE_RADL_R:
588 : case GF_HEVC_NALU_SLICE_RASL_N:
589 : case GF_HEVC_NALU_SLICE_RASL_R:
590 : case GF_HEVC_NALU_SLICE_BLA_W_LP:
591 : case GF_HEVC_NALU_SLICE_BLA_W_DLP:
592 : case GF_HEVC_NALU_SLICE_BLA_N_LP:
593 : case GF_HEVC_NALU_SLICE_IDR_W_DLP:
594 : case GF_HEVC_NALU_SLICE_IDR_N_LP:
595 : case GF_HEVC_NALU_SLICE_CRA:
596 13500 : *out_tile_index = hevcsplit_get_slice_tile_index(hevc);
597 13500 : buf_size = hevcsplit_remove_slice_address(ctx, in_nal, in_nal_size);
598 13500 : *out_nal_size = buf_size;
599 13500 : return ctx->buffer_nal;
600 : //non-vcl, write to bitstream
601 1502 : default:
602 1502 : *out_nal_size = in_nal_size;
603 : return in_nal;
604 : }
605 : return NULL;
606 : }
607 :
608 18 : static GF_Err hevcsplit_rewrite_dsi(GF_HEVCSplitCtx *ctx, GF_FilterPid *opid, char *data, u32 size, u32 new_width, u32 new_height)
609 : {
610 : u32 i, j;
611 : u8 *new_dsi;
612 : u32 new_size;
613 18 : GF_HEVCConfig *hvcc = gf_odf_hevc_cfg_read(data, size, GF_FALSE);
614 18 : if (!hvcc) return GF_NON_COMPLIANT_BITSTREAM;
615 :
616 : // for all the list objects in param_array
617 54 : for (i = 0; i < gf_list_count(hvcc->param_array); i++) { // hvcc->param_array:list object
618 54 : GF_NALUFFParamArray *ar = (GF_NALUFFParamArray *)gf_list_get(hvcc->param_array, i); // ar contains the i-th item in param_array
619 108 : for (j = 0; j < gf_list_count(ar->nalus); j++) { // for all the nalus the i-th param got
620 : /*! used for storing AVC sequenceParameterSetNALUnit and pictureParameterSetNALUnit*/
621 54 : GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_list_get(ar->nalus, j); // store j-th nalus in *sl
622 :
623 54 : if (ar->type == GF_HEVC_NALU_SEQ_PARAM) {
624 18 : char *outSPS=NULL;
625 18 : u32 outSize=0;
626 18 : hevc_rewrite_sps(sl->data, sl->size, new_width, new_height, &outSPS, &outSize);
627 18 : gf_free(sl->data);
628 18 : sl->data = outSPS;
629 18 : sl->size= outSize;
630 : }
631 36 : else if (ar->type == GF_HEVC_NALU_VID_PARAM) {
632 : }
633 18 : else if (ar->type == GF_HEVC_NALU_PIC_PARAM) {
634 18 : char *outPPS=NULL;
635 18 : u32 outSize=0;
636 18 : hevcsplit_rewrite_pps_no_grid(ctx, sl->data, sl->size, &outPPS, &outSize);
637 18 : gf_free(sl->data);
638 18 : sl->data = outPPS;
639 18 : sl->size = outSize;
640 : }
641 : }
642 : }
643 18 : gf_odf_hevc_cfg_write(hvcc, &new_dsi, &new_size);
644 18 : gf_odf_hevc_cfg_del(hvcc);
645 :
646 18 : gf_filter_pid_set_property(opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(new_dsi, new_size));
647 18 : return GF_OK;
648 : }
649 :
650 : static void hevcsplit_write_nal(char *output_nal, char *rewritten_nal, u32 out_nal_size, u32 hevc_nalu_size_length)
651 : {
652 27018 : u32 n = 8*(hevc_nalu_size_length);
653 135090 : while (n) {
654 108072 : u32 v = (out_nal_size >> (n-8)) & 0xFF;
655 108072 : *output_nal = v;
656 108072 : output_nal++;
657 : n-=8;
658 : }
659 27018 : memcpy(output_nal, rewritten_nal, out_nal_size);
660 : }
661 :
662 2 : static GF_Err hevcsplit_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
663 : {
664 : u32 cfg_crc = 0, codecid, o_width, o_height;
665 : s32 pps_id = -1, sps_id = -1;
666 : const GF_PropertyValue *p, *dsi;
667 : GF_Err e;
668 2 : GF_HEVCSplitCtx *ctx = (GF_HEVCSplitCtx*)gf_filter_get_udta(filter);
669 :
670 2 : if (is_remove) {
671 : u32 i, count;
672 0 : count = gf_filter_get_opid_count(filter);
673 0 : for (i=0; i<count; i++) {
674 : GF_FilterPid *opid;
675 : HEVCTilePid *tpid;
676 0 : opid = gf_filter_get_opid(filter, i);
677 0 : tpid = gf_filter_pid_get_udta(opid);
678 :
679 0 : if (tpid->opid) {
680 0 : gf_filter_pid_remove(tpid->opid);
681 0 : tpid->opid = NULL;
682 : }
683 0 : if (tpid) gf_free(tpid);
684 0 : if (opid) {
685 0 : gf_filter_pid_set_udta(opid, NULL);
686 0 : gf_filter_pid_remove(opid);
687 : }
688 : }
689 0 : ctx->ipid = NULL;
690 0 : return GF_OK;
691 : }
692 : // checks if input pid matchs its destination filter.
693 2 : if (!gf_filter_pid_check_caps(pid))
694 : return GF_NOT_SUPPORTED;
695 :
696 2 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
697 2 : codecid = p ? p->value.uint : 0;
698 2 : if (!codecid || (codecid != GF_CODECID_HEVC)) {
699 : return GF_NOT_SUPPORTED;
700 : }
701 :
702 2 : dsi = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
703 : cfg_crc = 0;
704 2 : if (dsi && dsi->value.data.ptr && dsi->value.data.size) {
705 2 : cfg_crc = gf_crc_32(dsi->value.data.ptr, dsi->value.data.size);
706 : }
707 : //same config, skip reconf
708 2 : if (!dsi || (cfg_crc == ctx->cfg_crc)) return GF_OK;
709 2 : ctx->cfg_crc = cfg_crc;
710 2 : ctx->ipid = pid;
711 :
712 : // parse otherwise they should refer to something else
713 : u32 i, j;
714 : GF_HEVCConfig *hvcc;
715 :
716 2 : memset(&ctx->hevc_state, 0, sizeof(HEVCState));
717 2 : ctx->hevc_state.full_slice_header_parse = GF_TRUE;
718 :
719 2 : hvcc = gf_odf_hevc_cfg_read(dsi->value.data.ptr, dsi->value.data.size, GF_FALSE);
720 2 : if (!hvcc) return GF_NON_COMPLIANT_BITSTREAM;
721 2 : ctx->hevc_nalu_size_length = hvcc->nal_unit_size;
722 :
723 8 : for (i = 0; i < gf_list_count(hvcc->param_array); i++) { // hvcc->param_array:list object
724 : // ar contains the i-th item in param_array
725 6 : GF_NALUFFParamArray *ar = (GF_NALUFFParamArray *)gf_list_get(hvcc->param_array, i);
726 12 : for (j = 0; j < gf_list_count(ar->nalus); j++) { // for all the nalus the i-th param got
727 : /*! used for storing AVC sequenceParameterSetNALUnit and pictureParameterSetNALUnit*/
728 6 : GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_list_get(ar->nalus, j); // store j-th nalus in *sl
729 : s32 idx;
730 :
731 6 : if (ar->type == GF_HEVC_NALU_SEQ_PARAM) {
732 2 : idx = gf_hevc_read_sps(sl->data, sl->size, &ctx->hevc_state);
733 2 : if ((idx >= 0) && sps_id<0)
734 : sps_id = idx;
735 : }
736 4 : else if (ar->type == GF_HEVC_NALU_PIC_PARAM) {
737 2 : s32 id = gf_hevc_read_pps(sl->data, sl->size, &ctx->hevc_state);
738 2 : if ((id >= 0) && pps_id<0)
739 : pps_id = id;
740 : }
741 2 : else if (ar->type == GF_HEVC_NALU_VID_PARAM) {
742 2 : /*s32 id = */ gf_hevc_read_vps(sl->data, sl->size, &ctx->hevc_state);
743 : }
744 : }
745 : }
746 2 : gf_odf_hevc_cfg_del(hvcc);
747 :
748 2 : if (pps_id < 0) return GF_NON_COMPLIANT_BITSTREAM;
749 2 : if (sps_id < 0) return GF_NON_COMPLIANT_BITSTREAM;
750 :
751 2 : o_width = ctx->hevc_state.sps[sps_id].width;
752 2 : o_height = ctx->hevc_state.sps[sps_id].height;
753 2 : ctx->num_tiles = ctx->hevc_state.pps[pps_id].num_tile_rows * ctx->hevc_state.pps[pps_id].num_tile_columns;
754 :
755 2 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[HEVCTileSplit] Input stream %dx%d with %d tiles:\n", o_width, o_height, ctx->num_tiles));
756 :
757 : // Done with parsing SPS/pps/vps
758 2 : u32 rows = ctx->hevc_state.pps[pps_id].num_tile_rows;
759 2 : u32 cols = ctx->hevc_state.pps[pps_id].num_tile_columns;
760 :
761 8 : for (i = 0; i < rows; i++) {
762 18 : for (j = 0; j < cols; j++) {
763 18 : u32 tile_idx = i * cols + j;
764 18 : HEVCTilePid *tpid = gf_list_get(ctx->outputs, tile_idx);
765 18 : if (!tpid) {
766 : assert(gf_list_count(ctx->outputs) == tile_idx);
767 :
768 18 : GF_SAFEALLOC(tpid, HEVCTilePid);
769 18 : if (!tpid) return GF_OUT_OF_MEM;
770 18 : gf_list_add(ctx->outputs, tpid);
771 18 : tpid->opid = gf_filter_pid_new(filter);
772 18 : gf_filter_pid_set_udta(tpid->opid, tpid);
773 : }
774 :
775 18 : hevcsplit_get_tile_pixel_coords(&ctx->hevc_state, i, j, pps_id, &tpid->width, &tpid->height, &tpid->orig_x, &tpid->orig_y);
776 18 : gf_filter_pid_copy_properties(tpid->opid, ctx->ipid);
777 : // for each output pid, set decoder_config, width and height.
778 18 : gf_filter_pid_set_property(tpid->opid, GF_PROP_PID_WIDTH, &PROP_UINT(tpid->width));
779 18 : gf_filter_pid_set_property(tpid->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(tpid->height));
780 18 : gf_filter_pid_set_property(tpid->opid, GF_PROP_PID_CROP_POS, &PROP_VEC2I_INT(tpid->orig_x, tpid->orig_y));
781 18 : gf_filter_pid_set_property(tpid->opid, GF_PROP_PID_ORIG_SIZE, &PROP_VEC2I_INT(o_width, o_height));
782 : // rewrite the decoder config
783 18 : e = hevcsplit_rewrite_dsi(ctx, tpid->opid, dsi->value.data.ptr, dsi->value.data.size, tpid->width, tpid->height);
784 18 : if (e) return e;
785 :
786 18 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[HEVCTileSplit] output pid %dx%d (position was %dx%d)\n", tpid->width, tpid->height, tpid->orig_x, tpid->orig_y));
787 : }
788 : }
789 : // reaggregate to form complete frame.
790 2 : gf_filter_pid_set_framing_mode(pid, GF_TRUE);
791 2 : return GF_OK;
792 : }
793 :
794 15000 : static GF_Err hevcsplit_process(GF_Filter *filter)
795 : {
796 : u32 hevc_nalu_size_length;
797 15000 : u32 data_size, nal_length, opid_idx = 0;
798 : u8 temporal_id, layer_id, nal_unit_type, i;
799 : u8 *data;
800 : u8 *output_nal;
801 : u32 out_nal_size;
802 : GF_FilterPid * opid;
803 : HEVCTilePid * tpid;
804 15000 : GF_HEVCSplitCtx *ctx = (GF_HEVCSplitCtx*)gf_filter_get_udta(filter);
805 15000 : GF_FilterPacket *pck_src = gf_filter_pid_get_packet(ctx->ipid);
806 15000 : if (!pck_src) {
807 13500 : if (gf_filter_pid_is_eos(ctx->ipid)) {
808 : return GF_EOS;
809 : }
810 782 : return GF_OK;
811 : }
812 1500 : data = (u8*)gf_filter_pck_get_data(pck_src, &data_size);
813 : //this is a clock signaling, for now just trash ..
814 1500 : if (!data) {
815 0 : gf_filter_pid_drop_packet(ctx->ipid);
816 0 : return GF_OK;
817 : }
818 : /*create a bitstream reader for the whole packet*/
819 1500 : gf_bs_reassign_buffer(ctx->bs_au_in, data, data_size);
820 1500 : ctx->nb_pck++;
821 1500 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[HEVCTileSplit] splitting frame %d DTS "LLU" CTS "LLU"\n", ctx->nb_pck, gf_filter_pck_get_dts(pck_src), gf_filter_pck_get_cts(pck_src)));
822 :
823 16502 : while (gf_bs_available(ctx->bs_au_in)) {
824 : u8 *rewritten_nal;
825 : // ctx->hevc_nalu_size_length filled using hvcc
826 15002 : nal_length = gf_bs_read_int(ctx->bs_au_in, ctx->hevc_nalu_size_length * 8);
827 15002 : u32 pos = (u32) gf_bs_get_position(ctx->bs_au_in);
828 : // skip the content of the nal from bs to buffer (useful for the next nal)
829 15002 : gf_bs_skip_bytes(ctx->bs_au_in, nal_length);
830 : // data+pos is an address
831 15002 : gf_hevc_parse_nalu(data+pos, nal_length, &ctx->hevc_state, &nal_unit_type, &temporal_id, &layer_id);
832 :
833 : // todo: might need to rewrite crypto info
834 :
835 15002 : rewritten_nal = hevcsplit_rewrite_nal(filter, ctx, data+pos, nal_length, &opid_idx, &out_nal_size);
836 15002 : if (!rewritten_nal) continue;
837 :
838 15002 : hevc_nalu_size_length = ctx->hevc_nalu_size_length;
839 : //non-vcl NAL, forward to all outputs
840 15002 : if (nal_unit_type > 34) {
841 13518 : for (i=0; i<ctx->num_tiles; i++) {
842 13518 : opid = gf_filter_get_opid(filter, i);
843 13518 : tpid = gf_filter_pid_get_udta(opid);
844 13518 : if (!tpid->opid) {
845 0 : continue;
846 : }
847 13518 : if (!tpid->cur_pck) {
848 18 : tpid->cur_pck = gf_filter_pck_new_alloc(tpid->opid, ctx->hevc_nalu_size_length + out_nal_size, &output_nal);
849 18 : if (!tpid->cur_pck) return GF_OUT_OF_MEM;
850 :
851 18 : gf_filter_pck_merge_properties(pck_src, tpid->cur_pck);
852 : } else {
853 : u8 *data_start;
854 : u32 new_size;
855 13500 : gf_filter_pck_expand(tpid->cur_pck, ctx->hevc_nalu_size_length + out_nal_size, &data_start, &output_nal, &new_size);
856 : }
857 13518 : hevcsplit_write_nal(output_nal, rewritten_nal, out_nal_size, hevc_nalu_size_length);
858 : }
859 : } else {
860 13500 : opid = gf_filter_get_opid(filter, opid_idx);
861 13500 : tpid = gf_filter_pid_get_udta(opid);
862 13500 : if (!tpid->opid) {
863 0 : continue;
864 : }
865 13500 : if (!tpid->cur_pck) {
866 13482 : tpid->cur_pck = gf_filter_pck_new_alloc(tpid->opid, ctx->hevc_nalu_size_length + out_nal_size, &output_nal);
867 13482 : if (!tpid->cur_pck) return GF_OUT_OF_MEM;
868 :
869 13482 : gf_filter_pck_merge_properties(pck_src, tpid->cur_pck);
870 : } else {
871 : u8 *data_start;
872 : u32 new_size;
873 18 : gf_filter_pck_expand(tpid->cur_pck, ctx->hevc_nalu_size_length + out_nal_size, &data_start, &output_nal, &new_size);
874 : }
875 13500 : hevcsplit_write_nal(output_nal, rewritten_nal, out_nal_size, hevc_nalu_size_length);
876 : }
877 : }
878 1500 : gf_filter_pid_drop_packet(ctx->ipid);
879 : // done rewriting all nals from input, send all output
880 15000 : for (i=0; i < ctx->num_tiles; i++) {
881 13500 : opid = gf_filter_get_opid(filter, i);
882 13500 : tpid = gf_filter_pid_get_udta(opid);
883 :
884 13500 : if (!tpid->opid) continue;
885 13500 : if (tpid->cur_pck) {
886 13500 : gf_filter_pck_send(tpid->cur_pck);
887 13500 : tpid->cur_pck = NULL;
888 : }
889 : }
890 : return GF_OK;
891 : }
892 :
893 2 : static GF_Err hevcsplit_initialize(GF_Filter *filter)
894 : {
895 2 : GF_HEVCSplitCtx *ctx = (GF_HEVCSplitCtx *) gf_filter_get_udta(filter);
896 2 : ctx->bs_au_in = gf_bs_new((char *)ctx, 1, GF_BITSTREAM_READ);
897 2 : ctx->bs_nal_in = gf_bs_new((char *)ctx, 1, GF_BITSTREAM_READ);
898 2 : ctx->outputs = gf_list_new();
899 2 : return GF_OK;
900 : }
901 :
902 2 : static void hevcsplit_finalize(GF_Filter *filter)
903 : {
904 : u32 i, count;
905 2 : GF_HEVCSplitCtx *ctx = (GF_HEVCSplitCtx *) gf_filter_get_udta(filter);
906 2 : if (ctx->buffer_nal) gf_free(ctx->buffer_nal);
907 2 : if (ctx->output_no_epb) gf_free(ctx->output_no_epb);
908 2 : if (ctx->input_no_epb) gf_free(ctx->input_no_epb);
909 :
910 2 : gf_bs_del(ctx->bs_au_in);
911 2 : gf_bs_del(ctx->bs_nal_in);
912 2 : if (ctx->bs_nal_out) gf_bs_del(ctx->bs_nal_out);
913 :
914 2 : count = gf_list_count(ctx->outputs);
915 20 : for (i=0; i<count; i++) {
916 : HEVCTilePid *tpid;
917 18 : tpid = gf_list_get(ctx->outputs, i);
918 18 : gf_free(tpid);
919 : }
920 2 : gf_list_del(ctx->outputs);
921 2 : }
922 :
923 : static const GF_FilterCapability HEVCSplitCaps[] =
924 : {
925 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
926 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC),
927 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
928 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
929 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_HEVC)
930 : };
931 :
932 : #define OFFS(_n) #_n, offsetof(GF_HEVCSplitCtx, _n)
933 :
934 : static const GF_FilterArgs HEVCSplitArgs[] =
935 : {
936 : {0}
937 : };
938 :
939 : GF_FilterRegister HEVCSplitRegister = {
940 : .name = "hevcsplit",
941 : GF_FS_SET_DESCRIPTION("HEVC tile splitter")
942 : GF_FS_SET_HELP("This filter splits a motion-constrained tiled HEVC PID into N independent HEVC PIDs.\n"
943 : "Use hevcmerge filter to merge initially motion-constrained tiled HEVC PID in a single output.")
944 : .private_size = sizeof(GF_HEVCSplitCtx),
945 : SETCAPS(HEVCSplitCaps),
946 : //hevc split shall be explicitly loaded
947 : .flags = GF_FS_REG_EXPLICIT_ONLY,
948 : .initialize = hevcsplit_initialize,
949 : .finalize = hevcsplit_finalize,
950 : .args = HEVCSplitArgs,
951 : .configure_pid = hevcsplit_configure_pid,
952 : .process = hevcsplit_process,
953 : };
954 :
955 2877 : const GF_FilterRegister* hevcsplit_register(GF_FilterSession *session)
956 : {
957 2877 : return &HEVCSplitRegister;
958 : }
959 :
960 : #else
961 : const GF_FilterRegister* hevcsplit_register(GF_FilterSession *session)
962 : {
963 : return NULL;
964 : }
965 : #endif // GPAC_DISABLE_AV_PARSERS
966 :
|