|
|
|
@ -20,7 +20,11 @@ |
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <dlfcn.h> |
|
|
|
|
#include <jni.h> |
|
|
|
|
#include <media/NdkMediaFormat.h> |
|
|
|
|
#include <media/NdkMediaCodec.h> |
|
|
|
|
#include <android/native_window_jni.h> |
|
|
|
|
|
|
|
|
|
#include "libavutil/avassert.h" |
|
|
|
|
#include "libavutil/mem.h" |
|
|
|
@ -1794,23 +1798,607 @@ static const FFAMediaCodec media_codec_jni = { |
|
|
|
|
.cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
FFAMediaFormat *ff_AMediaFormat_new(void) |
|
|
|
|
typedef struct FFAMediaFormatNdk { |
|
|
|
|
FFAMediaFormat api; |
|
|
|
|
|
|
|
|
|
void *libmedia; |
|
|
|
|
AMediaFormat *impl; |
|
|
|
|
|
|
|
|
|
AMediaFormat *(*new)(void); |
|
|
|
|
media_status_t (*delete)(AMediaFormat*); |
|
|
|
|
|
|
|
|
|
const char* (*toString)(AMediaFormat*); |
|
|
|
|
|
|
|
|
|
bool (*getInt32)(AMediaFormat*, const char *name, int32_t *out); |
|
|
|
|
bool (*getInt64)(AMediaFormat*, const char *name, int64_t *out); |
|
|
|
|
bool (*getFloat)(AMediaFormat*, const char *name, float *out); |
|
|
|
|
bool (*getSize)(AMediaFormat*, const char *name, size_t *out); |
|
|
|
|
bool (*getBuffer)(AMediaFormat*, const char *name, void** data, size_t *size); |
|
|
|
|
bool (*getString)(AMediaFormat*, const char *name, const char **out); |
|
|
|
|
|
|
|
|
|
void (*setInt32)(AMediaFormat*, const char* name, int32_t value); |
|
|
|
|
void (*setInt64)(AMediaFormat*, const char* name, int64_t value); |
|
|
|
|
void (*setFloat)(AMediaFormat*, const char* name, float value); |
|
|
|
|
void (*setString)(AMediaFormat*, const char* name, const char* value); |
|
|
|
|
void (*setBuffer)(AMediaFormat*, const char* name, const void* data, size_t size); |
|
|
|
|
} FFAMediaFormatNdk; |
|
|
|
|
|
|
|
|
|
typedef struct FFAMediaCodecNdk { |
|
|
|
|
FFAMediaCodec api; |
|
|
|
|
|
|
|
|
|
void *libmedia; |
|
|
|
|
AMediaCodec *impl; |
|
|
|
|
ANativeWindow *window; |
|
|
|
|
|
|
|
|
|
AMediaCodec* (*createCodecByName)(const char *name); |
|
|
|
|
AMediaCodec* (*createDecoderByType)(const char *mime_type); |
|
|
|
|
AMediaCodec* (*createEncoderByType)(const char *mime_type); |
|
|
|
|
media_status_t (*delete)(AMediaCodec*); |
|
|
|
|
|
|
|
|
|
media_status_t (*configure)(AMediaCodec *, |
|
|
|
|
const AMediaFormat *format, |
|
|
|
|
ANativeWindow *surface, |
|
|
|
|
AMediaCrypto *crypto, |
|
|
|
|
uint32_t flags); |
|
|
|
|
media_status_t (*start)(AMediaCodec*); |
|
|
|
|
media_status_t (*stop)(AMediaCodec*); |
|
|
|
|
media_status_t (*flush)(AMediaCodec*); |
|
|
|
|
|
|
|
|
|
uint8_t* (*getInputBuffer)(AMediaCodec*, size_t idx, size_t *out_size); |
|
|
|
|
uint8_t* (*getOutputBuffer)(AMediaCodec*, size_t idx, size_t *out_size); |
|
|
|
|
|
|
|
|
|
ssize_t (*dequeueInputBuffer)(AMediaCodec*, int64_t timeoutUs); |
|
|
|
|
media_status_t (*queueInputBuffer)(AMediaCodec*, size_t idx, |
|
|
|
|
long offset, size_t size, |
|
|
|
|
uint64_t time, uint32_t flags); |
|
|
|
|
|
|
|
|
|
ssize_t (*dequeueOutputBuffer)(AMediaCodec*, AMediaCodecBufferInfo *info, int64_t timeoutUs); |
|
|
|
|
AMediaFormat* (*getOutputFormat)(AMediaCodec*); |
|
|
|
|
|
|
|
|
|
media_status_t (*releaseOutputBuffer)(AMediaCodec*, size_t idx, bool render); |
|
|
|
|
media_status_t (*releaseOutputBufferAtTime)(AMediaCodec *mData, size_t idx, int64_t timestampNs); |
|
|
|
|
|
|
|
|
|
// Available since API level 28.
|
|
|
|
|
media_status_t (*getName)(AMediaCodec*, char** out_name); |
|
|
|
|
void (*releaseName)(AMediaCodec*, char* name); |
|
|
|
|
} FFAMediaCodecNdk; |
|
|
|
|
|
|
|
|
|
static const FFAMediaFormat media_format_ndk; |
|
|
|
|
static const FFAMediaCodec media_codec_ndk; |
|
|
|
|
|
|
|
|
|
static const AVClass amediaformat_ndk_class = { |
|
|
|
|
.class_name = "amediaformat_ndk", |
|
|
|
|
.item_name = av_default_item_name, |
|
|
|
|
.version = LIBAVUTIL_VERSION_INT, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const AVClass amediacodec_ndk_class = { |
|
|
|
|
.class_name = "amediacodec_ndk", |
|
|
|
|
.item_name = av_default_item_name, |
|
|
|
|
.version = LIBAVUTIL_VERSION_INT, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static FFAMediaFormat *mediaformat_ndk_create(AMediaFormat *impl) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = av_mallocz(sizeof(*format)); |
|
|
|
|
if (!format) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
format->api = media_format_ndk; |
|
|
|
|
|
|
|
|
|
format->libmedia = dlopen("libmediandk.so", RTLD_NOW); |
|
|
|
|
if (!format->libmedia) |
|
|
|
|
goto error; |
|
|
|
|
|
|
|
|
|
#define GET_SYMBOL(sym) \ |
|
|
|
|
format->sym = dlsym(format->libmedia, "AMediaFormat_" #sym); \
|
|
|
|
|
if (!format->sym) \
|
|
|
|
|
goto error; |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(new) |
|
|
|
|
GET_SYMBOL(delete) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(toString) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(getInt32) |
|
|
|
|
GET_SYMBOL(getInt64) |
|
|
|
|
GET_SYMBOL(getFloat) |
|
|
|
|
GET_SYMBOL(getSize) |
|
|
|
|
GET_SYMBOL(getBuffer) |
|
|
|
|
GET_SYMBOL(getString) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(setInt32) |
|
|
|
|
GET_SYMBOL(setInt64) |
|
|
|
|
GET_SYMBOL(setFloat) |
|
|
|
|
GET_SYMBOL(setString) |
|
|
|
|
GET_SYMBOL(setBuffer) |
|
|
|
|
|
|
|
|
|
#undef GET_SYMBOL |
|
|
|
|
|
|
|
|
|
if (impl) { |
|
|
|
|
format->impl = impl; |
|
|
|
|
} else { |
|
|
|
|
format->impl = format->new(); |
|
|
|
|
if (!format->impl) |
|
|
|
|
goto error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (FFAMediaFormat *)format; |
|
|
|
|
|
|
|
|
|
error: |
|
|
|
|
if (format->libmedia) |
|
|
|
|
dlclose(format->libmedia); |
|
|
|
|
av_freep(&format); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static FFAMediaFormat *mediaformat_ndk_new(void) |
|
|
|
|
{ |
|
|
|
|
return mediaformat_ndk_create(NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediaformat_ndk_delete(FFAMediaFormat* ctx) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
int ret = 0; |
|
|
|
|
if (!format) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
av_assert0(format->api.class == &amediaformat_ndk_class); |
|
|
|
|
|
|
|
|
|
if (format->impl && (format->delete(format->impl) != AMEDIA_OK)) |
|
|
|
|
ret = AVERROR_EXTERNAL; |
|
|
|
|
if (format->libmedia) |
|
|
|
|
dlclose(format->libmedia); |
|
|
|
|
av_free(format); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static char* mediaformat_ndk_toString(FFAMediaFormat* ctx) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
const char *str = format->toString(format->impl); |
|
|
|
|
return av_strdup(str); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediaformat_ndk_getInt32(FFAMediaFormat* ctx, const char *name, int32_t *out) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
return format->getInt32(format->impl, name, out); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediaformat_ndk_getInt64(FFAMediaFormat* ctx, const char *name, int64_t *out) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
return format->getInt64(format->impl, name, out); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediaformat_ndk_getFloat(FFAMediaFormat* ctx, const char *name, float *out) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
return format->getFloat(format->impl, name, out); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediaformat_ndk_getBuffer(FFAMediaFormat* ctx, const char *name, void** data, size_t *size) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
return format->getBuffer(format->impl, name, data, size); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediaformat_ndk_getString(FFAMediaFormat* ctx, const char *name, const char **out) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
const char *tmp = NULL; |
|
|
|
|
int ret = format->getString(format->impl, name, &tmp); |
|
|
|
|
|
|
|
|
|
if (tmp) |
|
|
|
|
*out = av_strdup(tmp); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mediaformat_ndk_setInt32(FFAMediaFormat* ctx, const char* name, int32_t value) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
format->setInt32(format->impl, name, value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mediaformat_ndk_setInt64(FFAMediaFormat* ctx, const char* name, int64_t value) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
format->setInt64(format->impl, name, value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mediaformat_ndk_setFloat(FFAMediaFormat* ctx, const char* name, float value) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
format->setFloat(format->impl, name, value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mediaformat_ndk_setString(FFAMediaFormat* ctx, const char* name, const char* value) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
format->setString(format->impl, name, value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mediaformat_ndk_setBuffer(FFAMediaFormat* ctx, const char* name, void* data, size_t size) |
|
|
|
|
{ |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)ctx; |
|
|
|
|
format->setBuffer(format->impl, name, data, size); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static char *mediacodec_ndk_getName(FFAMediaCodec *ctx) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
char *ret = NULL; |
|
|
|
|
char *name = NULL; |
|
|
|
|
|
|
|
|
|
if (!codec->getName || !codec->releaseName) { |
|
|
|
|
av_log(ctx, AV_LOG_DEBUG, "getName() unavailable\n"); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
codec->getName(codec->impl, &name); |
|
|
|
|
if (name) { |
|
|
|
|
ret = av_strdup(name); |
|
|
|
|
codec->releaseName(codec->impl, name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline FFAMediaCodec *ndk_codec_create(int method, const char *arg) { |
|
|
|
|
FFAMediaCodecNdk *codec = av_mallocz(sizeof(*codec)); |
|
|
|
|
const char *lib_name = "libmediandk.so"; |
|
|
|
|
|
|
|
|
|
if (!codec) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
codec->api = media_codec_ndk; |
|
|
|
|
codec->libmedia = dlopen(lib_name, RTLD_NOW); |
|
|
|
|
if (!codec->libmedia) |
|
|
|
|
goto error; |
|
|
|
|
|
|
|
|
|
#define GET_SYMBOL(sym, required) \ |
|
|
|
|
codec->sym = dlsym(codec->libmedia, "AMediaCodec_" #sym); \
|
|
|
|
|
if (!codec->sym) { \
|
|
|
|
|
av_log(codec, required ? AV_LOG_ERROR : AV_LOG_INFO, \
|
|
|
|
|
#sym "() unavailable from %s\n", lib_name); \ |
|
|
|
|
if (required) \
|
|
|
|
|
goto error; \
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(createCodecByName, 1) |
|
|
|
|
GET_SYMBOL(createDecoderByType, 1) |
|
|
|
|
GET_SYMBOL(createEncoderByType, 1) |
|
|
|
|
GET_SYMBOL(delete, 1) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(configure, 1) |
|
|
|
|
GET_SYMBOL(start, 1) |
|
|
|
|
GET_SYMBOL(stop, 1) |
|
|
|
|
GET_SYMBOL(flush, 1) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(getInputBuffer, 1) |
|
|
|
|
GET_SYMBOL(getOutputBuffer, 1) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(dequeueInputBuffer, 1) |
|
|
|
|
GET_SYMBOL(queueInputBuffer, 1) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(dequeueOutputBuffer, 1) |
|
|
|
|
GET_SYMBOL(getOutputFormat, 1) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(releaseOutputBuffer, 1) |
|
|
|
|
GET_SYMBOL(releaseOutputBufferAtTime, 1) |
|
|
|
|
|
|
|
|
|
GET_SYMBOL(getName, 0) |
|
|
|
|
GET_SYMBOL(releaseName, 0) |
|
|
|
|
|
|
|
|
|
#undef GET_SYMBOL |
|
|
|
|
|
|
|
|
|
switch (method) { |
|
|
|
|
case CREATE_CODEC_BY_NAME: |
|
|
|
|
codec->impl = codec->createCodecByName(arg); |
|
|
|
|
break; |
|
|
|
|
case CREATE_DECODER_BY_TYPE: |
|
|
|
|
codec->impl = codec->createDecoderByType(arg); |
|
|
|
|
break; |
|
|
|
|
case CREATE_ENCODER_BY_TYPE: |
|
|
|
|
codec->impl = codec->createEncoderByType(arg); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
av_assert0(0); |
|
|
|
|
} |
|
|
|
|
if (!codec->impl) |
|
|
|
|
goto error; |
|
|
|
|
|
|
|
|
|
return (FFAMediaCodec *)codec; |
|
|
|
|
|
|
|
|
|
error: |
|
|
|
|
if (codec->libmedia) |
|
|
|
|
dlclose(codec->libmedia); |
|
|
|
|
av_freep(&codec); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(name, method) \ |
|
|
|
|
static FFAMediaCodec *mediacodec_ndk_##name(const char *arg) \
|
|
|
|
|
{ \
|
|
|
|
|
return ndk_codec_create(method, arg); \
|
|
|
|
|
} \
|
|
|
|
|
|
|
|
|
|
DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createCodecByName, CREATE_CODEC_BY_NAME) |
|
|
|
|
DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createDecoderByType, CREATE_DECODER_BY_TYPE) |
|
|
|
|
DECLARE_NDK_AMEDIACODEC_CREATE_FUNC(createEncoderByType, CREATE_ENCODER_BY_TYPE) |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_delete(FFAMediaCodec* ctx) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
|
|
if (!codec) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
av_assert0(codec->api.class == &amediacodec_ndk_class); |
|
|
|
|
|
|
|
|
|
if (codec->impl && (codec->delete(codec->impl) != AMEDIA_OK)) |
|
|
|
|
ret = AVERROR_EXTERNAL; |
|
|
|
|
if (codec->window) |
|
|
|
|
ANativeWindow_release(codec->window); |
|
|
|
|
if (codec->libmedia) |
|
|
|
|
dlclose(codec->libmedia); |
|
|
|
|
av_free(codec); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_configure(FFAMediaCodec* ctx, const FFAMediaFormat* format_ctx, void* surface, void *crypto, uint32_t flags) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
FFAMediaFormatNdk *format = (FFAMediaFormatNdk *)format_ctx; |
|
|
|
|
media_status_t status; |
|
|
|
|
|
|
|
|
|
if (surface) { |
|
|
|
|
JNIEnv *env = NULL; |
|
|
|
|
JNI_GET_ENV_OR_RETURN(env, ctx, -1); |
|
|
|
|
codec->window = ANativeWindow_fromSurface(env, surface); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (format_ctx->class != &amediaformat_ndk_class) { |
|
|
|
|
av_log(ctx, AV_LOG_ERROR, "invalid media format\n"); |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
status = codec->configure(codec->impl, format->impl, codec->window, NULL, flags); |
|
|
|
|
if (status != AMEDIA_OK) { |
|
|
|
|
av_log(codec, AV_LOG_ERROR, "configure failed, %d\n", status); |
|
|
|
|
return AVERROR_EXTERNAL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define MEDIACODEC_NDK_WRAPPER(method) \ |
|
|
|
|
static int mediacodec_ndk_ ## method(FFAMediaCodec* ctx) \
|
|
|
|
|
{ \
|
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; \
|
|
|
|
|
media_status_t status = codec->method(codec->impl); \
|
|
|
|
|
\
|
|
|
|
|
if (status != AMEDIA_OK) { \
|
|
|
|
|
av_log(codec, AV_LOG_ERROR, #method " failed, %d\n", status); \
|
|
|
|
|
return AVERROR_EXTERNAL; \
|
|
|
|
|
} \
|
|
|
|
|
\
|
|
|
|
|
return 0; \
|
|
|
|
|
} \
|
|
|
|
|
|
|
|
|
|
MEDIACODEC_NDK_WRAPPER(start) |
|
|
|
|
MEDIACODEC_NDK_WRAPPER(stop) |
|
|
|
|
MEDIACODEC_NDK_WRAPPER(flush) |
|
|
|
|
|
|
|
|
|
static uint8_t* mediacodec_ndk_getInputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
return codec->getInputBuffer(codec->impl, idx, out_size); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static uint8_t* mediacodec_ndk_getOutputBuffer(FFAMediaCodec* ctx, size_t idx, size_t *out_size) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
return codec->getOutputBuffer(codec->impl, idx, out_size); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static ssize_t mediacodec_ndk_dequeueInputBuffer(FFAMediaCodec* ctx, int64_t timeoutUs) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
return codec->dequeueInputBuffer(codec->impl, timeoutUs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_queueInputBuffer(FFAMediaCodec *ctx, size_t idx, |
|
|
|
|
off_t offset, size_t size, |
|
|
|
|
uint64_t time, uint32_t flags) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
return codec->queueInputBuffer(codec->impl, idx, offset, size, time, flags); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static ssize_t mediacodec_ndk_dequeueOutputBuffer(FFAMediaCodec* ctx, FFAMediaCodecBufferInfo *info, int64_t timeoutUs) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
AMediaCodecBufferInfo buf_info = {0}; |
|
|
|
|
ssize_t ret; |
|
|
|
|
|
|
|
|
|
ret = codec->dequeueOutputBuffer(codec->impl, &buf_info, timeoutUs); |
|
|
|
|
info->offset = buf_info.offset; |
|
|
|
|
info->size = buf_info.size; |
|
|
|
|
info->presentationTimeUs = buf_info.presentationTimeUs; |
|
|
|
|
info->flags = buf_info.flags; |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static FFAMediaFormat* mediacodec_ndk_getOutputFormat(FFAMediaCodec* ctx) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
AMediaFormat *format = codec->getOutputFormat(codec->impl); |
|
|
|
|
|
|
|
|
|
if (!format) |
|
|
|
|
return NULL; |
|
|
|
|
return mediaformat_ndk_create(format); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_releaseOutputBuffer(FFAMediaCodec* ctx, size_t idx, int render) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
media_status_t status; |
|
|
|
|
|
|
|
|
|
status = codec->releaseOutputBuffer(codec->impl, idx, render); |
|
|
|
|
if (status != AMEDIA_OK) { |
|
|
|
|
av_log(codec, AV_LOG_ERROR, "release output buffer failed, %d\n", status); |
|
|
|
|
return AVERROR_EXTERNAL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_releaseOutputBufferAtTime(FFAMediaCodec *ctx, size_t idx, int64_t timestampNs) |
|
|
|
|
{ |
|
|
|
|
FFAMediaCodecNdk *codec = (FFAMediaCodecNdk *)ctx; |
|
|
|
|
media_status_t status; |
|
|
|
|
|
|
|
|
|
status = codec->releaseOutputBufferAtTime(codec->impl, idx, timestampNs); |
|
|
|
|
if (status != AMEDIA_OK) { |
|
|
|
|
av_log(codec, AV_LOG_ERROR, "releaseOutputBufferAtTime failed, %d\n", status); |
|
|
|
|
return AVERROR_EXTERNAL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_infoTryAgainLater(FFAMediaCodec *ctx, ssize_t idx) |
|
|
|
|
{ |
|
|
|
|
return idx == AMEDIACODEC_INFO_TRY_AGAIN_LATER; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_infoOutputBuffersChanged(FFAMediaCodec *ctx, ssize_t idx) |
|
|
|
|
{ |
|
|
|
|
return idx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_infoOutputFormatChanged(FFAMediaCodec *ctx, ssize_t idx) |
|
|
|
|
{ |
|
|
|
|
return idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_getBufferFlagCodecConfig(FFAMediaCodec *ctx) |
|
|
|
|
{ |
|
|
|
|
return AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_getBufferFlagEndOfStream(FFAMediaCodec *ctx) |
|
|
|
|
{ |
|
|
|
|
return AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_getBufferFlagKeyFrame(FFAMediaCodec *ctx) |
|
|
|
|
{ |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_getConfigureFlagEncode(FFAMediaCodec *ctx) |
|
|
|
|
{ |
|
|
|
|
return AMEDIACODEC_CONFIGURE_FLAG_ENCODE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mediacodec_ndk_cleanOutputBuffers(FFAMediaCodec *ctx) |
|
|
|
|
{ |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const FFAMediaFormat media_format_ndk = { |
|
|
|
|
.class = &amediaformat_ndk_class, |
|
|
|
|
|
|
|
|
|
.create = mediaformat_ndk_new, |
|
|
|
|
.delete = mediaformat_ndk_delete, |
|
|
|
|
|
|
|
|
|
.toString = mediaformat_ndk_toString, |
|
|
|
|
|
|
|
|
|
.getInt32 = mediaformat_ndk_getInt32, |
|
|
|
|
.getInt64 = mediaformat_ndk_getInt64, |
|
|
|
|
.getFloat = mediaformat_ndk_getFloat, |
|
|
|
|
.getBuffer = mediaformat_ndk_getBuffer, |
|
|
|
|
.getString = mediaformat_ndk_getString, |
|
|
|
|
|
|
|
|
|
.setInt32 = mediaformat_ndk_setInt32, |
|
|
|
|
.setInt64 = mediaformat_ndk_setInt64, |
|
|
|
|
.setFloat = mediaformat_ndk_setFloat, |
|
|
|
|
.setString = mediaformat_ndk_setString, |
|
|
|
|
.setBuffer = mediaformat_ndk_setBuffer, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const FFAMediaCodec media_codec_ndk = { |
|
|
|
|
.class = &amediacodec_ndk_class, |
|
|
|
|
|
|
|
|
|
.getName = mediacodec_ndk_getName, |
|
|
|
|
|
|
|
|
|
.createCodecByName = mediacodec_ndk_createCodecByName, |
|
|
|
|
.createDecoderByType = mediacodec_ndk_createDecoderByType, |
|
|
|
|
.createEncoderByType = mediacodec_ndk_createEncoderByType, |
|
|
|
|
.delete = mediacodec_ndk_delete, |
|
|
|
|
|
|
|
|
|
.configure = mediacodec_ndk_configure, |
|
|
|
|
.start = mediacodec_ndk_start, |
|
|
|
|
.stop = mediacodec_ndk_stop, |
|
|
|
|
.flush = mediacodec_ndk_flush, |
|
|
|
|
|
|
|
|
|
.getInputBuffer = mediacodec_ndk_getInputBuffer, |
|
|
|
|
.getOutputBuffer = mediacodec_ndk_getOutputBuffer, |
|
|
|
|
|
|
|
|
|
.dequeueInputBuffer = mediacodec_ndk_dequeueInputBuffer, |
|
|
|
|
.queueInputBuffer = mediacodec_ndk_queueInputBuffer, |
|
|
|
|
|
|
|
|
|
.dequeueOutputBuffer = mediacodec_ndk_dequeueOutputBuffer, |
|
|
|
|
.getOutputFormat = mediacodec_ndk_getOutputFormat, |
|
|
|
|
|
|
|
|
|
.releaseOutputBuffer = mediacodec_ndk_releaseOutputBuffer, |
|
|
|
|
.releaseOutputBufferAtTime = mediacodec_ndk_releaseOutputBufferAtTime, |
|
|
|
|
|
|
|
|
|
.infoTryAgainLater = mediacodec_ndk_infoTryAgainLater, |
|
|
|
|
.infoOutputBuffersChanged = mediacodec_ndk_infoOutputBuffersChanged, |
|
|
|
|
.infoOutputFormatChanged = mediacodec_ndk_infoOutputFormatChanged, |
|
|
|
|
|
|
|
|
|
.getBufferFlagCodecConfig = mediacodec_ndk_getBufferFlagCodecConfig, |
|
|
|
|
.getBufferFlagEndOfStream = mediacodec_ndk_getBufferFlagEndOfStream, |
|
|
|
|
.getBufferFlagKeyFrame = mediacodec_ndk_getBufferFlagKeyFrame, |
|
|
|
|
|
|
|
|
|
.getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode, |
|
|
|
|
.cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
FFAMediaFormat *ff_AMediaFormat_new(int ndk) |
|
|
|
|
{ |
|
|
|
|
if (ndk) |
|
|
|
|
return media_format_ndk.create(); |
|
|
|
|
return media_format_jni.create(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name) |
|
|
|
|
FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name, int ndk) |
|
|
|
|
{ |
|
|
|
|
if (ndk) |
|
|
|
|
return media_codec_ndk.createCodecByName(name); |
|
|
|
|
return media_codec_jni.createCodecByName(name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime_type) |
|
|
|
|
FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime_type, int ndk) |
|
|
|
|
{ |
|
|
|
|
if (ndk) |
|
|
|
|
return media_codec_ndk.createDecoderByType(mime_type); |
|
|
|
|
return media_codec_jni.createDecoderByType(mime_type); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime_type) |
|
|
|
|
FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime_type, int ndk) |
|
|
|
|
{ |
|
|
|
|
if (ndk) |
|
|
|
|
return media_codec_ndk.createEncoderByType(mime_type); |
|
|
|
|
return media_codec_jni.createEncoderByType(mime_type); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|