source: titan/libeplayer3/output/writer/mipsel/aac.c @ 42162

Last change on this file since 42162 was 42162, checked in by obi, 6 years ago

update libeplayer3 to v47

File size: 11.7 KB
Line 
1/*
2 * linuxdvb output/writer handling.
3 *
4 * konfetti 2010 based on linuxdvb.c code from libeplayer2
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22/* ***************************** */
23/* Includes                      */
24/* ***************************** */
25
26#include <stdio.h>
27#include <string.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <fcntl.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <sys/ioctl.h>
34#include <linux/dvb/video.h>
35#include <linux/dvb/audio.h>
36#include <memory.h>
37#include <asm/types.h>
38#include <pthread.h>
39#include <errno.h>
40#include <sys/uio.h>
41
42#include <libavutil/intreadwrite.h>
43#include "ffmpeg/latmenc.h"
44
45#include "stm_ioctls.h"
46#include "bcm_ioctls.h"
47
48#include "common.h"
49#include "output.h"
50#include "debug.h"
51#include "misc.h"
52#include "pes.h"
53#include "writer.h"
54#include "aac.h"
55
56/* ***************************** */
57/* Makros/Constants              */
58/* ***************************** */
59
60//#define SAM_WITH_DEBUG
61
62#ifdef SAM_WITH_DEBUG
63#define AAC_DEBUG
64#else
65#define AAC_SILENT
66#endif
67
68#ifdef AAC_DEBUG
69
70static short debug_level = 0;
71
72#define aac_printf(level, fmt, x...) do { \
73if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
74#else
75#define aac_printf(level, fmt, x...)
76#endif
77
78#ifndef AAC_SILENT
79#define aac_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
80#else
81#define aac_err(fmt, x...)
82#endif
83
84/* ***************************** */
85/* Types                         */
86/* ***************************** */
87
88/* ***************************** */
89/* Varaibles                     */
90/* ***************************** */
91
92/// ** AAC ADTS format **
93///
94/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM
95/// MMMMMMMM MMMNNNNN NNNNNNOO ........
96///
97/// Sign            Length          Position         Description
98///
99/// A                12             (31-20)          Sync code
100/// B                 1              (19)            ID
101/// C                 2             (18-17)          layer
102/// D                 1              (16)            protect absent
103/// E                 2             (15-14)          profile
104/// F                 4             (13-10)          sample freq index
105/// G                 1              (9)             private
106/// H                 3             (8-6)            channel config
107/// I                 1              (5)             original/copy
108/// J                 1              (4)             home
109/// K                 1              (3)             copyright id
110/// L                 1              (2)             copyright start
111/// M                 13         (1-0,31-21)         frame length
112/// N                 11           (20-10)           adts buffer fullness
113/// O                 2             (9-8)            num of raw data blocks in frame
114
115/*
116LC: Audio: aac, 44100 Hz, stereo, s16, 192 kb/ ->ff f1 50 80 00 1f fc
117HE: Audio: aac, 48000 Hz, stereo, s16, 77 kb/s ->ff f1 4c 80 00 1f fc
118*/
119
120/*
121ADIF = basic format called Audio Data Interchange Format (ADIF)
122       consisting of a single header followed by the raw AAC audio data blocks
123ADTS = streaming format called Audio Data Transport Stream (ADTS)
124       consisting of a series of frames, each frame having a header followed by the AAC audio data
125LOAS = Low Overhead Audio Stream (LOAS), a self-synchronizing streaming format
126*/
127
128static unsigned char DefaultAACHeader[]    =  {
129    0xff,
130    0xf1,
131    /*0x00, 0x00*/0x50,  //((Profile & 0x03) << 6)  | (SampleIndex << 2) | ((Channels >> 2) & 0x01);s
132    0x80,                //(Channels & 0x03) << 6;
133    0x00,
134    0x1f,
135    0xfc
136};
137
138LATMContext *pLATMCtx = NULL;
139
140/* ***************************** */
141/* Prototypes                    */
142/* ***************************** */
143
144/* ***************************** */
145/* MISC Functions                */
146/* ***************************** */
147
148static int reset()
149{
150    if (pLATMCtx)
151    {
152        free(pLATMCtx);
153        pLATMCtx = NULL;
154    }
155    return 0;
156}
157
158static int _writeData(void *_call, int type)
159{
160    WriterAVCallData_t* call = (WriterAVCallData_t*) _call;
161   
162    aac_printf(10, "\n _writeData type[%d]\n", type);
163
164    if (call == NULL)
165    {
166        aac_err("call data is NULL...\n");
167        return 0;
168    }
169   
170    if ((call->data == NULL) || (call->len < 8))
171    {
172        aac_err("parsing Data with missing AAC header. ignoring...\n");
173        return 0;
174    }
175   
176    /* simple validation */
177    if (0 == type) // check ADTS header
178    {
179        if (0xFF != call->data[0] || 0xF0 != (0xF0 & call->data[1]))
180        {
181            aac_err("parsing Data with missing syncword. ignoring...\n");
182            return 0;
183        }
184       
185        // STB can handle only AAC LC profile
186        if (0 == (call->data[2] & 0xC0))
187        {
188            // change profile AAC Main -> AAC LC (Low Complexity)
189            aac_printf(1, "change profile AAC Main -> AAC LC (Low Complexity) in the ADTS header");
190            call->data[2] = (call->data[2] & 0x1F) | 0x40;
191        }
192    }
193    else // check LOAS header
194    {
195        if( !(call->len > 2 && call->data[0] == 0x56 && (call->data[1] >> 4) == 0xe &&
196            (AV_RB16(call->data + 1) & 0x1FFF) + 3 == call->len))
197        {
198            aac_err("parsing Data with wrong latm header. ignoring...\n");
199            return 0;
200        }
201    }
202   
203    unsigned char PesHeader[PES_MAX_HEADER_SIZE];
204
205    aac_printf(10, "AudioPts %lld\n", call->Pts);
206
207    unsigned int  HeaderLength = InsertPesHeader (PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
208
209    struct iovec iov[2];
210    iov[0].iov_base = PesHeader;
211    iov[0].iov_len = HeaderLength;
212    iov[1].iov_base = call->data;
213    iov[1].iov_len = call->len;
214    return call->WriteV(call->fd, iov, 2);
215}
216
217static int writeDataADTS(void *_call)
218{
219    WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
220   
221    aac_printf(10, "\n");
222
223    if (call == NULL)
224    {
225        aac_err("call data is NULL...\n");
226        return 0;
227    }
228   
229    if ((call->data == NULL) || (call->len <= 0))
230    {
231        aac_err("parsing NULL Data. ignoring...\n");
232        return 0;
233    }
234
235    if (call->fd < 0)
236    {
237        aac_err("file pointer < 0. ignoring ...\n");
238        return 0;
239    }
240   
241    if( (call->private_data && 0 == strncmp("ADTS", call->private_data, call->private_size)) ||
242        HasADTSHeader(call->data, call->len) )
243    {
244        //printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n", call->data[0], call->data[1], call->data[2], call->data[3], call->data[4], call->data[5], call->data[6], call->data[7]);
245        return _writeData(_call, 0);
246    }
247
248    uint32_t PacketLength = call->len + AAC_HEADER_LENGTH;
249    uint8_t PesHeader[PES_MAX_HEADER_SIZE + AAC_HEADER_LENGTH];
250    uint32_t headerSize = InsertPesHeader (PesHeader, PacketLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
251    uint8_t *pExtraData = &PesHeader[headerSize];
252   
253    aac_printf(10, "AudioPts %lld\n", call->Pts);
254    if (call->private_data == NULL)
255    {
256        aac_printf(10, "private_data = NULL\n");
257        memcpy (pExtraData, DefaultAACHeader, AAC_HEADER_LENGTH);
258    }
259    else
260    {
261        memcpy (pExtraData, call->private_data, AAC_HEADER_LENGTH);
262    }
263   
264    pExtraData[3] &= 0xC0;
265    /* frame size over last 2 bits */
266    pExtraData[3] |= (PacketLength & 0x1800) >> 11;
267    /* frame size continued over full byte */
268    pExtraData[4] = (PacketLength & 0x1FF8) >> 3;
269    /* frame size continued first 3 bits */
270    pExtraData[5] = (PacketLength & 7) << 5;
271    /* buffer fullness(0x7FF for VBR) over 5 last bits */
272    pExtraData[5] |= 0x1F;
273    /* buffer fullness(0x7FF for VBR) continued over 6 first bits + 2 zeros for
274     * number of raw data blocks */
275    pExtraData[6] = 0xFC;
276   
277    //PesHeader[6] = 0x81;
278
279    struct iovec iov[2];
280    iov[0].iov_base = PesHeader;
281    iov[0].iov_len = headerSize + AAC_HEADER_LENGTH;
282    iov[1].iov_base = call->data;
283    iov[1].iov_len = call->len;
284   
285    return call->WriteV(call->fd, iov, 2);
286}
287
288static int writeDataLATM(void *_call)
289{
290    WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
291   
292    aac_printf(10, "\n");
293
294    if (call == NULL)
295    {
296        aac_err("call data is NULL...\n");
297        return 0;
298    }
299   
300    if ((call->data == NULL) || (call->len <= 0))
301    {
302        aac_err("parsing NULL Data. ignoring...\n");
303        return 0;
304    }
305   
306    if( call->private_data && 0 == strncmp("LATM", call->private_data, call->private_size))
307    {
308        return _writeData(_call, 1);
309    }
310
311    aac_printf(10, "AudioPts %lld\n", call->Pts);
312   
313    if (!pLATMCtx)
314    {
315        pLATMCtx = malloc(sizeof(LATMContext));
316        memset(pLATMCtx, 0x00, sizeof(LATMContext));
317        pLATMCtx->mod = 14;
318        pLATMCtx->counter = 0;
319    }
320   
321    if (!pLATMCtx)
322    {
323        aac_err("parsing NULL pLATMCtx. ignoring...\n");
324        return 0;
325    }
326   
327    unsigned char PesHeader[PES_MAX_HEADER_SIZE];
328    int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size);
329    if (ret)
330    {
331        printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3],\
332                                                            (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]);
333        aac_err("latm_decode_extradata failed. ignoring...\n");
334        return 0;
335    }
336    ret = latmenc_write_packet(pLATMCtx, call->data, call->len, call->private_data, call->private_size);
337    if (ret)
338    {
339        aac_err("latm_write_packet failed. ignoring...\n");
340        return 0;
341    }
342   
343    unsigned int  HeaderLength = InsertPesHeader (PesHeader,  pLATMCtx->len + 3, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
344
345    struct iovec iov[3];
346    iov[0].iov_base = PesHeader;
347    iov[0].iov_len  = HeaderLength;
348   
349    iov[1].iov_base = pLATMCtx->loas_header;
350    iov[1].iov_len  = 3;
351   
352    iov[2].iov_base = pLATMCtx->buffer;
353    iov[2].iov_len  = pLATMCtx->len;
354   
355    return call->WriteV(call->fd, iov, 3);
356}
357
358/* ***************************** */
359/* Writer  Definition            */
360/* ***************************** */
361
362static WriterCaps_t caps = {
363    "aac",
364    eAudio,
365    "A_AAC",
366    -1,
367    AUDIOTYPE_AAC_PLUS,
368    -1
369};
370
371struct Writer_s WriterAudioAAC = {
372    &reset,
373    &writeDataADTS,
374    NULL,
375    &caps
376};
377
378static WriterCaps_t caps_aac_latm = {
379    "aac",
380    eAudio,
381    "A_AAC_LATM",
382    -1,
383    AUDIOTYPE_AAC_HE, // it is some misunderstanding, this should be AUDIOTYPE_AAC_LATM
384    -1
385};
386
387struct Writer_s WriterAudioAACLATM = {
388    &reset,
389    &writeDataLATM,
390    NULL,
391    &caps_aac_latm
392};
393
394static WriterCaps_t caps_aacplus = {
395    "aac",
396    eAudio,
397    "A_AAC_PLUS",
398    -1,
399    AUDIOTYPE_AAC_PLUS,
400    -1
401};
402
403struct Writer_s WriterAudioAACPLUS = {
404    &reset,
405    &writeDataADTS,
406    NULL,
407    &caps_aacplus
408};
Note: See TracBrowser for help on using the repository browser.