History

avcodec/mediacodec_wrapper: add async mode support

Zhao Zhili committed 2 years ago

Commit 9aacbfb1 parent fa2ff5e2 files · +158 −0Browse files

Unified · Split

2 files
  1. libavcodec/mediacodec_wrapper.c +130 −0
  2. libavcodec/mediacodec_wrapper.h +28 −0
libavcodec/mediacodec_wrapper.c+130−0
@@ -1762,6 +1762,14 @@ static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx) · 1761 unmodified lines
17621762 return 0;
17631763 }
17641764
1765+static int mediacodec_jni_setAsyncNotifyCallback(FFAMediaCodec *codec,
1766+ const FFAMediaCodecOnAsyncNotifyCallback *callback,
1767+ void *userdata)
1768+{
1769+ av_log(codec, AV_LOG_ERROR, "Doesn't support aync mode with JNI, please try ndk_codec=1\n");
1770+ return AVERROR(ENOSYS);
1771+}
1772+
17651773 static const FFAMediaFormat media_format_jni = {
17661774 .class = &amediaformat_class,
17671775
@@ -1821,6 +1829,7 @@ static const FFAMediaCodec media_codec_jni = { · 53 unmodified lines
18211829 .getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode,
18221830 .cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers,
18231831 .signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream,
1832+ .setAsyncNotifyCallback = mediacodec_jni_setAsyncNotifyCallback,
18241833 };
18251834
18261835 typedef struct FFAMediaFormatNdk {
@@ -1842,6 +1851,9 @@ typedef struct FFAMediaCodecNdk { · 15 unmodified lines
18421851 AMediaCodec *impl;
18431852 ANativeWindow *window;
18441853
1854+ FFAMediaCodecOnAsyncNotifyCallback async_cb;
1855+ void *async_userdata;
1856+
18451857 // Available since API level 28.
18461858 media_status_t (*getName)(AMediaCodec*, char** out_name);
18471859 void (*releaseName)(AMediaCodec*, char* name);
@@ -1849,6 +1861,8 @@ typedef struct FFAMediaCodecNdk { · 1 unmodified line
18491861 // Available since API level 26.
18501862 media_status_t (*setInputSurface)(AMediaCodec*, ANativeWindow *);
18511863 media_status_t (*signalEndOfInputStream)(AMediaCodec *);
1864+ media_status_t (*setAsyncNotifyCallback)(AMediaCodec *,
1865+ struct AMediaCodecOnAsyncNotifyCallback callback, void *userdata);
18521866 } FFAMediaCodecNdk;
18531867
18541868 static const FFAMediaFormat media_format_ndk;
@@ -1866,6 +1880,32 @@ static const AVClass amediacodec_ndk_class = { · 11 unmodified lines
18661880 .version = LIBAVUTIL_VERSION_INT,
18671881 };
18681882
1883+static int media_status_to_error(media_status_t status)
1884+{
1885+ switch (status) {
1886+ case AMEDIA_OK:
1887+ return 0;
1888+ case AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE:
1889+ return AVERROR(ENOMEM);
1890+ case AMEDIA_ERROR_MALFORMED:
1891+ return AVERROR_INVALIDDATA;
1892+ case AMEDIA_ERROR_UNSUPPORTED:
1893+ return AVERROR(ENOTSUP);
1894+ case AMEDIA_ERROR_INVALID_PARAMETER:
1895+ return AVERROR(EINVAL);
1896+ case AMEDIA_ERROR_INVALID_OPERATION:
1897+ return AVERROR(EOPNOTSUPP);
1898+ case AMEDIA_ERROR_END_OF_STREAM:
1899+ return AVERROR_EOF;
1900+ case AMEDIA_ERROR_IO:
1901+ return AVERROR(EIO);
1902+ case AMEDIA_ERROR_WOULD_BLOCK:
1903+ return AVERROR(EWOULDBLOCK);
1904+ default:
1905+ return AVERROR_EXTERNAL;
1906+ }
1907+}
1908+
18691909 static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl)
18701910 {
18711911 FFAMediaFormatNdk *format = av_mallocz(sizeof(*format));
@@ -2060,6 +2100,7 @@ static inline FFAMediaCodec *ndk_codec_create(int method, const char *arg) { · 188 unmodified lines
20602100
20612101 GET_SYMBOL(setInputSurface)
20622102 GET_SYMBOL(signalEndOfInputStream)
2103+ GET_SYMBOL(setAsyncNotifyCallback)
20632104
20642105 #undef GET_SYMBOL
20652106
@@ -2335,6 +2376,94 @@ static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx) · 269 unmodified lines
23352376 return 0;
23362377 }
23372378
2379+static void mediacodec_ndk_onInputAvailable(AMediaCodec *impl, void *userdata,
2380+ int32_t index)
2381+{
2382+ FFAMediaCodecNdk *codec = userdata;
2383+ codec->async_cb.onAsyncInputAvailable((FFAMediaCodec *) codec,
2384+ codec->async_userdata, index);
2385+}
2386+
2387+static void mediacodec_ndk_onOutputAvailable(AMediaCodec *impl,
2388+ void *userdata,
2389+ int32_t index,
2390+ AMediaCodecBufferInfo *buffer_info)
2391+{
2392+ FFAMediaCodecNdk *codec = userdata;
2393+ FFAMediaCodecBufferInfo info = {
2394+ .offset = buffer_info->offset,
2395+ .size = buffer_info->size,
2396+ .presentationTimeUs = buffer_info->presentationTimeUs,
2397+ .flags = buffer_info->flags,
2398+ };
2399+
2400+ codec->async_cb.onAsyncOutputAvailable(&codec->api, codec->async_userdata,
2401+ index, &info);
2402+}
2403+
2404+static void mediacodec_ndk_onFormatChanged(AMediaCodec *impl, void *userdata,
2405+ AMediaFormat *format)
2406+{
2407+ FFAMediaCodecNdk *codec = userdata;
2408+ FFAMediaFormat *media_format = mediaformat_ndk_create(format);
2409+ if (!media_format)
2410+ return;
2411+
2412+ codec->async_cb.onAsyncFormatChanged(&codec->api, codec->async_userdata,
2413+ media_format);
2414+ ff_AMediaFormat_delete(media_format);
2415+}
2416+
2417+static void mediacodec_ndk_onError(AMediaCodec *impl, void *userdata,
2418+ media_status_t status,
2419+ int32_t actionCode,
2420+ const char *detail)
2421+{
2422+ FFAMediaCodecNdk *codec = userdata;
2423+ int error = media_status_to_error(status);
2424+
2425+ codec->async_cb.onAsyncError(&codec->api, codec->async_userdata, error,
2426+ detail);
2427+}
2428+
2429+static int mediacodec_ndk_setAsyncNotifyCallback(FFAMediaCodec *ctx,
2430+ const FFAMediaCodecOnAsyncNotifyCallback *callback,
2431+ void *userdata)
2432+{
2433+ FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx;
2434+ struct AMediaCodecOnAsyncNotifyCallback cb = {
2435+ .onAsyncInputAvailable = mediacodec_ndk_onInputAvailable,
2436+ .onAsyncOutputAvailable = mediacodec_ndk_onOutputAvailable,
2437+ .onAsyncFormatChanged = mediacodec_ndk_onFormatChanged,
2438+ .onAsyncError = mediacodec_ndk_onError,
2439+ };
2440+ media_status_t status;
2441+
2442+ if (!codec->setAsyncNotifyCallback) {
2443+ av_log(codec, AV_LOG_ERROR, "setAsyncNotifyCallback unavailable\n");
2444+ return AVERROR(ENOSYS);
2445+ }
2446+
2447+ if (!callback ||
2448+ !callback->onAsyncInputAvailable ||
2449+ !callback->onAsyncOutputAvailable ||
2450+ !callback->onAsyncFormatChanged ||
2451+ !callback->onAsyncError)
2452+ return AVERROR(EINVAL);
2453+
2454+ codec->async_cb = *callback;
2455+ codec->async_userdata = userdata;
2456+
2457+ status = codec->setAsyncNotifyCallback(codec->impl, cb, codec);
2458+ if (status != AMEDIA_OK) {
2459+ av_log(codec, AV_LOG_ERROR, "setAsyncNotifyCallback failed, %d\n",
2460+ status);
2461+ return AVERROR_EXTERNAL;
2462+ }
2463+
2464+ return 0;
2465+}
2466+
23382467 static const FFAMediaFormat media_format_ndk = {
23392468 .class = &amediaformat_ndk_class,
23402469
@@ -2396,6 +2525,7 @@ static const FFAMediaCodec media_codec_ndk = { · 55 unmodified lines
23962525 .getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode,
23972526 .cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers,
23982527 .signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream,
2528+ .setAsyncNotifyCallback = mediacodec_ndk_setAsyncNotifyCallback,
23992529 };
24002530
24012531 FFAMediaFormat *ff_AMediaFormat_new(int ndk)
libavcodec/mediacodec_wrapper.h+28−0
@@ -178,6 +178,22 @@ struct FFAMediaCodecBufferInfo { · 177 unmodified lines
178178 typedef struct FFAMediaCodecBufferInfo FFAMediaCodecBufferInfo;
179179
180180 typedef struct FFAMediaCodec FFAMediaCodec;
181+
182+typedef struct FFAMediaCodecOnAsyncNotifyCallback {
183+ void (*onAsyncInputAvailable)(FFAMediaCodec *codec, void *userdata,
184+ int32_t index);
185+
186+ void (*onAsyncOutputAvailable)(FFAMediaCodec *codec, void *userdata,
187+ int32_t index,
188+ FFAMediaCodecBufferInfo *buffer_info);
189+
190+ void (*onAsyncFormatChanged)(FFAMediaCodec *codec, void *userdata,
191+ FFAMediaFormat *format);
192+
193+ void (*onAsyncError)(FFAMediaCodec *codec, void *userdata, int error,
194+ const char *detail);
195+} FFAMediaCodecOnAsyncNotifyCallback;
196+
181197 struct FFAMediaCodec {
182198 const AVClass *class;
183199
@@ -219,6 +235,11 @@ struct FFAMediaCodec { · 35 unmodified lines
219235
220236 // For encoder with FFANativeWindow as input.
221237 int (*signalEndOfInputStream)(FFAMediaCodec *);
238+
239+ // Introduced in Android API 28
240+ int (*setAsyncNotifyCallback)(FFAMediaCodec *codec,
241+ const FFAMediaCodecOnAsyncNotifyCallback *callback,
242+ void *userdata);
222243 };
223244
224245 static inline char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
@@ -343,6 +364,13 @@ static inline int ff_AMediaCodec_signalEndOfInputStream(FFAMediaCodec *codec) · 118 unmodified lines
343364 return codec->signalEndOfInputStream(codec);
344365 }
345366
367+static inline int ff_AMediaCodec_setAsyncNotifyCallback(FFAMediaCodec *codec,
368+ const FFAMediaCodecOnAsyncNotifyCallback *callback,
369+ void *userdata)
370+{
371+ return codec->setAsyncNotifyCallback(codec, callback, userdata);
372+}
373+
346374 int ff_Build_SDK_INT(AVCodecContext *avctx);
347375
348376 enum FFAMediaFormatColorRange {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t