LCOV - code coverage report
Current view: top level - filters - hevcsplit.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 371 449 82.6 %
Date: 2021-04-29 23:48:07 Functions: 13 13 100.0 %

          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             : 

Generated by: LCOV version 1.13