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//#define LOG_NDEBUG 0
18#define LOG_TAG "DataConverter"
19
20#include "include/DataConverter.h"
21
22#include <audio_utils/primitives.h>
23
24#include <media/stagefright/foundation/ABuffer.h>
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/AUtils.h>
27
28namespace android {
29
30status_t DataConverter::convert(const sp<ABuffer> &source, sp<ABuffer> &target) {
31    CHECK(source->base() != target->base());
32    size_t size = targetSize(source->size());
33    status_t err = OK;
34    if (size > target->capacity()) {
35        ALOGE("data size (%zu) is greater than buffer capacity (%zu)",
36                size,          // this is the data received/to be converted
37                target->capacity()); // this is out buffer size
38        err = FAILED_TRANSACTION;
39    } else {
40        err = safeConvert(source, target);
41    }
42    target->setRange(0, err == OK ? size : 0);
43    return err;
44}
45
46status_t DataConverter::safeConvert(const sp<ABuffer> &source, sp<ABuffer> &target) {
47    memcpy(target->base(), source->data(), source->size());
48    return OK;
49}
50
51size_t DataConverter::sourceSize(size_t targetSize) {
52    return targetSize;
53}
54
55size_t DataConverter::targetSize(size_t sourceSize) {
56    return sourceSize;
57}
58
59DataConverter::~DataConverter() { }
60
61
62size_t SampleConverterBase::sourceSize(size_t targetSize) {
63    size_t numSamples = targetSize / mTargetSampleSize;
64    if (numSamples > SIZE_MAX / mSourceSampleSize) {
65        ALOGW("limiting source size due to overflow (%zu*%zu/%zu)",
66                targetSize, mSourceSampleSize, mTargetSampleSize);
67        return SIZE_MAX;
68    }
69    return numSamples * mSourceSampleSize;
70}
71
72size_t SampleConverterBase::targetSize(size_t sourceSize) {
73    // we round up on conversion
74    size_t numSamples = divUp(sourceSize, (size_t)mSourceSampleSize);
75    if (numSamples > SIZE_MAX / mTargetSampleSize) {
76        ALOGW("limiting target size due to overflow (%zu*%zu/%zu)",
77                sourceSize, mTargetSampleSize, mSourceSampleSize);
78        return SIZE_MAX;
79    }
80    return numSamples * mTargetSampleSize;
81}
82
83
84static size_t getAudioSampleSize(AudioEncoding e) {
85    switch (e) {
86        case kAudioEncodingPcm16bit: return 2;
87        case kAudioEncodingPcm8bit:  return 1;
88        case kAudioEncodingPcmFloat: return 4;
89        default: return 0;
90    }
91}
92
93
94// static
95AudioConverter* AudioConverter::Create(AudioEncoding source, AudioEncoding target) {
96    uint32_t sourceSampleSize = getAudioSampleSize(source);
97    uint32_t targetSampleSize = getAudioSampleSize(target);
98    if (sourceSampleSize && targetSampleSize && sourceSampleSize != targetSampleSize) {
99        return new AudioConverter(source, sourceSampleSize, target, targetSampleSize);
100    }
101    return NULL;
102}
103
104status_t AudioConverter::safeConvert(const sp<ABuffer> &src, sp<ABuffer> &tgt) {
105    if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcm16bit) {
106        memcpy_to_u8_from_i16((uint8_t*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
107    } else if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcmFloat) {
108        memcpy_to_u8_from_float((uint8_t*)tgt->base(), (const float*)src->data(), src->size() / 4);
109    } else if (mTo == kAudioEncodingPcm16bit && mFrom == kAudioEncodingPcm8bit) {
110        memcpy_to_i16_from_u8((int16_t*)tgt->base(), (const uint8_t*)src->data(), src->size());
111    } else if (mTo == kAudioEncodingPcm16bit && mFrom == kAudioEncodingPcmFloat) {
112        memcpy_to_i16_from_float((int16_t*)tgt->base(), (const float*)src->data(), src->size() / 4);
113    } else if (mTo == kAudioEncodingPcmFloat && mFrom == kAudioEncodingPcm8bit) {
114        memcpy_to_float_from_u8((float*)tgt->base(), (const uint8_t*)src->data(), src->size());
115    } else if (mTo == kAudioEncodingPcmFloat && mFrom == kAudioEncodingPcm16bit) {
116        memcpy_to_float_from_i16((float*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
117    } else {
118        return INVALID_OPERATION;
119    }
120    return OK;
121}
122
123} // namespace android
124