Imported Debian version 0.1.3.1
[deb_fdk-aac.git] / libMpegTPEnc / src / tpenc_lib.cpp
1
2 /* -----------------------------------------------------------------------------------------------------------
3 Software 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
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@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;
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 */
184 static 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
240 TRANSPORTENC_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
331 HANDLE_FDK_BITSTREAM transportEnc_GetBitstream( HANDLE_TRANSPORTENC hTp )
332 {
333 return &hTp->bitStream;
334 }
335
336 int 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
347 TRANSPORTENC_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
442 TRANSPORTENC_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
468 TRANSPORTENC_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
503 INT 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
537 void transportEnc_Close(HANDLE_TRANSPORTENC *phTp)
538 {
539 if (phTp != NULL)
540 {
541 if (*phTp != NULL) {
542 FreeRam_TransportEncoder(phTp);
543 }
544 }
545 }
546
547 int 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
562 void 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
574 TRANSPORTENC_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
603 TRANSPORTENC_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