| @@ -1762,6 +1762,14 @@ static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx) · 1761 unmodified lines |
| 1762 | 1762 | return 0; |
| 1763 | 1763 | } |
| 1764 | 1764 | |
| 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 | + |
| 1765 | 1773 | static const FFAMediaFormat media_format_jni = { |
| 1766 | 1774 | .class = &amediaformat_class, |
| 1767 | 1775 | |
| @@ -1821,6 +1829,7 @@ static const FFAMediaCodec media_codec_jni = { · 53 unmodified lines |
| 1821 | 1829 | .getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode, |
| 1822 | 1830 | .cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers, |
| 1823 | 1831 | .signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream, |
| 1832 | + .setAsyncNotifyCallback = mediacodec_jni_setAsyncNotifyCallback, |
| 1824 | 1833 | }; |
| 1825 | 1834 | |
| 1826 | 1835 | typedef struct FFAMediaFormatNdk { |
| @@ -1842,6 +1851,9 @@ typedef struct FFAMediaCodecNdk { · 15 unmodified lines |
| 1842 | 1851 | AMediaCodec *impl; |
| 1843 | 1852 | ANativeWindow *window; |
| 1844 | 1853 | |
| 1854 | + FFAMediaCodecOnAsyncNotifyCallback async_cb; |
| 1855 | + void *async_userdata; |
| 1856 | + |
| 1845 | 1857 | // Available since API level 28. |
| 1846 | 1858 | media_status_t (*getName)(AMediaCodec*, char** out_name); |
| 1847 | 1859 | void (*releaseName)(AMediaCodec*, char* name); |
| @@ -1849,6 +1861,8 @@ typedef struct FFAMediaCodecNdk { · 1 unmodified line |
| 1849 | 1861 | // Available since API level 26. |
| 1850 | 1862 | media_status_t (*setInputSurface)(AMediaCodec*, ANativeWindow *); |
| 1851 | 1863 | media_status_t (*signalEndOfInputStream)(AMediaCodec *); |
| 1864 | + media_status_t (*setAsyncNotifyCallback)(AMediaCodec *, |
| 1865 | + struct AMediaCodecOnAsyncNotifyCallback callback, void *userdata); |
| 1852 | 1866 | } FFAMediaCodecNdk; |
| 1853 | 1867 | |
| 1854 | 1868 | static const FFAMediaFormat media_format_ndk; |
| @@ -1866,6 +1880,32 @@ static const AVClass amediacodec_ndk_class = { · 11 unmodified lines |
| 1866 | 1880 | .version = LIBAVUTIL_VERSION_INT, |
| 1867 | 1881 | }; |
| 1868 | 1882 | |
| 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 | + |
| 1869 | 1909 | static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl) |
| 1870 | 1910 | { |
| 1871 | 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 | 2101 | GET_SYMBOL(setInputSurface) |
| 2062 | 2102 | GET_SYMBOL(signalEndOfInputStream) |
| 2103 | + GET_SYMBOL(setAsyncNotifyCallback) |
| 2063 | 2104 | |
| 2064 | 2105 | #undef GET_SYMBOL |
| 2065 | 2106 | |
| @@ -2335,6 +2376,94 @@ static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx) · 269 unmodified lines |
| 2335 | 2376 | return 0; |
| 2336 | 2377 | } |
| 2337 | 2378 | |
| 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 | + |
| 2338 | 2467 | static const FFAMediaFormat media_format_ndk = { |
| 2339 | 2468 | .class = &amediaformat_ndk_class, |
| 2340 | 2469 | |
| @@ -2396,6 +2525,7 @@ static const FFAMediaCodec media_codec_ndk = { · 55 unmodified lines |
| 2396 | 2525 | .getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode, |
| 2397 | 2526 | .cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers, |
| 2398 | 2527 | .signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream, |
| 2528 | + .setAsyncNotifyCallback = mediacodec_ndk_setAsyncNotifyCallback, |
| 2399 | 2529 | }; |
| 2400 | 2530 | |
| 2401 | 2531 | FFAMediaFormat *ff_AMediaFormat_new(int ndk) |