Showing the changes to libavcodec (2 of 2 files). Show all
Unified · Split
| @@ -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) |
| @@ -178,6 +178,22 @@ struct FFAMediaCodecBufferInfo { · 177 unmodified lines | ||
| 178 | 178 | typedef struct FFAMediaCodecBufferInfo FFAMediaCodecBufferInfo; |
| 179 | 179 | |
| 180 | 180 | 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 | + | |
| 181 | 197 | struct FFAMediaCodec { |
| 182 | 198 | const AVClass *class; |
| 183 | 199 | |
| @@ -219,6 +235,11 @@ struct FFAMediaCodec { · 35 unmodified lines | ||
| 219 | 235 | |
| 220 | 236 | // For encoder with FFANativeWindow as input. |
| 221 | 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 | |
| 224 | 245 | static inline char *ff_AMediaCodec_getName(FFAMediaCodec *codec) |
| @@ -343,6 +364,13 @@ static inline int ff_AMediaCodec_signalEndOfInputStream(FFAMediaCodec *codec) · 118 unmodified lines | ||
| 343 | 364 | return codec->signalEndOfInputStream(codec); |
| 344 | 365 | } |
| 345 | 366 | |
| 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 | + | |
| 346 | 374 | int ff_Build_SDK_INT(AVCodecContext *avctx); |
| 347 | 375 | |
| 348 | 376 | enum FFAMediaFormatColorRange { |