1 /*
2 * Copyright (C) 2019 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 "decoder"
19
20 #include <iostream>
21
22 #include "Decoder.h"
23
readSampleData(uint8_t * inputBuffer,int32_t & offset,vector<AMediaCodecBufferInfo> & frameInfo,uint8_t * buf,int32_t frameID,size_t bufSize)24 tuple<ssize_t, uint32_t, int64_t> readSampleData(uint8_t *inputBuffer, int32_t &offset,
25 vector<AMediaCodecBufferInfo> &frameInfo,
26 uint8_t *buf, int32_t frameID, size_t bufSize) {
27 ALOGV("In %s", __func__);
28 if (frameID == (int32_t)frameInfo.size()) {
29 return make_tuple(0, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM, 0);
30 }
31 uint32_t flags = frameInfo[frameID].flags;
32 int64_t timestamp = frameInfo[frameID].presentationTimeUs;
33 ssize_t bytesCount = frameInfo[frameID].size;
34 if (bufSize < bytesCount) {
35 ALOGE("Error : Buffer size is insufficient to read sample");
36 return make_tuple(0, AMEDIA_ERROR_MALFORMED, 0);
37 }
38
39 memcpy(buf, inputBuffer + offset, bytesCount);
40 offset += bytesCount;
41 return make_tuple(bytesCount, flags, timestamp);
42 }
43
onInputAvailable(AMediaCodec * mediaCodec,int32_t bufIdx)44 void Decoder::onInputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx) {
45 ALOGV("In %s", __func__);
46 if (mediaCodec == mCodec && mediaCodec) {
47 if (mSawInputEOS || bufIdx < 0) return;
48 if (mSignalledError) {
49 CallBackHandle::mSawError = true;
50 mDecoderDoneCondition.notify_one();
51 return;
52 }
53
54 size_t bufSize;
55 uint8_t *buf = AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
56 if (!buf) {
57 mErrorCode = AMEDIA_ERROR_IO;
58 mSignalledError = true;
59 mDecoderDoneCondition.notify_one();
60 return;
61 }
62
63 ssize_t bytesRead = 0;
64 uint32_t flag = 0;
65 int64_t presentationTimeUs = 0;
66 tie(bytesRead, flag, presentationTimeUs) =
67 readSampleData(mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
68 if (flag == AMEDIA_ERROR_MALFORMED) {
69 mErrorCode = (media_status_t)flag;
70 mSignalledError = true;
71 mDecoderDoneCondition.notify_one();
72 return;
73 }
74
75 if (flag == AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) mSawInputEOS = true;
76 ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRId64 " mSawInputEOS : %s", __FUNCTION__,
77 bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
78
79 media_status_t status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */,
80 bytesRead, presentationTimeUs, flag);
81 if (AMEDIA_OK != status) {
82 mErrorCode = status;
83 mSignalledError = true;
84 mDecoderDoneCondition.notify_one();
85 return;
86 }
87 mStats->addFrameSize(bytesRead);
88 mNumInputFrame++;
89 }
90 }
91
onOutputAvailable(AMediaCodec * mediaCodec,int32_t bufIdx,AMediaCodecBufferInfo * bufferInfo)92 void Decoder::onOutputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx,
93 AMediaCodecBufferInfo *bufferInfo) {
94 ALOGV("In %s", __func__);
95 if (mediaCodec == mCodec && mediaCodec) {
96 if (mSawOutputEOS || bufIdx < 0) return;
97 if (mSignalledError) {
98 CallBackHandle::mSawError = true;
99 mDecoderDoneCondition.notify_one();
100 return;
101 }
102
103 if (mOutFp != nullptr) {
104 size_t bufSize;
105 uint8_t *buf = AMediaCodec_getOutputBuffer(mCodec, bufIdx, &bufSize);
106 if (buf) {
107 fwrite(buf, sizeof(char), bufferInfo->size, mOutFp);
108 ALOGV("bytes written into file %d\n", bufferInfo->size);
109 }
110 }
111
112 AMediaCodec_releaseOutputBuffer(mCodec, bufIdx, false);
113 mSawOutputEOS = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
114 mNumOutputFrame++;
115 ALOGV("%s index : %d mSawOutputEOS : %s count : %u", __FUNCTION__, bufIdx,
116 mSawOutputEOS ? "TRUE" : "FALSE", mNumOutputFrame);
117
118 if (mSawOutputEOS) {
119 CallBackHandle::mIsDone = true;
120 mDecoderDoneCondition.notify_one();
121 }
122 }
123 }
124
onFormatChanged(AMediaCodec * mediaCodec,AMediaFormat * format)125 void Decoder::onFormatChanged(AMediaCodec *mediaCodec, AMediaFormat *format) {
126 ALOGV("In %s", __func__);
127 if (mediaCodec == mCodec && mediaCodec) {
128 ALOGV("%s { %s }", __FUNCTION__, AMediaFormat_toString(format));
129 mFormat = format;
130 }
131 }
132
onError(AMediaCodec * mediaCodec,media_status_t err)133 void Decoder::onError(AMediaCodec *mediaCodec, media_status_t err) {
134 ALOGV("In %s", __func__);
135 if (mediaCodec == mCodec && mediaCodec) {
136 ALOGE("Received Error %d", err);
137 mErrorCode = err;
138 mSignalledError = true;
139 mDecoderDoneCondition.notify_one();
140 }
141 }
142
setupDecoder()143 void Decoder::setupDecoder() {
144 if (!mFormat) mFormat = mExtractor->getFormat();
145 }
146
getFormat()147 AMediaFormat *Decoder::getFormat() {
148 ALOGV("In %s", __func__);
149 return AMediaCodec_getOutputFormat(mCodec);
150 }
151
decode(uint8_t * inputBuffer,vector<AMediaCodecBufferInfo> & frameInfo,string & codecName,bool asyncMode,FILE * outFp)152 int32_t Decoder::decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
153 string &codecName, bool asyncMode, FILE *outFp) {
154 ALOGV("In %s", __func__);
155 mInputBuffer = inputBuffer;
156 mFrameMetaData = frameInfo;
157 mOffset = 0;
158 mOutFp = outFp;
159
160 const char *mime = nullptr;
161 AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime);
162 if (!mime) return AMEDIA_ERROR_INVALID_OBJECT;
163
164 int64_t sTime = mStats->getCurTime();
165 mCodec = createMediaCodec(mFormat, mime, codecName, false /*isEncoder*/);
166 if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
167
168 if (asyncMode) {
169 AMediaCodecOnAsyncNotifyCallback aCB = {OnInputAvailableCB, OnOutputAvailableCB,
170 OnFormatChangedCB, OnErrorCB};
171 AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
172
173 mIOThread = thread(&CallBackHandle::ioThread, this);
174 }
175
176 AMediaCodec_start(mCodec);
177 int64_t eTime = mStats->getCurTime();
178 int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
179 mStats->setInitTime(timeTaken);
180
181 mStats->setStartTime();
182 if (!asyncMode) {
183 while (!mSawOutputEOS && !mSignalledError) {
184 /* Queue input data */
185 if (!mSawInputEOS) {
186 ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
187 if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
188 ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
189 mErrorCode = (media_status_t)inIdx;
190 return mErrorCode;
191 } else if (inIdx >= 0) {
192 mStats->addInputTime();
193 onInputAvailable(mCodec, inIdx);
194 }
195 }
196
197 /* Dequeue output data */
198 AMediaCodecBufferInfo info;
199 ssize_t outIdx = AMediaCodec_dequeueOutputBuffer(mCodec, &info, kQueueDequeueTimeoutUs);
200 if (outIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
201 mFormat = AMediaCodec_getOutputFormat(mCodec);
202 const char *s = AMediaFormat_toString(mFormat);
203 ALOGI("Output format: %s\n", s);
204 } else if (outIdx >= 0) {
205 mStats->addOutputTime();
206 onOutputAvailable(mCodec, outIdx, &info);
207 } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
208 outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
209 ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
210 mErrorCode = (media_status_t)outIdx;
211 return mErrorCode;
212 }
213 }
214 } else {
215 unique_lock<mutex> lock(mMutex);
216 mDecoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
217 }
218 if (mSignalledError) {
219 ALOGE("Received Error while Decoding");
220 return mErrorCode;
221 }
222
223 if (codecName.empty()) {
224 char *decName;
225 AMediaCodec_getName(mCodec, &decName);
226 codecName.assign(decName);
227 AMediaCodec_releaseName(mCodec, decName);
228 }
229 return AMEDIA_OK;
230 }
231
deInitCodec()232 void Decoder::deInitCodec() {
233 if (mFormat) {
234 AMediaFormat_delete(mFormat);
235 mFormat = nullptr;
236 }
237 if (!mCodec) return;
238 int64_t sTime = mStats->getCurTime();
239 AMediaCodec_stop(mCodec);
240 AMediaCodec_delete(mCodec);
241 int64_t eTime = mStats->getCurTime();
242 int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
243 mStats->setDeInitTime(timeTaken);
244 }
245
dumpStatistics(string inputReference,string componentName,string mode,string statsFile)246 void Decoder::dumpStatistics(string inputReference, string componentName, string mode,
247 string statsFile) {
248 int64_t durationUs = mExtractor->getClipDuration();
249 string operation = "decode";
250 mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
251 }
252
resetDecoder()253 void Decoder::resetDecoder() {
254 if (mStats) mStats->reset();
255 if (mInputBuffer) mInputBuffer = nullptr;
256 if (!mFrameMetaData.empty()) mFrameMetaData.clear();
257 }
258