LCOV - code coverage report
Current view: top level - filters - bsrw.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 197 310 63.5 %
Date: 2021-04-29 23:48:07 Functions: 13 16 81.2 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2020-2021
       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             :         GF_Err (*rewrite_pid_config)(GF_BSRWCtx *ctx, BSRWPid *pctx);
      40             :         GF_Err (*rewrite_packet)(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck);
      41             : 
      42             :         s32 prev_cprim, prev_ctfc, prev_cmx, prev_sar;
      43             : 
      44             :         u32 nalu_size_length;
      45             : 
      46             :         GF_VUIInfo vui;
      47             :         Bool rewrite_vui;
      48             : };
      49             : 
      50             : struct _bsrw_ctx
      51             : {
      52             :         GF_Fraction sar;
      53             :         s32 m4vpl, prof, lev, pcomp, pidc, pspace, gpcflags;
      54             :         s32 cprim, ctfc, cmx, vidfmt;
      55             :         Bool rmsei, fullrange, novsi;
      56             : 
      57             :         GF_List *pids;
      58             :         Bool reconfigure;
      59             : };
      60             : 
      61        1273 : static GF_Err none_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck)
      62             : {
      63        1273 :         return gf_filter_pck_forward(pck, pctx->opid);
      64             : }
      65             : 
      66           2 : 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           2 :         prop = gf_filter_pid_get_property(pctx->ipid, GF_PROP_PID_DECODER_CONFIG);
      74           2 :         if (!prop) return GF_OK;
      75             : 
      76           2 :         pctx->reconfigure = GF_FALSE;
      77             : 
      78             : 
      79           2 :         dsi_size = prop->value.data.size;
      80           2 :         dsi = gf_malloc(sizeof(u8) * dsi_size);
      81           2 :         memcpy(dsi, prop->value.data.ptr, sizeof(u8) * dsi_size);
      82             : 
      83           2 :         if (ctx->sar.num && ctx->sar.den) {
      84           2 :                 e = gf_m4v_rewrite_par(&dsi, &dsi_size, ctx->sar.num, ctx->sar.den);
      85           2 :                 if (e) {
      86           0 :                         gf_free(dsi);
      87           0 :                         return e;
      88             :                 }
      89           2 :                 gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(ctx->sar) );
      90             :         }
      91           2 :         if (ctx->m4vpl>=0) {
      92           2 :                 gf_m4v_rewrite_pl(&dsi, &dsi_size, (u32) ctx->m4vpl);
      93           2 :                 gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT(ctx->m4vpl) );
      94             :         }
      95             : 
      96           2 :         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
      97             : 
      98           2 :         return GF_OK;
      99             : }
     100             : 
     101           0 : 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           0 :         const u8 *data = gf_filter_pck_get_data(pck, &pck_size);
     107           0 :         if (!data)
     108           0 :                 return gf_filter_pck_forward(pck, pctx->opid);
     109             : 
     110             :         final_size = 0;
     111             :         size=0;
     112           0 :         while (size<pck_size) {
     113             :                 u8 nal_type=0;
     114           0 :                 u32 nal_hdr = pctx->nalu_size_length;
     115             :                 u32 nal_size = 0;
     116           0 :                 while (nal_hdr) {
     117           0 :                         nal_size |= data[size];
     118           0 :                         size++;
     119           0 :                         nal_hdr--;
     120           0 :                         if (!nal_hdr) break;
     121           0 :                         nal_size<<=8;
     122             :                 }
     123           0 :                 nal_type = data[size];
     124           0 :                 nal_type = nal_type & 0x1F;
     125           0 :                 if (nal_type != GF_AVC_NALU_SEI) {
     126           0 :                         final_size += nal_size+pctx->nalu_size_length;
     127             :                 }
     128           0 :                 size += nal_size;
     129             :         }
     130           0 :         if (final_size == pck_size)
     131           0 :                 return gf_filter_pck_forward(pck, pctx->opid);
     132             : 
     133           0 :         dst = gf_filter_pck_new_alloc(pctx->opid, final_size, &output);
     134           0 :         if (!dst) return GF_OUT_OF_MEM;
     135             : 
     136           0 :         gf_filter_pck_merge_properties(pck, dst);
     137             : 
     138             :         size=0;
     139           0 :         while (size<pck_size) {
     140             :                 u8 nal_type=0;
     141           0 :                 u32 nal_hdr = pctx->nalu_size_length;
     142             :                 u32 nal_size = 0;
     143           0 :                 while (nal_hdr) {
     144           0 :                         nal_size |= data[size];
     145           0 :                         size++;
     146           0 :                         nal_hdr--;
     147           0 :                         if (!nal_hdr) break;
     148           0 :                         nal_size<<=8;
     149             :                 }
     150           0 :                 nal_type = data[size];
     151           0 :                 nal_type = nal_type & 0x1F;
     152           0 :                 if (nal_type == GF_AVC_NALU_SEI) {
     153           0 :                         size += nal_size;
     154           0 :                         continue;
     155             :                 }
     156           0 :                 memcpy(output, &data[size-pctx->nalu_size_length], pctx->nalu_size_length+nal_size);
     157           0 :                 output += pctx->nalu_size_length+nal_size;
     158           0 :                 size += nal_size;
     159             :         }
     160           0 :         return gf_filter_pck_send(dst);
     161             : }
     162             : 
     163           4 : static void update_props(BSRWPid *pctx, GF_VUIInfo *vui)
     164             : {
     165           4 :         if ((vui->ar_num>0) && (vui->ar_den>0))
     166           4 :                 gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_SAR, &PROP_FRAC_INT(vui->ar_num, vui->ar_den) );
     167             : 
     168           4 :         if (vui->fullrange>0)
     169           0 :                 gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_RANGE, &PROP_BOOL(vui->fullrange) );
     170             : 
     171           4 :         if (!vui->remove_video_info) {
     172           4 :                 if (vui->color_prim>=0)
     173           0 :                         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_PRIMARIES, &PROP_UINT(vui->color_prim) );
     174           4 :                 if (vui->color_tfc>=0)
     175           0 :                         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_TRANSFER, &PROP_UINT(vui->color_tfc) );
     176           4 :                 if (vui->color_matrix>=0)
     177           0 :                         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_PRIMARIES, &PROP_UINT(vui->color_matrix) );
     178             :         }
     179           4 : }
     180             : 
     181           6 : static GF_Err avc_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
     182             : {
     183             :         GF_AVCConfig *avcc;
     184             :         GF_Err e = GF_OK;
     185             :         u8 *dsi;
     186             :         u32 dsi_size;
     187             :         const GF_PropertyValue *prop;
     188             : 
     189           6 :         prop = gf_filter_pid_get_property(pctx->ipid, GF_PROP_PID_DECODER_CONFIG);
     190           6 :         if (!prop) return GF_OK;
     191           6 :         pctx->reconfigure = GF_FALSE;
     192             : 
     193           6 :         avcc = gf_odf_avc_cfg_read(prop->value.data.ptr, prop->value.data.size);
     194             : 
     195           6 :         if (pctx->rewrite_vui) {
     196           2 :                 GF_VUIInfo tmp_vui = pctx->vui;
     197           2 :                 tmp_vui.update = GF_TRUE;
     198           2 :                 e = gf_avc_change_vui(avcc, &tmp_vui);
     199           2 :                 if (!e) {
     200           2 :                         update_props(pctx, &tmp_vui);
     201             :                 }
     202             :         }
     203             : 
     204           6 :         if ((ctx->lev>=0) || (ctx->prof>=0) || (ctx->pcomp>=0)) {
     205           2 :                 u32 i, count = gf_list_count(avcc->sequenceParameterSets);
     206           4 :                 for (i=0; i<count; i++) {
     207           2 :                         GF_NALUFFParam *sps = gf_list_get(avcc->sequenceParameterSets, i);
     208             :                         //first byte is nalu header, then profile_idc (8bits), prof_comp (8bits), and level_idc (8bits)
     209           2 :                         if (ctx->prof>=0) {
     210           2 :                                 sps->data[1] = (u8) ctx->prof;
     211             :                         }
     212           2 :                         if (ctx->pcomp>=0) {
     213           2 :                                 sps->data[2] = (u8) ctx->pcomp;
     214             :                         }
     215           2 :                         if (ctx->lev>=0) {
     216           2 :                                 sps->data[3] = (u8) ctx->lev;
     217             :                         }
     218             :                 }
     219           2 :                 if (ctx->lev>=0) avcc->AVCLevelIndication = ctx->lev;
     220           2 :                 if (ctx->prof>=0) avcc->AVCProfileIndication = ctx->prof;
     221           2 :                 if (ctx->pcomp>=0) avcc->profile_compatibility = ctx->pcomp;
     222             :         }
     223             : 
     224           6 :         gf_odf_avc_cfg_write(avcc, &dsi, &dsi_size);
     225           6 :         pctx->nalu_size_length = avcc->nal_unit_size;
     226             : 
     227           6 :         gf_odf_avc_cfg_del(avcc);
     228           6 :         if (e) return e;
     229             : 
     230           6 :         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
     231             : 
     232           6 :         if (ctx->rmsei) {
     233           0 :                 pctx->rewrite_packet = avc_rewrite_packet;
     234             :         } else {
     235           6 :                 pctx->rewrite_packet = none_rewrite_packet;
     236             :         }
     237             :         return GF_OK;
     238             : }
     239             : 
     240             : #ifndef GPAC_DISABLE_HEVC
     241             : 
     242           0 : static GF_Err hevc_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck)
     243             : {
     244             :         u32 size, pck_size, final_size;
     245             :         GF_FilterPacket *dst;
     246             :         u8 *output;
     247           0 :         const u8 *data = gf_filter_pck_get_data(pck, &pck_size);
     248           0 :         if (!data)
     249           0 :                 return gf_filter_pck_forward(pck, pctx->opid);
     250             : 
     251             :         final_size = 0;
     252             :         size=0;
     253           0 :         while (size<pck_size) {
     254             :                 u8 nal_type=0;
     255           0 :                 u32 nal_hdr = pctx->nalu_size_length;
     256             :                 u32 nal_size = 0;
     257           0 :                 while (nal_hdr) {
     258           0 :                         nal_size |= data[size];
     259           0 :                         size++;
     260           0 :                         nal_hdr--;
     261           0 :                         if (!nal_hdr) break;
     262           0 :                         nal_size<<=8;
     263             :                 }
     264           0 :                 nal_type = data[size];
     265           0 :                 nal_type = (nal_type & 0x7E) >> 1;
     266           0 :                 if ((nal_type != GF_HEVC_NALU_SEI_PREFIX) && (nal_type != GF_HEVC_NALU_SEI_SUFFIX) ) {
     267           0 :                         final_size += nal_size+pctx->nalu_size_length;
     268             :                 }
     269           0 :                 size += nal_size;
     270             :         }
     271           0 :         if (final_size == pck_size)
     272           0 :                 return gf_filter_pck_forward(pck, pctx->opid);
     273             : 
     274           0 :         dst = gf_filter_pck_new_alloc(pctx->opid, final_size, &output);
     275           0 :         if (!dst) return GF_OUT_OF_MEM;
     276             :         
     277           0 :         gf_filter_pck_merge_properties(pck, dst);
     278             : 
     279             :         size=0;
     280           0 :         while (size<pck_size) {
     281             :                 u8 nal_type=0;
     282           0 :                 u32 nal_hdr = pctx->nalu_size_length;
     283             :                 u32 nal_size = 0;
     284           0 :                 while (nal_hdr) {
     285           0 :                         nal_size |= data[size];
     286           0 :                         size++;
     287           0 :                         nal_hdr--;
     288           0 :                         if (!nal_hdr) break;
     289           0 :                         nal_size<<=8;
     290             :                 }
     291           0 :                 nal_type = data[size];
     292           0 :                 nal_type = (nal_type & 0x7E) >> 1;
     293           0 :                 if ((nal_type == GF_HEVC_NALU_SEI_PREFIX) || (nal_type == GF_HEVC_NALU_SEI_SUFFIX) ) {
     294           0 :                         size += nal_size;
     295           0 :                         continue;
     296             :                 }
     297           0 :                 memcpy(output, &data[size-pctx->nalu_size_length], pctx->nalu_size_length+nal_size);
     298           0 :                 output += pctx->nalu_size_length+nal_size;
     299           0 :                 size += nal_size;
     300             :         }
     301           0 :         return gf_filter_pck_send(dst);
     302             : }
     303             : 
     304           4 : static GF_Err hevc_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
     305             : {
     306             :         GF_HEVCConfig *hvcc;
     307             :         GF_Err e = GF_OK;
     308             :         u8 *dsi;
     309             :         u32 dsi_size;
     310             :         const GF_PropertyValue *prop;
     311             : 
     312           4 :         prop = gf_filter_pid_get_property(pctx->ipid, GF_PROP_PID_DECODER_CONFIG);
     313           4 :         if (!prop) return GF_OK;
     314           4 :         pctx->reconfigure = GF_FALSE;
     315             : 
     316           4 :         hvcc = gf_odf_hevc_cfg_read(prop->value.data.ptr, prop->value.data.size, (pctx->codec_id==GF_CODECID_LHVC) ? GF_TRUE : GF_FALSE);
     317           4 :         if (pctx->rewrite_vui) {
     318           2 :                 GF_VUIInfo tmp_vui = pctx->vui;
     319           2 :                 tmp_vui.update = GF_TRUE;
     320           2 :                 e = gf_hevc_change_vui(hvcc, &tmp_vui);
     321           2 :                 if (!e) {
     322           2 :                         update_props(pctx, &tmp_vui);
     323             :                 }
     324             :         }
     325             : 
     326           4 :         if (ctx->pidc>=0) hvcc->profile_idc = ctx->pidc;
     327           4 :         if (ctx->pspace>=0) hvcc->profile_space = ctx->pspace;
     328           4 :         if (ctx->gpcflags>=0) hvcc->general_profile_compatibility_flags = ctx->gpcflags;
     329             : 
     330             : 
     331           4 :         gf_odf_hevc_cfg_write(hvcc, &dsi, &dsi_size);
     332           4 :         pctx->nalu_size_length = hvcc->nal_unit_size;
     333           4 :         gf_odf_hevc_cfg_del(hvcc);
     334           4 :         if (e) return e;
     335             : 
     336           4 :         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
     337             : 
     338           4 :         if (ctx->rmsei) {
     339           0 :                 pctx->rewrite_packet = hevc_rewrite_packet;
     340             :         } else {
     341           4 :                 pctx->rewrite_packet = none_rewrite_packet;
     342             :         }
     343             :         return GF_OK;
     344             : }
     345             : #endif // GPAC_DISABLE_HEVC
     346             : 
     347           2 : static GF_Err none_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
     348             : {
     349           2 :         pctx->reconfigure = GF_FALSE;
     350           2 :         return GF_OK;
     351             : }
     352             : 
     353             : static GF_Err rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx)
     354             : {
     355          14 :         GF_Err e = pctx->rewrite_pid_config(ctx, pctx);
     356          14 :         if (e) return e;
     357          14 :         pctx->prev_cprim = pctx->prev_ctfc = pctx->prev_cmx = pctx->prev_sar = -1;
     358             :         return GF_OK;
     359             : }
     360             : 
     361          14 : static void init_vui(GF_BSRWCtx *ctx, BSRWPid *pctx)
     362             : {
     363          14 :         pctx->vui.ar_num = ctx->sar.num;
     364          14 :         pctx->vui.ar_den = ctx->sar.den;
     365          14 :         pctx->vui.color_matrix = ctx->cmx;
     366          14 :         pctx->vui.color_prim = ctx->cprim;
     367          14 :         pctx->vui.fullrange = ctx->fullrange;
     368          14 :         pctx->vui.remove_video_info = ctx->novsi;
     369          14 :         pctx->vui.color_tfc = ctx->ctfc;
     370          14 :         pctx->vui.video_format = ctx->vidfmt;
     371             : 
     372          14 :         pctx->rewrite_vui = GF_TRUE;
     373          14 :         if (ctx->sar.num>=0) return;
     374           6 :         if ((s32) ctx->sar.den>=0) return;
     375           6 :         if (ctx->cmx>-1) return;
     376           6 :         if (ctx->cprim>-1) return;
     377           6 :         if (ctx->fullrange) return;
     378           6 :         if (ctx->novsi) return;
     379           6 :         if (ctx->ctfc>-1) return;
     380           6 :         if (ctx->vidfmt>-1) return;
     381             :         //all default
     382           6 :         pctx->rewrite_vui = GF_FALSE;
     383             : }
     384             : 
     385          31 : static GF_Err prores_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck)
     386             : {
     387             :         u8 *output;
     388          31 :         GF_FilterPacket *dst_pck = gf_filter_pck_new_clone(pctx->opid, pck, &output);
     389          31 :         if (!dst_pck) return GF_OUT_OF_MEM;
     390             :         
     391             :         //starting at offset 20 in frame:
     392             :         /*
     393             :         prores_frame->chroma_format = gf_bs_read_int(bs, 2);
     394             :         gf_bs_read_int(bs, 2);
     395             :         prores_frame->interlaced_mode = gf_bs_read_int(bs, 2);
     396             :         gf_bs_read_int(bs, 2);
     397             :         prores_frame->aspect_ratio_information = gf_bs_read_int(bs, 4);
     398             :         prores_frame->framerate_code = gf_bs_read_int(bs, 4);
     399             :         prores_frame->color_primaries = gf_bs_read_u8(bs);
     400             :         prores_frame->transfer_characteristics = gf_bs_read_u8(bs);
     401             :         prores_frame->matrix_coefficients = gf_bs_read_u8(bs);
     402             :         gf_bs_read_int(bs, 4);
     403             :         prores_frame->alpha_channel_type = gf_bs_read_int(bs, 4);
     404             :         */
     405             : 
     406          31 :         if (ctx->sar.num && ctx->sar.den) {
     407          31 :                 u32 framerate_code = output[21] & 0xF;
     408             :                 u32 new_ar = 0;
     409          31 :                 if (ctx->sar.num==ctx->sar.den) new_ar = 1;
     410          31 :                 else if (ctx->sar.num * 3 == ctx->sar.den * 4) new_ar = 2;
     411          31 :                 else if (ctx->sar.num * 9 == ctx->sar.den * 16) new_ar = 3;
     412             :                 else {
     413           0 :                         if (pctx->prev_sar != new_ar) {
     414           0 :                                 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));
     415             :                         }
     416             :                 }
     417          31 :                 new_ar <<= 4;
     418          31 :                 framerate_code |= new_ar;
     419          31 :                 output[21] = (u8) framerate_code;
     420          31 :                 if (pctx->prev_sar != new_ar) {
     421           1 :                         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(ctx->sar) );
     422           1 :                         pctx->prev_sar = new_ar;
     423             :                 }
     424             :         }
     425          31 :         if (ctx->cprim>=0) {
     426           0 :                 output[22] = (u8) ctx->cprim;
     427           0 :                 if (pctx->prev_cprim != ctx->cprim) {
     428           0 :                         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_PRIMARIES, &PROP_UINT(ctx->cprim) );
     429           0 :                         pctx->prev_cprim = ctx->cprim;
     430             :                 }
     431             :         }
     432          31 :         if (ctx->ctfc>=0) {
     433           0 :                 output[23] = (u8) ctx->ctfc;
     434           0 :                 if (ctx->ctfc != pctx->prev_ctfc) {
     435           0 :                         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_TRANSFER, &PROP_UINT(ctx->ctfc) );
     436           0 :                         pctx->prev_ctfc = ctx->ctfc;
     437             :                 }
     438             :         }
     439          31 :         if (ctx->cmx>=0) {
     440           0 :                 output[24] = (u8) ctx->cmx;
     441           0 :                 if (pctx->prev_cmx != ctx->cmx) {
     442           0 :                         gf_filter_pid_set_property(pctx->opid, GF_PROP_PID_COLR_MX, &PROP_UINT(ctx->cmx) );
     443           0 :                         pctx->prev_cmx = ctx->cmx;
     444             :                 }
     445             :         }
     446          31 :         return gf_filter_pck_send(dst_pck);
     447             : }
     448             : 
     449             : 
     450           7 : static GF_Err bsrw_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     451             : {
     452             :         const GF_PropertyValue *prop;
     453           7 :         GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
     454           7 :         BSRWPid *pctx = gf_filter_pid_get_udta(pid);
     455             : 
     456             :         //disconnect of src pid (not yet supported)
     457           7 :         if (is_remove) {
     458           0 :                 if (pctx) {
     459           0 :                         if (pctx->opid) {
     460           0 :                                 gf_filter_pid_remove(pctx->opid);
     461           0 :                                 pctx->opid = NULL;
     462             :                         }
     463           0 :                         gf_filter_pid_set_udta(pid, NULL);
     464           0 :                         gf_list_del_item(ctx->pids, pctx);
     465           0 :                         gf_free(pctx);
     466             :                 }
     467             :                 return GF_OK;
     468             :         }
     469           7 :         if (! gf_filter_pid_check_caps(pid))
     470             :                 return GF_NOT_SUPPORTED;
     471             : 
     472           7 :         if (!pctx) {
     473           7 :                 GF_SAFEALLOC(pctx, BSRWPid);
     474           7 :                 if (!pctx) return GF_OUT_OF_MEM;
     475           7 :                 pctx->ipid = pid;
     476           7 :                 gf_filter_pid_set_udta(pid, pctx);
     477           7 :                 pctx->rewrite_pid_config = none_rewrite_pid_config;
     478           7 :                 pctx->rewrite_packet = none_rewrite_packet;
     479           7 :                 gf_list_add(ctx->pids, pctx);
     480           7 :                 pctx->opid = gf_filter_pid_new(filter);
     481           7 :                 if (!pctx->opid) return GF_OUT_OF_MEM;
     482           7 :                 init_vui(ctx, pctx);
     483             :         }
     484             : 
     485           7 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
     486             :         assert(prop);
     487           7 :         switch (prop->value.uint) {
     488           3 :         case GF_CODECID_AVC:
     489             :         case GF_CODECID_SVC:
     490             :         case GF_CODECID_MVC:
     491           3 :                 pctx->rewrite_pid_config = avc_rewrite_pid_config;
     492           3 :                 break;
     493             : #ifndef GPAC_DISABLE_HEVC
     494           2 :         case GF_CODECID_HEVC:
     495             :         case GF_CODECID_HEVC_TILES:
     496             :         case GF_CODECID_LHVC:
     497           2 :                 pctx->rewrite_pid_config = hevc_rewrite_pid_config;
     498           2 :                 break;
     499             : #endif
     500           1 :         case GF_CODECID_MPEG4_PART2:
     501           1 :                 pctx->rewrite_pid_config = m4v_rewrite_pid_config;
     502           1 :                 break;
     503           1 :         case GF_CODECID_AP4H:
     504             :         case GF_CODECID_AP4X:
     505             :         case GF_CODECID_APCH:
     506             :         case GF_CODECID_APCN:
     507             :         case GF_CODECID_APCO:
     508             :         case GF_CODECID_APCS:
     509           1 :                 pctx->rewrite_pid_config = none_rewrite_pid_config;
     510           1 :                 pctx->rewrite_packet = prores_rewrite_packet;
     511           1 :                 break;
     512             : 
     513           0 :         default:
     514           0 :                 pctx->rewrite_pid_config = none_rewrite_pid_config;
     515           0 :                 pctx->rewrite_packet = none_rewrite_packet;
     516           0 :                 break;
     517             :         }
     518             : 
     519           7 :         gf_filter_pid_copy_properties(pctx->opid, pctx->ipid);
     520           7 :         pctx->codec_id = prop->value.uint;
     521           7 :         pctx->reconfigure = GF_FALSE;
     522           7 :         gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     523             :         //rewrite asap - waiting for first packet could lead to issues further down the chain, especially for movie fragments
     524             :         //were the init segment could have already been flushed at the time we will dispatch the first packet
     525             :         rewrite_pid_config(ctx, pctx);
     526             :         return GF_OK;
     527             : }
     528             : 
     529             : 
     530        1618 : static GF_Err bsrw_process(GF_Filter *filter)
     531             : {
     532             :         u32 i, count;
     533        1618 :         GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
     534             : 
     535        1618 :         count = gf_filter_get_ipid_count(filter);
     536        3236 :         for (i=0; i<count; i++) {
     537             :                 BSRWPid *pctx;
     538             :                 GF_FilterPacket *pck;
     539        1618 :                 GF_FilterPid *pid = gf_filter_get_ipid(filter, i);
     540        1618 :                 if (!pid) break;
     541        1618 :                 pctx = gf_filter_pid_get_udta(pid);
     542        1618 :                 if (!pctx) break;
     543        1618 :                 if (ctx->reconfigure)
     544           7 :                         pctx->reconfigure = GF_TRUE;
     545             : 
     546        1618 :                 if (pctx->reconfigure) {
     547           7 :                         init_vui(ctx, pctx);
     548             :                         GF_Err e = rewrite_pid_config(ctx, pctx);
     549             :                         if (e) return e;
     550             :                 }
     551        1618 :                 pck = gf_filter_pid_get_packet(pid);
     552        1618 :                 if (!pck) {
     553         314 :                         if (gf_filter_pid_is_eos(pctx->ipid))
     554           7 :                                 gf_filter_pid_set_eos(pctx->opid);
     555         314 :                         continue;
     556             :                 }
     557        1304 :                 pctx->rewrite_packet(ctx, pctx, pck);
     558        1304 :                 gf_filter_pid_drop_packet(pid);
     559             :         }
     560        1618 :         ctx->reconfigure = GF_FALSE;
     561        1618 :         return GF_OK;
     562             : }
     563             : 
     564           0 : static GF_Err bsrw_update_arg(GF_Filter *filter, const char *arg_name, const GF_PropertyValue *new_val)
     565             : {
     566           7 :         GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
     567           7 :         ctx->reconfigure = GF_TRUE;
     568           0 :         return GF_OK;
     569             : }
     570             : 
     571           7 : static GF_Err bsrw_initialize(GF_Filter *filter)
     572             : {
     573           7 :         GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
     574           7 :         ctx->pids = gf_list_new();
     575             : 
     576             : #ifdef GPAC_ENABLE_COVERAGE
     577             :         bsrw_update_arg(filter, NULL, NULL);
     578             : #endif
     579           7 :         return GF_OK;
     580             : }
     581           7 : static void bsrw_finalize(GF_Filter *filter)
     582             : {
     583           7 :         GF_BSRWCtx *ctx = (GF_BSRWCtx *) gf_filter_get_udta(filter);
     584          21 :         while (gf_list_count(ctx->pids)) {
     585           7 :                 BSRWPid *pctx = gf_list_pop_back(ctx->pids);
     586           7 :                 gf_free(pctx);
     587             :         }
     588           7 :         gf_list_del(ctx->pids);
     589           7 : }
     590             : 
     591             : #define OFFS(_n)        #_n, offsetof(GF_BSRWCtx, _n)
     592             : static GF_FilterArgs BSRWArgs[] =
     593             : {
     594             :         ///do not change order of the first 3
     595             :         { OFFS(cprim), "color primaries according to ISO/IEC 23001-8 / 23091-2", GF_PROP_CICP_COL_PRIM, "-1", NULL, GF_FS_ARG_UPDATE},
     596             :         { OFFS(ctfc), "color transfer characteristics according to ISO/IEC 23001-8 / 23091-2", GF_PROP_CICP_COL_TFC, "-1", NULL, GF_FS_ARG_UPDATE},
     597             :         { OFFS(cmx), "color matrix coeficients according to ISO/IEC 23001-8 / 23091-2", GF_PROP_CICP_COL_MX, "-1", NULL, GF_FS_ARG_UPDATE},
     598             :         { OFFS(sar), "aspect ratio to rewrite - see filter help", GF_PROP_FRACTION, "-1/-1", NULL, GF_FS_ARG_UPDATE},
     599             :         { OFFS(m4vpl), "set ProfileLevel for MPEG-4 video part two", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
     600             :         { OFFS(fullrange), "video full range for AVC|H264 and HEVC", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
     601             :         { OFFS(novsi), "remove video_signal_type from VUI in AVC|H264 and HEVC", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
     602             :         { OFFS(prof), "profile indication for AVC|H264", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
     603             :         { OFFS(lev), "level indication for AVC|H264", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
     604             :         { OFFS(pcomp), "profile compatibility for AVC|H264", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
     605             :         { OFFS(pidc), "profile IDC for HEVC", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
     606             :         { OFFS(pspace), "profile space for HEVC", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
     607             :         { OFFS(gpcflags), "general compatibility flags for HEVC", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_UPDATE},
     608             :         { OFFS(rmsei), "remove SEI messages from bitstream for AVC|H264 and HEVC", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE},
     609             :         { OFFS(vidfmt), "video format for AVC|H264 and HEVC", GF_PROP_UINT, "-1", "component|pal|ntsc|secam|mac|undef", GF_FS_ARG_UPDATE},
     610             :         {0}
     611             : };
     612             : 
     613             : static const GF_FilterCapability BSRWCaps[] =
     614             : {
     615             :         //this is correct but we want the filter to act as passthrough for other media
     616             : #if 0
     617             :         CAP_UINT(GF_CAPS_INPUT_STATIC ,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
     618             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED|GF_CAPFLAG_STATIC , GF_PROP_PID_UNFRAMED, GF_TRUE),
     619             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC),
     620             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_SVC),
     621             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_MVC),
     622             :         {0},
     623             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC),
     624             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC_TILES),
     625             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_LHVC),
     626             :         {0},
     627             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2),
     628             :         {0},
     629             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4H),
     630             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4X),
     631             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCH),
     632             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCN),
     633             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCO),
     634             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_APCS),
     635             : #else
     636             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     637             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     638             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     639             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_NONE),
     640             : #endif
     641             : 
     642             : };
     643             : 
     644             : GF_FilterRegister BSRWRegister = {
     645             :         .name = "bsrw",
     646             :         GF_FS_SET_DESCRIPTION("Compressed bitstream rewriter")
     647             :         GF_FS_SET_HELP("This filter rewrites some metadata of various bitstream formats.\n"
     648             :         "The filter can currently modify the following properties in video bitstreams:\n"
     649             :         "- MPEG-4 Visual:\n"
     650             :         "  - sample aspect ratio\n"
     651             :         "  - profile and level\n"
     652             :         "- AVC|H264 and HEVC:\n"
     653             :         "  - sample aspect ratio\n"
     654             :         "  - profile, level, profile compatibility\n"
     655             :         "  - video format, video fullrange\n"
     656             :         "  - color primaries, transfer characteristics and matrix coefficients (or remove all info)\n"
     657             :         "- ProRes:\n"
     658             :         "  - sample aspect ratio\n"
     659             :         "  - color primaries, transfer characteristics and matrix coefficients\n"
     660             :         "  \n"
     661             :         "Values are by default initialized to -1, implying to keep the related info (present or not) in the bitstream.\n"
     662             :         "A [-sar]() value of `0/0` will remove sample aspect ratio info from bitstream if possible.\n"
     663             :         "  \n"
     664             :         "The filter can currently modify the following properties in the stream configuration but not in the bitstream:\n"
     665             :         "- HEVC: profile IDC, profile space, general compatibility flags\n"
     666             :         "  \n"
     667             :         "The filter will work in passthrough mode for all other codecs and media types.\n"
     668             :         )
     669             :         .private_size = sizeof(GF_BSRWCtx),
     670             :         .max_extra_pids = 0xFFFFFFFF,
     671             :         .flags = GF_FS_REG_EXPLICIT_ONLY,
     672             :         .args = BSRWArgs,
     673             :         SETCAPS(BSRWCaps),
     674             :         .initialize = bsrw_initialize,
     675             :         .finalize = bsrw_finalize,
     676             :         .configure_pid = bsrw_configure_pid,
     677             :         .process = bsrw_process,
     678             :         .update_arg = bsrw_update_arg
     679             : };
     680             : 
     681        2877 : const GF_FilterRegister *bsrw_register(GF_FilterSession *session)
     682             : {
     683             :         //assign runtime caps on first load
     684        2877 :         if (gf_opts_get_bool("temp", "helponly")) {
     685          31 :                 BSRWArgs[0].min_max_enum = gf_cicp_color_primaries_all_names();
     686          31 :                 BSRWArgs[1].min_max_enum = gf_cicp_color_transfer_all_names();
     687          31 :                 BSRWArgs[2].min_max_enum = gf_cicp_color_matrix_all_names();
     688             :         }
     689        2877 :         return (const GF_FilterRegister *) &BSRWRegister;
     690             : }

Generated by: LCOV version 1.13