• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "include/flac_parser.h"
18 
19 #include <android/log.h>
20 #include <jni.h>
21 
22 #include <cassert>
23 #include <cstdlib>
24 #include <cstring>
25 
26 #define LOG_TAG "FLACParser"
27 #define ALOGE(...) \
28   ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
29 #define ALOGV(...) \
30   ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
31 
32 #define LOG_ALWAYS_FATAL(...) \
33   (__android_log_assert(NULL, LOG_TAG, ##__VA_ARGS__))
34 
35 #define LITERAL_TO_STRING_INTERNAL(x) #x
36 #define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
37 
38 #define TRESPASS()          \
39   LOG_ALWAYS_FATAL(__FILE__ \
40                    ":" LITERAL_TO_STRING(__LINE__) " Should not be here.");
41 #define CHECK(x) \
42   if (!(x)) ALOGE("Check failed: %s ", #x)
43 
44 const int endian = 1;
45 #define isBigEndian() (*(reinterpret_cast<const char *>(&endian)) == 0)
46 
47 // The FLAC parser calls our C++ static callbacks using C calling conventions,
48 // inside FLAC__stream_decoder_process_until_end_of_metadata
49 // and FLAC__stream_decoder_process_single.
50 // We immediately then call our corresponding C++ instance methods
51 // with the same parameter list, but discard redundant information.
52 
read_callback(const FLAC__StreamDecoder *,FLAC__byte buffer[],size_t * bytes,void * client_data)53 FLAC__StreamDecoderReadStatus FLACParser::read_callback(
54     const FLAC__StreamDecoder * /* decoder */, FLAC__byte buffer[],
55     size_t *bytes, void *client_data) {
56   return reinterpret_cast<FLACParser *>(client_data)
57       ->readCallback(buffer, bytes);
58 }
59 
seek_callback(const FLAC__StreamDecoder *,FLAC__uint64 absolute_byte_offset,void * client_data)60 FLAC__StreamDecoderSeekStatus FLACParser::seek_callback(
61     const FLAC__StreamDecoder * /* decoder */,
62     FLAC__uint64 absolute_byte_offset, void *client_data) {
63   return reinterpret_cast<FLACParser *>(client_data)
64       ->seekCallback(absolute_byte_offset);
65 }
66 
tell_callback(const FLAC__StreamDecoder *,FLAC__uint64 * absolute_byte_offset,void * client_data)67 FLAC__StreamDecoderTellStatus FLACParser::tell_callback(
68     const FLAC__StreamDecoder * /* decoder */,
69     FLAC__uint64 *absolute_byte_offset, void *client_data) {
70   return reinterpret_cast<FLACParser *>(client_data)
71       ->tellCallback(absolute_byte_offset);
72 }
73 
length_callback(const FLAC__StreamDecoder *,FLAC__uint64 * stream_length,void * client_data)74 FLAC__StreamDecoderLengthStatus FLACParser::length_callback(
75     const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *stream_length,
76     void *client_data) {
77   return reinterpret_cast<FLACParser *>(client_data)
78       ->lengthCallback(stream_length);
79 }
80 
eof_callback(const FLAC__StreamDecoder *,void * client_data)81 FLAC__bool FLACParser::eof_callback(const FLAC__StreamDecoder * /* decoder */,
82                                     void *client_data) {
83   return reinterpret_cast<FLACParser *>(client_data)->eofCallback();
84 }
85 
write_callback(const FLAC__StreamDecoder *,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)86 FLAC__StreamDecoderWriteStatus FLACParser::write_callback(
87     const FLAC__StreamDecoder * /* decoder */, const FLAC__Frame *frame,
88     const FLAC__int32 *const buffer[], void *client_data) {
89   return reinterpret_cast<FLACParser *>(client_data)
90       ->writeCallback(frame, buffer);
91 }
92 
metadata_callback(const FLAC__StreamDecoder *,const FLAC__StreamMetadata * metadata,void * client_data)93 void FLACParser::metadata_callback(const FLAC__StreamDecoder * /* decoder */,
94                                    const FLAC__StreamMetadata *metadata,
95                                    void *client_data) {
96   reinterpret_cast<FLACParser *>(client_data)->metadataCallback(metadata);
97 }
98 
error_callback(const FLAC__StreamDecoder *,FLAC__StreamDecoderErrorStatus status,void * client_data)99 void FLACParser::error_callback(const FLAC__StreamDecoder * /* decoder */,
100                                 FLAC__StreamDecoderErrorStatus status,
101                                 void *client_data) {
102   reinterpret_cast<FLACParser *>(client_data)->errorCallback(status);
103 }
104 
105 // These are the corresponding callbacks with C++ calling conventions
106 
readCallback(FLAC__byte buffer[],size_t * bytes)107 FLAC__StreamDecoderReadStatus FLACParser::readCallback(FLAC__byte buffer[],
108                                                        size_t *bytes) {
109   size_t requested = *bytes;
110   ssize_t actual = mDataSource->readAt(mCurrentPos, buffer, requested);
111   if (0 > actual) {
112     *bytes = 0;
113     return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
114   } else if (0 == actual) {
115     *bytes = 0;
116     mEOF = true;
117     return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
118   } else {
119     assert(actual <= requested);
120     *bytes = actual;
121     mCurrentPos += actual;
122     return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
123   }
124 }
125 
seekCallback(FLAC__uint64 absolute_byte_offset)126 FLAC__StreamDecoderSeekStatus FLACParser::seekCallback(
127     FLAC__uint64 absolute_byte_offset) {
128   mCurrentPos = absolute_byte_offset;
129   mEOF = false;
130   return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
131 }
132 
tellCallback(FLAC__uint64 * absolute_byte_offset)133 FLAC__StreamDecoderTellStatus FLACParser::tellCallback(
134     FLAC__uint64 *absolute_byte_offset) {
135   *absolute_byte_offset = mCurrentPos;
136   return FLAC__STREAM_DECODER_TELL_STATUS_OK;
137 }
138 
lengthCallback(FLAC__uint64 * stream_length)139 FLAC__StreamDecoderLengthStatus FLACParser::lengthCallback(
140     FLAC__uint64 *stream_length) {
141   return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
142 }
143 
eofCallback()144 FLAC__bool FLACParser::eofCallback() { return mEOF; }
145 
writeCallback(const FLAC__Frame * frame,const FLAC__int32 * const buffer[])146 FLAC__StreamDecoderWriteStatus FLACParser::writeCallback(
147     const FLAC__Frame *frame, const FLAC__int32 *const buffer[]) {
148   if (mWriteRequested) {
149     mWriteRequested = false;
150     // FLAC parser doesn't free or realloc buffer until next frame or finish
151     mWriteHeader = frame->header;
152     mWriteBuffer = buffer;
153     mWriteCompleted = true;
154     return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
155   } else {
156     ALOGE("FLACParser::writeCallback unexpected");
157     return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
158   }
159 }
160 
metadataCallback(const FLAC__StreamMetadata * metadata)161 void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata) {
162   switch (metadata->type) {
163     case FLAC__METADATA_TYPE_STREAMINFO:
164       if (!mStreamInfoValid) {
165         mStreamInfo = metadata->data.stream_info;
166         mStreamInfoValid = true;
167       } else {
168         ALOGE("FLACParser::metadataCallback unexpected STREAMINFO");
169       }
170       break;
171     case FLAC__METADATA_TYPE_SEEKTABLE:
172       mSeekTable = &metadata->data.seek_table;
173       break;
174     case FLAC__METADATA_TYPE_VORBIS_COMMENT:
175       if (!mVorbisCommentsValid) {
176         FLAC__StreamMetadata_VorbisComment vorbisComment =
177             metadata->data.vorbis_comment;
178         for (FLAC__uint32 i = 0; i < vorbisComment.num_comments; ++i) {
179           FLAC__StreamMetadata_VorbisComment_Entry vorbisCommentEntry =
180               vorbisComment.comments[i];
181           if (vorbisCommentEntry.entry != NULL) {
182             std::string comment(
183                 reinterpret_cast<char *>(vorbisCommentEntry.entry),
184                 vorbisCommentEntry.length);
185             mVorbisComments.push_back(comment);
186           }
187         }
188         mVorbisCommentsValid = true;
189       } else {
190         ALOGE("FLACParser::metadataCallback unexpected VORBISCOMMENT");
191       }
192       break;
193     case FLAC__METADATA_TYPE_PICTURE: {
194       const FLAC__StreamMetadata_Picture *parsedPicture =
195           &metadata->data.picture;
196       FlacPicture picture;
197       picture.mimeType.assign(std::string(parsedPicture->mime_type));
198       picture.description.assign(
199           std::string((char *)parsedPicture->description));
200       picture.data.assign(parsedPicture->data,
201                           parsedPicture->data + parsedPicture->data_length);
202       picture.width = parsedPicture->width;
203       picture.height = parsedPicture->height;
204       picture.depth = parsedPicture->depth;
205       picture.colors = parsedPicture->colors;
206       picture.type = parsedPicture->type;
207       mPictures.push_back(picture);
208       mPicturesValid = true;
209       break;
210     }
211     default:
212       ALOGE("FLACParser::metadataCallback unexpected type %u", metadata->type);
213       break;
214   }
215 }
216 
errorCallback(FLAC__StreamDecoderErrorStatus status)217 void FLACParser::errorCallback(FLAC__StreamDecoderErrorStatus status) {
218   ALOGE("FLACParser::errorCallback status=%d", status);
219   mErrorStatus = status;
220 }
221 
222 // Copy samples from FLAC native 32-bit non-interleaved to
223 // correct bit-depth (non-zero padded), interleaved.
224 // These are candidates for optimization if needed.
copyToByteArrayBigEndian(int8_t * dst,const int * const * src,unsigned bytesPerSample,unsigned nSamples,unsigned nChannels)225 static void copyToByteArrayBigEndian(int8_t *dst, const int *const *src,
226                                      unsigned bytesPerSample, unsigned nSamples,
227                                      unsigned nChannels) {
228   for (unsigned i = 0; i < nSamples; ++i) {
229     for (unsigned c = 0; c < nChannels; ++c) {
230       // point to the first byte of the source address
231       // and then skip the first few bytes (most significant bytes)
232       // depending on the bit depth
233       const int8_t *byteSrc =
234           reinterpret_cast<const int8_t *>(&src[c][i]) + 4 - bytesPerSample;
235       memcpy(dst, byteSrc, bytesPerSample);
236       dst = dst + bytesPerSample;
237     }
238   }
239 }
240 
copyToByteArrayLittleEndian(int8_t * dst,const int * const * src,unsigned bytesPerSample,unsigned nSamples,unsigned nChannels)241 static void copyToByteArrayLittleEndian(int8_t *dst, const int *const *src,
242                                         unsigned bytesPerSample,
243                                         unsigned nSamples, unsigned nChannels) {
244   for (unsigned i = 0; i < nSamples; ++i) {
245     for (unsigned c = 0; c < nChannels; ++c) {
246       // with little endian, the most significant bytes will be at the end
247       // copy the bytes in little endian will remove the most significant byte
248       // so we are good here.
249       memcpy(dst, &(src[c][i]), bytesPerSample);
250       dst = dst + bytesPerSample;
251     }
252   }
253 }
254 
copyTrespass(int8_t *,const int * const *,unsigned,unsigned,unsigned)255 static void copyTrespass(int8_t * /* dst */, const int *const * /* src */,
256                          unsigned /* bytesPerSample */, unsigned /* nSamples */,
257                          unsigned /* nChannels */) {
258   TRESPASS();
259 }
260 
261 // FLACParser
262 
FLACParser(DataSource * source)263 FLACParser::FLACParser(DataSource *source)
264     : mDataSource(source),
265       mCopy(copyTrespass),
266       mDecoder(NULL),
267       mCurrentPos(0LL),
268       mEOF(false),
269       mStreamInfoValid(false),
270       mSeekTable(NULL),
271       firstFrameOffset(0LL),
272       mVorbisCommentsValid(false),
273       mPicturesValid(false),
274       mWriteRequested(false),
275       mWriteCompleted(false),
276       mWriteBuffer(NULL),
277       mErrorStatus((FLAC__StreamDecoderErrorStatus)-1) {
278   ALOGV("FLACParser::FLACParser");
279   memset(&mStreamInfo, 0, sizeof(mStreamInfo));
280   memset(&mWriteHeader, 0, sizeof(mWriteHeader));
281 }
282 
~FLACParser()283 FLACParser::~FLACParser() {
284   ALOGV("FLACParser::~FLACParser");
285   if (mDecoder != NULL) {
286     FLAC__stream_decoder_delete(mDecoder);
287     mDecoder = NULL;
288   }
289 }
290 
init()291 bool FLACParser::init() {
292   // setup libFLAC parser
293   mDecoder = FLAC__stream_decoder_new();
294   if (mDecoder == NULL) {
295     // The new should succeed, since probably all it does is a malloc
296     // that always succeeds in Android.  But to avoid dependence on the
297     // libFLAC internals, we check and log here.
298     ALOGE("new failed");
299     return false;
300   }
301   FLAC__stream_decoder_set_md5_checking(mDecoder, false);
302   FLAC__stream_decoder_set_metadata_ignore_all(mDecoder);
303   FLAC__stream_decoder_set_metadata_respond(mDecoder,
304                                             FLAC__METADATA_TYPE_STREAMINFO);
305   FLAC__stream_decoder_set_metadata_respond(mDecoder,
306                                             FLAC__METADATA_TYPE_SEEKTABLE);
307   FLAC__stream_decoder_set_metadata_respond(mDecoder,
308                                             FLAC__METADATA_TYPE_VORBIS_COMMENT);
309   FLAC__stream_decoder_set_metadata_respond(mDecoder,
310                                             FLAC__METADATA_TYPE_PICTURE);
311   FLAC__StreamDecoderInitStatus initStatus;
312   initStatus = FLAC__stream_decoder_init_stream(
313       mDecoder, read_callback, seek_callback, tell_callback, length_callback,
314       eof_callback, write_callback, metadata_callback, error_callback,
315       reinterpret_cast<void *>(this));
316   if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
317     // A failure here probably indicates a programming error and so is
318     // unlikely to happen. But we check and log here similarly to above.
319     ALOGE("init_stream failed %d", initStatus);
320     return false;
321   }
322   return true;
323 }
324 
decodeMetadata()325 bool FLACParser::decodeMetadata() {
326   // parse all metadata
327   if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder)) {
328     ALOGE("metadata decoding failed");
329     return false;
330   }
331   // store first frame offset
332   FLAC__stream_decoder_get_decode_position(mDecoder, &firstFrameOffset);
333 
334   if (mStreamInfoValid) {
335     // check channel count
336     if (getChannels() == 0 || getChannels() > 8) {
337       ALOGE("unsupported channel count %u", getChannels());
338       return false;
339     }
340     // check bit depth
341     switch (getBitsPerSample()) {
342       case 8:
343       case 16:
344       case 24:
345       case 32:
346         break;
347       default:
348         ALOGE("unsupported bits per sample %u", getBitsPerSample());
349         return false;
350     }
351     // configure the appropriate copy function based on device endianness.
352     if (isBigEndian()) {
353       mCopy = copyToByteArrayBigEndian;
354     } else {
355       mCopy = copyToByteArrayLittleEndian;
356     }
357   } else {
358     ALOGE("missing STREAMINFO");
359     return false;
360   }
361   return true;
362 }
363 
readBuffer(void * output,size_t output_size)364 size_t FLACParser::readBuffer(void *output, size_t output_size) {
365   mWriteRequested = true;
366   mWriteCompleted = false;
367 
368   if (!FLAC__stream_decoder_process_single(mDecoder)) {
369     ALOGE("FLACParser::readBuffer process_single failed. Status: %s",
370           getDecoderStateString());
371     return -1;
372   }
373   if (!mWriteCompleted) {
374     if (FLAC__stream_decoder_get_state(mDecoder) !=
375         FLAC__STREAM_DECODER_END_OF_STREAM) {
376       ALOGE("FLACParser::readBuffer write did not complete. Status: %s",
377             getDecoderStateString());
378     }
379     return -1;
380   }
381 
382   // verify that block header keeps the promises made by STREAMINFO
383   unsigned blocksize = mWriteHeader.blocksize;
384   if (blocksize == 0 || blocksize > getMaxBlockSize()) {
385     ALOGE("FLACParser::readBuffer write invalid blocksize %u", blocksize);
386     return -1;
387   }
388   if (mWriteHeader.sample_rate != getSampleRate() ||
389       mWriteHeader.channels != getChannels() ||
390       mWriteHeader.bits_per_sample != getBitsPerSample()) {
391     ALOGE(
392         "FLACParser::readBuffer write changed parameters mid-stream: %d/%d/%d "
393         "-> %d/%d/%d",
394         getSampleRate(), getChannels(), getBitsPerSample(),
395         mWriteHeader.sample_rate, mWriteHeader.channels,
396         mWriteHeader.bits_per_sample);
397     return -1;
398   }
399 
400   unsigned bytesPerSample = getBitsPerSample() >> 3;
401   size_t bufferSize = blocksize * getChannels() * bytesPerSample;
402   if (bufferSize > output_size) {
403     ALOGE(
404         "FLACParser::readBuffer not enough space in output buffer "
405         "%zu < %zu",
406         output_size, bufferSize);
407     return -1;
408   }
409 
410   // copy PCM from FLAC write buffer to our media buffer, with interleaving.
411   (*mCopy)(reinterpret_cast<int8_t *>(output), mWriteBuffer, bytesPerSample,
412            blocksize, getChannels());
413 
414   // fill in buffer metadata
415   CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
416 
417   return bufferSize;
418 }
419 
getSeekPositions(int64_t timeUs,std::array<int64_t,4> & result)420 bool FLACParser::getSeekPositions(int64_t timeUs,
421                                   std::array<int64_t, 4> &result) {
422   if (!mSeekTable) {
423     return false;
424   }
425 
426   unsigned sampleRate = getSampleRate();
427   int64_t totalSamples = getTotalSamples();
428   int64_t targetSampleNumber = (timeUs * sampleRate) / 1000000LL;
429   if (targetSampleNumber >= totalSamples) {
430     targetSampleNumber = totalSamples - 1;
431   }
432 
433   FLAC__StreamMetadata_SeekPoint *points = mSeekTable->points;
434   unsigned length = mSeekTable->num_points;
435 
436   for (unsigned i = length; i != 0; i--) {
437     int64_t sampleNumber = points[i - 1].sample_number;
438     if (sampleNumber == -1) {  // placeholder
439       continue;
440     }
441     if (sampleNumber <= targetSampleNumber) {
442       result[0] = (sampleNumber * 1000000LL) / sampleRate;
443       result[1] = firstFrameOffset + points[i - 1].stream_offset;
444       if (sampleNumber == targetSampleNumber || i >= length ||
445           points[i].sample_number == -1) {  // placeholder
446         // exact seek, or no following non-placeholder seek point
447         result[2] = result[0];
448         result[3] = result[1];
449       } else {
450         result[2] = (points[i].sample_number * 1000000LL) / sampleRate;
451         result[3] = firstFrameOffset + points[i].stream_offset;
452       }
453       return true;
454     }
455   }
456   result[0] = 0;
457   result[1] = firstFrameOffset;
458   result[2] = 0;
459   result[3] = firstFrameOffset;
460   return true;
461 }
462