1 /*
2 * Copyright (C) 2009-2015 Christian Heckendorf <heckendorfc@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details->
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "../plugin.h"
19 //#include "mp4ff.h"
20 #include "mp4lib/mp4lib.h"
21 #include <neaacdec.h>
22 #include <stdio.h>
23
24 #define AAC_MAX_CHANNELS (6)
25
26 #include "aacmeta.c"
27
28 static struct aacHandles{
29 volatile unsigned int *total;
30 volatile unsigned int *sample;
31 unsigned int *rate;
32 int framesize;
33 int channels;
34 }h;
35
plugin_open(const char * path,const char * mode)36 static FILE * plugin_open(const char *path, const char *mode){
37 return plugin_std_fopen(path,mode);
38 }
39
plugin_close(FILE * ffd)40 static void plugin_close(FILE *ffd){
41 plugin_std_fclose(ffd);
42 }
43
filetype_by_data(FILE * ffd)44 static int filetype_by_data(FILE *ffd){
45 unsigned char buf[10];
46 fseek(ffd,4*sizeof(buf[0]),SEEK_SET);
47 if(!fread(buf,sizeof(buf),1,ffd))return 0;
48 if(buf[0]=='f' && buf[1]=='t' && buf[2]=='y' && buf[3]=='p'){
49 return 1;
50 }
51 return 0;
52 }
53
plugin_seek(struct playerHandles * ph,int modtime)54 static void plugin_seek(struct playerHandles *ph, int modtime){
55 long ht=0,hs=0;
56 struct aacHandles *h=(struct aacHandles *)ph->dechandle;
57
58 if(ph->dechandle==NULL)return;
59
60 if(modtime==0){
61 *h->sample=0;
62 if(h->total)
63 *h->total=0;
64 snd_clear(ph);
65 return;
66 }
67
68 if(h->total){
69 ht=*h->total;
70 ht+=modtime*((int)*h->rate);
71 }
72
73 hs=*h->sample;
74 hs+=(((int)*h->rate)*modtime)/(h->framesize);
75
76 if(hs<0)
77 hs=0;
78 if(ht<0)
79 ht=0;
80
81 *h->sample=hs;
82 if(h->total)
83 *h->total=ht;
84
85 snd_clear(ph);
86 }
87
GetAACTrack(mp4handle_t * infile)88 static int GetAACTrack(mp4handle_t *infile){
89 int i,ret;
90 int numtracks=mp4lib_total_tracks(infile);
91
92 for(i=0;i<numtracks;i++){
93 unsigned char *buff=NULL;
94 unsigned int buffsize=0;
95
96 mp4AudioSpecificConfig mp4cfg;
97 mp4lib_get_decoder_config(infile,i,&buff,&buffsize);
98
99 if(buff){
100 ret=NeAACDecAudioSpecificConfig(buff,buffsize,&mp4cfg);
101 //free(buff);
102
103 if(ret<0)
104 continue;
105 return i;
106 }
107 }
108 return -1;
109 }
110
111 /**
112 * Check whether the buffer head is an AAC frame, and return the frame
113 * length. Returns 0 if it is not a frame.
114 */
adts_check_frame(const unsigned char * data)115 static size_t adts_check_frame(const unsigned char *data){
116 /* check syncword */
117 if (!((data[0] == 0xFF) && ((data[1] & 0xF6) == 0xF0)))
118 return 0;
119
120 return (((unsigned int)data[3] & 0x3) << 11) |
121 (((unsigned int)data[4]) << 3) |
122 (data[5] >> 5);
123 }
124
fill_buffer(FILE * ffd,char * buf,const int buf_len)125 static size_t fill_buffer(FILE *ffd, char *buf, const int buf_len){
126 size_t length=fread(buf,1,buf_len,ffd);
127 //if(length>0)fprintf(stderr,"\nRead %d\n",length);
128 return length;
129 }
130
131 /**
132 * Find the next AAC frame in the buffer. Returns 0 if no frame is
133 * found or if not enough data is available.
134 */
adts_find_frame(FILE * ffd,char * buf,const int start,const int buf_len)135 static size_t adts_find_frame(FILE *ffd, char *buf, const int start, const int buf_len){
136 char *p, *bp;
137 size_t tmp, bp_len, length, frame_length, next_frame;
138
139 bp=buf;
140 bp_len=0;
141 length=0;
142
143 tmp=fill_buffer(ffd,bp+start,buf_len-start);
144 bp_len=start+tmp;
145 while (1) {
146 if(bp_len<8){
147 if(bp_len>0)
148 memmove(buf,bp,bp_len);
149 usleep(100000);
150 tmp=fill_buffer(ffd,buf+bp_len,buf_len-bp_len);
151 if(tmp==0) // nothing left to get
152 break;
153 bp_len+=tmp;
154 bp=buf;
155 continue;
156 }
157
158 p = memchr(bp, 0xff, bp_len);
159 if (p == NULL){
160 /* No marker found. clear buffer */
161 bp=buf;
162 bp_len=0;
163 continue;
164 }
165
166 if(p>bp){
167 /* discard data before marker */
168 bp_len-=(p-bp);
169 bp=p;
170 }
171
172 /* is it a frame? */
173 frame_length = adts_check_frame((unsigned char*)bp);
174 next_frame = adts_check_frame((unsigned char*)bp+frame_length);
175 if (frame_length == 0 || next_frame == 0) {
176 /* it's just some random 0xff byte; discard it
177 and continue searching */
178 bp++;
179 bp_len--;
180 continue;
181 }
182
183 if(bp_len<frame_length){
184 int cnt=0;
185 /* we don't have a full frame in the buffer. */
186 if(buf_len<frame_length){
187 /* ... and we never will. Clear the buffer and look for the next frame. */
188 /* Should we give up at this point? */
189 fprintf(stderr,"AAC | Buffer too small for this frame\n");
190 bp=buf;
191 bp_len=0;
192 continue;
193 }
194
195 memmove(buf,bp,bp_len);
196 while(cnt<2 && bp_len<frame_length){
197 int i;
198 usleep(100000);
199 bp_len+=i=fill_buffer(ffd,buf+bp_len,buf_len-bp_len);
200 if(i==0)
201 cnt++;
202 }
203 }
204 else
205 memmove(buf,bp,bp_len);
206
207 return frame_length;
208 }
209 return 0;
210 }
211
decodeAAC(struct playerHandles * ph,char * key,int * totaltime,char * o_buf,const int buf_filled,const int bufsize)212 static int decodeAAC(struct playerHandles *ph, char *key, int *totaltime, char *o_buf, const int buf_filled, const int bufsize){
213 unsigned char *buf=(unsigned char*)o_buf;
214 char *out;
215 int fmt,ret,channels,retval=DEC_RET_SUCCESS;
216 unsigned int rate;
217 unsigned char channelchar;
218 unsigned long ratel;
219 char tail[OUTPUT_TAIL_SIZE];
220 NeAACDecFrameInfo hInfo;
221 unsigned int total=0;
222 struct outputdetail *details=ph->outdetail;
223 size_t frame_size;
224 int bufstart=0;
225 uint32_t adts_header=0;
226
227 NeAACDecHandle hAac = NeAACDecOpen();
228 NeAACDecConfigurationPtr config = NeAACDecGetCurrentConfiguration(hAac);
229
230 config->useOldADTSFormat=0;
231 //config->defObjectType=LC;
232 config->outputFormat = FAAD_FMT_16BIT;
233 #ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX
234 config->downMatrix = 1;
235 #endif
236 #ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
237 config->dontUpSampleImplicitSBR = 0;
238 #endif
239
240 if(NeAACDecSetConfiguration(hAac,config)==0){
241 fprintf(stderr,"set conf failed");
242 return DEC_RET_ERROR;
243 }
244
245 fmt=(int)config->outputFormat;
246 if(fmt==FAAD_FMT_16BIT)
247 fmt=16;
248 else if(fmt==FAAD_FMT_24BIT)
249 fmt=24;
250 else if(fmt==FAAD_FMT_32BIT || fmt==FAAD_FMT_FLOAT || fmt==FAAD_FMT_FIXED)
251 fmt=32;
252 else if(fmt==FAAD_FMT_DOUBLE)
253 fmt=64;
254
255 frame_size=adts_find_frame(ph->ffd,(char*)buf,buf_filled,bufsize);
256 adts_header=(((uint32_t*)buf)[0]) >> 6;
257
258 if((ret=NeAACDecInit(hAac,buf,frame_size,&ratel,&channelchar)) == 0){
259 //channels=buf[3]>>6;
260 //fprintf(stderr,"%d %d %d\n\n",((buf[2]>>2)&0xf),channels,(int)channelchar);
261 //if(channels==0)
262 //channels=1;
263 rate=(unsigned int)ratel;
264 channels=(int)channelchar;
265 /*
266 if(channelchar!=channels){
267 rate*=(int)channelchar;
268 rate/=channels;
269 }
270 */
271 }
272 else{
273 fprintf(stderr,"NeAACDecInit error %d\n",ret);
274 channels=2;
275 rate=44100;
276 }
277 snprintf(tail,OUTPUT_TAIL_SIZE,"New format: %dHz %dch",rate, channels);
278 addStatusTail(tail,ph->outdetail);
279
280 snd_param_init(ph,&fmt,&channels,&rate);
281
282 details->totaltime=*totaltime;
283
284 h.total=&total;
285 //h.sample=&sample;
286 h.rate=&rate;
287 h.framesize=frame_size;
288 h.channels=channels;
289
290 ph->dechandle=&h;
291
292
293 #if WITH_ALSA==1
294 #define OUTSIZE_AAC(x) (x/channels)
295 #else
296 #define OUTSIZE_AAC(x) (x*channels)
297 #endif
298
299 do{
300 if(0 && adts_header != (((uint32_t*)buf)[0]) >> 6){
301 adts_header=(((uint32_t*)buf)[0]) >> 6;
302 NeAACDecClose(hAac);
303 if((ret=NeAACDecInit(hAac,buf,bufsize,&ratel,&channelchar)) == 0){
304 channels=(int)channelchar;
305 fmt=(int)config->outputFormat;
306 rate=(unsigned int)ratel;
307 }
308 else{
309 fprintf(stderr,"New format init failed.\n");
310 }
311 }
312 out=(char *)NeAACDecDecode(hAac,&hInfo,buf,bufsize);
313
314 if(hInfo.error>0){
315 fprintf(stderr,"AAC | Error while decoding - %d: %s\n",hInfo.error,NeAACDecGetErrorMessage(hInfo.error));
316 //retval=DEC_RET_ERROR;
317 //break;
318 }
319 else if(hInfo.samples>0){
320 total+=hInfo.samples/channels; // framesize?
321 if(writei_snd(ph,out,OUTSIZE_AAC(hInfo.samples))<0)break;
322
323 details->curtime=total/rate;
324 //details->percent=(sample*100)/numsamples;
325 }
326
327 if(ph->pflag->exit!=DEC_RET_SUCCESS){
328 retval=ph->pflag->exit;
329 break;
330 }
331
332 memmove(buf,buf+frame_size,bufsize-frame_size);
333 bufstart=bufsize-frame_size;
334 frame_size=adts_find_frame(ph->ffd,(char*)buf,bufstart,bufsize);
335 if(frame_size==0){
336 //fprintf(stderr,"\nframe_size==0\n");
337 if(ferror(ph->ffd))
338 retval=DEC_RET_ERROR;
339 else
340 retval=DEC_RET_SUCCESS;
341 writei_snd(ph,out,0); // drain what's in the sound buffer
342 break;
343 }
344 }while(1);
345
346 free(buf);
347 NeAACDecClose(hAac);
348 *totaltime=details->curtime;
349 return retval;
350
351 }
352
decodeMP4(struct playerHandles * ph,char * key,int * totaltime,char * o_buf,const int buf_filled,const int buf_len)353 static int decodeMP4(struct playerHandles *ph, char *key, int *totaltime, char *o_buf, const int buf_filled, const int buf_len){
354 unsigned char *buf=NULL;
355 char *out;
356 int track,fmt,ret,channels,retval=DEC_RET_SUCCESS;
357 unsigned int rate,bufsize;
358 //mp4ff_t infile;
359 mp4handle_t infile;
360 unsigned char channelchar;
361 unsigned long ratel;
362 char tail[OUTPUT_TAIL_SIZE];
363 unsigned int framesize=1024;
364 volatile unsigned int total=0,sample;
365 unsigned int numsamples;
366 struct outputdetail *details;
367 int outsize;
368
369 mp4lib_open(&infile);
370
371 if(mp4lib_parse_meta(ph->ffd,&infile)){
372 fprintf(stderr,"Metadata parsing failed.\n:");
373 mp4lib_close(&infile);
374 return DEC_RET_ERROR;
375 }
376
377 if((track=GetAACTrack(&infile))<0){
378 fprintf(stderr,"getaactrack failed");
379 mp4lib_close(&infile);
380 return DEC_RET_ERROR;
381 }
382
383
384 NeAACDecFrameInfo hInfo;
385 //unsigned long ca = NeAACDecGetCapabilities();
386 //fprintf(stderr,"%x %x %x %x %x %x\n",ca&LC_DEC_CAP,ca&MAIN_DEC_CAP,ca<P_DEC_CAP,ca&LD_DEC_CAP,ca&ERROR_RESILIENCE_CAP,ca&FIXED_POINT_CAP);
387 NeAACDecHandle hAac = NeAACDecOpen();
388 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(hAac);
389 /* TODO: Change values if needed.
390 conf->defObjectType=LC;
391 conf->outputFormat=FAAD_FMT_16BIT;
392 conf->defSampleRate=44100;
393 conf->downMatrix=1;*/
394 if(NeAACDecSetConfiguration(hAac,conf)==0){
395 fprintf(stderr,"set conf failed");
396 mp4lib_close(&infile);
397 return DEC_RET_ERROR;
398 }
399
400 fmt=(int)conf->outputFormat;
401 if(fmt==FAAD_FMT_16BIT)
402 fmt=16;
403 else if(fmt==FAAD_FMT_24BIT)
404 fmt=24;
405 else if(fmt==FAAD_FMT_32BIT || fmt==FAAD_FMT_FLOAT || fmt==FAAD_FMT_FIXED)
406 fmt=32;
407 else if(fmt==FAAD_FMT_DOUBLE)
408 fmt=64;
409
410 mp4lib_get_decoder_config(&infile,track,&buf,&bufsize);
411
412 if((ret=NeAACDecInit2(hAac,buf,bufsize,&ratel,&channelchar)) == 0){
413 channels=(int)channelchar;
414 rate=(unsigned int)ratel;
415 }
416 else{
417 fprintf(stderr,"NeAACDecInit2 error %d\n",ret);
418 channels=2;
419 rate=44100;
420 }
421 //fprintf(stderr,"mp4 %d %d %d\n\n",channels,fmt,rate);
422 snprintf(tail,OUTPUT_TAIL_SIZE,"New format: %dHz %dch",rate, channels);
423 addStatusTail(tail,ph->outdetail);
424
425 mp4AudioSpecificConfig mp4cfg;
426 if(buf){
427 if(NeAACDecAudioSpecificConfig(buf,bufsize,&mp4cfg)>=0){
428 if(mp4cfg.frameLengthFlag==1)framesize=960;
429 if(mp4cfg.sbr_present_flag==1)framesize<<=1;
430 }
431 }
432 //fprintf(stderr,"framesize: %d\n",framesize);
433
434 snd_param_init(ph,&fmt,&channels,&rate);
435
436 numsamples=mp4lib_num_samples(&infile);
437 details=ph->outdetail;
438 details->totaltime=*totaltime;
439
440 h.total=&total;
441 h.sample=&sample;
442 h.rate=&rate;
443 h.framesize=framesize;
444 h.channels=channels;
445
446 ph->dechandle=&h;
447
448 #if WITH_ALSA==1
449 outsize=framesize;
450 #else
451 outsize=framesize*channels*2;
452 #endif
453
454 if(mp4lib_prime_read(ph->ffd,&infile)){
455 fprintf(stderr,"Prime failed\n");
456 }
457 for(sample=0;sample<numsamples;sample++){
458 ret=mp4lib_read_sample(ph->ffd,&infile,sample,&buf,&bufsize);
459 if(ret!=0){
460 fprintf(stderr,"error reading sample\n");
461 retval=DEC_RET_ERROR;
462 break;
463 }
464 out=(char *)NeAACDecDecode(hAac,&hInfo,buf,bufsize);
465
466 total+=hInfo.samples/channels; // framesize?
467 if(hInfo.error!=0){
468 fprintf(stderr,"Error while decoding %d %s\n",hInfo.error,NeAACDecGetErrorMessage(hInfo.error));
469 retval=DEC_RET_ERROR;
470 break;
471 }
472 if(hInfo.samples<1)continue;
473
474 if(writei_snd(ph,out,outsize)<0)break;
475
476 details->curtime=total/rate;
477 details->percent=(sample*100)/numsamples;
478
479 if(ph->pflag->exit!=DEC_RET_SUCCESS){
480 retval=ph->pflag->exit;
481 break;
482 }
483 }
484
485 /* Done decoding, now just clean up and leave. */
486 mp4lib_close(&infile);
487 NeAACDecClose(hAac);
488 *totaltime=details->curtime;
489 return retval;
490 }
491
plugin_run(struct playerHandles * ph,char * key,int * totaltime)492 static int plugin_run(struct playerHandles *ph, char *key, int *totaltime){
493 char *buf=NULL;
494 int bufsize=FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS;
495 int frame_size;
496
497 if(!(buf=malloc(bufsize)))
498 return DEC_RET_ERROR;
499
500 frame_size=fill_buffer(ph->ffd,buf,8);
501
502 if(buf[4]=='f' && buf[5]=='t' && buf[6]=='y' && buf[7]=='p'){
503 fseek(ph->ffd,0,SEEK_SET);
504 return decodeMP4(ph,key,totaltime,buf,frame_size,bufsize);
505 }
506 else{
507 return decodeAAC(ph,key,totaltime,buf,frame_size,bufsize);
508 }
509 }
510
511 struct pluginitem aacitem={
512 .modopen=plugin_open,
513 .modclose=plugin_close,
514 .modmeta=aac_plugin_meta,
515 .moddata=filetype_by_data,
516 .modplay=plugin_run,
517 .modseek=plugin_seek,
518 .contenttype="aac;aacp;mp4",
519 .extension={"m4a","m4b","aac","mp4",NULL},
520 .name="AAC",
521 };
522