| @@ -1762,6 +1762,14 @@ static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx) · 1761 unmodified lines |
| 1762 | return 0; | 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 | static const FFAMediaFormat media_format_jni = { | 1773 | static 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 | |
| 1826 | typedef struct FFAMediaFormatNdk { | 1835 | typedef 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 | |
| 1854 | static const FFAMediaFormat media_format_ndk; | 1868 | static 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 | |
| | 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 | static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl) | 1909 | static 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_SYMBOL | 2105 | #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 | |
| | 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 | static const FFAMediaFormat media_format_ndk = { | 2467 | static 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 | |
| 2401 | FFAMediaFormat *ff_AMediaFormat_new(int ndk) | 2531 | FFAMediaFormat *ff_AMediaFormat_new(int ndk) |