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