2525
2626#include " NDKExtractor.h"
2727
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" };
3938 }
4039
4140 // 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 );
4342
4443 int32_t sampleRate;
4544 if (AMediaFormat_getInt32 (format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate)){
46- LOGD (" File sample rate: %d" , sampleRate);
4745 if (sampleRate != targetProperties.sampleRate ){
4846 std::stringstream error;
4947 error
@@ -53,15 +51,14 @@ DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor(int fd, int offset
5351 << " , doesn't match the sample rate of the stream, "
5452 << targetProperties.sampleRate << " ." ;
5553
56- return {.bytesRead = 0 , . error = error.str ()};
54+ return {.error = error.str ()};
5755 }
5856 } 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" };
6058 };
6159
6260 int32_t channelCount;
6361 if (AMediaFormat_getInt32 (format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &channelCount)){
64- LOGD (" File channel count: %d" , channelCount);
6562 if (channelCount != targetProperties.channelCount ){
6663 std::stringstream error;
6764 error
@@ -70,113 +67,70 @@ DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor(int fd, int offset
7067 << " , doesn't match the channel count of the stream, "
7168 << targetProperties.channelCount << " ." ;
7269
73- return {.bytesRead = 0 , . error = error.str ()};
70+ return {.error = error.str ()};
7471 }
7572 } 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" };
7774 }
7875
7976 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" };
8479 }
8580
8681 // Obtain the correct decoder
87- AMediaCodec *codec = nullptr ;
8882 AMediaExtractor_selectTrack (extractor, 0 );
89- codec = AMediaCodec_createDecoderByType (mimeType);
83+ auto codec = AMediaCodec_createDecoderByType (mimeType);
9084 AMediaCodec_configure (codec, format, nullptr , nullptr , 0 );
9185 AMediaCodec_start (codec);
9286
87+ std::vector<uint8_t > data{};
9388 // DECODE
9489
9590 bool isExtracting = true ;
9691 bool isDecoding = true ;
97- int32_t bytesWritten = 0 ;
9892
9993 while (isExtracting || isDecoding){
10094
10195 if (isExtracting){
10296
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 );
10698
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 ) {
115100
116101 // 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+ }
139116 }
140117 }
141118 }
142119
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 );
154127 }
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 ;
163128 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 ;
180134 }
181135 }
182136 }
@@ -186,6 +140,6 @@ DecodeFileDescriptorResult NDKExtractor::decodeFileDescriptor(int fd, int offset
186140 AMediaCodec_delete (codec);
187141 AMediaExtractor_delete (extractor);
188142
189- return {.bytesRead = bytesWritten, . error = std:: nullopt };
143+ return {.data = data };
190144}
191145
0 commit comments