History

avcodec/mediacodec_wrapper: add async mode support

Zhao Zhili committed 2 years ago

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

Showing the changes to libavcodec (2 of 2 files). Show all

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
1762 return 0;1762 return 0;
1763}1763}
1764 1764
1765static 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
1765static const FFAMediaFormat media_format_jni = {1773static const FFAMediaFormat media_format_jni = {
1766 .class = &amediaformat_class,1774 .class = &amediaformat_class,
1767 1775
@@ -1821,6 +1829,7 @@ static const FFAMediaCodec media_codec_jni = { · 53 unmodified lines
1821 .getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode,1829 .getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode,
1822 .cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers,1830 .cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers,
1823 .signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream,1831 .signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream,
1832 .setAsyncNotifyCallback = mediacodec_jni_setAsyncNotifyCallback,
1824};1833};
1825 1834
1826typedef struct FFAMediaFormatNdk {1835typedef struct FFAMediaFormatNdk {
@@ -1842,6 +1851,9 @@ typedef struct FFAMediaCodecNdk { · 15 unmodified lines
1842 AMediaCodec *impl;1851 AMediaCodec *impl;
1843 ANativeWindow *window;1852 ANativeWindow *window;
1844 1853
1854 FFAMediaCodecOnAsyncNotifyCallback async_cb;
1855 void *async_userdata;
1856
1845 // Available since API level 28.1857 // Available since API level 28.
1846 media_status_t (*getName)(AMediaCodec*, char** out_name);1858 media_status_t (*getName)(AMediaCodec*, char** out_name);
1847 void (*releaseName)(AMediaCodec*, char* name);1859 void (*releaseName)(AMediaCodec*, char* name);
@@ -1849,6 +1861,8 @@ typedef struct FFAMediaCodecNdk { · 1 unmodified line
1849 // Available since API level 26.1861 // Available since API level 26.
1850 media_status_t (*setInputSurface)(AMediaCodec*, ANativeWindow *);1862 media_status_t (*setInputSurface)(AMediaCodec*, ANativeWindow *);
1851 media_status_t (*signalEndOfInputStream)(AMediaCodec *);1863 media_status_t (*signalEndOfInputStream)(AMediaCodec *);
1864 media_status_t (*setAsyncNotifyCallback)(AMediaCodec *,
1865 struct AMediaCodecOnAsyncNotifyCallback callback, void *userdata);
1852} FFAMediaCodecNdk;1866} FFAMediaCodecNdk;
1853 1867
1854static const FFAMediaFormat media_format_ndk;1868static const FFAMediaFormat media_format_ndk;
@@ -1866,6 +1880,32 @@ static const AVClass amediacodec_ndk_class = { · 11 unmodified lines
1866 .version = LIBAVUTIL_VERSION_INT,1880 .version = LIBAVUTIL_VERSION_INT,
1867};1881};
1868 1882
1883static 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
1869static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl)1909static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl)
1870{1910{
1871 FFAMediaFormatNdk *format = av_mallocz(sizeof(*format));1911 FFAMediaFormatNdk *format = av_mallocz(sizeof(*format));
@@ -2060,6 +2100,7 @@ static inline FFAMediaCodec *ndk_codec_create(int method, const char *arg) { · 188 unmodified lines
2060 2100
2061 GET_SYMBOL(setInputSurface)2101 GET_SYMBOL(setInputSurface)
2062 GET_SYMBOL(signalEndOfInputStream)2102 GET_SYMBOL(signalEndOfInputStream)
2103 GET_SYMBOL(setAsyncNotifyCallback)
2063 2104
2064#undef GET_SYMBOL2105#undef GET_SYMBOL
2065 2106
@@ -2335,6 +2376,94 @@ static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx) · 269 unmodified lines
2335 return 0;2376 return 0;
2336}2377}
2337 2378
2379static 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
2387static 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
2404static 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
2417static 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
2429static 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
2338static const FFAMediaFormat media_format_ndk = {2467static const FFAMediaFormat media_format_ndk = {
2339 .class = &amediaformat_ndk_class,2468 .class = &amediaformat_ndk_class,
2340 2469
@@ -2396,6 +2525,7 @@ static const FFAMediaCodec media_codec_ndk = { · 55 unmodified lines
2396 .getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode,2525 .getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode,
2397 .cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers,2526 .cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers,
2398 .signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream,2527 .signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream,
2528 .setAsyncNotifyCallback = mediacodec_ndk_setAsyncNotifyCallback,
2399};2529};
2400 2530
2401FFAMediaFormat *ff_AMediaFormat_new(int ndk)2531FFAMediaFormat *ff_AMediaFormat_new(int ndk)
libavcodec/mediacodec_wrapper.h+28−0
@@ -178,6 +178,22 @@ struct FFAMediaCodecBufferInfo { · 177 unmodified lines
178typedef struct FFAMediaCodecBufferInfo FFAMediaCodecBufferInfo;178typedef struct FFAMediaCodecBufferInfo FFAMediaCodecBufferInfo;
179 179
180typedef struct FFAMediaCodec FFAMediaCodec;180typedef struct FFAMediaCodec FFAMediaCodec;
181
182typedef 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
181struct FFAMediaCodec {197struct FFAMediaCodec {
182 const AVClass *class;198 const AVClass *class;
183 199
@@ -219,6 +235,11 @@ struct FFAMediaCodec { · 35 unmodified lines
219 235
220 // For encoder with FFANativeWindow as input.236 // For encoder with FFANativeWindow as input.
221 int (*signalEndOfInputStream)(FFAMediaCodec *);237 int (*signalEndOfInputStream)(FFAMediaCodec *);
238
239 // Introduced in Android API 28
240 int (*setAsyncNotifyCallback)(FFAMediaCodec *codec,
241 const FFAMediaCodecOnAsyncNotifyCallback *callback,
242 void *userdata);
222};243};
223 244
224static inline char *ff_AMediaCodec_getName(FFAMediaCodec *codec)245static inline char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
@@ -343,6 +364,13 @@ static inline int ff_AMediaCodec_signalEndOfInputStream(FFAMediaCodec *codec) · 118 unmodified lines
343 return codec->signalEndOfInputStream(codec);364 return codec->signalEndOfInputStream(codec);
344}365}
345 366
367static inline int ff_AMediaCodec_setAsyncNotifyCallback(FFAMediaCodec *codec,
368 const FFAMediaCodecOnAsyncNotifyCallback *callback,
369 void *userdata)
370{
371 return codec->setAsyncNotifyCallback(codec, callback, userdata);
372}
373
346int ff_Build_SDK_INT(AVCodecContext *avctx);374int ff_Build_SDK_INT(AVCodecContext *avctx);
347 375
348enum FFAMediaFormatColorRange {376enum 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