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