• 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 //#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 #include <system/audio.h>
28 #include <audio_utils/primitives.h>
29 #include <audio_utils/format.h>
30 
31 
32 namespace android {
33 
convert(const sp<MediaCodecBuffer> & source,sp<MediaCodecBuffer> & target)34 status_t DataConverter::convert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) {
35     CHECK(source->base() != target->base());
36     size_t size = targetSize(source->size());
37     status_t err = OK;
38     if (size > target->capacity()) {
39         ALOGE("data size (%zu) is greater than buffer capacity (%zu)",
40                 size,          // this is the data received/to be converted
41                 target->capacity()); // this is out buffer size
42         err = FAILED_TRANSACTION;
43     } else {
44         err = safeConvert(source, target);
45     }
46     target->setRange(0, err == OK ? size : 0);
47     return err;
48 }
49 
safeConvert(const sp<MediaCodecBuffer> & source,sp<MediaCodecBuffer> & target)50 status_t DataConverter::safeConvert(
51         const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) {
52     memcpy(target->base(), source->data(), source->size());
53     return OK;
54 }
55 
sourceSize(size_t targetSize)56 size_t DataConverter::sourceSize(size_t targetSize) {
57     return targetSize;
58 }
59 
targetSize(size_t sourceSize)60 size_t DataConverter::targetSize(size_t sourceSize) {
61     return sourceSize;
62 }
63 
~DataConverter()64 DataConverter::~DataConverter() { }
65 
66 
sourceSize(size_t targetSize)67 size_t SampleConverterBase::sourceSize(size_t targetSize) {
68     size_t numSamples = targetSize / mTargetSampleSize;
69     if (numSamples > SIZE_MAX / mSourceSampleSize) {
70         ALOGW("limiting source size due to overflow (%zu*%zu/%zu)",
71                 targetSize, mSourceSampleSize, mTargetSampleSize);
72         return SIZE_MAX;
73     }
74     return numSamples * mSourceSampleSize;
75 }
76 
targetSize(size_t sourceSize)77 size_t SampleConverterBase::targetSize(size_t sourceSize) {
78     // we round up on conversion
79     size_t numSamples = divUp(sourceSize, (size_t)mSourceSampleSize);
80     if (numSamples > SIZE_MAX / mTargetSampleSize) {
81         ALOGW("limiting target size due to overflow (%zu*%zu/%zu)",
82                 sourceSize, mTargetSampleSize, mSourceSampleSize);
83         return SIZE_MAX;
84     }
85     return numSamples * mTargetSampleSize;
86 }
87 
getAudioFormat(AudioEncoding e)88 static audio_format_t getAudioFormat(AudioEncoding e) {
89     audio_format_t format = AUDIO_FORMAT_INVALID;
90     switch (e) {
91         case kAudioEncodingPcm16bit:
92             format = AUDIO_FORMAT_PCM_16_BIT;
93             break;
94         case kAudioEncodingPcm8bit:
95             format = AUDIO_FORMAT_PCM_8_BIT;
96             break;
97         case kAudioEncodingPcmFloat:
98             format = AUDIO_FORMAT_PCM_FLOAT;
99             break;
100        case kAudioEncodingPcm24bitPacked:
101             format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
102             break;
103        case kAudioEncodingPcm32bit:
104             format = AUDIO_FORMAT_PCM_32_BIT;
105             break;
106         default:
107             ALOGE("Invalid AudioEncoding %d", e);
108         }
109         return format;
110 }
111 
getAudioSampleSize(AudioEncoding e)112 static size_t getAudioSampleSize(AudioEncoding e) {
113     switch (e) {
114         case kAudioEncodingPcm16bit:
115         case kAudioEncodingPcm8bit:
116         case kAudioEncodingPcmFloat:
117         case kAudioEncodingPcm24bitPacked:
118         case kAudioEncodingPcm32bit:
119             return audio_bytes_per_sample(getAudioFormat(e));
120         default: return 0;
121     }
122 }
123 
124 
125 // static
Create(AudioEncoding source,AudioEncoding target)126 AudioConverter* AudioConverter::Create(AudioEncoding source, AudioEncoding target) {
127     uint32_t sourceSampleSize = getAudioSampleSize(source);
128     uint32_t targetSampleSize = getAudioSampleSize(target);
129     if (sourceSampleSize && targetSampleSize && sourceSampleSize != targetSampleSize) {
130         return new AudioConverter(source, sourceSampleSize, target, targetSampleSize);
131     }
132     return NULL;
133 }
134 
safeConvert(const sp<MediaCodecBuffer> & src,sp<MediaCodecBuffer> & tgt)135 status_t AudioConverter::safeConvert(const sp<MediaCodecBuffer> &src, sp<MediaCodecBuffer> &tgt) {
136     if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcm16bit) {
137         memcpy_to_u8_from_i16((uint8_t*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
138     } else if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcmFloat) {
139         memcpy_to_u8_from_float((uint8_t*)tgt->base(), (const float*)src->data(), src->size() / 4);
140     } else if (mTo == kAudioEncodingPcm16bit && mFrom == kAudioEncodingPcm8bit) {
141         memcpy_to_i16_from_u8((int16_t*)tgt->base(), (const uint8_t*)src->data(), src->size());
142     } else if (mTo == kAudioEncodingPcm16bit && mFrom == kAudioEncodingPcmFloat) {
143         memcpy_to_i16_from_float((int16_t*)tgt->base(), (const float*)src->data(), src->size() / 4);
144     } else if (mTo == kAudioEncodingPcmFloat && mFrom == kAudioEncodingPcm8bit) {
145         memcpy_to_float_from_u8((float*)tgt->base(), (const uint8_t*)src->data(), src->size());
146     } else if (mTo == kAudioEncodingPcmFloat && mFrom == kAudioEncodingPcm16bit) {
147         memcpy_to_float_from_i16((float*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
148     } else {
149         audio_format_t srcFormat = getAudioFormat(mFrom);
150         audio_format_t dstFormat = getAudioFormat(mTo);
151 
152         if ((srcFormat == AUDIO_FORMAT_INVALID) || (dstFormat == AUDIO_FORMAT_INVALID))
153             return INVALID_OPERATION;
154 
155         size_t frames = src->size() / audio_bytes_per_sample(srcFormat);
156         memcpy_by_audio_format((void*)tgt->base(), dstFormat, (void*)src->data(),
157                 srcFormat, frames);
158     }
159     return OK;
160 }
161 
162 } // namespace android
163