11004
|
1 /*
|
|
2 * This is FLAC decoder for MPlayer using stream_decoder from libFLAC
|
|
3 * (directly or from libmpflac).
|
|
4 * This file is part of MPlayer, see http://mplayerhq.hu/ for info.
|
|
5 * Copyright (C) 2003 Dmitry Baryshkov <mitya at school.ioffe.ru>
|
|
6 *
|
|
7 * This program is free software; you can redistribute it and/or modify
|
|
8 * it under the terms of the GNU General Public License as published by
|
|
9 * the Free Software Foundation; either version 2 of the License, or
|
|
10 * (at your option) any later version.
|
|
11 *
|
|
12 * This program is distributed in the hope that it will be useful,
|
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 * GNU General Public License for more details.
|
|
16 *
|
|
17 * You should have received a copy of the GNU General Public License
|
|
18 * along with this program; if not, write to the Free Software
|
|
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
20 *
|
|
21 * parse_double_, grabbag__replaygain_load_from_vorbiscomment, grabbag__replaygain_compute_scale_factor
|
|
22 * functions are imported from FLAC project (from grabbag lib sources (replaygain.c)) and are
|
|
23 * Copyright (C) 2002,2003 Josh Coalson under the terms of GPL.
|
|
24 */
|
|
25
|
|
26 /*
|
|
27 * TODO:
|
|
28 * in demux_audio use data from seektable block for seeking.
|
|
29 * support FLAC-in-Ogg.
|
|
30 */
|
|
31
|
|
32 #include <stdio.h>
|
|
33 #include <stdlib.h>
|
|
34 #include <unistd.h>
|
|
35 #include <math.h>
|
|
36
|
|
37 #include "config.h"
|
|
38 #ifdef HAVE_FLAC
|
|
39 #include "ad_internal.h"
|
|
40 #include "mp_msg.h"
|
|
41
|
|
42 static ad_info_t info = {
|
|
43 "FLAC audio decoder", // name of the driver
|
|
44 "flac", // driver name. should be the same as filename without ad_
|
|
45 "Dmitry Baryshkov", // writer/maintainer of _this_ file
|
|
46 "http://flac.sf.net/", // writer/maintainer/site of the _codec_
|
|
47 "" // comments
|
|
48 };
|
|
49
|
|
50 LIBAD_EXTERN(flac)
|
|
51
|
|
52 #ifdef USE_MPFLAC_DECODER
|
|
53 #include "FLAC_stream_decoder.h"
|
|
54 #include "FLAC_assert.h"
|
|
55 #include "FLAC_metadata.h"
|
|
56 #else
|
|
57 #include "FLAC/stream_decoder.h"
|
|
58 #include "FLAC/assert.h"
|
|
59 #include "FLAC/metadata.h"
|
|
60 #endif
|
|
61
|
|
62 /* dithering & replaygain always from libmpflac */
|
|
63 #include "dither.h"
|
|
64 #include "replaygain_synthesis.h"
|
|
65
|
|
66 /* Some global constants. Thay have to be configurable, so leaved them as globals. */
|
|
67 static const FLAC__bool album_mode = true;
|
|
68 static const int preamp = 0;
|
|
69 static const FLAC__bool hard_limit = false;
|
|
70 static const int noise_shaping = 1;
|
|
71 static const FLAC__bool dither = true;
|
|
72 typedef struct flac_struct_st
|
|
73 {
|
|
74 FLAC__StreamDecoder *flac_dec; /*decoder handle*/
|
|
75 sh_audio_t *sh; /* link back to corresponding sh */
|
|
76
|
|
77 /* set this fields before calling FLAC__stream_decoder_process_single */
|
|
78 unsigned char *buf;
|
|
79 int minlen;
|
|
80 int maxlen;
|
|
81 /* Here goes number written at write_callback */
|
|
82 int written;
|
|
83
|
|
84 /* replaygain and dithering via plugin_common */
|
|
85 FLAC__bool has_replaygain;
|
|
86 double replay_scale;
|
|
87 DitherContext dither_context;
|
|
88 int bits_per_sample;
|
|
89 } flac_struct_t;
|
|
90
|
|
91 FLAC__StreamDecoderReadStatus flac_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
|
92 {
|
|
93 int b = demux_read_data(((flac_struct_t*)client_data)->sh->ds, buffer, *bytes);
|
|
94 mp_msg(MSGT_DECAUDIO, MSGL_DBG2, "\nread %d bytes\n", b);
|
|
95 *bytes = b;
|
|
96 if (b <= 0)
|
|
97 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
|
98 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
|
99 }
|
|
100
|
|
101 /*FIXME: we need to support format conversion:(flac specs allow bits/sample to be from 4 to 32. Not only 8 and 16 !!!)*/
|
|
102 FLAC__StreamDecoderWriteStatus flac_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
|
103 {
|
|
104 FLAC__byte *buf = ((flac_struct_t*)(client_data))->buf;
|
|
105 int channel, sample;
|
|
106 int bps = ((flac_struct_t*)(client_data))->sh->samplesize;
|
|
107 mp_msg(MSGT_DECAUDIO, MSGL_DBG2, "\nWrite callback (%d bytes)!!!!\n", bps*frame->header.blocksize*frame->header.channels);
|
|
108 if (buf == NULL)
|
|
109 {
|
|
110 /* This is used in control for skipping 1 audio frame */
|
|
111 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
|
112 }
|
|
113 #if 0
|
|
114 for (sample = 0; sample < frame->header.blocksize; sample ++)
|
|
115 for (channel = 0; channel < frame->header.channels; channel ++)
|
|
116 switch (bps)
|
|
117 {
|
|
118 case 3:
|
|
119 buf[bps*(sample*frame->header.channels+channel)+2] = (FLAC__byte)(buffer[channel][sample]>>16);
|
|
120 case 2:
|
|
121 buf[bps*(sample*frame->header.channels+channel)+1] = (FLAC__byte)(buffer[channel][sample]>>8);
|
|
122 buf[bps*(sample*frame->header.channels+channel)+0] = (FLAC__byte)(buffer[channel][sample]);
|
|
123 break;
|
|
124 case 1:
|
|
125 buf[bps*(sample*frame->header.channels+channel)] = buffer[channel][sample]^0x80;
|
|
126 break;
|
|
127 }
|
|
128 #else
|
|
129 FLAC__plugin_common__apply_gain(
|
|
130 buf,
|
|
131 buffer,
|
|
132 frame->header.blocksize,
|
|
133 frame->header.channels,
|
|
134 ((flac_struct_t*)(client_data))->bits_per_sample,
|
|
135 ((flac_struct_t*)(client_data))->sh->samplesize * 8,
|
|
136 ((flac_struct_t*)(client_data))->replay_scale,
|
|
137 hard_limit,
|
|
138 dither,
|
|
139 &(((flac_struct_t*)(client_data))->dither_context)
|
|
140 );
|
|
141 #endif
|
|
142 ((flac_struct_t*)(client_data))->written += bps*frame->header.blocksize*frame->header.channels;
|
|
143 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
|
144 }
|
|
145
|
|
146 #ifdef local_min
|
|
147 #undef local_min
|
|
148 #endif
|
|
149 #define local_min(a,b) ((a)<(b)?(a):(b))
|
|
150
|
|
151 static FLAC__bool parse_double_(const FLAC__StreamMetadata_VorbisComment_Entry *entry, double *val)
|
|
152 {
|
|
153 char s[32], *end;
|
|
154 const char *p, *q;
|
|
155 double v;
|
|
156
|
|
157 FLAC__ASSERT(0 != entry);
|
|
158 FLAC__ASSERT(0 != val);
|
|
159
|
|
160 p = (const char *)entry->entry;
|
|
161 q = strchr(p, '=');
|
|
162 if(0 == q)
|
|
163 return false;
|
|
164 q++;
|
|
165 memset(s, 0, sizeof(s)-1);
|
|
166 strncpy(s, q, local_min(sizeof(s)-1, entry->length - (q-p)));
|
|
167
|
|
168 v = strtod(s, &end);
|
|
169 if(end == s)
|
|
170 return false;
|
|
171
|
|
172 *val = v;
|
|
173 return true;
|
|
174 }
|
|
175
|
|
176 FLAC__bool grabbag__replaygain_load_from_vorbiscomment(const FLAC__StreamMetadata *block, FLAC__bool album_mode, double *gain, double *peak)
|
|
177 {
|
|
178 int gain_offset, peak_offset;
|
|
179 static const FLAC__byte *tag_title_gain_ = "REPLAYGAIN_TRACK_GAIN";
|
|
180 static const FLAC__byte *tag_title_peak_ = "REPLAYGAIN_TRACK_PEAK";
|
|
181 static const FLAC__byte *tag_album_gain_ = "REPLAYGAIN_ALBUM_GAIN";
|
|
182 static const FLAC__byte *tag_album_peak_ = "REPLAYGAIN_ALBUM_PEAK";
|
|
183
|
|
184 FLAC__ASSERT(0 != block);
|
|
185 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
|
186
|
|
187 if(0 > (gain_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? tag_album_gain_ : tag_title_gain_))))
|
|
188 return false;
|
|
189 if(0 > (peak_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? tag_album_peak_ : tag_title_peak_))))
|
|
190 return false;
|
|
191
|
|
192 if(!parse_double_(block->data.vorbis_comment.comments + gain_offset, gain))
|
|
193 return false;
|
|
194 if(!parse_double_(block->data.vorbis_comment.comments + peak_offset, peak))
|
|
195 return false;
|
|
196
|
|
197 return true;
|
|
198 }
|
|
199
|
|
200 double grabbag__replaygain_compute_scale_factor(double peak, double gain, double preamp, FLAC__bool prevent_clipping)
|
|
201 {
|
|
202 double scale;
|
|
203 FLAC__ASSERT(peak >= 0.0);
|
|
204 gain += preamp;
|
|
205 scale = (float) pow(10.0, gain * 0.05);
|
|
206 if(prevent_clipping && peak > 0.0) {
|
|
207 const double max_scale = (float)(1.0 / peak);
|
|
208 if(scale > max_scale)
|
|
209 scale = max_scale;
|
|
210 }
|
|
211 return scale;
|
|
212 }
|
|
213
|
|
214 void flac_metadata_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
|
215 {
|
|
216 int i, j;
|
|
217 sh_audio_t *sh = ((flac_struct_t*)client_data)->sh;
|
|
218 mp_msg(MSGT_DECAUDIO, MSGL_DBG2, "Metadata received\n");
|
|
219 switch (metadata->type)
|
|
220 {
|
|
221 case FLAC__METADATA_TYPE_STREAMINFO:
|
|
222 mp_msg(MSGT_DECAUDIO, MSGL_V, "STREAMINFO block (%u bytes):\n", metadata->length);
|
|
223 mp_msg(MSGT_DECAUDIO, MSGL_V, "min_blocksize: %u samples\n", metadata->data.stream_info.min_blocksize);
|
|
224 mp_msg(MSGT_DECAUDIO, MSGL_V, "max_blocksize: %u samples\n", metadata->data.stream_info.max_blocksize);
|
|
225 mp_msg(MSGT_DECAUDIO, MSGL_V, "min_framesize: %u bytes\n", metadata->data.stream_info.min_framesize);
|
|
226 mp_msg(MSGT_DECAUDIO, MSGL_V, "max_framesize: %u bytes\n", metadata->data.stream_info.max_framesize);
|
|
227 mp_msg(MSGT_DECAUDIO, MSGL_V, "sample_rate: %u Hz\n", metadata->data.stream_info.sample_rate);
|
|
228 sh->samplerate = metadata->data.stream_info.sample_rate;
|
|
229 mp_msg(MSGT_DECAUDIO, MSGL_V, "channels: %u\n", metadata->data.stream_info.channels);
|
|
230 sh->channels = metadata->data.stream_info.channels;
|
|
231 mp_msg(MSGT_DECAUDIO, MSGL_V, "bits_per_sample: %u\n", metadata->data.stream_info.bits_per_sample);
|
|
232 ((flac_struct_t*)client_data)->bits_per_sample = metadata->data.stream_info.bits_per_sample;
|
|
233 sh->samplesize = (metadata->data.stream_info.bits_per_sample<=8)?1:2;
|
|
234 /* FIXME: need to support dithering to samplesize 4 */
|
|
235 sh->sample_format=(sh->samplesize==1)?AFMT_U8:AFMT_S16_LE; // sample format, see libao2/afmt.h
|
|
236 sh->o_bps = sh->samplesize * metadata->data.stream_info.channels * metadata->data.stream_info.sample_rate;
|
|
237 sh->i_bps = metadata->data.stream_info.bits_per_sample * metadata->data.stream_info.channels * metadata->data.stream_info.sample_rate / 8 / 2;
|
|
238 // input data rate (compressed bytes per second)
|
|
239 // Compression rate is near 0.5
|
|
240 mp_msg(MSGT_DECAUDIO, MSGL_V, "total_samples: %llu\n", metadata->data.stream_info.total_samples);
|
|
241 mp_msg(MSGT_DECAUDIO, MSGL_V, "md5sum: ");
|
|
242 for (i = 0; i < 16; i++)
|
|
243 mp_msg(MSGT_DECAUDIO, MSGL_V, "%02hhx", metadata->data.stream_info.md5sum[i]);
|
|
244 mp_msg(MSGT_DECAUDIO, MSGL_V, "\n");
|
|
245
|
|
246 break;
|
|
247 case FLAC__METADATA_TYPE_PADDING:
|
|
248 mp_msg(MSGT_DECAUDIO, MSGL_V, "PADDING block (%u bytes)\n", metadata->length);
|
|
249 break;
|
|
250 case FLAC__METADATA_TYPE_APPLICATION:
|
|
251 mp_msg(MSGT_DECAUDIO, MSGL_V, "APPLICATION block (%u bytes):\n", metadata->length);
|
|
252 mp_msg(MSGT_DECAUDIO, MSGL_V, "Application id: 0x");
|
|
253 for (i = 0; i < 4; i++)
|
|
254 mp_msg(MSGT_DECAUDIO, MSGL_V, "%02hhx", metadata->data.application.id[i]);
|
|
255 mp_msg(MSGT_DECAUDIO, MSGL_V, "\nData: \n");
|
|
256 for (i = 0; i < (metadata->length-4)/8; i++)
|
|
257 {
|
|
258 for(j = 0; j < 8; j++)
|
|
259 mp_msg(MSGT_DECAUDIO, MSGL_V, "%c", (unsigned char)metadata->data.application.data[i*8+j]<0x20?'.':metadata->data.application.data[i*8+j]);
|
|
260 mp_msg(MSGT_DECAUDIO, MSGL_V, " | ");
|
|
261 for(j = 0; j < 8; j++)
|
|
262 mp_msg(MSGT_DECAUDIO, MSGL_V, "%#02hhx ", metadata->data.application.data[i*8+j]);
|
|
263 mp_msg(MSGT_DECAUDIO, MSGL_V, "\n");
|
|
264 }
|
|
265 if (metadata->length-4-i*8 != 0)
|
|
266 {
|
|
267 for(j = 0; j < metadata->length-4-i*8; j++)
|
|
268 mp_msg(MSGT_DECAUDIO, MSGL_V, "%c", (unsigned char)metadata->data.application.data[i*8+j]<0x20?'.':metadata->data.application.data[i*8+j]);
|
|
269 for(; j <8; j++)
|
|
270 mp_msg(MSGT_DECAUDIO, MSGL_V, " ");
|
|
271 mp_msg(MSGT_DECAUDIO, MSGL_V, " | ");
|
|
272 for(j = 0; j < metadata->length-4-i*8; j++)
|
|
273 mp_msg(MSGT_DECAUDIO, MSGL_V, "%#02hhx ", metadata->data.application.data[i*8+j]);
|
|
274 mp_msg(MSGT_DECAUDIO, MSGL_V, "\n");
|
|
275 }
|
|
276 break;
|
|
277 case FLAC__METADATA_TYPE_SEEKTABLE:
|
|
278 mp_msg(MSGT_DECAUDIO, MSGL_V, "SEEKTABLE block (%u bytes):\n", metadata->length);
|
|
279 mp_msg(MSGT_DECAUDIO, MSGL_V, "%d seekpoints:\n", metadata->data.seek_table.num_points);
|
|
280 for (i = 0; i < metadata->data.seek_table.num_points; i++)
|
|
281 if (metadata->data.seek_table.points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER)
|
|
282 mp_msg(MSGT_DECAUDIO, MSGL_V, " %3d) sample_number=%llu stream_offset=%llu frame_samples=%u\n", i,
|
|
283 metadata->data.seek_table.points[i].sample_number,
|
|
284 metadata->data.seek_table.points[i].stream_offset,
|
|
285 metadata->data.seek_table.points[i].frame_samples);
|
|
286 else
|
|
287 mp_msg(MSGT_DECAUDIO, MSGL_V, " %3d) PLACEHOLDER\n", i);
|
|
288 break;
|
|
289 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
|
|
290 mp_msg(MSGT_DECAUDIO, MSGL_V, "VORBISCOMMENT block (%u bytes):\n", metadata->length);
|
|
291 {
|
|
292 char entry[metadata->data.vorbis_comment.vendor_string.length+1];
|
|
293 memcpy(&entry, metadata->data.vorbis_comment.vendor_string.entry, metadata->data.vorbis_comment.vendor_string.length);
|
|
294 entry[metadata->data.vorbis_comment.vendor_string.length] = '\0';
|
|
295 mp_msg(MSGT_DECAUDIO, MSGL_V, "vendor_string: %s\n", entry);
|
|
296 }
|
|
297 mp_msg(MSGT_DECAUDIO, MSGL_V, "%d comment(s):\n", metadata->data.vorbis_comment.num_comments);
|
|
298 for (i = 0; i < metadata->data.vorbis_comment.num_comments; i++)
|
|
299 {
|
|
300 char entry[metadata->data.vorbis_comment.comments[i].length];
|
|
301 memcpy(&entry, metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length);
|
|
302 entry[metadata->data.vorbis_comment.comments[i].length] = '\0';
|
|
303 mp_msg(MSGT_DECAUDIO, MSGL_V, "%s\n", entry);
|
|
304 }
|
|
305 {
|
|
306 double gain, peak;
|
|
307 if(grabbag__replaygain_load_from_vorbiscomment(metadata, album_mode, &gain, &peak))
|
|
308 {
|
|
309 ((flac_struct_t*)client_data)->has_replaygain = true;
|
|
310 ((flac_struct_t*)client_data)->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)preamp, /*prevent_clipping=*/!hard_limit);
|
|
311 mp_msg(MSGT_DECAUDIO, MSGL_V, "calculated replay_scale: %lf\n", ((flac_struct_t*)client_data)->replay_scale);
|
|
312 }
|
|
313 }
|
|
314 break;
|
|
315 case FLAC__METADATA_TYPE_CUESHEET:
|
|
316 mp_msg(MSGT_DECAUDIO, MSGL_V, "CUESHEET block (%u bytes):\n", metadata->length);
|
|
317 mp_msg(MSGT_DECAUDIO, MSGL_V, "mcn: '%s'\n", metadata->data.cue_sheet.media_catalog_number);
|
|
318 mp_msg(MSGT_DECAUDIO, MSGL_V, "lead_in: %llu\n", metadata->data.cue_sheet.lead_in);
|
|
319 mp_msg(MSGT_DECAUDIO, MSGL_V, "is_cd: %s\n", metadata->data.cue_sheet.is_cd?"true":"false");
|
|
320 mp_msg(MSGT_DECAUDIO, MSGL_V, "num_tracks: %u\n", metadata->data.cue_sheet.num_tracks);
|
|
321 for (i = 0; i < metadata->data.cue_sheet.num_tracks; i++)
|
|
322 {
|
|
323 mp_msg(MSGT_DECAUDIO, MSGL_V, "track[%d]:\n", i);
|
|
324 mp_msg(MSGT_DECAUDIO, MSGL_V, "offset: %llu\n", metadata->data.cue_sheet.tracks[i].offset);
|
|
325 mp_msg(MSGT_DECAUDIO, MSGL_V, "number: %hhu%s\n", metadata->data.cue_sheet.tracks[i].number, metadata->data.cue_sheet.tracks[i].number==170?"(LEAD-OUT)":"");
|
|
326 mp_msg(MSGT_DECAUDIO, MSGL_V, "isrc: '%s'\n", metadata->data.cue_sheet.tracks[i].isrc);
|
|
327 mp_msg(MSGT_DECAUDIO, MSGL_V, "type: %s\n", metadata->data.cue_sheet.tracks[i].type?"non-audio":"audio");
|
|
328 mp_msg(MSGT_DECAUDIO, MSGL_V, "pre_emphasis: %s\n", metadata->data.cue_sheet.tracks[i].pre_emphasis?"true":"false");
|
|
329 mp_msg(MSGT_DECAUDIO, MSGL_V, "num_indices: %hhu\n", metadata->data.cue_sheet.tracks[i].num_indices);
|
|
330 for (j = 0; j < metadata->data.cue_sheet.tracks[i].num_indices; j++)
|
|
331 {
|
|
332 mp_msg(MSGT_DECAUDIO, MSGL_V, "index[%d]:\n", j);
|
|
333 mp_msg(MSGT_DECAUDIO, MSGL_V, "offset:%llu\n", metadata->data.cue_sheet.tracks[i].indices[j].offset);
|
|
334 mp_msg(MSGT_DECAUDIO, MSGL_V, "number:%hhu\n", metadata->data.cue_sheet.tracks[i].indices[j].number);
|
|
335 }
|
|
336 }
|
|
337 break;
|
|
338 default: if (metadata->type >= FLAC__METADATA_TYPE_UNDEFINED)
|
|
339 mp_msg(MSGT_DECAUDIO, MSGL_V, "UNKNOWN block (%u bytes):\n", metadata->length);
|
|
340 else
|
|
341 mp_msg(MSGT_DECAUDIO, MSGL_V, "Strange block: UNKNOWN #%d < FLAC__METADATA_TYPE_UNDEFINED (%u bytes):\n", metadata->type, metadata->length);
|
|
342 for (i = 0; i < (metadata->length)/8; i++)
|
|
343 {
|
|
344 for(j = 0; j < 8; j++)
|
|
345 mp_msg(MSGT_DECAUDIO, MSGL_V, "%c", (unsigned char)metadata->data.unknown.data[i*8+j]<0x20?'.':metadata->data.unknown.data[i*8+j]);
|
|
346 mp_msg(MSGT_DECAUDIO, MSGL_V, " | ");
|
|
347 for(j = 0; j < 8; j++)
|
|
348 mp_msg(MSGT_DECAUDIO, MSGL_V, "%#02hhx ", metadata->data.unknown.data[i*8+j]);
|
|
349 mp_msg(MSGT_DECAUDIO, MSGL_V, "\n");
|
|
350 }
|
|
351 if (metadata->length-i*8 != 0)
|
|
352 {
|
|
353 for(j = 0; j < metadata->length-i*8; j++)
|
|
354 mp_msg(MSGT_DECAUDIO, MSGL_V, "%c", (unsigned char)metadata->data.unknown.data[i*8+j]<0x20?'.':metadata->data.unknown.data[i*8+j]);
|
|
355 for(; j <8; j++)
|
|
356 mp_msg(MSGT_DECAUDIO, MSGL_V, " ");
|
|
357 mp_msg(MSGT_DECAUDIO, MSGL_V, " | ");
|
|
358 for(j = 0; j < metadata->length-i*8; j++)
|
|
359 mp_msg(MSGT_DECAUDIO, MSGL_V, "%#02hhx ", metadata->data.unknown.data[i*8+j]);
|
|
360 mp_msg(MSGT_DECAUDIO, MSGL_V, "\n");
|
|
361 }
|
|
362 break;
|
|
363 }
|
|
364 }
|
|
365
|
|
366 void flac_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
|
367 {
|
|
368 if (status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
|
|
369 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "\nError callback called (%s)!!!\n", FLAC__StreamDecoderErrorStatusString[status]);
|
|
370 }
|
|
371
|
|
372 static int preinit(sh_audio_t *sh){
|
|
373 // there are default values set for buffering, but you can override them:
|
|
374
|
|
375 sh->audio_out_minsize=8*4*65535; // due to specs: we assume max 8 channels,
|
|
376 // 4 bytes/sample and 65535 samples/frame
|
|
377 // So allocating 2Mbytes buffer :)
|
|
378
|
|
379 // minimum input buffer size (set only if you need input buffering)
|
|
380 // (should be the max compressed frame size)
|
|
381 sh->audio_in_minsize=2048; // Default: 0 (no input buffer)
|
|
382
|
|
383 // if you set audio_in_minsize non-zero, the buffer will be allocated
|
|
384 // before the init() call by the core, and you can access it via
|
|
385 // pointer: sh->audio_in_buffer
|
|
386 // it will free'd after uninit(), so you don't have to use malloc/free here!
|
|
387
|
|
388 return 1; // return values: 1=OK 0=ERROR
|
|
389 }
|
|
390
|
|
391 static int init(sh_audio_t *sh_audio){
|
|
392 flac_struct_t *context = (flac_struct_t*)calloc(sizeof(flac_struct_t), 1);
|
|
393
|
|
394 sh_audio->context = context;
|
|
395 context->sh = sh_audio;
|
|
396 if (context == NULL)
|
|
397 {
|
|
398 mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "flac_init: error allocating context.\n");
|
|
399 return 0;
|
|
400 }
|
|
401
|
|
402 context->flac_dec = FLAC__stream_decoder_new();
|
|
403 if (context->flac_dec == NULL)
|
|
404 {
|
|
405 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "flac_init: error allocaing FLAC decoder.\n");
|
|
406 return 0;
|
|
407 }
|
|
408
|
|
409 if (!FLAC__stream_decoder_set_client_data(context->flac_dec, context))
|
|
410 {
|
|
411 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting private data for callbacks.\n");
|
|
412 return 0;
|
|
413 }
|
|
414
|
|
415 if (!FLAC__stream_decoder_set_read_callback(context->flac_dec, &flac_read_callback))
|
|
416 {
|
|
417 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting read callback.\n");
|
|
418 return 0;
|
|
419 }
|
|
420
|
|
421 if (!FLAC__stream_decoder_set_write_callback(context->flac_dec, &flac_write_callback))
|
|
422 {
|
|
423 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting write callback.\n");
|
|
424 return 0;
|
|
425 }
|
|
426
|
|
427 if (!FLAC__stream_decoder_set_metadata_callback(context->flac_dec, &flac_metadata_callback))
|
|
428 {
|
|
429 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting metadata callback.\n");
|
|
430 return 0;
|
|
431 }
|
|
432
|
|
433 if (!FLAC__stream_decoder_set_error_callback(context->flac_dec, &flac_error_callback))
|
|
434 {
|
|
435 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting error callback.\n");
|
|
436 return 0;
|
|
437 }
|
|
438
|
|
439 if (!FLAC__stream_decoder_set_metadata_respond_all(context->flac_dec))
|
|
440 {
|
|
441 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error during setting metadata_respond_all.\n");
|
|
442 return 0;
|
|
443 }
|
|
444
|
|
445 if (FLAC__stream_decoder_init(context->flac_dec) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
|
|
446 {
|
|
447 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error initializing decoder!\n");
|
|
448 return 0;
|
|
449 }
|
|
450
|
|
451 context->buf = NULL;
|
|
452 context->minlen = context->maxlen = 0;
|
|
453 context->replay_scale = 1.0;
|
|
454
|
|
455 FLAC__stream_decoder_process_until_end_of_metadata(context->flac_dec);
|
|
456
|
|
457 FLAC__plugin_common__init_dither_context(&(context->dither_context), sh_audio->samplesize * 8, noise_shaping);
|
|
458
|
|
459 return 1; // return values: 1=OK 0=ERROR
|
|
460 }
|
|
461
|
|
462 static void uninit(sh_audio_t *sh){
|
|
463 // uninit the decoder etc...
|
|
464 FLAC__stream_decoder_finish(((flac_struct_t*)(sh->context))->flac_dec);
|
|
465 FLAC__stream_decoder_delete(((flac_struct_t*)(sh->context))->flac_dec);
|
|
466 // again: you don't have to free() a_in_buffer here! it's done by the core.
|
|
467 }
|
|
468
|
|
469 static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){
|
|
470 FLAC__StreamDecoderState decstate;
|
|
471 FLAC__bool status;
|
|
472
|
|
473 // audio decoding. the most important thing :)
|
|
474 // parameters you get:
|
|
475 // buf = pointer to the output buffer, you have to store uncompressed
|
|
476 // samples there
|
|
477 // minlen = requested minimum size (in bytes!) of output. it's just a
|
|
478 // _recommendation_, you can decode more or less, it just tell you that
|
|
479 // the caller process needs 'minlen' bytes. if it gets less, it will
|
|
480 // call decode_audio() again.
|
|
481 // maxlen = maximum size (bytes) of output. you MUST NOT write more to the
|
|
482 // buffer, it's the upper-most limit!
|
|
483 // note: maxlen will be always greater or equal to sh->audio_out_minsize
|
|
484
|
|
485 // Store params in private context for callback:
|
|
486 ((flac_struct_t*)(sh_audio->context))->buf = buf;
|
|
487 ((flac_struct_t*)(sh_audio->context))->minlen = minlen;
|
|
488 ((flac_struct_t*)(sh_audio->context))->maxlen = maxlen;
|
|
489 ((flac_struct_t*)(sh_audio->context))->written = 0;
|
|
490
|
|
491 status = FLAC__stream_decoder_process_single(((flac_struct_t*)(sh_audio->context))->flac_dec);
|
|
492 decstate = FLAC__stream_decoder_get_state(((flac_struct_t*)(sh_audio->context))->flac_dec);
|
|
493 if (!status || (
|
|
494 decstate != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA &&
|
|
495 decstate != FLAC__STREAM_DECODER_READ_METADATA &&
|
|
496 decstate != FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC &&
|
|
497 decstate != FLAC__STREAM_DECODER_READ_FRAME
|
|
498 ))
|
|
499 {
|
|
500 if (decstate == FLAC__STREAM_DECODER_END_OF_STREAM)
|
|
501 {
|
|
502 /* return what we have decoded */
|
|
503 if (((flac_struct_t*)(sh_audio->context))->written != 0)
|
|
504 return ((flac_struct_t*)(sh_audio->context))->written;
|
|
505 mp_msg(MSGT_DECAUDIO, MSGL_V, "End of stream.\n");
|
|
506 return -1;
|
|
507 }
|
|
508 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "process_single problem: returned %s, state is %s!\n", status?"true":"false", FLAC__StreamDecoderStateString[decstate]);
|
|
509 FLAC__stream_decoder_flush(((flac_struct_t*)(sh_audio->context))->flac_dec);
|
|
510 return -1;
|
|
511 }
|
|
512
|
|
513
|
|
514 return ((flac_struct_t*)(sh_audio->context))->written; // return value: number of _bytes_ written to output buffer,
|
|
515 // or -1 for EOF (or uncorrectable error)
|
|
516 }
|
|
517
|
|
518 static int control(sh_audio_t *sh,int cmd,void* arg, ...){
|
|
519 switch(cmd){
|
|
520 case ADCTRL_RESYNC_STREAM:
|
|
521 // it is called once after seeking, to resync.
|
|
522 // Note: sh_audio->a_in_buffer_len=0; is done _before_ this call!
|
|
523 FLAC__stream_decoder_flush (((flac_struct_t*)(sh->context))->flac_dec);
|
|
524 return CONTROL_TRUE;
|
|
525 case ADCTRL_SKIP_FRAME:
|
|
526 // it is called to skip (jump over) small amount (1/10 sec or 1 frame)
|
|
527 // of audio data - used to sync audio to video after seeking
|
|
528 // if you don't return CONTROL_TRUE, it will defaults to:
|
|
529 // ds_fill_buffer(sh_audio->ds); // skip 1 demux packet
|
|
530 ((flac_struct_t*)(sh->context))->buf = NULL;
|
|
531 ((flac_struct_t*)(sh->context))->minlen =
|
|
532 ((flac_struct_t*)(sh->context))->maxlen = 0;
|
|
533 FLAC__stream_decoder_process_single(((flac_struct_t*)(sh->context))->flac_dec);
|
|
534 return CONTROL_TRUE;
|
|
535 }
|
|
536 return CONTROL_UNKNOWN;
|
|
537 }
|
|
538 #endif
|