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