Home | History | Annotate | Download | only in spdif
      1 /*
      2  * Copyright 2014, 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 <stdint.h>
     18 #include <string.h>
     19 
     20 #define LOG_TAG "AudioSPDIF"
     21 #include <utils/Log.h>
     22 #include <audio_utils/spdif/SPDIFEncoder.h>
     23 
     24 #include "AC3FrameScanner.h"
     25 #include "DTSFrameScanner.h"
     26 
     27 namespace android {
     28 
     29 // Burst Preamble defined in IEC61937-1
     30 const uint16_t SPDIFEncoder::kSPDIFSync1 = 0xF872; // Pa
     31 const uint16_t SPDIFEncoder::kSPDIFSync2 = 0x4E1F; // Pb
     32 
     33 static int32_t sEndianDetector = 1;
     34 #define isLittleEndian()  (*((uint8_t *)&sEndianDetector))
     35 
     36 SPDIFEncoder::SPDIFEncoder(audio_format_t format)
     37   : mFramer(NULL)
     38   , mSampleRate(48000)
     39   , mBurstBuffer(NULL)
     40   , mBurstBufferSizeBytes(0)
     41   , mRateMultiplier(1)
     42   , mBurstFrames(0)
     43   , mByteCursor(0)
     44   , mBitstreamNumber(0)
     45   , mPayloadBytesPending(0)
     46   , mScanning(true)
     47 {
     48     switch(format) {
     49         case AUDIO_FORMAT_AC3:
     50         case AUDIO_FORMAT_E_AC3:
     51             mFramer = new AC3FrameScanner(format);
     52             break;
     53         case AUDIO_FORMAT_DTS:
     54         case AUDIO_FORMAT_DTS_HD:
     55             mFramer = new DTSFrameScanner();
     56             break;
     57         default:
     58             break;
     59     }
     60 
     61     // This a programmer error. Call isFormatSupported() first.
     62     LOG_ALWAYS_FATAL_IF((mFramer == NULL),
     63         "SPDIFEncoder: invalid audio format = 0x%08X", format);
     64 
     65     mBurstBufferSizeBytes = sizeof(uint16_t)
     66             * SPDIF_ENCODED_CHANNEL_COUNT
     67             * mFramer->getMaxSampleFramesPerSyncFrame();
     68 
     69     ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %zu, littleEndian = %d",
     70             mBurstBufferSizeBytes, isLittleEndian());
     71     mBurstBuffer = new uint16_t[mBurstBufferSizeBytes >> 1];
     72     clearBurstBuffer();
     73 }
     74 
     75 SPDIFEncoder::SPDIFEncoder()
     76     : SPDIFEncoder(AUDIO_FORMAT_AC3)
     77 {
     78 }
     79 
     80 SPDIFEncoder::~SPDIFEncoder()
     81 {
     82     delete[] mBurstBuffer;
     83     delete mFramer;
     84 }
     85 
     86 bool SPDIFEncoder::isFormatSupported(audio_format_t format)
     87 {
     88     switch(format) {
     89         case AUDIO_FORMAT_AC3:
     90         case AUDIO_FORMAT_E_AC3:
     91         case AUDIO_FORMAT_DTS:
     92         case AUDIO_FORMAT_DTS_HD:
     93             return true;
     94         default:
     95             return false;
     96     }
     97 }
     98 
     99 int SPDIFEncoder::getBytesPerOutputFrame()
    100 {
    101     return SPDIF_ENCODED_CHANNEL_COUNT * sizeof(int16_t);
    102 }
    103 
    104 void SPDIFEncoder::writeBurstBufferShorts(const uint16_t *buffer, size_t numShorts)
    105 {
    106     // avoid static analyser warning
    107     LOG_ALWAYS_FATAL_IF((mBurstBuffer == NULL), "mBurstBuffer never allocated");
    108     mByteCursor = (mByteCursor + 1) & ~1; // round up to even byte
    109     size_t bytesToWrite = numShorts * sizeof(uint16_t);
    110     if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
    111         ALOGE("SPDIFEncoder: Burst buffer overflow!");
    112         reset();
    113         return;
    114     }
    115     memcpy(&mBurstBuffer[mByteCursor >> 1], buffer, bytesToWrite);
    116     mByteCursor += bytesToWrite;
    117 }
    118 
    119 // Pack the bytes into the short buffer in the order:
    120 //   byte[0] -> short[0] MSB
    121 //   byte[1] -> short[0] LSB
    122 //   byte[2] -> short[1] MSB
    123 //   byte[3] -> short[1] LSB
    124 //   etcetera
    125 // This way they should come out in the correct order for SPDIF on both
    126 // Big and Little Endian CPUs.
    127 void SPDIFEncoder::writeBurstBufferBytes(const uint8_t *buffer, size_t numBytes)
    128 {
    129     size_t bytesToWrite = numBytes;
    130     if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
    131         ALOGE("SPDIFEncoder: Burst buffer overflow!");
    132         clearBurstBuffer();
    133         return;
    134     }
    135     uint16_t pad = mBurstBuffer[mByteCursor >> 1];
    136     for (size_t i = 0; i < bytesToWrite; i++) {
    137         if (mByteCursor & 1 ) {
    138             pad |= *buffer++; // put second byte in LSB
    139             mBurstBuffer[mByteCursor >> 1] = pad;
    140             pad = 0;
    141         } else {
    142             pad |= (*buffer++) << 8; // put first byte in MSB
    143         }
    144         mByteCursor++;
    145     }
    146     // Save partially filled short.
    147     if (mByteCursor & 1 ){
    148         mBurstBuffer[mByteCursor >> 1] = pad;
    149     }
    150 }
    151 
    152 void SPDIFEncoder::sendZeroPad()
    153 {
    154     // Pad remainder of burst with zeros.
    155     size_t burstSize = mFramer->getSampleFramesPerSyncFrame() * sizeof(uint16_t)
    156             * SPDIF_ENCODED_CHANNEL_COUNT;
    157     if (mByteCursor > burstSize) {
    158         ALOGE("SPDIFEncoder: Burst buffer, contents too large!");
    159         clearBurstBuffer();
    160     } else {
    161         // We don't have to write zeros because buffer already set to zero
    162         // by clearBurstBuffer(). Just pretend we wrote zeros by
    163         // incrementing cursor.
    164         mByteCursor = burstSize;
    165     }
    166 }
    167 
    168 void SPDIFEncoder::reset()
    169 {
    170     ALOGV("SPDIFEncoder: reset()");
    171     clearBurstBuffer();
    172     if (mFramer != NULL) {
    173         mFramer->resetBurst();
    174     }
    175     mPayloadBytesPending = 0;
    176     mScanning = true;
    177 }
    178 
    179 void SPDIFEncoder::flushBurstBuffer()
    180 {
    181     const int preambleSize = 4 * sizeof(uint16_t);
    182     if (mByteCursor > preambleSize) {
    183         // Set lengthCode for valid payload before zeroPad.
    184         uint16_t numBytes = (mByteCursor - preambleSize);
    185         mBurstBuffer[3] = mFramer->convertBytesToLengthCode(numBytes);
    186 
    187         sendZeroPad();
    188         writeOutput(mBurstBuffer, mByteCursor);
    189     }
    190     reset();
    191 }
    192 
    193 void SPDIFEncoder::clearBurstBuffer()
    194 {
    195     if (mBurstBuffer) {
    196         memset(mBurstBuffer, 0, mBurstBufferSizeBytes);
    197     }
    198     mByteCursor = 0;
    199 }
    200 
    201 void SPDIFEncoder::startDataBurst()
    202 {
    203     // Encode IEC61937-1 Burst Preamble
    204     uint16_t preamble[4];
    205 
    206     uint16_t burstInfo = (mBitstreamNumber << 13)
    207         | (mFramer->getDataTypeInfo() << 8)
    208         | mFramer->getDataType();
    209 
    210     mRateMultiplier = mFramer->getRateMultiplier();
    211 
    212     preamble[0] = kSPDIFSync1;
    213     preamble[1] = kSPDIFSync2;
    214     preamble[2] = burstInfo;
    215     preamble[3] = 0; // lengthCode - This will get set after the buffer is full.
    216     writeBurstBufferShorts(preamble, 4);
    217 }
    218 
    219 size_t SPDIFEncoder::startSyncFrame()
    220 {
    221     // Write start of encoded frame that was buffered in frame detector.
    222     size_t syncSize = mFramer->getHeaderSizeBytes();
    223     writeBurstBufferBytes(mFramer->getHeaderAddress(), syncSize);
    224     return mFramer->getFrameSizeBytes() - syncSize;
    225 }
    226 
    227 // Wraps raw encoded data into a data burst.
    228 ssize_t SPDIFEncoder::write( const void *buffer, size_t numBytes )
    229 {
    230     size_t bytesLeft = numBytes;
    231     const uint8_t *data = (const uint8_t *)buffer;
    232     ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %zu)",
    233         mScanning, (uint) *data, numBytes);
    234     while (bytesLeft > 0) {
    235         if (mScanning) {
    236         // Look for beginning of next encoded frame.
    237             if (mFramer->scan(*data)) {
    238                 if (mByteCursor == 0) {
    239                     startDataBurst();
    240                 } else if (mFramer->isFirstInBurst()) {
    241                     // Make sure that this frame is at the beginning of the data burst.
    242                     flushBurstBuffer();
    243                     startDataBurst();
    244                 }
    245                 mPayloadBytesPending = startSyncFrame();
    246                 mScanning = false;
    247             }
    248             data++;
    249             bytesLeft--;
    250         } else {
    251             // Write payload until we hit end of frame.
    252             size_t bytesToWrite = bytesLeft;
    253             // Only write as many as we need to finish the frame.
    254             if (bytesToWrite > mPayloadBytesPending) {
    255                 bytesToWrite = mPayloadBytesPending;
    256             }
    257             writeBurstBufferBytes(data, bytesToWrite);
    258 
    259             data += bytesToWrite;
    260             bytesLeft -= bytesToWrite;
    261             mPayloadBytesPending -= bytesToWrite;
    262 
    263             // If we have all the payload then send a data burst.
    264             if (mPayloadBytesPending == 0) {
    265                 if (mFramer->isLastInBurst()) {
    266                     flushBurstBuffer();
    267                 }
    268                 mScanning = true;
    269             }
    270         }
    271     }
    272     return numBytes;
    273 }
    274 
    275 }  // namespace android
    276