MPEGPlayer: Fix leakage of file decriptors if file wasn't accepted by playback engine...
[kugel-rb.git] / apps / codecs / atrac3_oma.c
blob2085466ed53f5dc114d14d87afb1dc44cffe64dd
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 Mohamed Tarek
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <string.h>
24 #include "logf.h"
25 #include "codeclib.h"
26 #include "inttypes.h"
27 #include "libatrac/atrac3.h"
29 CODEC_HEADER
31 #define FRAMESIZE ci->id3->bytesperframe
32 #define BITRATE ci->id3->bitrate
34 static ATRAC3Context q IBSS_ATTR;
36 /* this is the codec entry point */
37 enum codec_status codec_main(void)
39 static size_t buff_size;
40 int datasize, res, frame_counter, total_frames, seek_frame_offset;
41 uint8_t *bit_buffer;
42 int elapsed = 0;
43 size_t resume_offset = ci->id3->offset;
45 next_track:
46 if (codec_init()) {
47 DEBUGF("codec init failed\n");
48 return CODEC_ERROR;
50 while (!*ci->taginfo_ready && !ci->stop_codec)
51 ci->sleep(1);
53 codec_set_replaygain(ci->id3);
54 ci->memset(&q,0,sizeof(ATRAC3Context));
56 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
57 ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */
58 ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ?
59 STEREO_MONO : STEREO_NONINTERLEAVED);
61 res =atrac3_decode_init(&q, ci->id3);
62 if(res < 0) {
63 DEBUGF("failed to initialize OMA atrac decoder\n");
64 return CODEC_ERROR;
67 /* check for a mid-track resume and force a seek time accordingly */
68 if(resume_offset > ci->id3->first_frame_offset) {
69 resume_offset -= ci->id3->first_frame_offset;
70 /* calculate resume_offset in frames */
71 resume_offset = (int)resume_offset / FRAMESIZE;
72 ci->seek_time = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE);
74 total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE;
75 frame_counter = 0;
77 ci->set_elapsed(0);
78 ci->seek_buffer(0);
79 ci->advance_buffer(ci->id3->first_frame_offset);
81 /* The main decoder loop */
82 seek_start :
83 while(frame_counter < total_frames)
85 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
87 ci->yield();
88 if (ci->stop_codec || ci->new_track)
89 goto done;
91 if (ci->seek_time) {
92 ci->set_elapsed(ci->seek_time);
94 /* Do not allow seeking beyond the file's length */
95 if ((unsigned) ci->seek_time > ci->id3->length) {
96 ci->seek_complete();
97 goto done;
100 /* Seek to the start of the track */
101 if (ci->seek_time == 1) {
102 ci->set_elapsed(0);
103 ci->seek_complete();
104 ci->seek_buffer(ci->id3->first_frame_offset);
105 elapsed = 0;
106 goto seek_start;
108 seek_frame_offset = (ci->seek_time * BITRATE) / (8 * FRAMESIZE);
109 frame_counter = seek_frame_offset;
110 ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE);
111 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
112 elapsed = ci->seek_time;
114 ci->set_elapsed(elapsed);
115 ci->seek_complete();
118 res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE);
120 if(res != (int)FRAMESIZE) {
121 DEBUGF("codec error\n");
122 return CODEC_ERROR;
125 if(datasize)
126 ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / ci->id3->channels);
128 elapsed += (FRAMESIZE * 8) / BITRATE;
129 ci->set_elapsed(elapsed);
131 ci->advance_buffer(FRAMESIZE);
132 frame_counter++;
135 done:
136 if (ci->request_next_track())
137 goto next_track;
139 return CODEC_OK;