Coverage Report

Created: 2025-07-01 06:21

/src/aac/libMpegTPEnc/src/tpenc_latm.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -----------------------------------------------------------------------------
2
Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4
© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5
Forschung e.V. All rights reserved.
6
7
 1.    INTRODUCTION
8
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9
that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10
scheme for digital audio. This FDK AAC Codec software is intended to be used on
11
a wide variety of Android devices.
12
13
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14
general perceptual audio codecs. AAC-ELD is considered the best-performing
15
full-bandwidth communications codec by independent studies and is widely
16
deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17
specifications.
18
19
Patent licenses for necessary patent claims for the FDK AAC Codec (including
20
those of Fraunhofer) may be obtained through Via Licensing
21
(www.vialicensing.com) or through the respective patent owners individually for
22
the purpose of encoding or decoding bit streams in products that are compliant
23
with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24
Android devices already license these patent claims through Via Licensing or
25
directly from the patent owners, and therefore FDK AAC Codec software may
26
already be covered under those patent licenses when it is used for those
27
licensed purposes only.
28
29
Commercially-licensed AAC software libraries, including floating-point versions
30
with enhanced sound quality, are also available from Fraunhofer. Users are
31
encouraged to check the Fraunhofer website for additional applications
32
information and documentation.
33
34
2.    COPYRIGHT LICENSE
35
36
Redistribution and use in source and binary forms, with or without modification,
37
are permitted without payment of copyright license fees provided that you
38
satisfy the following conditions:
39
40
You must retain the complete text of this software license in redistributions of
41
the FDK AAC Codec or your modifications thereto in source code form.
42
43
You must retain the complete text of this software license in the documentation
44
and/or other materials provided with redistributions of the FDK AAC Codec or
45
your modifications thereto in binary form. You must make available free of
46
charge copies of the complete source code of the FDK AAC Codec and your
47
modifications thereto to recipients of copies in binary form.
48
49
The name of Fraunhofer may not be used to endorse or promote products derived
50
from this library without prior written permission.
51
52
You may not charge copyright license fees for anyone to use, copy or distribute
53
the FDK AAC Codec software or your modifications thereto.
54
55
Your modified versions of the FDK AAC Codec must carry prominent notices stating
56
that you changed the software and the date of any change. For modified versions
57
of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58
must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59
AAC Codec Library for Android."
60
61
3.    NO PATENT LICENSE
62
63
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65
Fraunhofer provides no warranty of patent non-infringement with respect to this
66
software.
67
68
You may use this FDK AAC Codec software or modifications thereto only for
69
purposes that are authorized by appropriate patent licenses.
70
71
4.    DISCLAIMER
72
73
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74
holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75
including but not limited to the implied warranties of merchantability and
76
fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78
or consequential damages, including but not limited to procurement of substitute
79
goods or services; loss of use, data, or profits, or business interruption,
80
however caused and on any theory of liability, whether in contract, strict
81
liability, or tort (including negligence), arising in any way out of the use of
82
this software, even if advised of the possibility of such damage.
83
84
5.    CONTACT INFORMATION
85
86
Fraunhofer Institute for Integrated Circuits IIS
87
Attention: Audio and Multimedia Departments - FDK AAC LL
88
Am Wolfsmantel 33
89
91058 Erlangen, Germany
90
91
www.iis.fraunhofer.de/amm
92
amm-info@iis.fraunhofer.de
93
----------------------------------------------------------------------------- */
94
95
/******************* MPEG transport format encoder library *********************
96
97
   Author(s):
98
99
   Description:
100
101
*******************************************************************************/
102
103
#include "tpenc_latm.h"
104
105
#include "genericStds.h"
106
107
static const short celpFrameLengthTable[64] = {
108
    154, 170, 186, 147, 156, 165, 114, 120, 186, 126, 132, 138, 142,
109
    146, 154, 166, 174, 182, 190, 198, 206, 210, 214, 110, 114, 118,
110
    120, 122, 218, 230, 242, 254, 266, 278, 286, 294, 318, 342, 358,
111
    374, 390, 406, 422, 136, 142, 148, 154, 160, 166, 170, 174, 186,
112
    198, 206, 214, 222, 230, 238, 216, 160, 280, 338, 0,   0};
113
114
/*******
115
 write value to transport stream
116
 first two bits define the size of the value itself
117
 then the value itself, with a size of 0-3 bytes
118
*******/
119
0
static UINT transportEnc_LatmWriteValue(HANDLE_FDK_BITSTREAM hBs, int value) {
120
0
  UCHAR valueBytes = 4;
121
0
  unsigned int bitsWritten = 0;
122
0
  int i;
123
124
0
  if (value < (1 << 8)) {
125
0
    valueBytes = 1;
126
0
  } else if (value < (1 << 16)) {
127
0
    valueBytes = 2;
128
0
  } else if (value < (1 << 24)) {
129
0
    valueBytes = 3;
130
0
  } else {
131
0
    valueBytes = 4;
132
0
  }
133
134
0
  FDKwriteBits(hBs, valueBytes - 1, 2); /* size of value in Bytes */
135
0
  for (i = 0; i < valueBytes; i++) {
136
    /* write most significant Byte first */
137
0
    FDKwriteBits(hBs, (UCHAR)(value >> ((valueBytes - 1 - i) << 3)), 8);
138
0
  }
139
140
0
  bitsWritten = (valueBytes << 3) + 2;
141
142
0
  return bitsWritten;
143
0
}
144
145
0
static UINT transportEnc_LatmCountFixBitDemandHeader(HANDLE_LATM_STREAM hAss) {
146
0
  int bitDemand = 0;
147
0
  int insertSetupData = 0;
148
149
  /* only if start of new latm frame */
150
0
  if (hAss->subFrameCnt == 0) {
151
    /* AudioSyncStream */
152
153
0
    if (hAss->tt == TT_MP4_LOAS) {
154
0
      bitDemand += 11; /* syncword */
155
0
      bitDemand += 13; /* audioMuxLengthBytes */
156
0
    }
157
158
    /* AudioMuxElement*/
159
160
    /* AudioMuxElement::Stream Mux Config */
161
0
    if (hAss->muxConfigPeriod > 0) {
162
0
      insertSetupData = (hAss->latmFrameCounter == 0);
163
0
    } else {
164
0
      insertSetupData = 0;
165
0
    }
166
167
0
    if (hAss->tt != TT_MP4_LATM_MCP0) {
168
      /* AudioMuxElement::useSameStreamMux Flag */
169
0
      bitDemand += 1;
170
171
0
      if (insertSetupData) {
172
0
        bitDemand += hAss->streamMuxConfigBits;
173
0
      }
174
0
    }
175
176
    /* AudioMuxElement::otherDataBits */
177
0
    bitDemand += hAss->otherDataLenBits;
178
179
    /* AudioMuxElement::ByteAlign */
180
0
    if (bitDemand % 8) {
181
0
      hAss->fillBits = 8 - (bitDemand % 8);
182
0
      bitDemand += hAss->fillBits;
183
0
    } else {
184
0
      hAss->fillBits = 0;
185
0
    }
186
0
  }
187
188
0
  return bitDemand;
189
0
}
190
191
static UINT transportEnc_LatmCountVarBitDemandHeader(
192
0
    HANDLE_LATM_STREAM hAss, unsigned int streamDataLength) {
193
0
  int bitDemand = 0;
194
0
  int prog, layer;
195
196
  /* Payload Length Info*/
197
0
  if (hAss->allStreamsSameTimeFraming) {
198
0
    for (prog = 0; prog < hAss->noProgram; prog++) {
199
0
      for (layer = 0; layer < LATM_MAX_LAYERS; layer++) {
200
0
        LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]);
201
202
0
        if (p_linfo->streamID >= 0) {
203
0
          switch (p_linfo->frameLengthType) {
204
0
            case 0:
205
0
              if (streamDataLength > 0) {
206
0
                streamDataLength -= bitDemand;
207
0
                while (streamDataLength >= (255 << 3)) {
208
0
                  bitDemand += 8;
209
0
                  streamDataLength -= (255 << 3);
210
0
                }
211
0
                bitDemand += 8;
212
0
              }
213
0
              break;
214
215
0
            case 1:
216
0
            case 4:
217
0
            case 6:
218
0
              bitDemand += 2;
219
0
              break;
220
221
0
            default:
222
0
              return 0;
223
0
          }
224
0
        }
225
0
      }
226
0
    }
227
0
  } else {
228
    /* there are many possibilities to use this mechanism.  */
229
0
    switch (hAss->varMode) {
230
0
      case LATMVAR_SIMPLE_SEQUENCE: {
231
        /* Use the sequence generated by the encoder */
232
        // int streamCntPosition = transportEnc_SetWritePointer(
233
        // hAss->hAssemble, 0 );  int streamCntPosition = FDKgetValidBits(
234
        // hAss->hAssemble );
235
0
        bitDemand += 4;
236
237
0
        hAss->varStreamCnt = 0;
238
0
        for (prog = 0; prog < hAss->noProgram; prog++) {
239
0
          for (layer = 0; layer < LATM_MAX_LAYERS; layer++) {
240
0
            LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]);
241
242
0
            if (p_linfo->streamID >= 0) {
243
0
              bitDemand += 4; /* streamID */
244
0
              switch (p_linfo->frameLengthType) {
245
0
                case 0:
246
0
                  streamDataLength -= bitDemand;
247
0
                  while (streamDataLength >= (255 << 3)) {
248
0
                    bitDemand += 8;
249
0
                    streamDataLength -= (255 << 3);
250
0
                  }
251
252
0
                  bitDemand += 8;
253
0
                  break;
254
                  /*bitDemand += 1; endFlag
255
                  break;*/
256
257
0
                case 1:
258
0
                case 4:
259
0
                case 6:
260
261
0
                  break;
262
263
0
                default:
264
0
                  return 0;
265
0
              }
266
0
              hAss->varStreamCnt++;
267
0
            }
268
0
          }
269
0
        }
270
0
        bitDemand += 4;
271
        // transportEnc_UpdateBitstreamField( hAss->hAssemble,
272
        // streamCntPosition, hAss->varStreamCnt-1, 4 );  UINT pos =
273
        // streamCntPosition-FDKgetValidBits(hAss->hAssemble);  FDKpushBack(
274
        // hAss->hAssemble,  pos);  FDKwriteBits( hAss->hAssemble,
275
        // hAss->varStreamCnt-1, 4);  FDKpushFor( hAss->hAssemble, pos-4);
276
0
      } break;
277
278
0
      default:
279
0
        return 0;
280
0
    }
281
0
  }
282
283
0
  return bitDemand;
284
0
}
285
286
TRANSPORTENC_ERROR
287
CreateStreamMuxConfig(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs,
288
0
                      int bufferFullness, CSTpCallBacks *cb) {
289
0
  INT streamIDcnt, tmp;
290
0
  int layer, prog;
291
292
0
  USHORT coreFrameOffset = 0;
293
294
0
  hAss->taraBufferFullness = 0xFF;
295
0
  hAss->audioMuxVersionA = 0; /* for future extensions */
296
0
  hAss->streamMuxConfigBits = 0;
297
298
0
  FDKwriteBits(hBs, hAss->audioMuxVersion, 1); /* audioMuxVersion */
299
0
  hAss->streamMuxConfigBits += 1;
300
301
0
  if (hAss->audioMuxVersion == 1) {
302
0
    FDKwriteBits(hBs, hAss->audioMuxVersionA, 1); /* audioMuxVersionA */
303
0
    hAss->streamMuxConfigBits += 1;
304
0
  }
305
306
0
  if (hAss->audioMuxVersionA == 0) {
307
0
    if (hAss->audioMuxVersion == 1) {
308
0
      hAss->streamMuxConfigBits += transportEnc_LatmWriteValue(
309
0
          hBs, hAss->taraBufferFullness); /* taraBufferFullness */
310
0
    }
311
0
    FDKwriteBits(hBs, hAss->allStreamsSameTimeFraming ? 1 : 0,
312
0
                 1);                             /* allStreamsSameTimeFraming */
313
0
    FDKwriteBits(hBs, hAss->noSubframes - 1, 6); /* Number of Subframes */
314
0
    FDKwriteBits(hBs, hAss->noProgram - 1, 4);   /* Number of Programs */
315
316
0
    hAss->streamMuxConfigBits += 11;
317
318
0
    streamIDcnt = 0;
319
0
    for (prog = 0; prog < hAss->noProgram; prog++) {
320
0
      int transLayer = 0;
321
322
0
      FDKwriteBits(hBs, hAss->noLayer[prog] - 1, 3);
323
0
      hAss->streamMuxConfigBits += 3;
324
325
0
      for (layer = 0; layer < LATM_MAX_LAYERS; layer++) {
326
0
        LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]);
327
0
        CODER_CONFIG *p_lci = hAss->config[prog][layer];
328
329
0
        p_linfo->streamID = -1;
330
331
0
        if (hAss->config[prog][layer] != NULL) {
332
0
          int useSameConfig = 0;
333
334
0
          if (transLayer > 0) {
335
0
            FDKwriteBits(hBs, useSameConfig ? 1 : 0, 1);
336
0
            hAss->streamMuxConfigBits += 1;
337
0
          }
338
0
          if ((useSameConfig == 0) || (transLayer == 0)) {
339
0
            const UINT alignAnchor = FDKgetValidBits(hBs);
340
341
0
            if (0 !=
342
0
                (transportEnc_writeASC(hBs, hAss->config[prog][layer], cb))) {
343
0
              return TRANSPORTENC_UNKOWN_ERROR;
344
0
            }
345
346
0
            if (hAss->audioMuxVersion == 1) {
347
0
              UINT ascLen = transportEnc_LatmWriteValue(hBs, 0);
348
0
              FDKbyteAlign(hBs, alignAnchor);
349
0
              ascLen = FDKgetValidBits(hBs) - alignAnchor - ascLen;
350
0
              FDKpushBack(hBs, FDKgetValidBits(hBs) - alignAnchor);
351
352
0
              transportEnc_LatmWriteValue(hBs, ascLen);
353
354
0
              if (0 !=
355
0
                  (transportEnc_writeASC(hBs, hAss->config[prog][layer], cb))) {
356
0
                return TRANSPORTENC_UNKOWN_ERROR;
357
0
              }
358
359
0
              FDKbyteAlign(hBs, alignAnchor); /* asc length fillbits */
360
0
            }
361
362
0
            hAss->streamMuxConfigBits +=
363
0
                FDKgetValidBits(hBs) -
364
0
                alignAnchor; /* add asc length to smc summary */
365
0
          }
366
0
          transLayer++;
367
368
0
          if (!hAss->allStreamsSameTimeFraming) {
369
0
            if (streamIDcnt >= LATM_MAX_STREAM_ID)
370
0
              return TRANSPORTENC_INVALID_CONFIG;
371
0
          }
372
0
          p_linfo->streamID = streamIDcnt++;
373
374
0
          switch (p_lci->aot) {
375
0
            case AOT_AAC_MAIN:
376
0
            case AOT_AAC_LC:
377
0
            case AOT_AAC_SSR:
378
0
            case AOT_AAC_LTP:
379
0
            case AOT_AAC_SCAL:
380
0
            case AOT_ER_AAC_LD:
381
0
            case AOT_ER_AAC_ELD:
382
0
            case AOT_USAC:
383
0
              p_linfo->frameLengthType = 0;
384
385
0
              FDKwriteBits(hBs, p_linfo->frameLengthType,
386
0
                           3);                      /* frameLengthType */
387
0
              FDKwriteBits(hBs, bufferFullness, 8); /* bufferFullness */
388
0
              hAss->streamMuxConfigBits += 11;
389
390
0
              if (!hAss->allStreamsSameTimeFraming) {
391
0
                CODER_CONFIG *p_lci_prev = hAss->config[prog][layer - 1];
392
0
                if (((p_lci->aot == AOT_AAC_SCAL) ||
393
0
                     (p_lci->aot == AOT_ER_AAC_SCAL)) &&
394
0
                    ((p_lci_prev->aot == AOT_CELP) ||
395
0
                     (p_lci_prev->aot == AOT_ER_CELP))) {
396
0
                  FDKwriteBits(hBs, coreFrameOffset, 6); /* coreFrameOffset */
397
0
                  hAss->streamMuxConfigBits += 6;
398
0
                }
399
0
              }
400
0
              break;
401
402
0
            case AOT_TWIN_VQ:
403
0
              p_linfo->frameLengthType = 1;
404
0
              tmp = ((p_lci->bitsFrame + 7) >> 3) -
405
0
                    20; /* transmission frame length in bytes */
406
0
              if ((tmp < 0)) {
407
0
                return TRANSPORTENC_INVALID_TRANSMISSION_FRAME_LENGTH;
408
0
              }
409
0
              FDKwriteBits(hBs, p_linfo->frameLengthType,
410
0
                           3); /* frameLengthType */
411
0
              FDKwriteBits(hBs, tmp, 9);
412
0
              hAss->streamMuxConfigBits += 12;
413
414
0
              p_linfo->frameLengthBits = (tmp + 20) << 3;
415
0
              break;
416
417
0
            case AOT_CELP:
418
0
              p_linfo->frameLengthType = 4;
419
0
              FDKwriteBits(hBs, p_linfo->frameLengthType,
420
0
                           3); /* frameLengthType */
421
0
              hAss->streamMuxConfigBits += 3;
422
0
              {
423
0
                int i;
424
0
                for (i = 0; i < 62; i++) {
425
0
                  if (celpFrameLengthTable[i] == p_lci->bitsFrame) break;
426
0
                }
427
0
                if (i >= 62) {
428
0
                  return TRANSPORTENC_INVALID_CELP_FRAME_LENGTH;
429
0
                }
430
431
0
                FDKwriteBits(hBs, i, 6); /* CELPframeLengthTabelIndex */
432
0
                hAss->streamMuxConfigBits += 6;
433
0
              }
434
0
              p_linfo->frameLengthBits = p_lci->bitsFrame;
435
0
              break;
436
437
0
            case AOT_HVXC:
438
0
              p_linfo->frameLengthType = 6;
439
0
              FDKwriteBits(hBs, p_linfo->frameLengthType,
440
0
                           3); /* frameLengthType */
441
0
              hAss->streamMuxConfigBits += 3;
442
0
              {
443
0
                int i;
444
445
0
                if (p_lci->bitsFrame == 40) {
446
0
                  i = 0;
447
0
                } else if (p_lci->bitsFrame == 80) {
448
0
                  i = 1;
449
0
                } else {
450
0
                  return TRANSPORTENC_INVALID_FRAME_BITS;
451
0
                }
452
0
                FDKwriteBits(hBs, i, 1); /* HVXCframeLengthTableIndex */
453
0
                hAss->streamMuxConfigBits += 1;
454
0
              }
455
0
              p_linfo->frameLengthBits = p_lci->bitsFrame;
456
0
              break;
457
458
0
            case AOT_NULL_OBJECT:
459
0
            default:
460
0
              return TRANSPORTENC_INVALID_AOT;
461
0
          }
462
0
        }
463
0
      }
464
0
    }
465
466
0
    FDKwriteBits(hBs, (hAss->otherDataLenBits > 0) ? 1 : 0,
467
0
                 1); /* otherDataPresent */
468
0
    hAss->streamMuxConfigBits += 1;
469
470
0
    if (hAss->otherDataLenBits > 0) {
471
0
      FDKwriteBits(hBs, 0, 1);
472
0
      FDKwriteBits(hBs, hAss->otherDataLenBits, 8);
473
0
      hAss->streamMuxConfigBits += 9;
474
0
    }
475
476
0
    FDKwriteBits(hBs, 0, 1); /* crcCheckPresent=0 */
477
0
    hAss->streamMuxConfigBits += 1;
478
479
0
  } else { /* if ( audioMuxVersionA == 0 ) */
480
481
    /* for future extensions */
482
0
  }
483
484
0
  return TRANSPORTENC_OK;
485
0
}
486
487
static TRANSPORTENC_ERROR WriteAuPayloadLengthInfo(
488
0
    HANDLE_FDK_BITSTREAM hBitStream, int AuLengthBits) {
489
0
  int restBytes;
490
491
0
  if (AuLengthBits % 8) return TRANSPORTENC_INVALID_AU_LENGTH;
492
493
0
  while (AuLengthBits >= 255 * 8) {
494
0
    FDKwriteBits(hBitStream, 255, 8); /* 255 shows incomplete AU */
495
0
    AuLengthBits -= (255 * 8);
496
0
  }
497
498
0
  restBytes = (AuLengthBits) >> 3;
499
0
  FDKwriteBits(hBitStream, restBytes, 8);
500
501
0
  return TRANSPORTENC_OK;
502
0
}
503
504
static TRANSPORTENC_ERROR transportEnc_LatmSetNrOfSubframes(
505
    HANDLE_LATM_STREAM hAss, INT noSubframes_next) /* nr of access units /
506
                                                      payloads within a latm
507
                                                      frame */
508
0
{
509
  /* sanity chk */
510
0
  if (noSubframes_next < 1 || noSubframes_next > MAX_NR_OF_SUBFRAMES) {
511
0
    return TRANSPORTENC_LATM_INVALID_NR_OF_SUBFRAMES;
512
0
  }
513
514
0
  hAss->noSubframes_next = noSubframes_next;
515
516
  /* if at start then we can take over the value immediately, otherwise we have
517
   * to wait for the next SMC */
518
0
  if ((hAss->subFrameCnt == 0) && (hAss->latmFrameCounter == 0)) {
519
0
    hAss->noSubframes = noSubframes_next;
520
0
  }
521
522
0
  return TRANSPORTENC_OK;
523
0
}
524
525
static int allStreamsSameTimeFraming(HANDLE_LATM_STREAM hAss, UCHAR noProgram,
526
0
                                     UCHAR noLayer[] /* return */) {
527
0
  int prog, layer;
528
529
0
  signed int lastNoSamples = -1;
530
0
  signed int minFrameSamples = FDK_INT_MAX;
531
0
  signed int maxFrameSamples = 0;
532
533
0
  signed int highestSamplingRate = -1;
534
535
0
  for (prog = 0; prog < noProgram; prog++) {
536
0
    noLayer[prog] = 0;
537
538
0
    for (layer = 0; layer < LATM_MAX_LAYERS; layer++) {
539
0
      if (hAss->config[prog][layer] != NULL) {
540
0
        INT hsfSamplesFrame;
541
542
0
        noLayer[prog]++;
543
544
0
        if (highestSamplingRate < 0)
545
0
          highestSamplingRate = hAss->config[prog][layer]->samplingRate;
546
547
0
        hsfSamplesFrame = hAss->config[prog][layer]->samplesPerFrame *
548
0
                          highestSamplingRate /
549
0
                          hAss->config[prog][layer]->samplingRate;
550
551
0
        if (hsfSamplesFrame <= minFrameSamples)
552
0
          minFrameSamples = hsfSamplesFrame;
553
0
        if (hsfSamplesFrame >= maxFrameSamples)
554
0
          maxFrameSamples = hsfSamplesFrame;
555
556
0
        if (lastNoSamples == -1) {
557
0
          lastNoSamples = hsfSamplesFrame;
558
0
        } else {
559
0
          if (hsfSamplesFrame != lastNoSamples) {
560
0
            return 0;
561
0
          }
562
0
        }
563
0
      }
564
0
    }
565
0
  }
566
567
0
  return 1;
568
0
}
569
570
/**
571
 * Initialize LATM/LOAS Stream and add layer 0 at program 0.
572
 */
573
static TRANSPORTENC_ERROR transportEnc_InitLatmStream(
574
    HANDLE_LATM_STREAM hAss, int fractDelayPresent,
575
    signed int
576
        muxConfigPeriod, /* insert setup data every muxConfigPeriod frames */
577
0
    UINT audioMuxVersion, TRANSPORT_TYPE tt) {
578
0
  TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK;
579
580
0
  if (hAss == NULL) return TRANSPORTENC_INVALID_PARAMETER;
581
582
0
  hAss->tt = tt;
583
584
0
  hAss->noProgram = 1;
585
586
0
  hAss->audioMuxVersion = audioMuxVersion;
587
588
  /* Fill noLayer array using hAss->config */
589
0
  hAss->allStreamsSameTimeFraming =
590
0
      allStreamsSameTimeFraming(hAss, hAss->noProgram, hAss->noLayer);
591
  /* Only allStreamsSameTimeFraming==1 is supported */
592
0
  FDK_ASSERT(hAss->allStreamsSameTimeFraming);
593
594
0
  hAss->fractDelayPresent = fractDelayPresent;
595
0
  hAss->otherDataLenBits = 0;
596
597
0
  hAss->varMode = LATMVAR_SIMPLE_SEQUENCE;
598
599
  /* initialize counters */
600
0
  hAss->subFrameCnt = 0;
601
0
  hAss->noSubframes = DEFAULT_LATM_NR_OF_SUBFRAMES;
602
0
  hAss->noSubframes_next = DEFAULT_LATM_NR_OF_SUBFRAMES;
603
604
  /* sync layer related */
605
0
  hAss->audioMuxLengthBytes = 0;
606
607
0
  hAss->latmFrameCounter = 0;
608
0
  hAss->muxConfigPeriod = muxConfigPeriod;
609
610
0
  return ErrorStatus;
611
0
}
612
613
/**
614
 *
615
 */
616
UINT transportEnc_LatmCountTotalBitDemandHeader(HANDLE_LATM_STREAM hAss,
617
0
                                                unsigned int streamDataLength) {
618
0
  UINT bitDemand = 0;
619
620
0
  switch (hAss->tt) {
621
0
    case TT_MP4_LOAS:
622
0
    case TT_MP4_LATM_MCP0:
623
0
    case TT_MP4_LATM_MCP1:
624
0
      if (hAss->subFrameCnt == 0) {
625
0
        bitDemand = transportEnc_LatmCountFixBitDemandHeader(hAss);
626
0
      }
627
0
      bitDemand += transportEnc_LatmCountVarBitDemandHeader(
628
0
          hAss, streamDataLength /*- bitDemand*/);
629
0
      break;
630
0
    default:
631
0
      break;
632
0
  }
633
634
0
  return bitDemand;
635
0
}
636
637
static TRANSPORTENC_ERROR AdvanceAudioMuxElement(HANDLE_LATM_STREAM hAss,
638
                                                 HANDLE_FDK_BITSTREAM hBs,
639
                                                 int auBits, int bufferFullness,
640
0
                                                 CSTpCallBacks *cb) {
641
0
  TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK;
642
0
  int insertMuxSetup;
643
644
  /* Insert setup data to assemble Buffer */
645
0
  if (hAss->subFrameCnt == 0) {
646
0
    if (hAss->muxConfigPeriod > 0) {
647
0
      insertMuxSetup = (hAss->latmFrameCounter == 0);
648
0
    } else {
649
0
      insertMuxSetup = 0;
650
0
    }
651
652
0
    if (hAss->tt != TT_MP4_LATM_MCP0) {
653
0
      if (insertMuxSetup) {
654
0
        FDKwriteBits(hBs, 0, 1); /* useSameStreamMux useNewStreamMux */
655
0
        if (TRANSPORTENC_OK != (ErrorStatus = CreateStreamMuxConfig(
656
0
                                    hAss, hBs, bufferFullness, cb))) {
657
0
          return ErrorStatus;
658
0
        }
659
0
      } else {
660
0
        FDKwriteBits(hBs, 1, 1); /* useSameStreamMux */
661
0
      }
662
0
    }
663
0
  }
664
665
  /* PayloadLengthInfo */
666
0
  {
667
0
    int prog, layer;
668
669
0
    for (prog = 0; prog < hAss->noProgram; prog++) {
670
0
      for (layer = 0; layer < hAss->noLayer[prog]; layer++) {
671
0
        ErrorStatus = WriteAuPayloadLengthInfo(hBs, auBits);
672
0
        if (ErrorStatus != TRANSPORTENC_OK) return ErrorStatus;
673
0
      }
674
0
    }
675
0
  }
676
  /* At this point comes the access unit. */
677
678
0
  return TRANSPORTENC_OK;
679
0
}
680
681
TRANSPORTENC_ERROR
682
transportEnc_LatmWrite(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs,
683
0
                       int auBits, int bufferFullness, CSTpCallBacks *cb) {
684
0
  TRANSPORTENC_ERROR ErrorStatus;
685
686
0
  if (hAss->subFrameCnt == 0) {
687
    /* Start new frame */
688
0
    FDKresetBitbuffer(hBs, BS_WRITER);
689
0
  }
690
691
0
  hAss->latmSubframeStart = FDKgetValidBits(hBs);
692
693
  /* Insert syncword and syncword distance
694
     - only if loas
695
     - we must update the syncword distance (=audiomuxlengthbytes) later
696
   */
697
0
  if (hAss->tt == TT_MP4_LOAS && hAss->subFrameCnt == 0) {
698
    /* Start new LOAS frame */
699
0
    FDKwriteBits(hBs, 0x2B7, 11);
700
0
    hAss->audioMuxLengthBytes = 0;
701
0
    hAss->audioMuxLengthBytesPos =
702
0
        FDKgetValidBits(hBs); /* store read pointer position */
703
0
    FDKwriteBits(hBs, hAss->audioMuxLengthBytes, 13);
704
0
  }
705
706
0
  ErrorStatus = AdvanceAudioMuxElement(hAss, hBs, auBits, bufferFullness, cb);
707
708
0
  if (ErrorStatus != TRANSPORTENC_OK) return ErrorStatus;
709
710
0
  return ErrorStatus;
711
0
}
712
713
0
void transportEnc_LatmAdjustSubframeBits(HANDLE_LATM_STREAM hAss, int *bits) {
714
  /* Substract bits from possible previous subframe */
715
0
  *bits -= hAss->latmSubframeStart;
716
  /* Add fill bits */
717
0
  if (hAss->subFrameCnt == 0) {
718
0
    *bits += hAss->otherDataLenBits;
719
0
    *bits += hAss->fillBits;
720
0
  }
721
0
}
722
723
TRANSPORTENC_ERROR transportEnc_LatmGetFrame(HANDLE_LATM_STREAM hAss,
724
                                             HANDLE_FDK_BITSTREAM hBs,
725
0
                                             int *pBytes) {
726
0
  TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK;
727
728
0
  hAss->subFrameCnt++;
729
0
  if (hAss->subFrameCnt >= hAss->noSubframes) {
730
    /* Add LOAS frame length if required. */
731
0
    if (hAss->tt == TT_MP4_LOAS) {
732
0
      FDK_BITSTREAM tmpBuf;
733
734
      /* Determine frame length info */
735
0
      hAss->audioMuxLengthBytes =
736
0
          ((FDKgetValidBits(hBs) + hAss->otherDataLenBits + 7) >> 3) -
737
0
          3; /* 3=Syncword + length */
738
739
      /* Check frame length info */
740
0
      if (hAss->audioMuxLengthBytes >= (1 << 13)) {
741
0
        ErrorStatus = TRANSPORTENC_INVALID_AU_LENGTH;
742
0
        goto bail;
743
0
      }
744
745
      /* Write length info into assembler buffer */
746
0
      FDKinitBitStream(&tmpBuf, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0,
747
0
                       BS_WRITER);
748
0
      FDKpushFor(&tmpBuf, hAss->audioMuxLengthBytesPos);
749
0
      FDKwriteBits(&tmpBuf, hAss->audioMuxLengthBytes, 13);
750
0
      FDKsyncCache(&tmpBuf);
751
0
    }
752
753
    /* Write AudioMuxElement other data bits */
754
0
    FDKwriteBits(hBs, 0, hAss->otherDataLenBits);
755
756
    /* Write AudioMuxElement byte alignment fill bits */
757
0
    FDKwriteBits(hBs, 0, hAss->fillBits);
758
759
0
    FDK_ASSERT((FDKgetValidBits(hBs) % 8) == 0);
760
761
0
    hAss->subFrameCnt = 0;
762
763
0
    FDKsyncCache(hBs);
764
0
    *pBytes = (FDKgetValidBits(hBs) + 7) >> 3;
765
766
0
    if (hAss->muxConfigPeriod > 0) {
767
0
      hAss->latmFrameCounter++;
768
769
0
      if (hAss->latmFrameCounter >= hAss->muxConfigPeriod) {
770
0
        hAss->latmFrameCounter = 0;
771
0
        hAss->noSubframes = hAss->noSubframes_next;
772
0
      }
773
0
    }
774
0
  } else {
775
    /* No data this time */
776
0
    *pBytes = 0;
777
0
  }
778
779
0
bail:
780
0
  return ErrorStatus;
781
0
}
782
783
/**
784
 * Init LATM/LOAS
785
 */
786
TRANSPORTENC_ERROR transportEnc_Latm_Init(HANDLE_LATM_STREAM hAss,
787
                                          HANDLE_FDK_BITSTREAM hBs,
788
                                          CODER_CONFIG *layerConfig,
789
                                          UINT audioMuxVersion,
790
                                          TRANSPORT_TYPE tt,
791
0
                                          CSTpCallBacks *cb) {
792
0
  TRANSPORTENC_ERROR ErrorStatus;
793
0
  int fractDelayPresent = 0;
794
0
  int prog, layer;
795
796
0
  int setupDataDistanceFrames = layerConfig->headerPeriod;
797
798
0
  FDK_ASSERT(setupDataDistanceFrames >= 0);
799
800
0
  for (prog = 0; prog < LATM_MAX_PROGRAMS; prog++) {
801
0
    for (layer = 0; layer < LATM_MAX_LAYERS; layer++) {
802
0
      hAss->config[prog][layer] = NULL;
803
0
      hAss->m_linfo[prog][layer].streamID = -1;
804
0
    }
805
0
  }
806
807
0
  hAss->config[0][0] = layerConfig;
808
0
  hAss->m_linfo[0][0].streamID = 0;
809
810
0
  ErrorStatus = transportEnc_InitLatmStream(hAss, fractDelayPresent,
811
0
                                            setupDataDistanceFrames,
812
0
                                            (audioMuxVersion) ? 1 : 0, tt);
813
0
  if (ErrorStatus != TRANSPORTENC_OK) goto bail;
814
815
0
  ErrorStatus =
816
0
      transportEnc_LatmSetNrOfSubframes(hAss, layerConfig->nSubFrames);
817
0
  if (ErrorStatus != TRANSPORTENC_OK) goto bail;
818
819
  /* Get the size of the StreamMuxConfig somehow */
820
0
  if (TRANSPORTENC_OK !=
821
0
      (ErrorStatus = AdvanceAudioMuxElement(hAss, hBs, 0, 0, cb))) {
822
0
    goto bail;
823
0
  }
824
825
  // CreateStreamMuxConfig(hAss, hBs, 0);
826
827
0
bail:
828
0
  return ErrorStatus;
829
0
}
830
831
TRANSPORTENC_ERROR transportEnc_LatmAddOtherDataBits(HANDLE_LATM_STREAM hAss,
832
0
                                                     const int otherDataBits) {
833
0
  TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK;
834
835
0
  if ((hAss->otherDataLenBits != 0) || (otherDataBits % 8 != 0)) {
836
    /* This implementation allows to add other data bits only once.
837
       To keep existing alignment only whole bytes are allowed. */
838
0
    ErrorStatus = TRANSPORTENC_UNKOWN_ERROR;
839
0
  } else {
840
    /* Ensure correct addional bits in payload. */
841
0
    if (hAss->tt == TT_MP4_LATM_MCP0) {
842
0
      hAss->otherDataLenBits = otherDataBits;
843
0
    } else {
844
0
      hAss->otherDataLenBits = otherDataBits - 9;
845
0
      hAss->streamMuxConfigBits += 9;
846
0
    }
847
0
  }
848
849
0
  return ErrorStatus;
850
0
}