25
25
26
26
#include " NDKExtractor.h"
27
27
28
- DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor (int fd, int offset, int length, uint8_t * targetData, AudioProperties targetProperties) {
29
- LOGD (" Using NDK decoder" );
30
-
31
- // Extract the audio frames
32
- AMediaExtractor *extractor = AMediaExtractor_new ();
33
- media_status_t amresult = AMediaExtractor_setDataSourceFd (extractor, fd,
34
- static_cast <off64_t >(offset),
35
- static_cast <off64_t >(length));
36
- if (amresult != AMEDIA_OK){
37
- LOGE (" Error setting extractor data source, err %d" , amresult);
38
- return {.bytesRead = 0 , .error = " Decoding sound file failed" };
28
+ DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor (int fd, int offset, int length, AudioProperties targetProperties) {
29
+ auto extractor = AMediaExtractor_new ();
30
+ auto amResult = AMediaExtractor_setDataSourceFd (
31
+ extractor,
32
+ fd,
33
+ static_cast <off64_t >(offset),
34
+ static_cast <off64_t >(length));
35
+
36
+ if (amResult != AMEDIA_OK){
37
+ return {.error = " Decoding sound file failed" };
39
38
}
40
39
41
40
// Specify our desired output format by creating it from our source
42
- AMediaFormat * format = AMediaExtractor_getTrackFormat (extractor, 0 );
41
+ auto format = AMediaExtractor_getTrackFormat (extractor, 0 );
43
42
44
43
int32_t sampleRate;
45
44
if (AMediaFormat_getInt32 (format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate)){
46
- LOGD (" File sample rate: %d" , sampleRate);
47
45
if (sampleRate != targetProperties.sampleRate ){
48
46
std::stringstream error;
49
47
error
@@ -53,15 +51,14 @@ DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor(int fd, int offset
53
51
<< " , doesn't match the sample rate of the stream, "
54
52
<< targetProperties.sampleRate << " ." ;
55
53
56
- return {.bytesRead = 0 , . error = error.str ()};
54
+ return {.error = error.str ()};
57
55
}
58
56
} else {
59
- return {.bytesRead = 0 , . error = " Failed to load sound file: could not determine sample rate" };
57
+ return {.error = " Failed to load sound file: could not determine sample rate" };
60
58
};
61
59
62
60
int32_t channelCount;
63
61
if (AMediaFormat_getInt32 (format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &channelCount)){
64
- LOGD (" File channel count: %d" , channelCount);
65
62
if (channelCount != targetProperties.channelCount ){
66
63
std::stringstream error;
67
64
error
@@ -70,113 +67,70 @@ DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor(int fd, int offset
70
67
<< " , doesn't match the channel count of the stream, "
71
68
<< targetProperties.channelCount << " ." ;
72
69
73
- return {.bytesRead = 0 , . error = error.str ()};
70
+ return {.error = error.str ()};
74
71
}
75
72
} else {
76
- return {.bytesRead = 0 , . error = " Failed to load sound file: could not determine channel count" };
73
+ return {.error = " Failed to load sound file: could not determine channel count" };
77
74
}
78
75
79
76
const char *mimeType;
80
- if (AMediaFormat_getString (format, AMEDIAFORMAT_KEY_MIME, &mimeType)) {
81
- LOGD (" File mime type: %s" , mimeType);
82
- } else {
83
- return {.bytesRead = 0 , .error = " Failed to load sound file: could not determine mimeType" };
77
+ if (!AMediaFormat_getString (format, AMEDIAFORMAT_KEY_MIME, &mimeType)) {
78
+ return {.error = " Failed to load sound file: could not determine mimeType" };
84
79
}
85
80
86
81
// Obtain the correct decoder
87
- AMediaCodec *codec = nullptr ;
88
82
AMediaExtractor_selectTrack (extractor, 0 );
89
- codec = AMediaCodec_createDecoderByType (mimeType);
83
+ auto codec = AMediaCodec_createDecoderByType (mimeType);
90
84
AMediaCodec_configure (codec, format, nullptr , nullptr , 0 );
91
85
AMediaCodec_start (codec);
92
86
87
+ std::vector<uint8_t > data{};
93
88
// DECODE
94
89
95
90
bool isExtracting = true ;
96
91
bool isDecoding = true ;
97
- int32_t bytesWritten = 0 ;
98
92
99
93
while (isExtracting || isDecoding){
100
94
101
95
if (isExtracting){
102
96
103
- // Obtain the index of the next available input buffer
104
- ssize_t inputIndex = AMediaCodec_dequeueInputBuffer (codec, 2000 );
105
- // LOGV("Got input buffer %d", inputIndex);
97
+ auto inputIndex = AMediaCodec_dequeueInputBuffer (codec, 2000 );
106
98
107
- // The input index acts as a status if its negative
108
- if (inputIndex < 0 ){
109
- if (inputIndex == AMEDIACODEC_INFO_TRY_AGAIN_LATER){
110
- // LOGV("Codec.dequeueInputBuffer try again later");
111
- } else {
112
- LOGE (" Codec.dequeueInputBuffer unknown error status" );
113
- }
114
- } else {
99
+ if (inputIndex >= 0 ) {
115
100
116
101
// Obtain the actual buffer and read the encoded data into it
117
- size_t inputSize;
118
- uint8_t *inputBuffer = AMediaCodec_getInputBuffer (codec, inputIndex, &inputSize);
119
-
120
- ssize_t sampleSize = AMediaExtractor_readSampleData (extractor, inputBuffer, inputSize);
121
- auto presentationTimeUs = AMediaExtractor_getSampleTime (extractor);
122
-
123
- if (sampleSize > 0 ){
124
-
125
- // Enqueue the encoded data
126
- AMediaCodec_queueInputBuffer (codec, inputIndex, 0 , sampleSize,
127
- presentationTimeUs,
128
- 0 );
129
- AMediaExtractor_advance (extractor);
130
-
131
- } else {
132
- LOGD (" End of extractor data stream" );
133
- isExtracting = false ;
134
-
135
- // We need to tell the codec that we've reached the end of the stream
136
- AMediaCodec_queueInputBuffer (codec, inputIndex, 0 , 0 ,
137
- presentationTimeUs,
138
- AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
102
+ size_t inputSize {};
103
+ auto inputBuffer = AMediaCodec_getInputBuffer (codec, inputIndex, &inputSize);
104
+
105
+ if (inputBuffer) {
106
+ auto sampleSize = AMediaExtractor_readSampleData (extractor, inputBuffer, inputSize);
107
+ auto presentationTimeUs = AMediaExtractor_getSampleTime (extractor);
108
+
109
+ if (sampleSize > 0 ){
110
+ AMediaCodec_queueInputBuffer (codec, inputIndex, 0 , sampleSize, presentationTimeUs, 0 );
111
+ AMediaExtractor_advance (extractor);
112
+ } else {
113
+ isExtracting = false ;
114
+ AMediaCodec_queueInputBuffer (codec, inputIndex, 0 , 0 , presentationTimeUs, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
115
+ }
139
116
}
140
117
}
141
118
}
142
119
143
- if (isDecoding){
144
- // Dequeue the decoded data
145
- AMediaCodecBufferInfo info;
146
- ssize_t outputIndex = AMediaCodec_dequeueOutputBuffer (codec, &info, 0 );
147
-
148
- if (outputIndex >= 0 ){
149
-
150
- // Check whether this is set earlier
151
- if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM){
152
- LOGD (" Reached end of decoding stream" );
153
- isDecoding = false ;
120
+ if (isDecoding) {
121
+ AMediaCodecBufferInfo bufferInfo{};
122
+ auto outputIndex = AMediaCodec_dequeueOutputBuffer (codec, &bufferInfo, 2000 );
123
+ while (outputIndex >= 0 ) {
124
+ auto outputBuffer = AMediaCodec_getOutputBuffer (codec, outputIndex, nullptr );
125
+ if (outputBuffer) {
126
+ data.insert (data.end (), outputBuffer, outputBuffer + bufferInfo.size );
154
127
}
155
-
156
- // Valid index, acquire buffer
157
- size_t outputSize;
158
- uint8_t *outputBuffer = AMediaCodec_getOutputBuffer (codec, outputIndex, &outputSize);
159
-
160
- // copy the data out of the buffer
161
- memcpy (targetData + bytesWritten, outputBuffer, info.size );
162
- bytesWritten+=info.size ;
163
128
AMediaCodec_releaseOutputBuffer (codec, outputIndex, false );
164
- } else {
165
-
166
- // The outputIndex doubles as a status return if its value is < 0
167
- switch (outputIndex){
168
- case AMEDIACODEC_INFO_TRY_AGAIN_LATER:
169
- LOGD (" dequeueOutputBuffer: try again later" );
170
- break ;
171
- case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED:
172
- LOGD (" dequeueOutputBuffer: output buffers changed" );
173
- break ;
174
- case AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED:
175
- LOGD (" dequeueOutputBuffer: output outputFormat changed" );
176
- format = AMediaCodec_getOutputFormat (codec);
177
- LOGD (" outputFormat changed to: %s" , AMediaFormat_toString (format));
178
- break ;
179
- }
129
+ outputIndex = AMediaCodec_dequeueOutputBuffer (codec, &bufferInfo, 0 );
130
+ }
131
+
132
+ if (bufferInfo.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
133
+ isDecoding = false ;
180
134
}
181
135
}
182
136
}
@@ -186,6 +140,6 @@ DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor(int fd, int offset
186
140
AMediaCodec_delete (codec);
187
141
AMediaExtractor_delete (extractor);
188
142
189
- return {.bytesRead = bytesWritten, . error = std::nullopt };
143
+ return {.data = data };
190
144
}
191
145
0 commit comments