1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5� Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6  All rights reserved.
7
8 1.    INTRODUCTION
9The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16of the MPEG specifications.
17
18Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20individually for the purpose of encoding or decoding bit streams in products that are compliant with
21the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27applications information and documentation.
28
292.    COPYRIGHT LICENSE
30
31Redistribution and use in source and binary forms, with or without modification, are permitted without
32payment of copyright license fees provided that you satisfy the following conditions:
33
34You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35your modifications thereto in source code form.
36
37You must retain the complete text of this software license in the documentation and/or other materials
38provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40modifications thereto to recipients of copies in binary form.
41
42The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43prior written permission.
44
45You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46software or your modifications thereto.
47
48Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49and the date of any change. For modified versions of the FDK AAC Codec, the term
50"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52
533.    NO PATENT LICENSE
54
55NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57respect to this software.
58
59You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60by appropriate patent licenses.
61
624.    DISCLAIMER
63
64This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69or business interruption, however caused and on any theory of liability, whether in contract, strict
70liability, or tort (including negligence), arising in any way out of the use of this software, even if
71advised of the possibility of such damage.
72
735.    CONTACT INFORMATION
74
75Fraunhofer Institute for Integrated Circuits IIS
76Attention: Audio and Multimedia Departments - FDK AAC LL
77Am Wolfsmantel 33
7891058 Erlangen, Germany
79
80www.iis.fraunhofer.de/amm
81amm-info@iis.fraunhofer.de
82----------------------------------------------------------------------------------------------------------- */
83
84/**************************  MPEG-4 Transport Encoder  ************************
85
86   Author(s): Manuel Jander
87   Description: MPEG Transport encode
88
89******************************************************************************/
90
91#include "tpenc_lib.h"
92
93/* library info */
94#include "version"
95
96#define MODULE_NAME "transportEnc"
97
98#include "tpenc_asc.h"
99#include "conv_string.h"
100
101#include "tpenc_adts.h"
102
103#include "tpenc_adif.h"
104
105#include "tpenc_latm.h"
106
107
108
109typedef struct {
110  int curSubFrame;
111  int nSubFrames;
112  int prevBits;
113} RAWPACKETS_INFO;
114
115struct TRANSPORTENC
116{
117  CODER_CONFIG config;
118  TRANSPORT_TYPE transportFmt;          /*!< MPEG4 transport type. */
119
120  FDK_BITSTREAM bitStream;
121  UCHAR *bsBuffer;
122  INT bsBufferSize;
123
124  INT pceFrameCounter;                  /*!< Indicates frame period when PCE must be written in raw_data_block.
125                                             -1 means not to write a PCE in raw_dat_block. */
126  union {
127    STRUCT_ADTS adts;
128
129    ADIF_INFO adif;
130
131    LATM_STREAM latm;
132
133    RAWPACKETS_INFO raw;
134
135
136
137  } writer;
138
139  CSTpCallBacks callbacks;
140};
141
142typedef struct _TRANSPORTENC_STRUCT TRANSPORTENC_STRUCT;
143
144
145/*
146 * MEMORY Declaration
147 */
148
149C_ALLOC_MEM(Ram_TransportEncoder, TRANSPORTENC, 1)
150
151TRANSPORTENC_ERROR transportEnc_Open( HANDLE_TRANSPORTENC *phTpEnc )
152{
153  HANDLE_TRANSPORTENC hTpEnc;
154
155  if ( phTpEnc == NULL ){
156    return TRANSPORTENC_INVALID_PARAMETER;
157  }
158
159  hTpEnc = GetRam_TransportEncoder(0);
160
161  if ( hTpEnc == NULL ) {
162    return TRANSPORTENC_NO_MEM;
163  }
164
165  *phTpEnc = hTpEnc;
166  return TRANSPORTENC_OK;
167}
168
169/**
170 * \brief  Get frame period of PCE in raw_data_block.
171 *
172 *  - Write PCE only if necessary. PCE can be part of the ASC if chConfig==0 whererfore
173 *    no additonal PCE will be written in raw_data_block.
174 * - A matrixMixdown coefficient can only be written if chConfig is 5.0 or 5.1.
175 * - The PCE repetition rate in raw_data_block can be controlled via headerPeriod parameter.
176 *
177 * \param channelConfig         Channel Configuration derived from Channel Mode
178 * \param transportFmt          Format of the transport to be written.
179 * \param headerPeriod          Chosen PCE frame repetition rate.
180 * \param matrixMixdownA        Indicates if a valid Matrix Mixdown coefficient is available.
181 *
182 * \return  PCE frame repetition rate. -1 means no PCE present in raw_data_block.
183 */
184static INT getPceRepetitionRate(
185        const int            channelConfig,
186        const TRANSPORT_TYPE transportFmt,
187        const int            headerPeriod,
188        const int            matrixMixdownA
189        )
190{
191  INT pceFrameCounter = -1; /* variable to be returned */
192
193  if (headerPeriod>0) {
194    switch ( channelConfig ) {
195      case 0:
196        switch (transportFmt) {
197          case TT_MP4_ADTS:
198          case TT_MP4_LATM_MCP0:
199          case TT_MP4_RAW:
200            pceFrameCounter = headerPeriod;
201            break;
202          case TT_MP4_ADIF:                  /* ADIF header comprises PCE */
203          case TT_MP4_LOAS:                  /* PCE in ASC if chChonfig==0 */
204          case TT_MP4_LATM_MCP1:             /* PCE in ASC if chChonfig==0 */
205          case TT_DRM:                       /* PCE not allowed in DRM */
206          default:
207            pceFrameCounter = -1;            /* no PCE in raw_data_block */
208        }
209        break;
210      case 5: /* MODE_1_2_2 */
211      case 6: /* MODE_1_2_2_1 */
212        /* matrixMixdownCoefficient can only be written if 5.0 and 5.1 config present. */
213        if (matrixMixdownA!=0) {
214          switch (transportFmt) {
215            case TT_MP4_ADIF:                /* ADIF header comprises PCE */
216            case TT_MP4_ADTS:
217            case TT_MP4_LOAS:                /* no PCE in ASC because chConfig!=0 */
218            case TT_MP4_LATM_MCP1:           /* no PCE in ASC because chConfig!=0 */
219            case TT_MP4_LATM_MCP0:
220            case TT_MP4_RAW:
221              pceFrameCounter = headerPeriod;
222              break;
223            case TT_DRM:                     /* PCE not allowed in DRM */
224            default:
225              pceFrameCounter = -1;          /* no PCE in raw_data_block */
226          } /* switch transportFmt */
227        } /* if matrixMixdownA!=0 */
228        break;
229      default:
230        pceFrameCounter = -1;                /* no PCE in raw_data_block */
231    } /* switch getChannelConfig() */
232  } /* if headerPeriod>0  */
233  else {
234    pceFrameCounter = -1;                    /* no PCE in raw_data_block */
235  }
236
237  return pceFrameCounter;
238}
239
240TRANSPORTENC_ERROR transportEnc_Init(
241        HANDLE_TRANSPORTENC hTpEnc,
242        UCHAR             *bsBuffer,
243        INT                bsBufferSize,
244        TRANSPORT_TYPE     transportFmt,
245        CODER_CONFIG      *cconfig,
246        UINT               flags
247        )
248{
249  /* Copy configuration structure */
250  FDKmemcpy(&hTpEnc->config, cconfig, sizeof(CODER_CONFIG));
251
252  /* Init transportEnc struct. */
253  hTpEnc->transportFmt = transportFmt;
254
255  hTpEnc->bsBuffer = bsBuffer;
256  hTpEnc->bsBufferSize = bsBufferSize;
257
258  FDKinitBitStream(&hTpEnc->bitStream, hTpEnc->bsBuffer, hTpEnc->bsBufferSize, 0, BS_WRITER);
259
260  switch (transportFmt) {
261
262  case TT_MP4_ADIF:
263    /* Sanity checks */
264    if ( (hTpEnc->config.aot != AOT_AAC_LC)
265       ||(hTpEnc->config.samplesPerFrame != 1024))
266    {
267      return TRANSPORTENC_INVALID_PARAMETER;
268    }
269    hTpEnc->writer.adif.headerWritten = 0;
270    hTpEnc->writer.adif.samplingRate = hTpEnc->config.samplingRate;
271    hTpEnc->writer.adif.bitRate = hTpEnc->config.bitRate;
272    hTpEnc->writer.adif.profile = ((int)hTpEnc->config.aot) - 1;
273    hTpEnc->writer.adif.cm = hTpEnc->config.channelMode;
274    hTpEnc->writer.adif.bVariableRate = 0;
275    hTpEnc->writer.adif.instanceTag = 0;
276    break;
277
278  case TT_MP4_ADTS:
279    /* Sanity checks */
280    if ( ( hTpEnc->config.aot != AOT_AAC_LC)
281       ||(hTpEnc->config.samplesPerFrame != 1024) )
282    {
283      return TRANSPORTENC_INVALID_PARAMETER;
284    }
285    if ( adtsWrite_Init(&hTpEnc->writer.adts, &hTpEnc->config) != 0) {
286      return TRANSPORTENC_INVALID_PARAMETER;
287    }
288    break;
289
290  case TT_MP4_LOAS:
291  case TT_MP4_LATM_MCP0:
292  case TT_MP4_LATM_MCP1:
293    {
294      TRANSPORTENC_ERROR error;
295
296      error = transportEnc_Latm_Init(
297                &hTpEnc->writer.latm,
298                &hTpEnc->bitStream,
299                &hTpEnc->config,
300                 flags & TP_FLAG_LATM_AMV,
301                 transportFmt,
302                &hTpEnc->callbacks
303                 );
304      if (error != TRANSPORTENC_OK) {
305        return error;
306      }
307    }
308    break;
309
310  case TT_MP4_RAW:
311    hTpEnc->writer.raw.curSubFrame = 0;
312    hTpEnc->writer.raw.nSubFrames = hTpEnc->config.nSubFrames;
313    break;
314
315
316
317  default:
318    return TRANSPORTENC_INVALID_PARAMETER;
319  }
320
321  /* pceFrameCounter indicates if PCE must be written in raw_data_block. */
322  hTpEnc->pceFrameCounter = getPceRepetitionRate(
323                    getChannelConfig(hTpEnc->config.channelMode),
324                    transportFmt,
325                    hTpEnc->config.headerPeriod,
326                    hTpEnc->config.matrixMixdownA);
327
328  return TRANSPORTENC_OK;
329}
330
331HANDLE_FDK_BITSTREAM transportEnc_GetBitstream( HANDLE_TRANSPORTENC hTp )
332{
333  return &hTp->bitStream;
334}
335
336int transportEnc_RegisterSbrCallback( HANDLE_TRANSPORTENC hTpEnc, const cbSbr_t cbSbr, void* user_data)
337{
338  if (hTpEnc == NULL) {
339    return -1;
340  }
341  hTpEnc->callbacks.cbSbr = cbSbr;
342  hTpEnc->callbacks.cbSbrData = user_data;
343  return 0;
344}
345
346
347TRANSPORTENC_ERROR transportEnc_WriteAccessUnit(
348                                               HANDLE_TRANSPORTENC hTp,
349                                               INT frameUsedBits,
350                                               int bufferFullness,
351                                               int ncc
352                                              )
353{
354  TRANSPORTENC_ERROR err = TRANSPORTENC_OK;
355
356  if (!hTp) {
357    return TRANSPORTENC_INVALID_PARAMETER;
358  }
359  HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream;
360
361  /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */
362  if (hTp->pceFrameCounter>=hTp->config.headerPeriod) {
363    frameUsedBits += transportEnc_GetPCEBits(hTp->config.channelMode, hTp->config.matrixMixdownA, 3); /* Consider 3 bits ID signalling in alignment */
364  }
365
366  switch (hTp->transportFmt) {
367    case TT_MP4_ADIF:
368      FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER);
369      adifWrite_EncodeHeader(
370             &hTp->writer.adif,
371              hBs,
372              bufferFullness
373              );
374      break;
375    case TT_MP4_ADTS:
376      bufferFullness /= ncc;                          /* Number of Considered Channels */
377      bufferFullness /= 32;
378      bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */
379      adtsWrite_EncodeHeader(
380             &hTp->writer.adts,
381             &hTp->bitStream,
382              bufferFullness,
383              frameUsedBits
384              );
385      break;
386    case TT_MP4_LOAS:
387    case TT_MP4_LATM_MCP0:
388    case TT_MP4_LATM_MCP1:
389      bufferFullness /= ncc;                         /* Number of Considered Channels */
390      bufferFullness /= 32;
391      bufferFullness = FDKmin(0xFF, bufferFullness); /* Signal variable rate */
392      transportEnc_LatmWrite(
393             &hTp->writer.latm,
394              hBs,
395              frameUsedBits,
396              bufferFullness,
397             &hTp->callbacks
398              );
399    break;
400    case TT_MP4_RAW:
401      if (hTp->writer.raw.curSubFrame >= hTp->writer.raw.nSubFrames) {
402        hTp->writer.raw.curSubFrame = 0;
403        FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER);
404      }
405      hTp->writer.raw.prevBits = FDKgetValidBits(hBs);
406      break;
407    default:
408      err = TRANSPORTENC_UNSUPPORTED_FORMAT;
409      break;
410  }
411
412  /* Write PCE in raw_data_block if required */
413  if (hTp->pceFrameCounter>=hTp->config.headerPeriod) {
414    INT crcIndex = 0;
415    /* Align inside PCE with repsect to the first bit of the raw_data_block() */
416    UINT alignAnchor = FDKgetValidBits(&hTp->bitStream);
417
418    /* Write PCE element ID bits */
419    FDKwriteBits(&hTp->bitStream, ID_PCE, 3);
420
421    if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) {
422      crcIndex = adtsWrite_CrcStartReg(&hTp->writer.adts, &hTp->bitStream, 0);
423    }
424
425    /* Write PCE as first raw_data_block element */
426    transportEnc_writePCE(&hTp->bitStream, hTp->config.channelMode, hTp->config.samplingRate, 0, 1, hTp->config.matrixMixdownA, (hTp->config.flags&CC_PSEUDO_SURROUND)?1:0, alignAnchor);
427
428    if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) {
429      adtsWrite_CrcEndReg(&hTp->writer.adts, &hTp->bitStream, crcIndex);
430    }
431    hTp->pceFrameCounter = 0; /* reset pce frame counter */
432  }
433
434  if (hTp->pceFrameCounter!=-1) {
435    hTp->pceFrameCounter++; /* Update pceFrameCounter only if PCE writing is active. */
436  }
437
438  return err;
439}
440
441
442TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp, int *bits)
443{
444  switch (hTp->transportFmt) {
445    case TT_MP4_LATM_MCP0:
446    case TT_MP4_LATM_MCP1:
447    case TT_MP4_LOAS:
448      transportEnc_LatmAdjustSubframeBits(&hTp->writer.latm, bits);
449      break;
450    case TT_MP4_ADTS:
451      adtsWrite_EndRawDataBlock(&hTp->writer.adts, &hTp->bitStream, bits);
452      break;
453    case TT_MP4_ADIF:
454      /* Substract ADIF header from AU bits, not to be considered. */
455      *bits -= adifWrite_GetHeaderBits(&hTp->writer.adif);
456      hTp->writer.adif.headerWritten = 1;
457      break;
458    case TT_MP4_RAW:
459      *bits -= hTp->writer.raw.prevBits;
460      break;
461    default:
462      break;
463  }
464
465  return TRANSPORTENC_OK;
466}
467
468TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, int *nbytes)
469{
470  HANDLE_FDK_BITSTREAM hBs = &hTpEnc->bitStream;
471
472  switch (hTpEnc->transportFmt) {
473    case TT_MP4_LATM_MCP0:
474    case TT_MP4_LATM_MCP1:
475    case TT_MP4_LOAS:
476      *nbytes = hTpEnc->bsBufferSize;
477      transportEnc_LatmGetFrame(&hTpEnc->writer.latm, hBs, nbytes);
478      break;
479    case TT_MP4_ADTS:
480      if (hTpEnc->writer.adts.currentBlock >= hTpEnc->writer.adts.num_raw_blocks+1) {
481        *nbytes = (FDKgetValidBits(hBs) + 7)>>3;
482        hTpEnc->writer.adts.currentBlock = 0;
483      } else {
484        *nbytes = 0;
485      }
486      break;
487    case TT_MP4_ADIF:
488      FDK_ASSERT((INT)FDKgetValidBits(hBs) >= 0);
489      *nbytes = (FDKgetValidBits(hBs) + 7)>>3;
490      break;
491    case TT_MP4_RAW:
492      FDKsyncCache(hBs);
493      hTpEnc->writer.raw.curSubFrame++;
494      *nbytes = ((FDKgetValidBits(hBs)-hTpEnc->writer.raw.prevBits) + 7)>>3;
495      break;
496    default:
497      break;
498  }
499
500  return TRANSPORTENC_OK;
501}
502
503INT transportEnc_GetStaticBits( HANDLE_TRANSPORTENC hTp, int auBits )
504{
505  INT nbits = 0, nPceBits = 0;
506
507  /* Write PCE within raw_data_block in transport lib. */
508  if (hTp->pceFrameCounter>=hTp->config.headerPeriod) {
509    nPceBits = transportEnc_GetPCEBits(hTp->config.channelMode, hTp->config.matrixMixdownA, 3); /* Consider 3 bits ID signalling in alignment */
510    auBits += nPceBits; /* Adapt required raw_data_block bit consumtpion for AU length information e.g. in LATM/LOAS configuration. */
511  }
512
513  switch (hTp->transportFmt) {
514    case TT_MP4_ADIF:
515    case TT_MP4_RAW:
516      nbits = 0; /* Do not consider the ADIF header into the total bitrate */
517      break;
518    case TT_MP4_ADTS:
519      nbits = adtsWrite_GetHeaderBits(&hTp->writer.adts);
520      break;
521    case TT_MP4_LOAS:
522    case TT_MP4_LATM_MCP0:
523    case TT_MP4_LATM_MCP1:
524      nbits = transportEnc_LatmCountTotalBitDemandHeader( &hTp->writer.latm, auBits );
525      break;
526    default:
527      nbits = 0;
528      break;
529  }
530
531  /* PCE is written in the transport library therefore the bit consumption is part of the transport static bits. */
532  nbits += nPceBits;
533
534  return nbits;
535}
536
537void transportEnc_Close(HANDLE_TRANSPORTENC *phTp)
538{
539  if (phTp != NULL)
540  {
541    if (*phTp != NULL) {
542      FreeRam_TransportEncoder(phTp);
543    }
544  }
545}
546
547int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits)
548{
549  int crcReg = 0;
550
551  switch (hTpEnc->transportFmt) {
552  case TT_MP4_ADTS:
553    crcReg = adtsWrite_CrcStartReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, mBits);
554    break;
555  default:
556    break;
557  }
558
559  return crcReg;
560}
561
562void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg)
563{
564  switch (hTpEnc->transportFmt) {
565  case TT_MP4_ADTS:
566    adtsWrite_CrcEndReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, reg);
567    break;
568  default:
569    break;
570  }
571}
572
573
574TRANSPORTENC_ERROR transportEnc_GetConf(HANDLE_TRANSPORTENC  hTpEnc,
575                                        CODER_CONFIG        *cc,
576                                        FDK_BITSTREAM       *dataBuffer,
577                                        UINT                *confType)
578{
579  TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK;
580  HANDLE_LATM_STREAM hLatmConfig = &hTpEnc->writer.latm;
581
582  *confType = 0; /* set confType variable to default */
583
584  /* write StreamMuxConfig or AudioSpecificConfig depending on format used */
585  switch (hTpEnc->transportFmt)
586  {
587    case TT_MP4_LATM_MCP0:
588    case TT_MP4_LATM_MCP1:
589    case TT_MP4_LOAS:
590      tpErr = CreateStreamMuxConfig(hLatmConfig, dataBuffer, 0, &hTpEnc->callbacks);
591      *confType = 1; /* config is SMC */
592      break;
593    default:
594      if (transportEnc_writeASC(dataBuffer, cc, &hTpEnc->callbacks) != 0) {
595        tpErr = TRANSPORTENC_UNKOWN_ERROR;
596      }
597  }
598
599  return tpErr;
600
601}
602
603TRANSPORTENC_ERROR transportEnc_GetLibInfo( LIB_INFO *info )
604{
605  int i;
606
607  if (info == NULL) {
608    return TRANSPORTENC_INVALID_PARAMETER;
609  }
610  /* search for next free tab */
611  for (i = 0; i < FDK_MODULE_LAST; i++) {
612    if (info[i].module_id == FDK_NONE) break;
613  }
614  if (i == FDK_MODULE_LAST) {
615    return TRANSPORTENC_UNKOWN_ERROR;
616  }
617  info += i;
618
619  info->module_id = FDK_TPENC;
620  info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2);
621  LIB_VERSION_STRING(info);
622  info->build_date = __DATE__;
623  info->build_time = __TIME__;
624  info->title = TP_LIB_TITLE;
625
626  /* Set flags */
627  info->flags = 0
628    | CAPF_ADIF
629    | CAPF_ADTS
630    | CAPF_LATM
631    | CAPF_LOAS
632    | CAPF_RAWPACKETS
633    ;
634
635  return TRANSPORTENC_OK;
636}
637
638