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