upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
275
android/system/media/audio_utils/spdif/SPDIFEncoder.cpp
Normal file
275
android/system/media/audio_utils/spdif/SPDIFEncoder.cpp
Normal file
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* Copyright 2014, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "AudioSPDIF"
|
||||
#include <utils/Log.h>
|
||||
#include <audio_utils/spdif/SPDIFEncoder.h>
|
||||
|
||||
#include "AC3FrameScanner.h"
|
||||
#include "DTSFrameScanner.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// Burst Preamble defined in IEC61937-1
|
||||
const uint16_t SPDIFEncoder::kSPDIFSync1 = 0xF872; // Pa
|
||||
const uint16_t SPDIFEncoder::kSPDIFSync2 = 0x4E1F; // Pb
|
||||
|
||||
static int32_t sEndianDetector = 1;
|
||||
#define isLittleEndian() (*((uint8_t *)&sEndianDetector))
|
||||
|
||||
SPDIFEncoder::SPDIFEncoder(audio_format_t format)
|
||||
: mFramer(NULL)
|
||||
, mSampleRate(48000)
|
||||
, mBurstBuffer(NULL)
|
||||
, mBurstBufferSizeBytes(0)
|
||||
, mRateMultiplier(1)
|
||||
, mBurstFrames(0)
|
||||
, mByteCursor(0)
|
||||
, mBitstreamNumber(0)
|
||||
, mPayloadBytesPending(0)
|
||||
, mScanning(true)
|
||||
{
|
||||
switch(format) {
|
||||
case AUDIO_FORMAT_AC3:
|
||||
case AUDIO_FORMAT_E_AC3:
|
||||
mFramer = new AC3FrameScanner(format);
|
||||
break;
|
||||
case AUDIO_FORMAT_DTS:
|
||||
case AUDIO_FORMAT_DTS_HD:
|
||||
mFramer = new DTSFrameScanner();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// This a programmer error. Call isFormatSupported() first.
|
||||
LOG_ALWAYS_FATAL_IF((mFramer == NULL),
|
||||
"SPDIFEncoder: invalid audio format = 0x%08X", format);
|
||||
|
||||
mBurstBufferSizeBytes = sizeof(uint16_t)
|
||||
* SPDIF_ENCODED_CHANNEL_COUNT
|
||||
* mFramer->getMaxSampleFramesPerSyncFrame();
|
||||
|
||||
ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %zu, littleEndian = %d",
|
||||
mBurstBufferSizeBytes, isLittleEndian());
|
||||
mBurstBuffer = new uint16_t[mBurstBufferSizeBytes >> 1];
|
||||
clearBurstBuffer();
|
||||
}
|
||||
|
||||
SPDIFEncoder::SPDIFEncoder()
|
||||
: SPDIFEncoder(AUDIO_FORMAT_AC3)
|
||||
{
|
||||
}
|
||||
|
||||
SPDIFEncoder::~SPDIFEncoder()
|
||||
{
|
||||
delete[] mBurstBuffer;
|
||||
delete mFramer;
|
||||
}
|
||||
|
||||
bool SPDIFEncoder::isFormatSupported(audio_format_t format)
|
||||
{
|
||||
switch(format) {
|
||||
case AUDIO_FORMAT_AC3:
|
||||
case AUDIO_FORMAT_E_AC3:
|
||||
case AUDIO_FORMAT_DTS:
|
||||
case AUDIO_FORMAT_DTS_HD:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int SPDIFEncoder::getBytesPerOutputFrame()
|
||||
{
|
||||
return SPDIF_ENCODED_CHANNEL_COUNT * sizeof(int16_t);
|
||||
}
|
||||
|
||||
void SPDIFEncoder::writeBurstBufferShorts(const uint16_t *buffer, size_t numShorts)
|
||||
{
|
||||
// avoid static analyser warning
|
||||
LOG_ALWAYS_FATAL_IF((mBurstBuffer == NULL), "mBurstBuffer never allocated");
|
||||
mByteCursor = (mByteCursor + 1) & ~1; // round up to even byte
|
||||
size_t bytesToWrite = numShorts * sizeof(uint16_t);
|
||||
if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
|
||||
ALOGE("SPDIFEncoder: Burst buffer overflow!");
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
memcpy(&mBurstBuffer[mByteCursor >> 1], buffer, bytesToWrite);
|
||||
mByteCursor += bytesToWrite;
|
||||
}
|
||||
|
||||
// Pack the bytes into the short buffer in the order:
|
||||
// byte[0] -> short[0] MSB
|
||||
// byte[1] -> short[0] LSB
|
||||
// byte[2] -> short[1] MSB
|
||||
// byte[3] -> short[1] LSB
|
||||
// etcetera
|
||||
// This way they should come out in the correct order for SPDIF on both
|
||||
// Big and Little Endian CPUs.
|
||||
void SPDIFEncoder::writeBurstBufferBytes(const uint8_t *buffer, size_t numBytes)
|
||||
{
|
||||
size_t bytesToWrite = numBytes;
|
||||
if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
|
||||
ALOGE("SPDIFEncoder: Burst buffer overflow!");
|
||||
clearBurstBuffer();
|
||||
return;
|
||||
}
|
||||
uint16_t pad = mBurstBuffer[mByteCursor >> 1];
|
||||
for (size_t i = 0; i < bytesToWrite; i++) {
|
||||
if (mByteCursor & 1 ) {
|
||||
pad |= *buffer++; // put second byte in LSB
|
||||
mBurstBuffer[mByteCursor >> 1] = pad;
|
||||
pad = 0;
|
||||
} else {
|
||||
pad |= (*buffer++) << 8; // put first byte in MSB
|
||||
}
|
||||
mByteCursor++;
|
||||
}
|
||||
// Save partially filled short.
|
||||
if (mByteCursor & 1 ){
|
||||
mBurstBuffer[mByteCursor >> 1] = pad;
|
||||
}
|
||||
}
|
||||
|
||||
void SPDIFEncoder::sendZeroPad()
|
||||
{
|
||||
// Pad remainder of burst with zeros.
|
||||
size_t burstSize = mFramer->getSampleFramesPerSyncFrame() * sizeof(uint16_t)
|
||||
* SPDIF_ENCODED_CHANNEL_COUNT;
|
||||
if (mByteCursor > burstSize) {
|
||||
ALOGE("SPDIFEncoder: Burst buffer, contents too large!");
|
||||
clearBurstBuffer();
|
||||
} else {
|
||||
// We don't have to write zeros because buffer already set to zero
|
||||
// by clearBurstBuffer(). Just pretend we wrote zeros by
|
||||
// incrementing cursor.
|
||||
mByteCursor = burstSize;
|
||||
}
|
||||
}
|
||||
|
||||
void SPDIFEncoder::reset()
|
||||
{
|
||||
ALOGV("SPDIFEncoder: reset()");
|
||||
clearBurstBuffer();
|
||||
if (mFramer != NULL) {
|
||||
mFramer->resetBurst();
|
||||
}
|
||||
mPayloadBytesPending = 0;
|
||||
mScanning = true;
|
||||
}
|
||||
|
||||
void SPDIFEncoder::flushBurstBuffer()
|
||||
{
|
||||
const int preambleSize = 4 * sizeof(uint16_t);
|
||||
if (mByteCursor > preambleSize) {
|
||||
// Set lengthCode for valid payload before zeroPad.
|
||||
uint16_t numBytes = (mByteCursor - preambleSize);
|
||||
mBurstBuffer[3] = mFramer->convertBytesToLengthCode(numBytes);
|
||||
|
||||
sendZeroPad();
|
||||
writeOutput(mBurstBuffer, mByteCursor);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
void SPDIFEncoder::clearBurstBuffer()
|
||||
{
|
||||
if (mBurstBuffer) {
|
||||
memset(mBurstBuffer, 0, mBurstBufferSizeBytes);
|
||||
}
|
||||
mByteCursor = 0;
|
||||
}
|
||||
|
||||
void SPDIFEncoder::startDataBurst()
|
||||
{
|
||||
// Encode IEC61937-1 Burst Preamble
|
||||
uint16_t preamble[4];
|
||||
|
||||
uint16_t burstInfo = (mBitstreamNumber << 13)
|
||||
| (mFramer->getDataTypeInfo() << 8)
|
||||
| mFramer->getDataType();
|
||||
|
||||
mRateMultiplier = mFramer->getRateMultiplier();
|
||||
|
||||
preamble[0] = kSPDIFSync1;
|
||||
preamble[1] = kSPDIFSync2;
|
||||
preamble[2] = burstInfo;
|
||||
preamble[3] = 0; // lengthCode - This will get set after the buffer is full.
|
||||
writeBurstBufferShorts(preamble, 4);
|
||||
}
|
||||
|
||||
size_t SPDIFEncoder::startSyncFrame()
|
||||
{
|
||||
// Write start of encoded frame that was buffered in frame detector.
|
||||
size_t syncSize = mFramer->getHeaderSizeBytes();
|
||||
writeBurstBufferBytes(mFramer->getHeaderAddress(), syncSize);
|
||||
return mFramer->getFrameSizeBytes() - syncSize;
|
||||
}
|
||||
|
||||
// Wraps raw encoded data into a data burst.
|
||||
ssize_t SPDIFEncoder::write( const void *buffer, size_t numBytes )
|
||||
{
|
||||
size_t bytesLeft = numBytes;
|
||||
const uint8_t *data = (const uint8_t *)buffer;
|
||||
ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %zu)",
|
||||
mScanning, (uint) *data, numBytes);
|
||||
while (bytesLeft > 0) {
|
||||
if (mScanning) {
|
||||
// Look for beginning of next encoded frame.
|
||||
if (mFramer->scan(*data)) {
|
||||
if (mByteCursor == 0) {
|
||||
startDataBurst();
|
||||
} else if (mFramer->isFirstInBurst()) {
|
||||
// Make sure that this frame is at the beginning of the data burst.
|
||||
flushBurstBuffer();
|
||||
startDataBurst();
|
||||
}
|
||||
mPayloadBytesPending = startSyncFrame();
|
||||
mScanning = false;
|
||||
}
|
||||
data++;
|
||||
bytesLeft--;
|
||||
} else {
|
||||
// Write payload until we hit end of frame.
|
||||
size_t bytesToWrite = bytesLeft;
|
||||
// Only write as many as we need to finish the frame.
|
||||
if (bytesToWrite > mPayloadBytesPending) {
|
||||
bytesToWrite = mPayloadBytesPending;
|
||||
}
|
||||
writeBurstBufferBytes(data, bytesToWrite);
|
||||
|
||||
data += bytesToWrite;
|
||||
bytesLeft -= bytesToWrite;
|
||||
mPayloadBytesPending -= bytesToWrite;
|
||||
|
||||
// If we have all the payload then send a data burst.
|
||||
if (mPayloadBytesPending == 0) {
|
||||
if (mFramer->isLastInBurst()) {
|
||||
flushBurstBuffer();
|
||||
}
|
||||
mScanning = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
} // namespace android
|
Loading…
Add table
Add a link
Reference in a new issue