1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #include <charconv>
18*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
19*ec779b8eSAndroid Build Coastguard Worker #include <mutex>
20*ec779b8eSAndroid Build Coastguard Worker #include <set>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
23*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "NdkMediaCodec"
24*ec779b8eSAndroid Build Coastguard Worker
25*ec779b8eSAndroid Build Coastguard Worker #include <media/NdkMediaCodecPlatform.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/NdkMediaError.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <media/NdkMediaFormatPriv.h>
28*ec779b8eSAndroid Build Coastguard Worker #include "NdkMediaCryptoPriv.h"
29*ec779b8eSAndroid Build Coastguard Worker
30*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <utils/StrongPointer.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <gui/Surface.h>
33*ec779b8eSAndroid Build Coastguard Worker
34*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ALooper.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
36*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
37*ec779b8eSAndroid Build Coastguard Worker
38*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/PersistentSurface.h>
39*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaCodec.h>
40*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaErrors.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaCodecBuffer.h>
42*ec779b8eSAndroid Build Coastguard Worker #include <android/native_window.h>
43*ec779b8eSAndroid Build Coastguard Worker
44*ec779b8eSAndroid Build Coastguard Worker using namespace android;
45*ec779b8eSAndroid Build Coastguard Worker
46*ec779b8eSAndroid Build Coastguard Worker
translate_error(status_t err)47*ec779b8eSAndroid Build Coastguard Worker static media_status_t translate_error(status_t err) {
48*ec779b8eSAndroid Build Coastguard Worker
49*ec779b8eSAndroid Build Coastguard Worker if (err == OK) {
50*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
51*ec779b8eSAndroid Build Coastguard Worker } else if (err == -EAGAIN) {
52*ec779b8eSAndroid Build Coastguard Worker return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
53*ec779b8eSAndroid Build Coastguard Worker } else if (err == NO_MEMORY) {
54*ec779b8eSAndroid Build Coastguard Worker return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
55*ec779b8eSAndroid Build Coastguard Worker } else if (err == DEAD_OBJECT) {
56*ec779b8eSAndroid Build Coastguard Worker return AMEDIACODEC_ERROR_RECLAIMED;
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker
59*ec779b8eSAndroid Build Coastguard Worker {
60*ec779b8eSAndroid Build Coastguard Worker // minimize log flooding. Some CTS behavior made this noisy and apps could do the same.
61*ec779b8eSAndroid Build Coastguard Worker static std::set<status_t> untranslated;
62*ec779b8eSAndroid Build Coastguard Worker static std::mutex mutex;
63*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lg(mutex);
64*ec779b8eSAndroid Build Coastguard Worker
65*ec779b8eSAndroid Build Coastguard Worker if (untranslated.find(err) == untranslated.end()) {
66*ec779b8eSAndroid Build Coastguard Worker ALOGE("untranslated sf error code: %d", err);
67*ec779b8eSAndroid Build Coastguard Worker char err_as_string[32];
68*ec779b8eSAndroid Build Coastguard Worker snprintf(err_as_string, sizeof(err_as_string), "%d", err);
69*ec779b8eSAndroid Build Coastguard Worker android_errorWriteWithInfoLog(0x534e4554, "224869524", -1,
70*ec779b8eSAndroid Build Coastguard Worker err_as_string, strlen(err_as_string));
71*ec779b8eSAndroid Build Coastguard Worker untranslated.insert(err);
72*ec779b8eSAndroid Build Coastguard Worker }
73*ec779b8eSAndroid Build Coastguard Worker }
74*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_UNKNOWN;
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker
77*ec779b8eSAndroid Build Coastguard Worker enum {
78*ec779b8eSAndroid Build Coastguard Worker kWhatActivityNotify,
79*ec779b8eSAndroid Build Coastguard Worker kWhatAsyncNotify,
80*ec779b8eSAndroid Build Coastguard Worker kWhatRequestActivityNotifications,
81*ec779b8eSAndroid Build Coastguard Worker kWhatStopActivityNotifications,
82*ec779b8eSAndroid Build Coastguard Worker kWhatFrameRenderedNotify,
83*ec779b8eSAndroid Build Coastguard Worker };
84*ec779b8eSAndroid Build Coastguard Worker
85*ec779b8eSAndroid Build Coastguard Worker struct AMediaCodecPersistentSurface : public Surface {
86*ec779b8eSAndroid Build Coastguard Worker sp<PersistentSurface> mPersistentSurface;
AMediaCodecPersistentSurfaceAMediaCodecPersistentSurface87*ec779b8eSAndroid Build Coastguard Worker AMediaCodecPersistentSurface(
88*ec779b8eSAndroid Build Coastguard Worker const sp<IGraphicBufferProducer>& igbp,
89*ec779b8eSAndroid Build Coastguard Worker const sp<PersistentSurface>& ps)
90*ec779b8eSAndroid Build Coastguard Worker : Surface(igbp) {
91*ec779b8eSAndroid Build Coastguard Worker mPersistentSurface = ps;
92*ec779b8eSAndroid Build Coastguard Worker }
~AMediaCodecPersistentSurfaceAMediaCodecPersistentSurface93*ec779b8eSAndroid Build Coastguard Worker virtual ~AMediaCodecPersistentSurface() {
94*ec779b8eSAndroid Build Coastguard Worker //mPersistentSurface ref will be let go off here
95*ec779b8eSAndroid Build Coastguard Worker }
96*ec779b8eSAndroid Build Coastguard Worker };
97*ec779b8eSAndroid Build Coastguard Worker
98*ec779b8eSAndroid Build Coastguard Worker class CodecHandler: public AHandler {
99*ec779b8eSAndroid Build Coastguard Worker private:
100*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* mCodec;
101*ec779b8eSAndroid Build Coastguard Worker public:
102*ec779b8eSAndroid Build Coastguard Worker explicit CodecHandler(AMediaCodec *codec);
103*ec779b8eSAndroid Build Coastguard Worker virtual void onMessageReceived(const sp<AMessage> &msg);
104*ec779b8eSAndroid Build Coastguard Worker };
105*ec779b8eSAndroid Build Coastguard Worker
106*ec779b8eSAndroid Build Coastguard Worker typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
107*ec779b8eSAndroid Build Coastguard Worker
108*ec779b8eSAndroid Build Coastguard Worker struct AMediaCodec {
109*ec779b8eSAndroid Build Coastguard Worker sp<android::MediaCodec> mCodec;
110*ec779b8eSAndroid Build Coastguard Worker sp<ALooper> mLooper;
111*ec779b8eSAndroid Build Coastguard Worker sp<CodecHandler> mHandler;
112*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> mActivityNotification;
113*ec779b8eSAndroid Build Coastguard Worker int32_t mGeneration;
114*ec779b8eSAndroid Build Coastguard Worker bool mRequestedActivityNotification;
115*ec779b8eSAndroid Build Coastguard Worker OnCodecEvent mCallback;
116*ec779b8eSAndroid Build Coastguard Worker void *mCallbackUserData;
117*ec779b8eSAndroid Build Coastguard Worker
118*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> mAsyncNotify;
119*ec779b8eSAndroid Build Coastguard Worker mutable Mutex mAsyncCallbackLock;
120*ec779b8eSAndroid Build Coastguard Worker AMediaCodecOnAsyncNotifyCallback mAsyncCallback;
121*ec779b8eSAndroid Build Coastguard Worker void *mAsyncCallbackUserData;
122*ec779b8eSAndroid Build Coastguard Worker
123*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> mFrameRenderedNotify;
124*ec779b8eSAndroid Build Coastguard Worker mutable Mutex mFrameRenderedCallbackLock;
125*ec779b8eSAndroid Build Coastguard Worker AMediaCodecOnFrameRendered mFrameRenderedCallback;
126*ec779b8eSAndroid Build Coastguard Worker void *mFrameRenderedCallbackUserData;
127*ec779b8eSAndroid Build Coastguard Worker };
128*ec779b8eSAndroid Build Coastguard Worker
CodecHandler(AMediaCodec * codec)129*ec779b8eSAndroid Build Coastguard Worker CodecHandler::CodecHandler(AMediaCodec *codec) {
130*ec779b8eSAndroid Build Coastguard Worker mCodec = codec;
131*ec779b8eSAndroid Build Coastguard Worker }
132*ec779b8eSAndroid Build Coastguard Worker
onMessageReceived(const sp<AMessage> & msg)133*ec779b8eSAndroid Build Coastguard Worker void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
134*ec779b8eSAndroid Build Coastguard Worker
135*ec779b8eSAndroid Build Coastguard Worker switch (msg->what()) {
136*ec779b8eSAndroid Build Coastguard Worker case kWhatRequestActivityNotifications:
137*ec779b8eSAndroid Build Coastguard Worker {
138*ec779b8eSAndroid Build Coastguard Worker if (mCodec->mRequestedActivityNotification) {
139*ec779b8eSAndroid Build Coastguard Worker break;
140*ec779b8eSAndroid Build Coastguard Worker }
141*ec779b8eSAndroid Build Coastguard Worker
142*ec779b8eSAndroid Build Coastguard Worker mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
143*ec779b8eSAndroid Build Coastguard Worker mCodec->mRequestedActivityNotification = true;
144*ec779b8eSAndroid Build Coastguard Worker break;
145*ec779b8eSAndroid Build Coastguard Worker }
146*ec779b8eSAndroid Build Coastguard Worker
147*ec779b8eSAndroid Build Coastguard Worker case kWhatActivityNotify:
148*ec779b8eSAndroid Build Coastguard Worker {
149*ec779b8eSAndroid Build Coastguard Worker {
150*ec779b8eSAndroid Build Coastguard Worker int32_t generation;
151*ec779b8eSAndroid Build Coastguard Worker msg->findInt32("generation", &generation);
152*ec779b8eSAndroid Build Coastguard Worker
153*ec779b8eSAndroid Build Coastguard Worker if (generation != mCodec->mGeneration) {
154*ec779b8eSAndroid Build Coastguard Worker // stale
155*ec779b8eSAndroid Build Coastguard Worker break;
156*ec779b8eSAndroid Build Coastguard Worker }
157*ec779b8eSAndroid Build Coastguard Worker
158*ec779b8eSAndroid Build Coastguard Worker mCodec->mRequestedActivityNotification = false;
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker
161*ec779b8eSAndroid Build Coastguard Worker if (mCodec->mCallback) {
162*ec779b8eSAndroid Build Coastguard Worker mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
163*ec779b8eSAndroid Build Coastguard Worker }
164*ec779b8eSAndroid Build Coastguard Worker break;
165*ec779b8eSAndroid Build Coastguard Worker }
166*ec779b8eSAndroid Build Coastguard Worker
167*ec779b8eSAndroid Build Coastguard Worker case kWhatAsyncNotify:
168*ec779b8eSAndroid Build Coastguard Worker {
169*ec779b8eSAndroid Build Coastguard Worker int32_t cbID;
170*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32("callbackID", &cbID)) {
171*ec779b8eSAndroid Build Coastguard Worker ALOGE("kWhatAsyncNotify: callbackID is expected.");
172*ec779b8eSAndroid Build Coastguard Worker break;
173*ec779b8eSAndroid Build Coastguard Worker }
174*ec779b8eSAndroid Build Coastguard Worker
175*ec779b8eSAndroid Build Coastguard Worker ALOGV("kWhatAsyncNotify: cbID = %d", cbID);
176*ec779b8eSAndroid Build Coastguard Worker
177*ec779b8eSAndroid Build Coastguard Worker switch (cbID) {
178*ec779b8eSAndroid Build Coastguard Worker case MediaCodec::CB_INPUT_AVAILABLE:
179*ec779b8eSAndroid Build Coastguard Worker {
180*ec779b8eSAndroid Build Coastguard Worker int32_t index;
181*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32("index", &index)) {
182*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_INPUT_AVAILABLE: index is expected.");
183*ec779b8eSAndroid Build Coastguard Worker break;
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker
186*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
187*ec779b8eSAndroid Build Coastguard Worker if (mCodec->mAsyncCallback.onAsyncInputAvailable != NULL) {
188*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallback.onAsyncInputAvailable(
189*ec779b8eSAndroid Build Coastguard Worker mCodec,
190*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallbackUserData,
191*ec779b8eSAndroid Build Coastguard Worker index);
192*ec779b8eSAndroid Build Coastguard Worker }
193*ec779b8eSAndroid Build Coastguard Worker
194*ec779b8eSAndroid Build Coastguard Worker break;
195*ec779b8eSAndroid Build Coastguard Worker }
196*ec779b8eSAndroid Build Coastguard Worker
197*ec779b8eSAndroid Build Coastguard Worker case MediaCodec::CB_OUTPUT_AVAILABLE:
198*ec779b8eSAndroid Build Coastguard Worker {
199*ec779b8eSAndroid Build Coastguard Worker int32_t index;
200*ec779b8eSAndroid Build Coastguard Worker size_t offset;
201*ec779b8eSAndroid Build Coastguard Worker size_t size;
202*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs;
203*ec779b8eSAndroid Build Coastguard Worker int32_t flags;
204*ec779b8eSAndroid Build Coastguard Worker
205*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32("index", &index)) {
206*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_OUTPUT_AVAILABLE: index is expected.");
207*ec779b8eSAndroid Build Coastguard Worker break;
208*ec779b8eSAndroid Build Coastguard Worker }
209*ec779b8eSAndroid Build Coastguard Worker if (!msg->findSize("offset", &offset)) {
210*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_OUTPUT_AVAILABLE: offset is expected.");
211*ec779b8eSAndroid Build Coastguard Worker break;
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker if (!msg->findSize("size", &size)) {
214*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_OUTPUT_AVAILABLE: size is expected.");
215*ec779b8eSAndroid Build Coastguard Worker break;
216*ec779b8eSAndroid Build Coastguard Worker }
217*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt64("timeUs", &timeUs)) {
218*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_OUTPUT_AVAILABLE: timeUs is expected.");
219*ec779b8eSAndroid Build Coastguard Worker break;
220*ec779b8eSAndroid Build Coastguard Worker }
221*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32("flags", &flags)) {
222*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_OUTPUT_AVAILABLE: flags is expected.");
223*ec779b8eSAndroid Build Coastguard Worker break;
224*ec779b8eSAndroid Build Coastguard Worker }
225*ec779b8eSAndroid Build Coastguard Worker
226*ec779b8eSAndroid Build Coastguard Worker AMediaCodecBufferInfo bufferInfo = {
227*ec779b8eSAndroid Build Coastguard Worker (int32_t)offset,
228*ec779b8eSAndroid Build Coastguard Worker (int32_t)size,
229*ec779b8eSAndroid Build Coastguard Worker timeUs,
230*ec779b8eSAndroid Build Coastguard Worker (uint32_t)flags};
231*ec779b8eSAndroid Build Coastguard Worker
232*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
233*ec779b8eSAndroid Build Coastguard Worker if (mCodec->mAsyncCallback.onAsyncOutputAvailable != NULL) {
234*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallback.onAsyncOutputAvailable(
235*ec779b8eSAndroid Build Coastguard Worker mCodec,
236*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallbackUserData,
237*ec779b8eSAndroid Build Coastguard Worker index,
238*ec779b8eSAndroid Build Coastguard Worker &bufferInfo);
239*ec779b8eSAndroid Build Coastguard Worker }
240*ec779b8eSAndroid Build Coastguard Worker
241*ec779b8eSAndroid Build Coastguard Worker break;
242*ec779b8eSAndroid Build Coastguard Worker }
243*ec779b8eSAndroid Build Coastguard Worker
244*ec779b8eSAndroid Build Coastguard Worker case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
245*ec779b8eSAndroid Build Coastguard Worker {
246*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> format;
247*ec779b8eSAndroid Build Coastguard Worker if (!msg->findMessage("format", &format)) {
248*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_OUTPUT_FORMAT_CHANGED: format is expected.");
249*ec779b8eSAndroid Build Coastguard Worker break;
250*ec779b8eSAndroid Build Coastguard Worker }
251*ec779b8eSAndroid Build Coastguard Worker
252*ec779b8eSAndroid Build Coastguard Worker // Here format is MediaCodec's internal copy of output format.
253*ec779b8eSAndroid Build Coastguard Worker // Make a copy since the client might modify it.
254*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> copy;
255*ec779b8eSAndroid Build Coastguard Worker if (format != nullptr) {
256*ec779b8eSAndroid Build Coastguard Worker copy = format->dup();
257*ec779b8eSAndroid Build Coastguard Worker }
258*ec779b8eSAndroid Build Coastguard Worker AMediaFormat *aMediaFormat = AMediaFormat_fromMsg(©);
259*ec779b8eSAndroid Build Coastguard Worker
260*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
261*ec779b8eSAndroid Build Coastguard Worker if (mCodec->mAsyncCallback.onAsyncFormatChanged != NULL) {
262*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallback.onAsyncFormatChanged(
263*ec779b8eSAndroid Build Coastguard Worker mCodec,
264*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallbackUserData,
265*ec779b8eSAndroid Build Coastguard Worker aMediaFormat);
266*ec779b8eSAndroid Build Coastguard Worker }
267*ec779b8eSAndroid Build Coastguard Worker
268*ec779b8eSAndroid Build Coastguard Worker break;
269*ec779b8eSAndroid Build Coastguard Worker }
270*ec779b8eSAndroid Build Coastguard Worker
271*ec779b8eSAndroid Build Coastguard Worker case MediaCodec::CB_ERROR:
272*ec779b8eSAndroid Build Coastguard Worker {
273*ec779b8eSAndroid Build Coastguard Worker status_t err;
274*ec779b8eSAndroid Build Coastguard Worker int32_t actionCode;
275*ec779b8eSAndroid Build Coastguard Worker AString detail;
276*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32("err", &err)) {
277*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_ERROR: err is expected.");
278*ec779b8eSAndroid Build Coastguard Worker break;
279*ec779b8eSAndroid Build Coastguard Worker }
280*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32("actionCode", &actionCode)) {
281*ec779b8eSAndroid Build Coastguard Worker ALOGE("CB_ERROR: actionCode is expected.");
282*ec779b8eSAndroid Build Coastguard Worker break;
283*ec779b8eSAndroid Build Coastguard Worker }
284*ec779b8eSAndroid Build Coastguard Worker msg->findString("detail", &detail);
285*ec779b8eSAndroid Build Coastguard Worker ALOGE("Codec reported error(0x%x/%s), actionCode(%d), detail(%s)",
286*ec779b8eSAndroid Build Coastguard Worker err, StrMediaError(err).c_str(), actionCode, detail.c_str());
287*ec779b8eSAndroid Build Coastguard Worker
288*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
289*ec779b8eSAndroid Build Coastguard Worker if (mCodec->mAsyncCallback.onAsyncError != NULL) {
290*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallback.onAsyncError(
291*ec779b8eSAndroid Build Coastguard Worker mCodec,
292*ec779b8eSAndroid Build Coastguard Worker mCodec->mAsyncCallbackUserData,
293*ec779b8eSAndroid Build Coastguard Worker translate_error(err),
294*ec779b8eSAndroid Build Coastguard Worker actionCode,
295*ec779b8eSAndroid Build Coastguard Worker detail.c_str());
296*ec779b8eSAndroid Build Coastguard Worker }
297*ec779b8eSAndroid Build Coastguard Worker
298*ec779b8eSAndroid Build Coastguard Worker break;
299*ec779b8eSAndroid Build Coastguard Worker }
300*ec779b8eSAndroid Build Coastguard Worker
301*ec779b8eSAndroid Build Coastguard Worker default:
302*ec779b8eSAndroid Build Coastguard Worker {
303*ec779b8eSAndroid Build Coastguard Worker ALOGE("kWhatAsyncNotify: callbackID(%d) is unexpected.", cbID);
304*ec779b8eSAndroid Build Coastguard Worker break;
305*ec779b8eSAndroid Build Coastguard Worker }
306*ec779b8eSAndroid Build Coastguard Worker }
307*ec779b8eSAndroid Build Coastguard Worker break;
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker
310*ec779b8eSAndroid Build Coastguard Worker case kWhatStopActivityNotifications:
311*ec779b8eSAndroid Build Coastguard Worker {
312*ec779b8eSAndroid Build Coastguard Worker sp<AReplyToken> replyID;
313*ec779b8eSAndroid Build Coastguard Worker msg->senderAwaitsResponse(&replyID);
314*ec779b8eSAndroid Build Coastguard Worker
315*ec779b8eSAndroid Build Coastguard Worker mCodec->mGeneration++;
316*ec779b8eSAndroid Build Coastguard Worker mCodec->mRequestedActivityNotification = false;
317*ec779b8eSAndroid Build Coastguard Worker
318*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> response = new AMessage;
319*ec779b8eSAndroid Build Coastguard Worker response->postReply(replyID);
320*ec779b8eSAndroid Build Coastguard Worker break;
321*ec779b8eSAndroid Build Coastguard Worker }
322*ec779b8eSAndroid Build Coastguard Worker
323*ec779b8eSAndroid Build Coastguard Worker case kWhatFrameRenderedNotify:
324*ec779b8eSAndroid Build Coastguard Worker {
325*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> data;
326*ec779b8eSAndroid Build Coastguard Worker if (!msg->findMessage("data", &data)) {
327*ec779b8eSAndroid Build Coastguard Worker ALOGE("kWhatFrameRenderedNotify: data is expected.");
328*ec779b8eSAndroid Build Coastguard Worker break;
329*ec779b8eSAndroid Build Coastguard Worker }
330*ec779b8eSAndroid Build Coastguard Worker
331*ec779b8eSAndroid Build Coastguard Worker AMessage::Type type;
332*ec779b8eSAndroid Build Coastguard Worker size_t n = data->countEntries();
333*ec779b8eSAndroid Build Coastguard Worker
334*ec779b8eSAndroid Build Coastguard Worker thread_local std::vector<std::optional<int64_t>> mediaTimesInUs;
335*ec779b8eSAndroid Build Coastguard Worker thread_local std::vector<std::optional<int64_t>> systemTimesInNs;
336*ec779b8eSAndroid Build Coastguard Worker mediaTimesInUs.resize(n);
337*ec779b8eSAndroid Build Coastguard Worker systemTimesInNs.resize(n);
338*ec779b8eSAndroid Build Coastguard Worker std::fill_n(mediaTimesInUs.begin(), n, std::nullopt);
339*ec779b8eSAndroid Build Coastguard Worker std::fill_n(systemTimesInNs.begin(), n, std::nullopt);
340*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < n; i++) {
341*ec779b8eSAndroid Build Coastguard Worker AString name = data->getEntryNameAt(i, &type);
342*ec779b8eSAndroid Build Coastguard Worker if (name.endsWith("-media-time-us")) {
343*ec779b8eSAndroid Build Coastguard Worker int64_t mediaTimeUs;
344*ec779b8eSAndroid Build Coastguard Worker AMessage::ItemData itemData = data->getEntryAt(i);
345*ec779b8eSAndroid Build Coastguard Worker itemData.find(&mediaTimeUs);
346*ec779b8eSAndroid Build Coastguard Worker
347*ec779b8eSAndroid Build Coastguard Worker int index = -1;
348*ec779b8eSAndroid Build Coastguard Worker std::from_chars_result result = std::from_chars(
349*ec779b8eSAndroid Build Coastguard Worker name.c_str(), name.c_str() + name.find("-"), index);
350*ec779b8eSAndroid Build Coastguard Worker if (result.ec == std::errc() && 0 <= index && index < n) {
351*ec779b8eSAndroid Build Coastguard Worker mediaTimesInUs[index] = mediaTimeUs;
352*ec779b8eSAndroid Build Coastguard Worker } else {
353*ec779b8eSAndroid Build Coastguard Worker std::error_code ec = std::make_error_code(result.ec);
354*ec779b8eSAndroid Build Coastguard Worker ALOGE("Unexpected media time index: #%d with value %lldus (err=%d %s)",
355*ec779b8eSAndroid Build Coastguard Worker index, (long long)mediaTimeUs, ec.value(), ec.message().c_str());
356*ec779b8eSAndroid Build Coastguard Worker }
357*ec779b8eSAndroid Build Coastguard Worker } else if (name.endsWith("-system-nano")) {
358*ec779b8eSAndroid Build Coastguard Worker int64_t systemNano;
359*ec779b8eSAndroid Build Coastguard Worker AMessage::ItemData itemData = data->getEntryAt(i);
360*ec779b8eSAndroid Build Coastguard Worker itemData.find(&systemNano);
361*ec779b8eSAndroid Build Coastguard Worker
362*ec779b8eSAndroid Build Coastguard Worker int index = -1;
363*ec779b8eSAndroid Build Coastguard Worker std::from_chars_result result = std::from_chars(
364*ec779b8eSAndroid Build Coastguard Worker name.c_str(), name.c_str() + name.find("-"), index);
365*ec779b8eSAndroid Build Coastguard Worker if (result.ec == std::errc() && 0 <= index && index < n) {
366*ec779b8eSAndroid Build Coastguard Worker systemTimesInNs[index] = systemNano;
367*ec779b8eSAndroid Build Coastguard Worker } else {
368*ec779b8eSAndroid Build Coastguard Worker std::error_code ec = std::make_error_code(result.ec);
369*ec779b8eSAndroid Build Coastguard Worker ALOGE("Unexpected system time index: #%d with value %lldns (err=%d %s)",
370*ec779b8eSAndroid Build Coastguard Worker index, (long long)systemNano, ec.value(), ec.message().c_str());
371*ec779b8eSAndroid Build Coastguard Worker }
372*ec779b8eSAndroid Build Coastguard Worker }
373*ec779b8eSAndroid Build Coastguard Worker }
374*ec779b8eSAndroid Build Coastguard Worker
375*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mCodec->mFrameRenderedCallbackLock);
376*ec779b8eSAndroid Build Coastguard Worker if (mCodec->mFrameRenderedCallback != NULL) {
377*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < n; ++i) {
378*ec779b8eSAndroid Build Coastguard Worker if (mediaTimesInUs[i] && systemTimesInNs[i]) {
379*ec779b8eSAndroid Build Coastguard Worker mCodec->mFrameRenderedCallback(
380*ec779b8eSAndroid Build Coastguard Worker mCodec,
381*ec779b8eSAndroid Build Coastguard Worker mCodec->mFrameRenderedCallbackUserData,
382*ec779b8eSAndroid Build Coastguard Worker mediaTimesInUs[i].value(),
383*ec779b8eSAndroid Build Coastguard Worker systemTimesInNs[i].value());
384*ec779b8eSAndroid Build Coastguard Worker } else {
385*ec779b8eSAndroid Build Coastguard Worker break;
386*ec779b8eSAndroid Build Coastguard Worker }
387*ec779b8eSAndroid Build Coastguard Worker }
388*ec779b8eSAndroid Build Coastguard Worker }
389*ec779b8eSAndroid Build Coastguard Worker break;
390*ec779b8eSAndroid Build Coastguard Worker }
391*ec779b8eSAndroid Build Coastguard Worker
392*ec779b8eSAndroid Build Coastguard Worker default:
393*ec779b8eSAndroid Build Coastguard Worker ALOGE("shouldn't be here");
394*ec779b8eSAndroid Build Coastguard Worker break;
395*ec779b8eSAndroid Build Coastguard Worker }
396*ec779b8eSAndroid Build Coastguard Worker
397*ec779b8eSAndroid Build Coastguard Worker }
398*ec779b8eSAndroid Build Coastguard Worker
399*ec779b8eSAndroid Build Coastguard Worker
requestActivityNotification(AMediaCodec * codec)400*ec779b8eSAndroid Build Coastguard Worker static void requestActivityNotification(AMediaCodec *codec) {
401*ec779b8eSAndroid Build Coastguard Worker (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
402*ec779b8eSAndroid Build Coastguard Worker }
403*ec779b8eSAndroid Build Coastguard Worker
404*ec779b8eSAndroid Build Coastguard Worker extern "C" {
405*ec779b8eSAndroid Build Coastguard Worker
createAMediaCodec(const char * name,bool name_is_type,bool encoder,pid_t pid=android::MediaCodec::kNoPid,uid_t uid=android::MediaCodec::kNoUid)406*ec779b8eSAndroid Build Coastguard Worker static AMediaCodec * createAMediaCodec(const char *name,
407*ec779b8eSAndroid Build Coastguard Worker bool name_is_type,
408*ec779b8eSAndroid Build Coastguard Worker bool encoder,
409*ec779b8eSAndroid Build Coastguard Worker pid_t pid = android::MediaCodec::kNoPid,
410*ec779b8eSAndroid Build Coastguard Worker uid_t uid = android::MediaCodec::kNoUid) {
411*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData = new AMediaCodec();
412*ec779b8eSAndroid Build Coastguard Worker mData->mLooper = new ALooper;
413*ec779b8eSAndroid Build Coastguard Worker mData->mLooper->setName("NDK MediaCodec_looper");
414*ec779b8eSAndroid Build Coastguard Worker size_t res = mData->mLooper->start(
415*ec779b8eSAndroid Build Coastguard Worker false, // runOnCallingThread
416*ec779b8eSAndroid Build Coastguard Worker true, // canCallJava XXX
417*ec779b8eSAndroid Build Coastguard Worker PRIORITY_AUDIO);
418*ec779b8eSAndroid Build Coastguard Worker if (res != OK) {
419*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to start the looper");
420*ec779b8eSAndroid Build Coastguard Worker AMediaCodec_delete(mData);
421*ec779b8eSAndroid Build Coastguard Worker return NULL;
422*ec779b8eSAndroid Build Coastguard Worker }
423*ec779b8eSAndroid Build Coastguard Worker if (name_is_type) {
424*ec779b8eSAndroid Build Coastguard Worker mData->mCodec = android::MediaCodec::CreateByType(
425*ec779b8eSAndroid Build Coastguard Worker mData->mLooper,
426*ec779b8eSAndroid Build Coastguard Worker name,
427*ec779b8eSAndroid Build Coastguard Worker encoder,
428*ec779b8eSAndroid Build Coastguard Worker nullptr /* err */,
429*ec779b8eSAndroid Build Coastguard Worker pid,
430*ec779b8eSAndroid Build Coastguard Worker uid);
431*ec779b8eSAndroid Build Coastguard Worker } else {
432*ec779b8eSAndroid Build Coastguard Worker mData->mCodec = android::MediaCodec::CreateByComponentName(
433*ec779b8eSAndroid Build Coastguard Worker mData->mLooper,
434*ec779b8eSAndroid Build Coastguard Worker name,
435*ec779b8eSAndroid Build Coastguard Worker nullptr /* err */,
436*ec779b8eSAndroid Build Coastguard Worker pid,
437*ec779b8eSAndroid Build Coastguard Worker uid);
438*ec779b8eSAndroid Build Coastguard Worker }
439*ec779b8eSAndroid Build Coastguard Worker if (mData->mCodec == NULL) { // failed to create codec
440*ec779b8eSAndroid Build Coastguard Worker AMediaCodec_delete(mData);
441*ec779b8eSAndroid Build Coastguard Worker return NULL;
442*ec779b8eSAndroid Build Coastguard Worker }
443*ec779b8eSAndroid Build Coastguard Worker mData->mHandler = new CodecHandler(mData);
444*ec779b8eSAndroid Build Coastguard Worker mData->mLooper->registerHandler(mData->mHandler);
445*ec779b8eSAndroid Build Coastguard Worker mData->mGeneration = 1;
446*ec779b8eSAndroid Build Coastguard Worker mData->mRequestedActivityNotification = false;
447*ec779b8eSAndroid Build Coastguard Worker mData->mCallback = NULL;
448*ec779b8eSAndroid Build Coastguard Worker
449*ec779b8eSAndroid Build Coastguard Worker mData->mAsyncCallback = {};
450*ec779b8eSAndroid Build Coastguard Worker mData->mAsyncCallbackUserData = NULL;
451*ec779b8eSAndroid Build Coastguard Worker
452*ec779b8eSAndroid Build Coastguard Worker return mData;
453*ec779b8eSAndroid Build Coastguard Worker }
454*ec779b8eSAndroid Build Coastguard Worker
455*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createCodecByName(const char * name)456*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
457*ec779b8eSAndroid Build Coastguard Worker return createAMediaCodec(name, false /* name_is_type */, false /* encoder */);
458*ec779b8eSAndroid Build Coastguard Worker }
459*ec779b8eSAndroid Build Coastguard Worker
460*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createDecoderByType(const char * mime_type)461*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
462*ec779b8eSAndroid Build Coastguard Worker return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */);
463*ec779b8eSAndroid Build Coastguard Worker }
464*ec779b8eSAndroid Build Coastguard Worker
465*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createEncoderByType(const char * name)466*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
467*ec779b8eSAndroid Build Coastguard Worker return createAMediaCodec(name, true /* name_is_type */, true /* encoder */);
468*ec779b8eSAndroid Build Coastguard Worker }
469*ec779b8eSAndroid Build Coastguard Worker
470*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createCodecByNameForClient(const char * name,pid_t pid,uid_t uid)471*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* AMediaCodec_createCodecByNameForClient(const char *name,
472*ec779b8eSAndroid Build Coastguard Worker pid_t pid,
473*ec779b8eSAndroid Build Coastguard Worker uid_t uid) {
474*ec779b8eSAndroid Build Coastguard Worker return createAMediaCodec(name, false /* name_is_type */, false /* encoder */, pid, uid);
475*ec779b8eSAndroid Build Coastguard Worker }
476*ec779b8eSAndroid Build Coastguard Worker
477*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createDecoderByTypeForClient(const char * mime_type,pid_t pid,uid_t uid)478*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* AMediaCodec_createDecoderByTypeForClient(const char *mime_type,
479*ec779b8eSAndroid Build Coastguard Worker pid_t pid,
480*ec779b8eSAndroid Build Coastguard Worker uid_t uid) {
481*ec779b8eSAndroid Build Coastguard Worker return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */, pid, uid);
482*ec779b8eSAndroid Build Coastguard Worker }
483*ec779b8eSAndroid Build Coastguard Worker
484*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createEncoderByTypeForClient(const char * name,pid_t pid,uid_t uid)485*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* AMediaCodec_createEncoderByTypeForClient(const char *name,
486*ec779b8eSAndroid Build Coastguard Worker pid_t pid,
487*ec779b8eSAndroid Build Coastguard Worker uid_t uid) {
488*ec779b8eSAndroid Build Coastguard Worker return createAMediaCodec(name, true /* name_is_type */, true /* encoder */, pid, uid);
489*ec779b8eSAndroid Build Coastguard Worker }
490*ec779b8eSAndroid Build Coastguard Worker
491*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_delete(AMediaCodec * mData)492*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_delete(AMediaCodec *mData) {
493*ec779b8eSAndroid Build Coastguard Worker if (mData != NULL) {
494*ec779b8eSAndroid Build Coastguard Worker if (mData->mCodec != NULL) {
495*ec779b8eSAndroid Build Coastguard Worker mData->mCodec->release();
496*ec779b8eSAndroid Build Coastguard Worker mData->mCodec.clear();
497*ec779b8eSAndroid Build Coastguard Worker }
498*ec779b8eSAndroid Build Coastguard Worker
499*ec779b8eSAndroid Build Coastguard Worker if (mData->mLooper != NULL) {
500*ec779b8eSAndroid Build Coastguard Worker if (mData->mHandler != NULL) {
501*ec779b8eSAndroid Build Coastguard Worker mData->mLooper->unregisterHandler(mData->mHandler->id());
502*ec779b8eSAndroid Build Coastguard Worker }
503*ec779b8eSAndroid Build Coastguard Worker mData->mLooper->stop();
504*ec779b8eSAndroid Build Coastguard Worker mData->mLooper.clear();
505*ec779b8eSAndroid Build Coastguard Worker }
506*ec779b8eSAndroid Build Coastguard Worker delete mData;
507*ec779b8eSAndroid Build Coastguard Worker }
508*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
509*ec779b8eSAndroid Build Coastguard Worker }
510*ec779b8eSAndroid Build Coastguard Worker
511*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_getName(AMediaCodec * mData,char ** out_name)512*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_getName(
513*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData,
514*ec779b8eSAndroid Build Coastguard Worker char** out_name) {
515*ec779b8eSAndroid Build Coastguard Worker if (out_name == NULL) {
516*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
517*ec779b8eSAndroid Build Coastguard Worker }
518*ec779b8eSAndroid Build Coastguard Worker
519*ec779b8eSAndroid Build Coastguard Worker AString compName;
520*ec779b8eSAndroid Build Coastguard Worker status_t err = mData->mCodec->getName(&compName);
521*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
522*ec779b8eSAndroid Build Coastguard Worker return translate_error(err);
523*ec779b8eSAndroid Build Coastguard Worker }
524*ec779b8eSAndroid Build Coastguard Worker *out_name = strdup(compName.c_str());
525*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
526*ec779b8eSAndroid Build Coastguard Worker }
527*ec779b8eSAndroid Build Coastguard Worker
528*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_releaseName(AMediaCodec *,char * name)529*ec779b8eSAndroid Build Coastguard Worker void AMediaCodec_releaseName(
530*ec779b8eSAndroid Build Coastguard Worker AMediaCodec * /* mData */,
531*ec779b8eSAndroid Build Coastguard Worker char* name) {
532*ec779b8eSAndroid Build Coastguard Worker if (name != NULL) {
533*ec779b8eSAndroid Build Coastguard Worker free(name);
534*ec779b8eSAndroid Build Coastguard Worker }
535*ec779b8eSAndroid Build Coastguard Worker }
536*ec779b8eSAndroid Build Coastguard Worker
537*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_configure(AMediaCodec * mData,const AMediaFormat * format,ANativeWindow * window,AMediaCrypto * crypto,uint32_t flags)538*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_configure(
539*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData,
540*ec779b8eSAndroid Build Coastguard Worker const AMediaFormat* format,
541*ec779b8eSAndroid Build Coastguard Worker ANativeWindow* window,
542*ec779b8eSAndroid Build Coastguard Worker AMediaCrypto *crypto,
543*ec779b8eSAndroid Build Coastguard Worker uint32_t flags) {
544*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> nativeFormat;
545*ec779b8eSAndroid Build Coastguard Worker AMediaFormat_getFormat(format, &nativeFormat);
546*ec779b8eSAndroid Build Coastguard Worker // create our shallow copy, so we aren't victim to any later changes.
547*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> dupNativeFormat = nativeFormat->dup();
548*ec779b8eSAndroid Build Coastguard Worker ALOGV("configure with format: %s", dupNativeFormat->debugString(0).c_str());
549*ec779b8eSAndroid Build Coastguard Worker sp<Surface> surface = NULL;
550*ec779b8eSAndroid Build Coastguard Worker if (window != NULL) {
551*ec779b8eSAndroid Build Coastguard Worker surface = (Surface*) window;
552*ec779b8eSAndroid Build Coastguard Worker }
553*ec779b8eSAndroid Build Coastguard Worker
554*ec779b8eSAndroid Build Coastguard Worker status_t err = mData->mCodec->configure(dupNativeFormat, surface,
555*ec779b8eSAndroid Build Coastguard Worker crypto ? crypto->mCrypto : NULL, flags);
556*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
557*ec779b8eSAndroid Build Coastguard Worker ALOGE("configure: err(%d), failed with format: %s",
558*ec779b8eSAndroid Build Coastguard Worker err, dupNativeFormat->debugString(0).c_str());
559*ec779b8eSAndroid Build Coastguard Worker }
560*ec779b8eSAndroid Build Coastguard Worker return translate_error(err);
561*ec779b8eSAndroid Build Coastguard Worker }
562*ec779b8eSAndroid Build Coastguard Worker
563*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_setAsyncNotifyCallback(AMediaCodec * mData,AMediaCodecOnAsyncNotifyCallback callback,void * userdata)564*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_setAsyncNotifyCallback(
565*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData,
566*ec779b8eSAndroid Build Coastguard Worker AMediaCodecOnAsyncNotifyCallback callback,
567*ec779b8eSAndroid Build Coastguard Worker void *userdata) {
568*ec779b8eSAndroid Build Coastguard Worker
569*ec779b8eSAndroid Build Coastguard Worker {
570*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mData->mAsyncCallbackLock);
571*ec779b8eSAndroid Build Coastguard Worker if (mData->mAsyncNotify == NULL) {
572*ec779b8eSAndroid Build Coastguard Worker mData->mAsyncNotify = new AMessage(kWhatAsyncNotify, mData->mHandler);
573*ec779b8eSAndroid Build Coastguard Worker }
574*ec779b8eSAndroid Build Coastguard Worker // we set this ahead so that we can be ready
575*ec779b8eSAndroid Build Coastguard Worker // to receive callbacks as soon as the next call is a
576*ec779b8eSAndroid Build Coastguard Worker // success.
577*ec779b8eSAndroid Build Coastguard Worker mData->mAsyncCallback = callback;
578*ec779b8eSAndroid Build Coastguard Worker mData->mAsyncCallbackUserData = userdata;
579*ec779b8eSAndroid Build Coastguard Worker }
580*ec779b8eSAndroid Build Coastguard Worker
581*ec779b8eSAndroid Build Coastguard Worker // always call, codec may have been reset/re-configured since last call.
582*ec779b8eSAndroid Build Coastguard Worker status_t err = mData->mCodec->setCallback(mData->mAsyncNotify);
583*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
584*ec779b8eSAndroid Build Coastguard Worker {
585*ec779b8eSAndroid Build Coastguard Worker //The setup gone wrong. clean up the pointers.
586*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mData->mAsyncCallbackLock);
587*ec779b8eSAndroid Build Coastguard Worker mData->mAsyncCallback = {};
588*ec779b8eSAndroid Build Coastguard Worker mData->mAsyncCallbackUserData = nullptr;
589*ec779b8eSAndroid Build Coastguard Worker }
590*ec779b8eSAndroid Build Coastguard Worker ALOGE("setAsyncNotifyCallback: err(%d), failed to set async callback", err);
591*ec779b8eSAndroid Build Coastguard Worker return translate_error(err);
592*ec779b8eSAndroid Build Coastguard Worker }
593*ec779b8eSAndroid Build Coastguard Worker
594*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
595*ec779b8eSAndroid Build Coastguard Worker }
596*ec779b8eSAndroid Build Coastguard Worker
597*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_setOnFrameRenderedCallback(AMediaCodec * mData,AMediaCodecOnFrameRendered callback,void * userdata)598*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_setOnFrameRenderedCallback(
599*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData,
600*ec779b8eSAndroid Build Coastguard Worker AMediaCodecOnFrameRendered callback,
601*ec779b8eSAndroid Build Coastguard Worker void *userdata) {
602*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mData->mFrameRenderedCallbackLock);
603*ec779b8eSAndroid Build Coastguard Worker if (mData->mFrameRenderedNotify == NULL) {
604*ec779b8eSAndroid Build Coastguard Worker mData->mFrameRenderedNotify = new AMessage(kWhatFrameRenderedNotify, mData->mHandler);
605*ec779b8eSAndroid Build Coastguard Worker }
606*ec779b8eSAndroid Build Coastguard Worker status_t err = mData->mCodec->setOnFrameRenderedNotification(mData->mFrameRenderedNotify);
607*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
608*ec779b8eSAndroid Build Coastguard Worker ALOGE("setOnFrameRenderedNotifyCallback: err(%d), failed to set callback", err);
609*ec779b8eSAndroid Build Coastguard Worker return translate_error(err);
610*ec779b8eSAndroid Build Coastguard Worker }
611*ec779b8eSAndroid Build Coastguard Worker
612*ec779b8eSAndroid Build Coastguard Worker mData->mFrameRenderedCallback = callback;
613*ec779b8eSAndroid Build Coastguard Worker mData->mFrameRenderedCallbackUserData = userdata;
614*ec779b8eSAndroid Build Coastguard Worker
615*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
616*ec779b8eSAndroid Build Coastguard Worker }
617*ec779b8eSAndroid Build Coastguard Worker
618*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_releaseCrypto(AMediaCodec * mData)619*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_releaseCrypto(AMediaCodec *mData) {
620*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->releaseCrypto());
621*ec779b8eSAndroid Build Coastguard Worker }
622*ec779b8eSAndroid Build Coastguard Worker
623*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_start(AMediaCodec * mData)624*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_start(AMediaCodec *mData) {
625*ec779b8eSAndroid Build Coastguard Worker status_t ret = mData->mCodec->start();
626*ec779b8eSAndroid Build Coastguard Worker if (ret != OK) {
627*ec779b8eSAndroid Build Coastguard Worker return translate_error(ret);
628*ec779b8eSAndroid Build Coastguard Worker }
629*ec779b8eSAndroid Build Coastguard Worker mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
630*ec779b8eSAndroid Build Coastguard Worker mData->mActivityNotification->setInt32("generation", mData->mGeneration);
631*ec779b8eSAndroid Build Coastguard Worker requestActivityNotification(mData);
632*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
633*ec779b8eSAndroid Build Coastguard Worker }
634*ec779b8eSAndroid Build Coastguard Worker
635*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_stop(AMediaCodec * mData)636*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_stop(AMediaCodec *mData) {
637*ec779b8eSAndroid Build Coastguard Worker media_status_t ret = translate_error(mData->mCodec->stop());
638*ec779b8eSAndroid Build Coastguard Worker
639*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
640*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> response;
641*ec779b8eSAndroid Build Coastguard Worker msg->postAndAwaitResponse(&response);
642*ec779b8eSAndroid Build Coastguard Worker mData->mActivityNotification.clear();
643*ec779b8eSAndroid Build Coastguard Worker
644*ec779b8eSAndroid Build Coastguard Worker return ret;
645*ec779b8eSAndroid Build Coastguard Worker }
646*ec779b8eSAndroid Build Coastguard Worker
647*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_flush(AMediaCodec * mData)648*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_flush(AMediaCodec *mData) {
649*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->flush());
650*ec779b8eSAndroid Build Coastguard Worker }
651*ec779b8eSAndroid Build Coastguard Worker
652*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_dequeueInputBuffer(AMediaCodec * mData,int64_t timeoutUs)653*ec779b8eSAndroid Build Coastguard Worker ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
654*ec779b8eSAndroid Build Coastguard Worker size_t idx;
655*ec779b8eSAndroid Build Coastguard Worker status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
656*ec779b8eSAndroid Build Coastguard Worker requestActivityNotification(mData);
657*ec779b8eSAndroid Build Coastguard Worker if (ret == OK) {
658*ec779b8eSAndroid Build Coastguard Worker return idx;
659*ec779b8eSAndroid Build Coastguard Worker }
660*ec779b8eSAndroid Build Coastguard Worker return translate_error(ret);
661*ec779b8eSAndroid Build Coastguard Worker }
662*ec779b8eSAndroid Build Coastguard Worker
663*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_getInputBuffer(AMediaCodec * mData,size_t idx,size_t * out_size)664*ec779b8eSAndroid Build Coastguard Worker uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
665*ec779b8eSAndroid Build Coastguard Worker if (mData->mAsyncNotify != NULL) {
666*ec779b8eSAndroid Build Coastguard Worker // Asynchronous mode
667*ec779b8eSAndroid Build Coastguard Worker sp<MediaCodecBuffer> abuf;
668*ec779b8eSAndroid Build Coastguard Worker if (mData->mCodec->getInputBuffer(idx, &abuf) != 0) {
669*ec779b8eSAndroid Build Coastguard Worker return NULL;
670*ec779b8eSAndroid Build Coastguard Worker }
671*ec779b8eSAndroid Build Coastguard Worker
672*ec779b8eSAndroid Build Coastguard Worker if (out_size != NULL) {
673*ec779b8eSAndroid Build Coastguard Worker *out_size = abuf->capacity();
674*ec779b8eSAndroid Build Coastguard Worker }
675*ec779b8eSAndroid Build Coastguard Worker return abuf->data();
676*ec779b8eSAndroid Build Coastguard Worker }
677*ec779b8eSAndroid Build Coastguard Worker
678*ec779b8eSAndroid Build Coastguard Worker android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
679*ec779b8eSAndroid Build Coastguard Worker if (mData->mCodec->getInputBuffers(&abufs) == 0) {
680*ec779b8eSAndroid Build Coastguard Worker size_t n = abufs.size();
681*ec779b8eSAndroid Build Coastguard Worker if (idx >= n) {
682*ec779b8eSAndroid Build Coastguard Worker ALOGE("buffer index %zu out of range", idx);
683*ec779b8eSAndroid Build Coastguard Worker return NULL;
684*ec779b8eSAndroid Build Coastguard Worker }
685*ec779b8eSAndroid Build Coastguard Worker if (abufs[idx] == NULL) {
686*ec779b8eSAndroid Build Coastguard Worker ALOGE("buffer index %zu is NULL", idx);
687*ec779b8eSAndroid Build Coastguard Worker return NULL;
688*ec779b8eSAndroid Build Coastguard Worker }
689*ec779b8eSAndroid Build Coastguard Worker if (out_size != NULL) {
690*ec779b8eSAndroid Build Coastguard Worker *out_size = abufs[idx]->capacity();
691*ec779b8eSAndroid Build Coastguard Worker }
692*ec779b8eSAndroid Build Coastguard Worker return abufs[idx]->data();
693*ec779b8eSAndroid Build Coastguard Worker }
694*ec779b8eSAndroid Build Coastguard Worker ALOGE("couldn't get input buffers");
695*ec779b8eSAndroid Build Coastguard Worker return NULL;
696*ec779b8eSAndroid Build Coastguard Worker }
697*ec779b8eSAndroid Build Coastguard Worker
698*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_getOutputBuffer(AMediaCodec * mData,size_t idx,size_t * out_size)699*ec779b8eSAndroid Build Coastguard Worker uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
700*ec779b8eSAndroid Build Coastguard Worker if (mData->mAsyncNotify != NULL) {
701*ec779b8eSAndroid Build Coastguard Worker // Asynchronous mode
702*ec779b8eSAndroid Build Coastguard Worker sp<MediaCodecBuffer> abuf;
703*ec779b8eSAndroid Build Coastguard Worker if (mData->mCodec->getOutputBuffer(idx, &abuf) != 0) {
704*ec779b8eSAndroid Build Coastguard Worker return NULL;
705*ec779b8eSAndroid Build Coastguard Worker }
706*ec779b8eSAndroid Build Coastguard Worker
707*ec779b8eSAndroid Build Coastguard Worker if (out_size != NULL) {
708*ec779b8eSAndroid Build Coastguard Worker *out_size = abuf->capacity();
709*ec779b8eSAndroid Build Coastguard Worker }
710*ec779b8eSAndroid Build Coastguard Worker return abuf->data();
711*ec779b8eSAndroid Build Coastguard Worker }
712*ec779b8eSAndroid Build Coastguard Worker
713*ec779b8eSAndroid Build Coastguard Worker android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
714*ec779b8eSAndroid Build Coastguard Worker if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
715*ec779b8eSAndroid Build Coastguard Worker size_t n = abufs.size();
716*ec779b8eSAndroid Build Coastguard Worker if (idx >= n) {
717*ec779b8eSAndroid Build Coastguard Worker ALOGE("buffer index %zu out of range", idx);
718*ec779b8eSAndroid Build Coastguard Worker return NULL;
719*ec779b8eSAndroid Build Coastguard Worker }
720*ec779b8eSAndroid Build Coastguard Worker if (out_size != NULL) {
721*ec779b8eSAndroid Build Coastguard Worker *out_size = abufs[idx]->capacity();
722*ec779b8eSAndroid Build Coastguard Worker }
723*ec779b8eSAndroid Build Coastguard Worker return abufs[idx]->data();
724*ec779b8eSAndroid Build Coastguard Worker }
725*ec779b8eSAndroid Build Coastguard Worker ALOGE("couldn't get output buffers");
726*ec779b8eSAndroid Build Coastguard Worker return NULL;
727*ec779b8eSAndroid Build Coastguard Worker }
728*ec779b8eSAndroid Build Coastguard Worker
729*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_queueInputBuffer(AMediaCodec * mData,size_t idx,off_t offset,size_t size,uint64_t time,uint32_t flags)730*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
731*ec779b8eSAndroid Build Coastguard Worker size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
732*ec779b8eSAndroid Build Coastguard Worker
733*ec779b8eSAndroid Build Coastguard Worker AString errorMsg;
734*ec779b8eSAndroid Build Coastguard Worker status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
735*ec779b8eSAndroid Build Coastguard Worker return translate_error(ret);
736*ec779b8eSAndroid Build Coastguard Worker }
737*ec779b8eSAndroid Build Coastguard Worker
738*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_dequeueOutputBuffer(AMediaCodec * mData,AMediaCodecBufferInfo * info,int64_t timeoutUs)739*ec779b8eSAndroid Build Coastguard Worker ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
740*ec779b8eSAndroid Build Coastguard Worker AMediaCodecBufferInfo *info, int64_t timeoutUs) {
741*ec779b8eSAndroid Build Coastguard Worker size_t idx;
742*ec779b8eSAndroid Build Coastguard Worker size_t offset;
743*ec779b8eSAndroid Build Coastguard Worker size_t size;
744*ec779b8eSAndroid Build Coastguard Worker uint32_t flags;
745*ec779b8eSAndroid Build Coastguard Worker int64_t presentationTimeUs;
746*ec779b8eSAndroid Build Coastguard Worker status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
747*ec779b8eSAndroid Build Coastguard Worker &flags, timeoutUs);
748*ec779b8eSAndroid Build Coastguard Worker requestActivityNotification(mData);
749*ec779b8eSAndroid Build Coastguard Worker switch (ret) {
750*ec779b8eSAndroid Build Coastguard Worker case OK:
751*ec779b8eSAndroid Build Coastguard Worker info->offset = offset;
752*ec779b8eSAndroid Build Coastguard Worker info->size = size;
753*ec779b8eSAndroid Build Coastguard Worker info->flags = flags;
754*ec779b8eSAndroid Build Coastguard Worker info->presentationTimeUs = presentationTimeUs;
755*ec779b8eSAndroid Build Coastguard Worker return idx;
756*ec779b8eSAndroid Build Coastguard Worker case -EAGAIN:
757*ec779b8eSAndroid Build Coastguard Worker return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
758*ec779b8eSAndroid Build Coastguard Worker case android::INFO_FORMAT_CHANGED:
759*ec779b8eSAndroid Build Coastguard Worker return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
760*ec779b8eSAndroid Build Coastguard Worker case INFO_OUTPUT_BUFFERS_CHANGED:
761*ec779b8eSAndroid Build Coastguard Worker return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
762*ec779b8eSAndroid Build Coastguard Worker default:
763*ec779b8eSAndroid Build Coastguard Worker break;
764*ec779b8eSAndroid Build Coastguard Worker }
765*ec779b8eSAndroid Build Coastguard Worker return translate_error(ret);
766*ec779b8eSAndroid Build Coastguard Worker }
767*ec779b8eSAndroid Build Coastguard Worker
768*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_getOutputFormat(AMediaCodec * mData)769*ec779b8eSAndroid Build Coastguard Worker AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
770*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> format;
771*ec779b8eSAndroid Build Coastguard Worker mData->mCodec->getOutputFormat(&format);
772*ec779b8eSAndroid Build Coastguard Worker return AMediaFormat_fromMsg(&format);
773*ec779b8eSAndroid Build Coastguard Worker }
774*ec779b8eSAndroid Build Coastguard Worker
775*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_getInputFormat(AMediaCodec * mData)776*ec779b8eSAndroid Build Coastguard Worker AMediaFormat* AMediaCodec_getInputFormat(AMediaCodec *mData) {
777*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> format;
778*ec779b8eSAndroid Build Coastguard Worker mData->mCodec->getInputFormat(&format);
779*ec779b8eSAndroid Build Coastguard Worker return AMediaFormat_fromMsg(&format);
780*ec779b8eSAndroid Build Coastguard Worker }
781*ec779b8eSAndroid Build Coastguard Worker
782*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_getBufferFormat(AMediaCodec * mData,size_t index)783*ec779b8eSAndroid Build Coastguard Worker AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec *mData, size_t index) {
784*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> format;
785*ec779b8eSAndroid Build Coastguard Worker mData->mCodec->getOutputFormat(index, &format);
786*ec779b8eSAndroid Build Coastguard Worker return AMediaFormat_fromMsg(&format);
787*ec779b8eSAndroid Build Coastguard Worker }
788*ec779b8eSAndroid Build Coastguard Worker
789*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_releaseOutputBuffer(AMediaCodec * mData,size_t idx,bool render)790*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
791*ec779b8eSAndroid Build Coastguard Worker if (render) {
792*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
793*ec779b8eSAndroid Build Coastguard Worker } else {
794*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->releaseOutputBuffer(idx));
795*ec779b8eSAndroid Build Coastguard Worker }
796*ec779b8eSAndroid Build Coastguard Worker }
797*ec779b8eSAndroid Build Coastguard Worker
798*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_releaseOutputBufferAtTime(AMediaCodec * mData,size_t idx,int64_t timestampNs)799*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_releaseOutputBufferAtTime(
800*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData, size_t idx, int64_t timestampNs) {
801*ec779b8eSAndroid Build Coastguard Worker ALOGV("render @ %" PRId64, timestampNs);
802*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
803*ec779b8eSAndroid Build Coastguard Worker }
804*ec779b8eSAndroid Build Coastguard Worker
805*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_setOutputSurface(AMediaCodec * mData,ANativeWindow * window)806*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
807*ec779b8eSAndroid Build Coastguard Worker sp<Surface> surface = NULL;
808*ec779b8eSAndroid Build Coastguard Worker if (window != NULL) {
809*ec779b8eSAndroid Build Coastguard Worker surface = (Surface*) window;
810*ec779b8eSAndroid Build Coastguard Worker }
811*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->setSurface(surface));
812*ec779b8eSAndroid Build Coastguard Worker }
813*ec779b8eSAndroid Build Coastguard Worker
814*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createInputSurface(AMediaCodec * mData,ANativeWindow ** surface)815*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
816*ec779b8eSAndroid Build Coastguard Worker if (surface == NULL || mData == NULL) {
817*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
818*ec779b8eSAndroid Build Coastguard Worker }
819*ec779b8eSAndroid Build Coastguard Worker *surface = NULL;
820*ec779b8eSAndroid Build Coastguard Worker
821*ec779b8eSAndroid Build Coastguard Worker sp<IGraphicBufferProducer> igbp = NULL;
822*ec779b8eSAndroid Build Coastguard Worker status_t err = mData->mCodec->createInputSurface(&igbp);
823*ec779b8eSAndroid Build Coastguard Worker if (err != NO_ERROR) {
824*ec779b8eSAndroid Build Coastguard Worker return translate_error(err);
825*ec779b8eSAndroid Build Coastguard Worker }
826*ec779b8eSAndroid Build Coastguard Worker
827*ec779b8eSAndroid Build Coastguard Worker *surface = new Surface(igbp);
828*ec779b8eSAndroid Build Coastguard Worker ANativeWindow_acquire(*surface);
829*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
830*ec779b8eSAndroid Build Coastguard Worker }
831*ec779b8eSAndroid Build Coastguard Worker
832*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_createPersistentInputSurface(ANativeWindow ** surface)833*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_createPersistentInputSurface(ANativeWindow **surface) {
834*ec779b8eSAndroid Build Coastguard Worker if (surface == NULL) {
835*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
836*ec779b8eSAndroid Build Coastguard Worker }
837*ec779b8eSAndroid Build Coastguard Worker *surface = NULL;
838*ec779b8eSAndroid Build Coastguard Worker
839*ec779b8eSAndroid Build Coastguard Worker sp<PersistentSurface> ps = MediaCodec::CreatePersistentInputSurface();
840*ec779b8eSAndroid Build Coastguard Worker if (ps == NULL) {
841*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_UNKNOWN;
842*ec779b8eSAndroid Build Coastguard Worker }
843*ec779b8eSAndroid Build Coastguard Worker
844*ec779b8eSAndroid Build Coastguard Worker sp<IGraphicBufferProducer> igbp = ps->getBufferProducer();
845*ec779b8eSAndroid Build Coastguard Worker if (igbp == NULL) {
846*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_UNKNOWN;
847*ec779b8eSAndroid Build Coastguard Worker }
848*ec779b8eSAndroid Build Coastguard Worker
849*ec779b8eSAndroid Build Coastguard Worker *surface = new AMediaCodecPersistentSurface(igbp, ps);
850*ec779b8eSAndroid Build Coastguard Worker ANativeWindow_acquire(*surface);
851*ec779b8eSAndroid Build Coastguard Worker
852*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
853*ec779b8eSAndroid Build Coastguard Worker }
854*ec779b8eSAndroid Build Coastguard Worker
855*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_setInputSurface(AMediaCodec * mData,ANativeWindow * surface)856*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_setInputSurface(
857*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData, ANativeWindow *surface) {
858*ec779b8eSAndroid Build Coastguard Worker
859*ec779b8eSAndroid Build Coastguard Worker if (surface == NULL || mData == NULL) {
860*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
861*ec779b8eSAndroid Build Coastguard Worker }
862*ec779b8eSAndroid Build Coastguard Worker
863*ec779b8eSAndroid Build Coastguard Worker AMediaCodecPersistentSurface *aMediaPersistentSurface =
864*ec779b8eSAndroid Build Coastguard Worker static_cast<AMediaCodecPersistentSurface *>(surface);
865*ec779b8eSAndroid Build Coastguard Worker if (aMediaPersistentSurface->mPersistentSurface == NULL) {
866*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
867*ec779b8eSAndroid Build Coastguard Worker }
868*ec779b8eSAndroid Build Coastguard Worker
869*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->setInputSurface(
870*ec779b8eSAndroid Build Coastguard Worker aMediaPersistentSurface->mPersistentSurface));
871*ec779b8eSAndroid Build Coastguard Worker }
872*ec779b8eSAndroid Build Coastguard Worker
873*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_setParameters(AMediaCodec * mData,const AMediaFormat * params)874*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_setParameters(
875*ec779b8eSAndroid Build Coastguard Worker AMediaCodec *mData, const AMediaFormat* params) {
876*ec779b8eSAndroid Build Coastguard Worker if (params == NULL || mData == NULL) {
877*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
878*ec779b8eSAndroid Build Coastguard Worker }
879*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> nativeParams;
880*ec779b8eSAndroid Build Coastguard Worker AMediaFormat_getFormat(params, &nativeParams);
881*ec779b8eSAndroid Build Coastguard Worker ALOGV("setParameters: %s", nativeParams->debugString(0).c_str());
882*ec779b8eSAndroid Build Coastguard Worker
883*ec779b8eSAndroid Build Coastguard Worker return translate_error(mData->mCodec->setParameters(nativeParams));
884*ec779b8eSAndroid Build Coastguard Worker }
885*ec779b8eSAndroid Build Coastguard Worker
886*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_signalEndOfInputStream(AMediaCodec * mData)887*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) {
888*ec779b8eSAndroid Build Coastguard Worker
889*ec779b8eSAndroid Build Coastguard Worker if (mData == NULL) {
890*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
891*ec779b8eSAndroid Build Coastguard Worker }
892*ec779b8eSAndroid Build Coastguard Worker
893*ec779b8eSAndroid Build Coastguard Worker status_t err = mData->mCodec->signalEndOfInputStream();
894*ec779b8eSAndroid Build Coastguard Worker if (err == INVALID_OPERATION) {
895*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_OPERATION;
896*ec779b8eSAndroid Build Coastguard Worker }
897*ec779b8eSAndroid Build Coastguard Worker
898*ec779b8eSAndroid Build Coastguard Worker return translate_error(err);
899*ec779b8eSAndroid Build Coastguard Worker
900*ec779b8eSAndroid Build Coastguard Worker }
901*ec779b8eSAndroid Build Coastguard Worker
902*ec779b8eSAndroid Build Coastguard Worker //EXPORT
AMediaCodec_setNotificationCallback(AMediaCodec * mData,OnCodecEvent callback,void * userdata)903*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
904*ec779b8eSAndroid Build Coastguard Worker void *userdata) {
905*ec779b8eSAndroid Build Coastguard Worker mData->mCallback = callback;
906*ec779b8eSAndroid Build Coastguard Worker mData->mCallbackUserData = userdata;
907*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
908*ec779b8eSAndroid Build Coastguard Worker }
909*ec779b8eSAndroid Build Coastguard Worker
910*ec779b8eSAndroid Build Coastguard Worker typedef struct AMediaCodecCryptoInfo {
911*ec779b8eSAndroid Build Coastguard Worker int numsubsamples;
912*ec779b8eSAndroid Build Coastguard Worker uint8_t key[16];
913*ec779b8eSAndroid Build Coastguard Worker uint8_t iv[16];
914*ec779b8eSAndroid Build Coastguard Worker cryptoinfo_mode_t mode;
915*ec779b8eSAndroid Build Coastguard Worker cryptoinfo_pattern_t pattern;
916*ec779b8eSAndroid Build Coastguard Worker size_t *clearbytes;
917*ec779b8eSAndroid Build Coastguard Worker size_t *encryptedbytes;
918*ec779b8eSAndroid Build Coastguard Worker } AMediaCodecCryptoInfo;
919*ec779b8eSAndroid Build Coastguard Worker
920*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodec_queueSecureInputBuffer(AMediaCodec * codec,size_t idx,off_t offset,AMediaCodecCryptoInfo * crypto,uint64_t time,uint32_t flags)921*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodec_queueSecureInputBuffer(
922*ec779b8eSAndroid Build Coastguard Worker AMediaCodec* codec,
923*ec779b8eSAndroid Build Coastguard Worker size_t idx,
924*ec779b8eSAndroid Build Coastguard Worker off_t offset,
925*ec779b8eSAndroid Build Coastguard Worker AMediaCodecCryptoInfo* crypto,
926*ec779b8eSAndroid Build Coastguard Worker uint64_t time,
927*ec779b8eSAndroid Build Coastguard Worker uint32_t flags) {
928*ec779b8eSAndroid Build Coastguard Worker
929*ec779b8eSAndroid Build Coastguard Worker CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
930*ec779b8eSAndroid Build Coastguard Worker for (int i = 0; i < crypto->numsubsamples; i++) {
931*ec779b8eSAndroid Build Coastguard Worker subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
932*ec779b8eSAndroid Build Coastguard Worker subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
933*ec779b8eSAndroid Build Coastguard Worker }
934*ec779b8eSAndroid Build Coastguard Worker
935*ec779b8eSAndroid Build Coastguard Worker CryptoPlugin::Pattern pattern;
936*ec779b8eSAndroid Build Coastguard Worker pattern.mEncryptBlocks = crypto->pattern.encryptBlocks;
937*ec779b8eSAndroid Build Coastguard Worker pattern.mSkipBlocks = crypto->pattern.skipBlocks;
938*ec779b8eSAndroid Build Coastguard Worker
939*ec779b8eSAndroid Build Coastguard Worker AString errormsg;
940*ec779b8eSAndroid Build Coastguard Worker status_t err = codec->mCodec->queueSecureInputBuffer(idx,
941*ec779b8eSAndroid Build Coastguard Worker offset,
942*ec779b8eSAndroid Build Coastguard Worker subSamples,
943*ec779b8eSAndroid Build Coastguard Worker crypto->numsubsamples,
944*ec779b8eSAndroid Build Coastguard Worker crypto->key,
945*ec779b8eSAndroid Build Coastguard Worker crypto->iv,
946*ec779b8eSAndroid Build Coastguard Worker (CryptoPlugin::Mode)crypto->mode,
947*ec779b8eSAndroid Build Coastguard Worker pattern,
948*ec779b8eSAndroid Build Coastguard Worker time,
949*ec779b8eSAndroid Build Coastguard Worker flags,
950*ec779b8eSAndroid Build Coastguard Worker &errormsg);
951*ec779b8eSAndroid Build Coastguard Worker if (err != 0) {
952*ec779b8eSAndroid Build Coastguard Worker ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
953*ec779b8eSAndroid Build Coastguard Worker }
954*ec779b8eSAndroid Build Coastguard Worker delete [] subSamples;
955*ec779b8eSAndroid Build Coastguard Worker return translate_error(err);
956*ec779b8eSAndroid Build Coastguard Worker }
957*ec779b8eSAndroid Build Coastguard Worker
958*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecActionCode_isRecoverable(int32_t actionCode)959*ec779b8eSAndroid Build Coastguard Worker bool AMediaCodecActionCode_isRecoverable(int32_t actionCode) {
960*ec779b8eSAndroid Build Coastguard Worker return (actionCode == ACTION_CODE_RECOVERABLE);
961*ec779b8eSAndroid Build Coastguard Worker }
962*ec779b8eSAndroid Build Coastguard Worker
963*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecActionCode_isTransient(int32_t actionCode)964*ec779b8eSAndroid Build Coastguard Worker bool AMediaCodecActionCode_isTransient(int32_t actionCode) {
965*ec779b8eSAndroid Build Coastguard Worker return (actionCode == ACTION_CODE_TRANSIENT);
966*ec779b8eSAndroid Build Coastguard Worker }
967*ec779b8eSAndroid Build Coastguard Worker
968*ec779b8eSAndroid Build Coastguard Worker
969*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo * info,cryptoinfo_pattern_t * pattern)970*ec779b8eSAndroid Build Coastguard Worker void AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo *info,
971*ec779b8eSAndroid Build Coastguard Worker cryptoinfo_pattern_t *pattern) {
972*ec779b8eSAndroid Build Coastguard Worker info->pattern.encryptBlocks = pattern->encryptBlocks;
973*ec779b8eSAndroid Build Coastguard Worker info->pattern.skipBlocks = pattern->skipBlocks;
974*ec779b8eSAndroid Build Coastguard Worker }
975*ec779b8eSAndroid Build Coastguard Worker
976*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_new(int numsubsamples,uint8_t key[16],uint8_t iv[16],cryptoinfo_mode_t mode,size_t * clearbytes,size_t * encryptedbytes)977*ec779b8eSAndroid Build Coastguard Worker AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
978*ec779b8eSAndroid Build Coastguard Worker int numsubsamples,
979*ec779b8eSAndroid Build Coastguard Worker uint8_t key[16],
980*ec779b8eSAndroid Build Coastguard Worker uint8_t iv[16],
981*ec779b8eSAndroid Build Coastguard Worker cryptoinfo_mode_t mode,
982*ec779b8eSAndroid Build Coastguard Worker size_t *clearbytes,
983*ec779b8eSAndroid Build Coastguard Worker size_t *encryptedbytes) {
984*ec779b8eSAndroid Build Coastguard Worker
985*ec779b8eSAndroid Build Coastguard Worker // size needed to store all the crypto data
986*ec779b8eSAndroid Build Coastguard Worker size_t cryptosize;
987*ec779b8eSAndroid Build Coastguard Worker // = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
988*ec779b8eSAndroid Build Coastguard Worker if (__builtin_mul_overflow(sizeof(size_t) * 2, numsubsamples, &cryptosize) ||
989*ec779b8eSAndroid Build Coastguard Worker __builtin_add_overflow(cryptosize, sizeof(AMediaCodecCryptoInfo), &cryptosize)) {
990*ec779b8eSAndroid Build Coastguard Worker ALOGE("crypto size overflow");
991*ec779b8eSAndroid Build Coastguard Worker return NULL;
992*ec779b8eSAndroid Build Coastguard Worker }
993*ec779b8eSAndroid Build Coastguard Worker AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
994*ec779b8eSAndroid Build Coastguard Worker if (!ret) {
995*ec779b8eSAndroid Build Coastguard Worker ALOGE("couldn't allocate %zu bytes", cryptosize);
996*ec779b8eSAndroid Build Coastguard Worker return NULL;
997*ec779b8eSAndroid Build Coastguard Worker }
998*ec779b8eSAndroid Build Coastguard Worker ret->numsubsamples = numsubsamples;
999*ec779b8eSAndroid Build Coastguard Worker memcpy(ret->key, key, 16);
1000*ec779b8eSAndroid Build Coastguard Worker memcpy(ret->iv, iv, 16);
1001*ec779b8eSAndroid Build Coastguard Worker ret->mode = mode;
1002*ec779b8eSAndroid Build Coastguard Worker ret->pattern.encryptBlocks = 0;
1003*ec779b8eSAndroid Build Coastguard Worker ret->pattern.skipBlocks = 0;
1004*ec779b8eSAndroid Build Coastguard Worker
1005*ec779b8eSAndroid Build Coastguard Worker // clearbytes and encryptedbytes point at the actual data, which follows
1006*ec779b8eSAndroid Build Coastguard Worker ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
1007*ec779b8eSAndroid Build Coastguard Worker ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
1008*ec779b8eSAndroid Build Coastguard Worker
1009*ec779b8eSAndroid Build Coastguard Worker memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
1010*ec779b8eSAndroid Build Coastguard Worker memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
1011*ec779b8eSAndroid Build Coastguard Worker
1012*ec779b8eSAndroid Build Coastguard Worker return ret;
1013*ec779b8eSAndroid Build Coastguard Worker }
1014*ec779b8eSAndroid Build Coastguard Worker
1015*ec779b8eSAndroid Build Coastguard Worker
1016*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo * info)1017*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
1018*ec779b8eSAndroid Build Coastguard Worker free(info);
1019*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
1020*ec779b8eSAndroid Build Coastguard Worker }
1021*ec779b8eSAndroid Build Coastguard Worker
1022*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo * ci)1023*ec779b8eSAndroid Build Coastguard Worker size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
1024*ec779b8eSAndroid Build Coastguard Worker return ci->numsubsamples;
1025*ec779b8eSAndroid Build Coastguard Worker }
1026*ec779b8eSAndroid Build Coastguard Worker
1027*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo * ci,uint8_t * dst)1028*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
1029*ec779b8eSAndroid Build Coastguard Worker if (!ci) {
1030*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_OBJECT;
1031*ec779b8eSAndroid Build Coastguard Worker }
1032*ec779b8eSAndroid Build Coastguard Worker if (!dst) {
1033*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
1034*ec779b8eSAndroid Build Coastguard Worker }
1035*ec779b8eSAndroid Build Coastguard Worker memcpy(dst, ci->key, 16);
1036*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
1037*ec779b8eSAndroid Build Coastguard Worker }
1038*ec779b8eSAndroid Build Coastguard Worker
1039*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo * ci,uint8_t * dst)1040*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
1041*ec779b8eSAndroid Build Coastguard Worker if (!ci) {
1042*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_OBJECT;
1043*ec779b8eSAndroid Build Coastguard Worker }
1044*ec779b8eSAndroid Build Coastguard Worker if (!dst) {
1045*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
1046*ec779b8eSAndroid Build Coastguard Worker }
1047*ec779b8eSAndroid Build Coastguard Worker memcpy(dst, ci->iv, 16);
1048*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
1049*ec779b8eSAndroid Build Coastguard Worker }
1050*ec779b8eSAndroid Build Coastguard Worker
1051*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo * ci)1052*ec779b8eSAndroid Build Coastguard Worker cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
1053*ec779b8eSAndroid Build Coastguard Worker if (!ci) {
1054*ec779b8eSAndroid Build Coastguard Worker return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
1055*ec779b8eSAndroid Build Coastguard Worker }
1056*ec779b8eSAndroid Build Coastguard Worker return ci->mode;
1057*ec779b8eSAndroid Build Coastguard Worker }
1058*ec779b8eSAndroid Build Coastguard Worker
1059*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo * ci,size_t * dst)1060*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1061*ec779b8eSAndroid Build Coastguard Worker if (!ci) {
1062*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_OBJECT;
1063*ec779b8eSAndroid Build Coastguard Worker }
1064*ec779b8eSAndroid Build Coastguard Worker if (!dst) {
1065*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
1066*ec779b8eSAndroid Build Coastguard Worker }
1067*ec779b8eSAndroid Build Coastguard Worker memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
1068*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
1069*ec779b8eSAndroid Build Coastguard Worker }
1070*ec779b8eSAndroid Build Coastguard Worker
1071*ec779b8eSAndroid Build Coastguard Worker EXPORT
AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo * ci,size_t * dst)1072*ec779b8eSAndroid Build Coastguard Worker media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1073*ec779b8eSAndroid Build Coastguard Worker if (!ci) {
1074*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_OBJECT;
1075*ec779b8eSAndroid Build Coastguard Worker }
1076*ec779b8eSAndroid Build Coastguard Worker if (!dst) {
1077*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_ERROR_INVALID_PARAMETER;
1078*ec779b8eSAndroid Build Coastguard Worker }
1079*ec779b8eSAndroid Build Coastguard Worker memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
1080*ec779b8eSAndroid Build Coastguard Worker return AMEDIA_OK;
1081*ec779b8eSAndroid Build Coastguard Worker }
1082*ec779b8eSAndroid Build Coastguard Worker
1083*ec779b8eSAndroid Build Coastguard Worker EXPORT const char* AMEDIACODEC_KEY_HDR10_PLUS_INFO = AMEDIAFORMAT_KEY_HDR10_PLUS_INFO;
1084*ec779b8eSAndroid Build Coastguard Worker EXPORT const char* AMEDIACODEC_KEY_LOW_LATENCY = AMEDIAFORMAT_KEY_LOW_LATENCY;
1085*ec779b8eSAndroid Build Coastguard Worker EXPORT const char* AMEDIACODEC_KEY_OFFSET_TIME = "time-offset-us";
1086*ec779b8eSAndroid Build Coastguard Worker EXPORT const char* AMEDIACODEC_KEY_REQUEST_SYNC_FRAME = "request-sync";
1087*ec779b8eSAndroid Build Coastguard Worker EXPORT const char* AMEDIACODEC_KEY_SUSPEND = "drop-input-frames";
1088*ec779b8eSAndroid Build Coastguard Worker EXPORT const char* AMEDIACODEC_KEY_SUSPEND_TIME = "drop-start-time-us";
1089*ec779b8eSAndroid Build Coastguard Worker EXPORT const char* AMEDIACODEC_KEY_VIDEO_BITRATE = "video-bitrate";
1090*ec779b8eSAndroid Build Coastguard Worker
1091*ec779b8eSAndroid Build Coastguard Worker } // extern "C"
1092*ec779b8eSAndroid Build Coastguard Worker
1093