1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2020
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / compressed bitstream metadata rewrite filter
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #include <gpac/filters.h>
27 #include <gpac/constants.h>
28 #include <gpac/internal/media_dev.h>
29 #include <gpac/mpeg4_odf.h>
30 
31 typedef struct _bsrw_pid_ctx BSRWPid;
32 typedef struct _bsrw_ctx GF_BSRWCtx;
33 
34 struct _bsrw_pid_ctx
35 {
36 	GF_FilterPid *ipid, *opid;
37 	u32 codec_id;
38 	Bool reconfigure;
39 	s32 clrp, txchar, mxcoef;
40 	GF_Err (*rewrite_pid_config)(GF_BSRWCtx *ctx, BSRWPid *pctx);
41 	GF_Err (*rewrite_packet)(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck);
42 
43 	s32 prev_clrp, prev_txchar, prev_mxcoef, prev_sar;
44 
45 	u32 nalu_size_length;
46 };
47 
48 struct _bsrw_ctx
49 {
50 	GF_Fraction sar;
51 	s32 m4vpl, prof, lev, pcomp, pidc, pspace, gpcflags;
52 	char *clrp, *txchar, *mxcoef;
53 	Bool remsei;
54 
55 
56 	GF_List *pids;
57 	Bool reconfigure;
58 };
59 
none_rewrite_packet(GF_BSRWCtx * ctx,BSRWPid * pctx,GF_FilterPacket * pck)60 static GF_Err none_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck)
61 {
62 	return gf_filter_pck_forward(pck, pctx->opid);
63 }
64 
65 
m4v_rewrite_pid_config(GF_BSRWCtx * ctx,BSRWPid * pctx)66 static GF_Err m4v_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
67 {
68 	GF_Err e;
69 	u8 *dsi;
70 	u32 dsi_size;
71 	const GF_PropertyValue *prop;
72 
73 	prop = gf_filter_pid_get_property(pctx->ipid, GF_PROP_PID_DECODER_CONFIG);
74 	if (!prop) return GF_OK;
75 
76 	pctx->reconfigure = GF_FALSE;
77 
78 
79 	dsi_size = prop->value.data.size;
80 	dsi = gf_malloc(sizeof(u8) * dsi_size);
81 	memcpy(dsi, prop->value.data.ptr, sizeof(u8) * dsi_size);
82 
83 	if (ctx->sar.num && ctx->sar.den) {
84 		e = gf_m4v_rewrite_par(&dsi, &dsi_size, ctx->sar.num, ctx->sar.den);
85 		if (e) {
86 			gf_free(dsi);
87 			return e;
88 		}
89 		gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(ctx->sar) );
90 	}
91 	if (ctx->m4vpl>=0) {
92 		gf_m4v_rewrite_pl(&dsi, &dsi_size, (u32) ctx->m4vpl);
93 		gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT(ctx->m4vpl) );
94 	}
95 
96 	gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
97 
98 	return GF_OK;
99 }
100 
avc_rewrite_packet(GF_BSRWCtx * ctx,BSRWPid * pctx,GF_FilterPacket * pck)101 static GF_Err avc_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck)
102 {
103 	u32 size, pck_size, final_size;
104 	GF_FilterPacket *dst;
105 	u8 *output;
106 	const u8 *data = gf_filter_pck_get_data(pck, &pck_size);
107 	if (!data)
108 		return gf_filter_pck_forward(pck, pctx->opid);
109 
110 	final_size = 0;
111 	size=0;
112 	while (size<pck_size) {
113 		u8 nal_type=0;
114 		u32 nal_hdr = pctx->nalu_size_length;
115 		u32 nal_size = 0;
116 		while (nal_hdr) {
117 			nal_size |= data[size];
118 			size++;
119 			nal_hdr--;
120 			if (!nal_hdr) break;
121 			nal_size<<=8;
122 		}
123 		nal_type = data[size];
124 		nal_type = nal_type & 0x1F;
125 		if (nal_type != GF_AVC_NALU_SEI) {
126 			final_size += nal_size+pctx->nalu_size_length;
127 		}
128 		size += nal_size;
129 	}
130 	if (final_size == pck_size)
131 		return gf_filter_pck_forward(pck, pctx->opid);
132 
133 	dst = gf_filter_pck_new_alloc(pctx->opid, final_size, &output);
134 	gf_filter_pck_merge_properties(pck, dst);
135 
136 	size=0;
137 	while (size<pck_size) {
138 		u8 nal_type=0;
139 		u32 nal_hdr = pctx->nalu_size_length;
140 		u32 nal_size = 0;
141 		while (nal_hdr) {
142 			nal_size |= data[size];
143 			size++;
144 			nal_hdr--;
145 			if (!nal_hdr) break;
146 			nal_size<<=8;
147 		}
148 		nal_type = data[size];
149 		nal_type = nal_type & 0x1F;
150 		if (nal_type == GF_AVC_NALU_SEI) {
151 			size += nal_size;
152 			continue;
153 		}
154 		memcpy(output, &data[size-pctx->nalu_size_length], pctx->nalu_size_length+nal_size);
155 		output += pctx->nalu_size_length+nal_size;
156 		size += nal_size;
157 	}
158 	return gf_filter_pck_send(dst);
159 }
160 
avc_rewrite_pid_config(GF_BSRWCtx * ctx,BSRWPid * pctx)161 static GF_Err avc_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
162 {
163 	GF_AVCConfig *avcc;
164 	GF_Err e = GF_OK;
165 	u8 *dsi;
166 	u32 dsi_size;
167 	const GF_PropertyValue *prop;
168 
169 	prop = gf_filter_pid_get_property(pctx->ipid, GF_PROP_PID_DECODER_CONFIG);
170 	if (!prop) return GF_OK;
171 	pctx->reconfigure = GF_FALSE;
172 
173 	avcc = gf_odf_avc_cfg_read(prop->value.data.ptr, prop->value.data.size);
174 	if (ctx->sar.num && ctx->sar.den) {
175 		e = gf_media_avc_change_par(avcc, ctx->sar.num, ctx->sar.den);
176 		if (!e)
177 			gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(ctx->sar) );
178 	}
179 
180 	if ((ctx->lev>=0) || (ctx->prof>=0) || (ctx->pcomp>=0)) {
181 		u32 i, count = gf_list_count(avcc->sequenceParameterSets);
182 		for (i=0; i<count; i++) {
183 			GF_AVCConfigSlot *sps = gf_list_get(avcc->sequenceParameterSets, i);
184 			//first byte is nalu header, then profile_idc (8bits), prof_comp (8buts) a,d level_idc (8bits)
185 			if (ctx->prof>=0) {
186 				sps->data[1] = (u8) ctx->prof;
187 			}
188 			if (ctx->pcomp>=0) {
189 				sps->data[2] = (u8) ctx->pcomp;
190 			}
191 			if (ctx->lev>=0) {
192 				sps->data[3] = (u8) ctx->lev;
193 			}
194 		}
195 		if (ctx->lev>=0) avcc->AVCLevelIndication = ctx->lev;
196 		if (ctx->prof>=0) avcc->AVCProfileIndication = ctx->prof;
197 		if (ctx->pcomp>=0) avcc->profile_compatibility = ctx->pcomp;
198 	}
199 
200 	gf_odf_avc_cfg_write(avcc, &dsi, &dsi_size);
201 	pctx->nalu_size_length = avcc->nal_unit_size;
202 
203 	gf_odf_avc_cfg_del(avcc);
204 	if (e) return e;
205 
206 	gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
207 
208 	if (ctx->remsei) {
209 		pctx->rewrite_packet = avc_rewrite_packet;
210 	} else {
211 		pctx->rewrite_packet = none_rewrite_packet;
212 	}
213 	return GF_OK;
214 }
215 
hevc_rewrite_packet(GF_BSRWCtx * ctx,BSRWPid * pctx,GF_FilterPacket * pck)216 static GF_Err hevc_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck)
217 {
218 	u32 size, pck_size, final_size;
219 	GF_FilterPacket *dst;
220 	u8 *output;
221 	const u8 *data = gf_filter_pck_get_data(pck, &pck_size);
222 	if (!data)
223 		return gf_filter_pck_forward(pck, pctx->opid);
224 
225 	final_size = 0;
226 	size=0;
227 	while (size<pck_size) {
228 		u8 nal_type=0;
229 		u32 nal_hdr = pctx->nalu_size_length;
230 		u32 nal_size = 0;
231 		while (nal_hdr) {
232 			nal_size |= data[size];
233 			size++;
234 			nal_hdr--;
235 			if (!nal_hdr) break;
236 			nal_size<<=8;
237 		}
238 		nal_type = data[size];
239 		nal_type = (nal_type & 0x7E) >> 1;
240 		if ((nal_type != GF_HEVC_NALU_SEI_PREFIX) && (nal_type != GF_HEVC_NALU_SEI_SUFFIX) ) {
241 			final_size += nal_size+pctx->nalu_size_length;
242 		}
243 		size += nal_size;
244 	}
245 	if (final_size == pck_size)
246 		return gf_filter_pck_forward(pck, pctx->opid);
247 
248 	dst = gf_filter_pck_new_alloc(pctx->opid, final_size, &output);
249 	gf_filter_pck_merge_properties(pck, dst);
250 
251 	size=0;
252 	while (size<pck_size) {
253 		u8 nal_type=0;
254 		u32 nal_hdr = pctx->nalu_size_length;
255 		u32 nal_size = 0;
256 		while (nal_hdr) {
257 			nal_size |= data[size];
258 			size++;
259 			nal_hdr--;
260 			if (!nal_hdr) break;
261 			nal_size<<=8;
262 		}
263 		nal_type = data[size];
264 		nal_type = (nal_type & 0x7E) >> 1;
265 		if ((nal_type == GF_HEVC_NALU_SEI_PREFIX) || (nal_type == GF_HEVC_NALU_SEI_SUFFIX) ) {
266 			size += nal_size;
267 			continue;
268 		}
269 		memcpy(output, &data[size-pctx->nalu_size_length], pctx->nalu_size_length+nal_size);
270 		output += pctx->nalu_size_length+nal_size;
271 		size += nal_size;
272 	}
273 	return gf_filter_pck_send(dst);
274 }
275 
hevc_rewrite_pid_config(GF_BSRWCtx * ctx,BSRWPid * pctx)276 static GF_Err hevc_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
277 {
278 	GF_HEVCConfig *hvcc;
279 	GF_Err e = GF_OK;
280 	u8 *dsi;
281 	u32 dsi_size;
282 	const GF_PropertyValue *prop;
283 
284 	prop = gf_filter_pid_get_property(pctx->ipid, GF_PROP_PID_DECODER_CONFIG);
285 	if (!prop) return GF_OK;
286 	pctx->reconfigure = GF_FALSE;
287 
288 	hvcc = gf_odf_hevc_cfg_read(prop->value.data.ptr, prop->value.data.size, (pctx->codec_id==GF_CODECID_LHVC) ? GF_TRUE : GF_FALSE);
289 	if (ctx->sar.num && ctx->sar.den) {
290 		e = gf_media_hevc_change_par(hvcc, ctx->sar.num, ctx->sar.den);
291 		if (!e)
292 			gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(ctx->sar) );
293 	}
294 	if (ctx->pidc>=0) hvcc->profile_idc = ctx->pidc;
295 	if (ctx->pspace>=0) hvcc->profile_space = ctx->pspace;
296 	if (ctx->gpcflags>=0) hvcc->general_profile_compatibility_flags = ctx->gpcflags;
297 
298 
299 	gf_odf_hevc_cfg_write(hvcc, &dsi, &dsi_size);
300 	pctx->nalu_size_length = hvcc->nal_unit_size;
301 	gf_odf_hevc_cfg_del(hvcc);
302 	if (e) return e;
303 
304 	gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
305 
306 	if (ctx->remsei) {
307 		pctx->rewrite_packet = hevc_rewrite_packet;
308 	} else {
309 		pctx->rewrite_packet = none_rewrite_packet;
310 	}
311 	return GF_OK;
312 }
313 
none_rewrite_pid_config(GF_BSRWCtx * ctx,BSRWPid * pctx)314 static GF_Err none_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
315 {
316 	pctx->reconfigure = GF_FALSE;
317 	return GF_OK;
318 }
319 
rewrite_pid_config(GF_BSRWCtx * ctx,BSRWPid * pctx)320 static GF_Err rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
321 {
322 	GF_Err e = pctx->rewrite_pid_config(ctx, pctx);
323 	if (e) return e;
324 	pctx->clrp = pctx->txchar = pctx->mxcoef = -1;
325 	pctx->prev_clrp = pctx->prev_txchar = pctx->prev_mxcoef = pctx->prev_sar = -1;
326 
327 	if (ctx->clrp) {
328 		if (!stricmp(ctx->clrp, "BT.709") || !stricmp(ctx->clrp, "BT709")) pctx->clrp = 1;
329 		else if (!stricmp(ctx->clrp, "BT.601-625") || !stricmp(ctx->clrp, "BT601-625")) pctx->clrp = 5;
330 		else if (!stricmp(ctx->clrp, "BT.601-525") || !stricmp(ctx->clrp, "BT601-525")) pctx->clrp = 6;
331 		else if (!stricmp(ctx->clrp, "BT.2020") || !stricmp(ctx->clrp, "BT2020")) pctx->clrp = 9;
332 		else if (!stricmp(ctx->clrp, "P3")) pctx->clrp = 11;
333 		else if (!stricmp(ctx->clrp, "P3-D65")) pctx->clrp = 12;
334 		else {
335 			char szCoef[100];
336 			pctx->clrp = atoi(ctx->clrp);
337 			sprintf(szCoef, "%u", pctx->clrp);
338 			if (stricmp(szCoef, ctx->clrp))
339 				pctx->clrp = -1;
340 		}
341 	}
342 	if (ctx->txchar) {
343 		if (!strcmp(ctx->txchar, "BT-709") || !strcmp(ctx->txchar, "BT709")) pctx->txchar=1;
344 		else if (!strcmp(ctx->txchar, "ST-2084") || !strcmp(ctx->txchar, "ST2084")) pctx->txchar=16;
345 		else if (!strcmp(ctx->txchar, "STD-B67") || !strcmp(ctx->txchar, "STDB67")) pctx->txchar=18;
346 		else {
347 			char szTxChar[100];
348 			pctx->txchar = atoi(ctx->txchar);
349 			sprintf(szTxChar, "%u", pctx->txchar);
350 			if (stricmp(szTxChar, ctx->txchar))
351 				pctx->txchar = -1;
352 		}
353 	}
354 	if (ctx->mxcoef) {
355 		if (!strcmp(ctx->mxcoef, "BT.709") || !strcmp(ctx->mxcoef, "BT709")) pctx->mxcoef = 1;
356 		else if (!strcmp(ctx->mxcoef, "BT.601") || !strcmp(ctx->mxcoef, "BT601")) pctx->mxcoef = 6;
357 		else if (!strcmp(ctx->mxcoef, "BT.2020") || !strcmp(ctx->mxcoef, "BT2020")) pctx->mxcoef = 9;
358 		else {
359 			char szMx[100];
360 			pctx->mxcoef = atoi(ctx->mxcoef);
361 			sprintf(szMx, "%u", pctx->mxcoef);
362 			if (stricmp(szMx, ctx->mxcoef))
363 				pctx->mxcoef = -1;
364 		}
365 	}
366 	return GF_OK;
367 }
368 
369 
prores_rewrite_packet(GF_BSRWCtx * ctx,BSRWPid * pctx,GF_FilterPacket * pck)370 static GF_Err prores_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck)
371 {
372 	u8 *output;
373 	GF_FilterPacket *dst_pck = gf_filter_pck_new_clone(pctx->opid, pck, &output);
374 
375 	//starting at offset 20 in frame:
376 	/*
377 	prores_frame->chroma_format = gf_bs_read_int(bs, 2);
378 	gf_bs_read_int(bs, 2);
379 	prores_frame->interlaced_mode = gf_bs_read_int(bs, 2);
380 	gf_bs_read_int(bs, 2);
381 	prores_frame->aspect_ratio_information = gf_bs_read_int(bs, 4);
382 	prores_frame->framerate_code = gf_bs_read_int(bs, 4);
383 	prores_frame->color_primaries = gf_bs_read_u8(bs);
384 	prores_frame->transfer_characteristics = gf_bs_read_u8(bs);
385 	prores_frame->matrix_coefficients = gf_bs_read_u8(bs);
386 	gf_bs_read_int(bs, 4);
387 	prores_frame->alpha_channel_type = gf_bs_read_int(bs, 4);
388 	*/
389 
390 	if (ctx->sar.num && ctx->sar.den) {
391 		u32 framerate_code = output[21] & 0xF;
392 		u32 new_ar = 0;
393 		if (ctx->sar.num==ctx->sar.den) new_ar = 1;
394 		else if (ctx->sar.num * 3 == ctx->sar.den * 4) new_ar = 2;
395 		else if (ctx->sar.num * 9 == ctx->sar.den * 16) new_ar = 3;
396 		else {
397 			if (pctx->prev_sar != new_ar) {
398 				GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[BSRW] Aspect ratio %d/%d not registered in ProRes, using 0 (unknown)\n", ctx->sar.num, ctx->sar.den));
399 			}
400 		}
401 		new_ar <<= 4;
402 		framerate_code |= new_ar;
403 		output[21] = (u8) framerate_code;
404 		if (pctx->prev_sar != new_ar) {
405 			gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(ctx->sar) );
406 			pctx->prev_sar = new_ar;
407 		}
408 	}
409 	if (pctx->clrp>=0) {
410 		output[22] = (u8) pctx->clrp;
411 		if (pctx->prev_clrp != pctx->clrp) {
412 			gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_PRIMARIES, &PROP_UINT(pctx->clrp) );
413 			pctx->prev_clrp = pctx->clrp;
414 		}
415 	}
416 	if (pctx->txchar>=0) {
417 		output[23] = (u8) pctx->txchar;
418 		if (pctx->prev_txchar != pctx->txchar) {
419 			gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_TRANSFER, &PROP_UINT(pctx->txchar) );
420 			pctx->prev_txchar = pctx->txchar;
421 		}
422 	}
423 	if (pctx->mxcoef>=0) {
424 		output[24] = (u8) pctx->mxcoef;
425 		if (pctx->prev_mxcoef != pctx->mxcoef) {
426 			gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_MX, &PROP_UINT(pctx->mxcoef) );
427 			pctx->prev_mxcoef = pctx->mxcoef;
428 		}
429 	}
430 	return gf_filter_pck_send(dst_pck);
431 }
432 
433 
bsrw_configure_pid(GF_Filter * filter,GF_FilterPid * pid,Bool is_remove)434 static GF_Err bsrw_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
435 {
436 	const GF_PropertyValue *prop;
437 	GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
438 	BSRWPid *pctx = gf_filter_pid_get_udta(pid);
439 
440 	//disconnect of src pid (not yet supported)
441 	if (is_remove) {
442 		if (pctx) {
443 			//one in one out, this is simple
444 			gf_filter_pid_remove(pctx->opid);
445 			gf_filter_pid_set_udta(pid, NULL);
446 			gf_list_del_item(ctx->pids, pctx);
447  			gf_free(pctx);
448 		}
449 		return GF_OK;
450 	}
451 	if (! gf_filter_pid_check_caps(pid))
452 		return GF_NOT_SUPPORTED;
453 
454 	if (!pctx) {
455 		GF_SAFEALLOC(pctx, BSRWPid);
456 		if (!pctx) return GF_OUT_OF_MEM;
457 		pctx->ipid = pid;
458 		gf_filter_pid_set_udta(pid, pctx);
459 		pctx->rewrite_pid_config = none_rewrite_pid_config;
460 		pctx->rewrite_packet = none_rewrite_packet;
461 		gf_list_add(ctx->pids, pctx);
462 		pctx->opid = gf_filter_pid_new(filter);
463 		if (!pctx->opid) return GF_OUT_OF_MEM;
464 	}
465 
466 	prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
467 	assert(prop);
468 	switch (prop->value.uint) {
469 	case GF_CODECID_AVC:
470 	case GF_CODECID_SVC:
471 	case GF_CODECID_MVC:
472 		pctx->rewrite_pid_config = avc_rewrite_pid_config;
473 		break;
474 	case GF_CODECID_HEVC:
475 	case GF_CODECID_HEVC_TILES:
476 	case GF_CODECID_LHVC:
477 		pctx->rewrite_pid_config = hevc_rewrite_pid_config;
478 		break;
479 	case GF_CODECID_MPEG4_PART2:
480 		pctx->rewrite_pid_config = m4v_rewrite_pid_config;
481 		break;
482 	case GF_CODECID_AP4H:
483 	case GF_CODECID_AP4X:
484 	case GF_CODECID_APCH:
485 	case GF_CODECID_APCN:
486 	case GF_CODECID_APCO:
487 	case GF_CODECID_APCS:
488 		pctx->rewrite_pid_config = none_rewrite_pid_config;
489 		pctx->rewrite_packet = prores_rewrite_packet;
490 		break;
491 
492 	default:
493 		pctx->rewrite_pid_config = none_rewrite_pid_config;
494 		pctx->rewrite_packet = none_rewrite_packet;
495 		break;
496 	}
497 
498 	gf_filter_pid_copy_properties(pctx->opid, pctx->ipid);
499 	pctx->codec_id = prop->value.uint;
500 	pctx->reconfigure = GF_TRUE;
501 	gf_filter_pid_set_framing_mode(pid, GF_TRUE);
502 	return GF_OK;
503 }
504 
505 
bsrw_process(GF_Filter * filter)506 static GF_Err bsrw_process(GF_Filter *filter)
507 {
508 	u32 i, count;
509 	GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
510 
511 	count = gf_filter_get_ipid_count(filter);
512 	for (i=0; i<count; i++) {
513 		BSRWPid *pctx;
514 		GF_FilterPacket *pck;
515 		GF_FilterPid *pid = gf_filter_get_ipid(filter, i);
516 		if (!pid) break;
517 		pctx = gf_filter_pid_get_udta(pid);
518 		if (!pctx) break;
519 		if (ctx->reconfigure)
520 			pctx->reconfigure = GF_TRUE;
521 
522 		if (pctx->reconfigure) {
523 			GF_Err e = rewrite_pid_config(ctx, pctx);
524 			if (e) return e;
525 		}
526 		pck = gf_filter_pid_get_packet(pid);
527 		if (!pck) {
528 			if (gf_filter_pid_is_eos(pctx->ipid))
529 				gf_filter_pid_set_eos(pctx->opid);
530 			continue;
531 		}
532 		pctx->rewrite_packet(ctx, pctx, pck);
533 		gf_filter_pid_drop_packet(pid);
534 	}
535 	ctx->reconfigure = GF_FALSE;
536 	return GF_OK;
537 }
538 
bsrw_update_arg(GF_Filter * filter,const char * arg_name,const GF_PropertyValue * new_val)539 static GF_Err bsrw_update_arg(GF_Filter *filter, const char *arg_name, const GF_PropertyValue *new_val)
540 {
541 	GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
542 	ctx->reconfigure = GF_TRUE;
543 	return GF_OK;
544 }
545 
bsrw_initialize(GF_Filter * filter)546 static GF_Err bsrw_initialize(GF_Filter *filter)
547 {
548 	GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
549 	ctx->pids = gf_list_new();
550 
551 #ifdef GPAC_ENABLE_COVERAGE
552 	bsrw_update_arg(filter, NULL, NULL);
553 #endif
554 	return GF_OK;
555 }
bsrw_finalize(GF_Filter * filter)556 static void bsrw_finalize(GF_Filter *filter)
557 {
558 	GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
559 	while (gf_list_count(ctx->pids)) {
560 		BSRWPid *pctx = gf_list_pop_back(ctx->pids);
561 		gf_free(pctx);
562 	}
563 	gf_list_del(ctx->pids);
564 }
565 
566 #define OFFS(_n)	#_n, offsetof(GF_BSRWCtx, _n)
567 static const GF_FilterArgs BSRWArgs[] =
568 {
569 	{ OFFS(sar), "aspect ratio to rewrite", GF_PROP_FRACTION, "0/0", NULL, GF_FS_ARG_UPDATE},
570 	{ OFFS(m4vpl), "set ProfileLevel for MPEG-4 video part two", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
571 	{ OFFS(clrp), "color primaries according to ISO/IEC 23001-8 / 23091-2. Value can be the integer value or (case insensitive) `BT709`, `BT601-625`, `BT601-525`, `BT2020`, `P3` or `P3-D65`", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_UPDATE},
572 	{ OFFS(txchar), "transfer characteristics according to ISO/IEC 23001-8 / 23091-2. Value can be the integer value or (case insensitive) `BT709`, `ST2084` or `STDB67`", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_UPDATE},
573 	{ OFFS(mxcoef), "matrix coeficients according to ISO/IEC 23001-8 / 23091-2. Value can be the integer value or (case insensitive) `BT709`, `BT601` or `BT2020`", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_UPDATE},
574 
575 	{ OFFS(prof), "profile indication for AVC|H264", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
576 	{ OFFS(lev), "level indication for AVC|H264", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
577 	{ OFFS(pcomp), "profile compatibility for AVC|H264", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
578 	{ OFFS(pidc), "profile IDC for HEVC", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
579 	{ OFFS(pspace), "profile space for HEVC", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
580 	{ OFFS(gpcflags), "general compatibility flags for HEVC", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
581 
582 	{ OFFS(remsei), "remove SEI messages from bitstream", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
583 
584 	{0}
585 };
586 
587 static const GF_FilterCapability BSRWCaps[] =
588 {
589 	CAP_UINT(GF_CAPS_INPUT_STATIC ,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
590 	CAP_BOOL(GF_CAPS_INPUT_EXCLUDED|GF_CAPFLAG_STATIC , GF_PROP_PID_UNFRAMED, GF_TRUE),
591 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC),
592 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_SVC),
593 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_MVC),
594 	{0},
595 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC),
596 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC_TILES),
597 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_LHVC),
598 	{0},
599 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2),
600 	{0},
601 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4H),
602 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4X),
603 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCH),
604 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCN),
605 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCO),
606 	CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCS),
607 };
608 
609 GF_FilterRegister BSRWRegister = {
610 	.name = "bsrw",
611 	GF_FS_SET_DESCRIPTION("Compressed bitstream rewriter")
612 	GF_FS_SET_HELP("This filter rewrites some metadata of various bitstream formats.\n"
613 	"The filter can currently modify the following properties in the bitstream:\n"
614 	"- MPEG-4 Visual: aspect ratio and profile/level\n"
615 	"- AVC|H264: aspect ratio, profile, level, profile compatibility\n"
616 	"- HEVC: aspect ratio\n"
617 	"- ProRes: aspect ratio, color primaries, transfer characteristics and matrix coefficients\n"
618 	"  \n"
619 	"The filter can currently modify the following properties in the stream configuration but not in the bitstream:\n"
620 	"- HEVC: profile IDC, profile space, general compatibility flags\n"
621 	)
622 	.private_size = sizeof(GF_BSRWCtx),
623 	.max_extra_pids = 0xFFFFFFFF,
624 	.flags = GF_FS_REG_EXPLICIT_ONLY,
625 	.args = BSRWArgs,
626 	SETCAPS(BSRWCaps),
627 	.initialize = bsrw_initialize,
628 	.finalize = bsrw_finalize,
629 	.configure_pid = bsrw_configure_pid,
630 	.process = bsrw_process,
631 	.update_arg = bsrw_update_arg
632 };
633 
bsrw_register(GF_FilterSession * session)634 const GF_FilterRegister *bsrw_register(GF_FilterSession *session)
635 {
636 	return &BSRWRegister;
637 }
638