source: SHVCSoftware/branches/SHM-upgrade/source/App/utils/BLRewrite/BLRewrite.c @ 915

Last change on this file since 915 was 909, checked in by nokia, 10 years ago

Update BLRewrite tool (JCTVC-R0042).

  • Property svn:eol-style set to native
File size: 7.8 KB
Line 
1/* The copyright in this software is being made available under the BSD
2* License, included below. This software may be subject to other third party
3* and contributor rights, including patent rights, and no such rights are
4* granted under this license.
5*
6* Copyright (c) 2010-2014, ITU/ISO/IEC
7* All rights reserved.
8*
9* Redistribution and use in source and binary forms, with or without
10* modification, are permitted provided that the following conditions are met:
11*
12*  * Redistributions of source code must retain the above copyright notice,
13*    this list of conditions and the following disclaimer.
14*  * Redistributions in binary form must reproduce the above copyright notice,
15*    this list of conditions and the following disclaimer in the documentation
16*    and/or other materials provided with the distribution.
17*  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18*    be used to endorse or promote products derived from this software without
19*    specific prior written permission.
20*
21* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31* THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
34#include <stdlib.h>
35#include <stdio.h>
36
37
38enum NalUnitType
39{
40  NAL_UNIT_CODED_SLICE_TRAIL_N = 0,   // 0
41  NAL_UNIT_CODED_SLICE_TRAIL_R,   // 1
42
43  NAL_UNIT_CODED_SLICE_TSA_N,     // 2
44  NAL_UNIT_CODED_SLICE_TSA_R,       // 3
45
46  NAL_UNIT_CODED_SLICE_STSA_N,    // 4
47  NAL_UNIT_CODED_SLICE_STSA_R,    // 5
48
49  NAL_UNIT_CODED_SLICE_RADL_N,    // 6
50  NAL_UNIT_CODED_SLICE_RADL_R,      // 7
51
52  NAL_UNIT_CODED_SLICE_RASL_N,    // 8
53  NAL_UNIT_CODED_SLICE_RASL_R,      // 9
54
55  NAL_UNIT_RESERVED_VCL_N10,
56  NAL_UNIT_RESERVED_VCL_R11,
57  NAL_UNIT_RESERVED_VCL_N12,
58  NAL_UNIT_RESERVED_VCL_R13,
59  NAL_UNIT_RESERVED_VCL_N14,
60  NAL_UNIT_RESERVED_VCL_R15,
61
62  NAL_UNIT_CODED_SLICE_BLA_W_LP,    // 16
63  NAL_UNIT_CODED_SLICE_BLA_W_RADL,  // 17
64  NAL_UNIT_CODED_SLICE_BLA_N_LP,  // 18
65  NAL_UNIT_CODED_SLICE_IDR_W_RADL,  // 19
66  NAL_UNIT_CODED_SLICE_IDR_N_LP,  // 20
67  NAL_UNIT_CODED_SLICE_CRA,       // 21
68  NAL_UNIT_RESERVED_IRAP_VCL22,
69  NAL_UNIT_RESERVED_IRAP_VCL23,
70
71  NAL_UNIT_RESERVED_VCL24,
72  NAL_UNIT_RESERVED_VCL25,
73  NAL_UNIT_RESERVED_VCL26,
74  NAL_UNIT_RESERVED_VCL27,
75  NAL_UNIT_RESERVED_VCL28,
76  NAL_UNIT_RESERVED_VCL29,
77  NAL_UNIT_RESERVED_VCL30,
78  NAL_UNIT_RESERVED_VCL31,
79
80  NAL_UNIT_VPS,                   // 32
81  NAL_UNIT_SPS,                   // 33
82  NAL_UNIT_PPS,                   // 34
83  NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35
84  NAL_UNIT_EOS,                   // 36
85  NAL_UNIT_EOB,                   // 37
86  NAL_UNIT_FILLER_DATA,           // 38
87  NAL_UNIT_PREFIX_SEI,              // 39
88  NAL_UNIT_SUFFIX_SEI,              // 40
89  NAL_UNIT_RESERVED_NVCL41,
90  NAL_UNIT_RESERVED_NVCL42,
91  NAL_UNIT_RESERVED_NVCL43,
92  NAL_UNIT_RESERVED_NVCL44,
93  NAL_UNIT_RESERVED_NVCL45,
94  NAL_UNIT_RESERVED_NVCL46,
95  NAL_UNIT_RESERVED_NVCL47,
96  NAL_UNIT_UNSPECIFIED_48,
97  NAL_UNIT_UNSPECIFIED_49,
98  NAL_UNIT_UNSPECIFIED_50,
99  NAL_UNIT_UNSPECIFIED_51,
100  NAL_UNIT_UNSPECIFIED_52,
101  NAL_UNIT_UNSPECIFIED_53,
102  NAL_UNIT_UNSPECIFIED_54,
103  NAL_UNIT_UNSPECIFIED_55,
104  NAL_UNIT_UNSPECIFIED_56,
105  NAL_UNIT_UNSPECIFIED_57,
106  NAL_UNIT_UNSPECIFIED_58,
107  NAL_UNIT_UNSPECIFIED_59,
108  NAL_UNIT_UNSPECIFIED_60,
109  NAL_UNIT_UNSPECIFIED_61,
110  NAL_UNIT_UNSPECIFIED_62,
111  NAL_UNIT_UNSPECIFIED_63,
112  NAL_UNIT_INVALID,
113};
114
115typedef struct NalUnitHeader_s
116{
117  int nalUnitType;
118  int nuhLayerId;
119  int nuhTemporalIdPlus1;
120} NalUnitHeader;
121
122
123int findStartCodePrefix(FILE *inFile, int *numStartCodeZeros)
124{
125  int numZeros = 0;
126  int currByte;
127 
128  while (1)
129  {
130    currByte = fgetc(inFile);
131    if (currByte == EOF)
132    {
133      return 0;
134    }
135
136    if (currByte == 0x01 && numZeros > 1)
137    {
138      *numStartCodeZeros = numZeros;
139      return 1;
140    }
141    else if (currByte == 0)
142    {
143      numZeros++;
144    }
145    else
146    {
147      numZeros = 0;
148    }
149  }
150}
151
152int parseNalUnitHeader(FILE *inFile, NalUnitHeader *nalu)
153{
154  int byte0, byte1;
155
156  byte0 = fgetc(inFile);
157  byte1 = fgetc(inFile);
158
159  if (byte0 == EOF || byte1 == EOF)
160  {
161    return 0;
162  }
163
164  nalu->nalUnitType = (byte0 >> 1) & 0x3f;
165  nalu->nuhLayerId  = (((byte0 << 8) | byte1) >> 3) & 0x3f;
166  nalu->nuhTemporalIdPlus1 = byte1 & 0x07;
167
168  return 1;
169}
170
171void writeStartCodePrefixAndNUH(FILE *outFile, int numStartCodeZeros, NalUnitHeader *nalu)
172{
173  int byte0, byte1;
174  int i;
175
176  /* Start code prefix */
177  if (numStartCodeZeros > 3)
178  {
179    numStartCodeZeros = 3;
180  }
181  for (i = 0; i < numStartCodeZeros; i++)
182  {
183    fputc(0, outFile);
184  }
185  fputc(0x01, outFile);
186
187  /* NAL unit header */
188  byte0 = ((nalu->nalUnitType << 6) | nalu->nuhLayerId) >> 5;
189  byte1 = ((nalu->nuhLayerId << 3) | nalu->nuhTemporalIdPlus1) & 0xff;
190  fputc(byte0, outFile);
191  fputc(byte1, outFile);
192}
193
194int main(int argc, char **argv)
195{
196  FILE *inFile;
197  FILE *outFile;
198  int assignedBaseLayerId;
199  int tIdTarget = 6;
200  NalUnitHeader nalu;
201  int numStartCodeZeros;
202  int nalIsSpsPpsEob;
203  int removeNal;
204
205  if (argc < 4 || argc > 5)
206  {
207    fprintf(stderr, "Usage: BLRewrite <infile> <outfile> <assigned base layer ID> [<max temporal ID>]\n");
208    exit(1);
209  }
210
211  inFile = fopen(argv[1], "rb");
212  if (inFile == NULL)
213  {
214    fprintf(stderr, "Cannot open input file %s\n", argv[1]);
215    exit(1);
216  }
217
218  outFile = fopen(argv[2], "wb");
219  if (outFile == NULL)
220  {
221    fprintf(stderr, "Cannot open output file %s\n", argv[2]);
222    exit(1);
223  }
224
225  assignedBaseLayerId = atoi(argv[3]);
226  if (assignedBaseLayerId < 1 || assignedBaseLayerId > 7)
227  {
228    fprintf(stderr, "Invalid assigned base layer ID (must be in range 1-7)\n");
229    exit(1);
230  }
231
232  if (argc == 5)
233  {
234    tIdTarget = atoi(argv[4]);
235    if (tIdTarget < 0 || tIdTarget > 6)
236    {
237      fprintf(stderr, "Invalid maximum temporal ID (must be in range 0-6)\n");
238      exit(1);
239    }
240  }
241
242  while (1)
243  {
244    if (!findStartCodePrefix(inFile, &numStartCodeZeros))
245    {
246      break;
247    }
248    if (!parseNalUnitHeader(inFile, &nalu))
249    {
250      break;
251    }
252
253    printf("NAL unit type: %i,  NUH layer ID: %i,  NUH Temporal ID: %i\n", nalu.nalUnitType, nalu.nuhLayerId, nalu.nuhTemporalIdPlus1 - 1);
254
255    nalIsSpsPpsEob = (nalu.nalUnitType == NAL_UNIT_SPS || nalu.nalUnitType == NAL_UNIT_PPS || nalu.nalUnitType == NAL_UNIT_EOB);
256
257    removeNal = (!nalIsSpsPpsEob && (nalu.nuhLayerId != assignedBaseLayerId))
258             || (nalIsSpsPpsEob && (nalu.nuhLayerId != 0) && (nalu.nuhLayerId != assignedBaseLayerId))
259             || (nalu.nalUnitType == NAL_UNIT_VPS)
260             || ((nalu.nuhTemporalIdPlus1 - 1) > tIdTarget);
261
262    if (!removeNal)
263    {
264      /* Write current NAL unit to output bitstream */
265
266      long naluBytesStartPos;
267      long numNaluBytes;
268      long i;
269
270      nalu.nuhLayerId = 0;
271      writeStartCodePrefixAndNUH(outFile, numStartCodeZeros, &nalu);
272
273      naluBytesStartPos = ftell(inFile);
274      /* Find beginning of the next NAL unit to calculate length of the current unit */
275      if (findStartCodePrefix(inFile, &numStartCodeZeros))
276      {
277        numNaluBytes = ftell(inFile) - naluBytesStartPos - numStartCodeZeros - 1;
278      }
279      else
280      {
281        numNaluBytes = ftell(inFile) - naluBytesStartPos;
282      }
283      fseek(inFile, naluBytesStartPos, SEEK_SET);
284
285      for (i = 0; i < numNaluBytes; i++)
286      {
287        fputc(fgetc(inFile), outFile);
288      }
289    }
290  }
291
292  fclose(inFile);
293  fclose(outFile);
294
295
296  return 0;
297}
Note: See TracBrowser for help on using the repository browser.