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