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