Commit 5047681d authored by Samuel Mira's avatar Samuel Mira
Browse files

avcodec/mediacodec Add Mediacodec encoder

parent db42f70b
......@@ -3189,6 +3189,7 @@ h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
h264_cuvid_decoder_deps="cuvid"
h264_cuvid_decoder_select="h264_mp4toannexb_bsf"
h264_mediacodec_decoder_deps="mediacodec"
h264_mediacodec_encoder_deps="mediacodec"
h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser"
h264_mf_encoder_deps="mediafoundation"
h264_mmal_decoder_deps="mmal"
......@@ -3207,6 +3208,7 @@ hevc_amf_encoder_deps="amf"
hevc_cuvid_decoder_deps="cuvid"
hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf"
hevc_mediacodec_decoder_deps="mediacodec"
hevc_mediacodec_encoder_deps="mediacodec"
hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser"
hevc_mf_encoder_deps="mediafoundation"
hevc_nvenc_encoder_deps="nvenc"
......@@ -3233,6 +3235,7 @@ mpeg2_crystalhd_decoder_select="crystalhd"
mpeg2_cuvid_decoder_deps="cuvid"
mpeg2_mmal_decoder_deps="mmal"
mpeg2_mediacodec_decoder_deps="mediacodec"
mpeg2_mediacodec_encoder_deps="mediacodec"
mpeg2_qsv_decoder_select="qsvdec"
mpeg2_qsv_encoder_select="qsvenc"
mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode"
......@@ -3260,6 +3263,7 @@ vp8_v4l2m2m_decoder_deps="v4l2_m2m vp8_v4l2_m2m"
vp8_v4l2m2m_encoder_deps="v4l2_m2m vp8_v4l2_m2m"
vp9_cuvid_decoder_deps="cuvid"
vp9_mediacodec_decoder_deps="mediacodec"
vp9_mediacodec_encoder_deps="mediacodec"
vp9_qsv_decoder_select="qsvdec"
vp9_rkmpp_decoder_deps="rkmpp"
vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9"
......
......@@ -393,6 +393,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \
OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_H264_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_H264_MF_ENCODER) += mfenc.o mf_utils.o
OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o
OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o nvenc.o
......@@ -417,6 +418,7 @@ OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o
OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o nvenc.o
OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o
......@@ -521,6 +523,7 @@ OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o
OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o
OBJS-$(CONFIG_MPEG2_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_MPEG2_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_MPEG2_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_MPEG2_VAAPI_ENCODER) += vaapi_encode_mpeg2.o
OBJS-$(CONFIG_MPEG2_V4L2M2M_DECODER) += v4l2_m2m_dec.o
OBJS-$(CONFIG_MPEG4_DECODER) += mpeg4videodsp.o xvididct.o
......@@ -755,6 +758,7 @@ OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9r
vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o
OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_VP9_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o
OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o
OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o
......
......@@ -154,6 +154,7 @@ extern const FFCodec ff_h264_decoder;
extern const FFCodec ff_h264_crystalhd_decoder;
extern const FFCodec ff_h264_v4l2m2m_decoder;
extern const FFCodec ff_h264_mediacodec_decoder;
extern const FFCodec ff_h264_mediacodec_encoder;
extern const FFCodec ff_h264_mmal_decoder;
extern const FFCodec ff_h264_qsv_decoder;
extern const FFCodec ff_h264_rkmpp_decoder;
......@@ -218,6 +219,7 @@ extern const FFCodec ff_mpeg2_crystalhd_decoder;
extern const FFCodec ff_mpeg2_v4l2m2m_decoder;
extern const FFCodec ff_mpeg2_qsv_decoder;
extern const FFCodec ff_mpeg2_mediacodec_decoder;
extern const FFCodec ff_mpeg2_mediacodec_encoder;
extern const FFCodec ff_msa1_decoder;
extern const FFCodec ff_mscc_decoder;
extern const FFCodec ff_msmpeg4v1_decoder;
......@@ -842,6 +844,7 @@ extern const FFCodec ff_h264_videotoolbox_encoder;
extern const FFCodec ff_hevc_amf_encoder;
extern const FFCodec ff_hevc_cuvid_decoder;
extern const FFCodec ff_hevc_mediacodec_decoder;
extern const FFCodec ff_hevc_mediacodec_encoder;
extern const FFCodec ff_hevc_mf_encoder;
extern const FFCodec ff_hevc_nvenc_encoder;
extern const FFCodec ff_hevc_qsv_encoder;
......@@ -871,6 +874,7 @@ extern const FFCodec ff_vp8_v4l2m2m_encoder;
extern const FFCodec ff_vp8_vaapi_encoder;
extern const FFCodec ff_vp9_cuvid_decoder;
extern const FFCodec ff_vp9_mediacodec_decoder;
extern const FFCodec ff_vp9_mediacodec_encoder;
extern const FFCodec ff_vp9_qsv_decoder;
extern const FFCodec ff_vp9_vaapi_encoder;
extern const FFCodec ff_vp9_qsv_encoder;
......
......@@ -87,7 +87,7 @@ void av_mediacodec_default_free(AVCodecContext *avctx)
int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render)
{
MediaCodecDecContext *ctx = buffer->ctx;
MediaCodecContext *ctx = buffer->ctx;
int released = atomic_fetch_add(&buffer->released, 1);
if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) {
......@@ -103,7 +103,7 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render)
int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer, int64_t time)
{
MediaCodecDecContext *ctx = buffer->ctx;
MediaCodecContext *ctx = buffer->ctx;
int released = atomic_fetch_add(&buffer->released, 1);
if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) {
......
......@@ -74,7 +74,7 @@
*
*/
void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
......@@ -129,7 +129,7 @@ void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
}
void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
......@@ -179,7 +179,7 @@ void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
......@@ -270,7 +270,7 @@ static size_t qcom_tile_pos(size_t x, size_t y, size_t w, size_t h)
}
void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
......@@ -337,3 +337,26 @@ void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCod
height -= QCOM_TILE_HEIGHT;
}
}
void ff_mediacodec_copy_yuv420_semi_planar_to_semi_planar(AVCodecContext *avctx,
MediaCodecContext *s,
const AVFrame *frame,
uint8_t *dst)
{
int y;
uint8_t *src;
src = frame->data[0];
for (y = 0; y < avctx->height; y++) {
memcpy(dst, src, avctx->width);
dst += s->stride;
src += frame->linesize[0];
}
src = frame->data[1];
for (y = 0; y < avctx->height >> 1; y++) {
memcpy(dst, src, avctx->width);
dst += s->stride;
src += frame->linesize[1];
}
}
......@@ -32,31 +32,36 @@
#include "mediacodecdec_common.h"
void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
AVFrame *frame);
void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
AVFrame *frame);
void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
AVFrame *frame);
void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
FFAMediaCodecBufferInfo *info,
AVFrame *frame);
void ff_mediacodec_copy_yuv420_semi_planar_to_semi_planar(AVCodecContext *avctx,
MediaCodecContext *s,
const AVFrame *frame,
uint8_t *dst);
#endif /* AVCODEC_MEDIACODEC_SW_BUFFER_H */
......@@ -185,6 +185,9 @@ struct JNIAMediaCodecFields {
jmethodID create_decoder_by_type_id;
jmethodID create_encoder_by_type_id;
jmethodID create_input_surface_id;
jmethodID set_input_surface_id;
jmethodID get_name_id;
jmethodID configure_id;
......@@ -242,6 +245,9 @@ static const struct FFJniField jni_amediacodec_mapping[] = {
{ "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, stop_id), 1 },
{ "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_id), 1 },
{ "android/media/MediaCodec", "createInputSurface", "()Landroid/view/Surface;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, create_input_surface_id), 1 },
{ "android/media/MediaCodec", "setInputSurface", "(Landroid/view/Surface;)V",FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, set_input_surface_id), 1},
{ "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_format_id), 1 },
{ "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_input_buffer_id), 1 },
......@@ -1299,6 +1305,55 @@ DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createCodecByName, CREATE_CODEC_BY_NAME)
DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createDecoderByType, CREATE_DECODER_BY_TYPE)
DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createEncoderByType, CREATE_ENCODER_BY_TYPE)
void* ff_AMediaCodec_createInputSurface(FFAMediaCodec* codec)
{
JNIEnv *env = NULL;
jobject surface = NULL;
void *reference = NULL;
if (!codec) {
return NULL;
}
JNI_GET_ENV_OR_RETURN(env, codec, NULL);
surface = (*env)->CallObjectMethod(env, codec->object, codec->jfields.create_input_surface_id);
if (ff_jni_exception_check(env, 1, codec) < 0) {
return NULL;
}
reference = (*env)->NewGlobalRef(env, surface);
if (ff_jni_exception_check(env, 1, codec) < 0) {
return NULL;
}
if (surface) {
(*env)->DeleteLocalRef(env, surface);
}
return reference;
}
int ff_AMediaCodec_setInputSurface(FFAMediaCodec *codec, void *surface)
{
int ret = 0;
JNIEnv *env = NULL;
if (!codec) {
return ret;
}
JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL);
(*env)->CallVoidMethod(env, codec->object, codec->jfields.set_input_surface_id, surface);
ret = ff_jni_exception_check(env, 1, codec);
if (ret < 0) {
ret = AVERROR_EXTERNAL;
}
return ret;
}
int ff_AMediaCodec_delete(FFAMediaCodec* codec)
{
int ret = 0;
......@@ -1706,6 +1761,36 @@ fail:
return ret;
}
int ff_Surface_release(void *surface, void *log_ctx)
{
int ret = 0;
JNIEnv *env = NULL;
jmethodID method_id;
jclass class;
if (surface == NULL) {
return ret;
}
JNI_GET_ENV_OR_RETURN(env, log_ctx, -1);
class = (*env)->FindClass(env, "android/view/Surface");
method_id = (*env)->GetMethodID(env, class, "release", "()V");
if ((ret = ff_jni_exception_check(env, 1, log_ctx)) < 0) {
goto done;
}
(*env)->CallVoidMethod(env, surface, method_id);
if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
ret = AVERROR_EXTERNAL;
}
(*env)->DeleteGlobalRef(env, surface);
done:
return ret;
}
int ff_Build_SDK_INT(AVCodecContext *avctx)
{
int ret = -1;
......
......@@ -96,6 +96,9 @@ FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name);
FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime_type);
FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime_type);
void* ff_AMediaCodec_createInputSurface(FFAMediaCodec* codec);
int ff_AMediaCodec_setInputSurface(FFAMediaCodec *codec, void *surface);
int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags);
int ff_AMediaCodec_start(FFAMediaCodec* codec);
int ff_AMediaCodec_stop(FFAMediaCodec* codec);
......@@ -126,6 +129,8 @@ int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec *codec);
int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec);
int ff_Surface_release(void *surface, void *log_ctx);
int ff_Build_SDK_INT(AVCodecContext *avctx);
#endif /* AVCODEC_MEDIACODEC_WRAPPER_H */
......@@ -47,7 +47,7 @@ typedef struct MediaCodecH264DecContext {
AVClass *avclass;
MediaCodecDecContext *ctx;
MediaCodecContext *ctx;
AVPacket buffered_pkt;
......@@ -382,7 +382,7 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
s->ctx = av_mallocz(sizeof(*s->ctx));
if (!s->ctx) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate MediaCodecDecContext\n");
av_log(avctx, AV_LOG_ERROR, "Failed to allocate MediaCodecContext\n");
ret = AVERROR(ENOMEM);
goto done;
}
......
......@@ -33,6 +33,7 @@
#include "avcodec.h"
#include "decode.h"
#include "encode.h"
#include "mediacodec.h"
#include "mediacodec_surface.h"
......@@ -194,7 +195,7 @@ static const struct {
};
static enum AVPixelFormat mcdec_map_color_format(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
int color_format)
{
int i;
......@@ -220,12 +221,12 @@ static enum AVPixelFormat mcdec_map_color_format(AVCodecContext *avctx,
return ret;
}
static void ff_mediacodec_dec_ref(MediaCodecDecContext *s)
static void ff_mediacodec_context_ref(MediaCodecContext *s)
{
atomic_fetch_add(&s->refcount, 1);
}
static void ff_mediacodec_dec_unref(MediaCodecDecContext *s)
static void ff_mediacodec_context_unref(MediaCodecContext *s)
{
if (!s)
return;
......@@ -247,6 +248,7 @@ static void ff_mediacodec_dec_unref(MediaCodecDecContext *s)
}
av_freep(&s->codec_name);
av_freep(&s->extradata);
av_freep(&s);
}
}
......@@ -254,7 +256,7 @@ static void ff_mediacodec_dec_unref(MediaCodecDecContext *s)
static void mediacodec_buffer_release(void *opaque, uint8_t *data)
{
AVMediaCodecBuffer *buffer = opaque;
MediaCodecDecContext *ctx = buffer->ctx;
MediaCodecContext *ctx = buffer->ctx;
int released = atomic_load(&buffer->released);
if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) {
......@@ -265,12 +267,14 @@ static void mediacodec_buffer_release(void *opaque, uint8_t *data)
ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, 0);
}
ff_mediacodec_dec_unref(ctx);
if (ctx->delay_flush)
ff_mediacodec_context_unref(ctx);
av_freep(&buffer);
}
static int mediacodec_wrap_hw_buffer(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
ssize_t index,
FFAMediaCodecBufferInfo *info,
AVFrame *frame)
......@@ -320,7 +324,12 @@ static int mediacodec_wrap_hw_buffer(AVCodecContext *avctx,
buffer->ctx = s;
buffer->serial = atomic_load(&s->serial);
<<<<<<< Updated upstream
ff_mediacodec_dec_ref(s);
=======
if (s->delay_flush)
ff_mediacodec_context_ref(s);
>>>>>>> Stashed changes
buffer->index = index;
buffer->pts = info->presentationTimeUs;
......@@ -346,7 +355,7 @@ fail:
}
static int mediacodec_wrap_sw_buffer(AVCodecContext *avctx,
MediaCodecDecContext *s,
MediaCodecContext *s,
uint8_t *data,
size_t size,
ssize_t index,
......@@ -434,7 +443,7 @@ done:
} \
} while (0) \
static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecContext *s)
static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecContext *s)
{
int ret = 0;
int width = 0;
......@@ -527,7 +536,7 @@ fail:
return ret;
}
static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContext *s)
static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecContext *s)
{
FFAMediaCodec *codec = s->codec;
int status;
......@@ -550,7 +559,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex
return 0;
}
int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s,
int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecContext *s,
const char *mime, FFAMediaFormat *format)
{
int ret = 0;
......@@ -651,7 +660,7 @@ fail:
return ret;
}
int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecContext *s,
AVPacket *pkt, bool wait)
{
int offset = 0;
......@@ -745,7 +754,7 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
return offset;
}
int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s,
int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecContext *s,
AVFrame *frame, bool wait)
{
int ret;
......@@ -856,6 +865,307 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s,
return AVERROR(EAGAIN);
}
//encoder
static int mediacodec_enc_parse_format(AVCodecContext *avctx, MediaCodecContext *s)
{
int ret = 0;
char *format = NULL;
if (!s->format) {
av_log(avctx, AV_LOG_ERROR, "Output MediaFormat is not set\n");
return AVERROR(EINVAL);
}
format = ff_AMediaFormat_toString(s->format);
if (!format) {
return AVERROR_EXTERNAL;
}
av_log(avctx, AV_LOG_DEBUG, "Parsing MediaFormat %s\n", format);
/* Mandatory fields */
AMEDIAFORMAT_GET_INT32(s->width, "width", 1);
AMEDIAFORMAT_GET_INT32(s->height, "height", 1);
AMEDIAFORMAT_GET_INT32(s->stride, "stride", 0);
s->stride = s->stride > 0 ? s->stride : s->width;
av_freep(&format);
return 0;
fail:
av_freep(&format);
return ret;
}
int ff_mediacodec_enc_init(AVCodecContext *avctx, MediaCodecContext *s,
const char *mime, FFAMediaFormat *format)
{
int ret = 0;
int status;
int profile;
enum AVPixelFormat pix_fmt;
static const enum AVPixelFormat pix_fmts[] = {
AV_PIX_FMT_MEDIACODEC,
AV_PIX_FMT_NONE,
};
s->avctx = avctx;
atomic_init(&s->refcount, 1);
s->initial_pts = -1;
profile = ff_AMediaCodecProfile_getProfileFromAVCodecContext(avctx);
if (profile < 0) {
av_log(avctx, AV_LOG_WARNING, "Unsupported or unknown profile\n");
}
s->codec_name = ff_AMediaCodecList_getCodecNameByType(mime, profile, 1, avctx);
if (!s->codec_name) {
av_log(avctx, AV_LOG_ERROR, "Could not find encoder for mime: %s\n", mime);
ret = AVERROR_EXTERNAL;
goto fail;
}
av_log(avctx, AV_LOG_DEBUG, "Found encoder %s\n", s->codec_name);
s->color_format = COLOR_FormatYUV420SemiPlanar;
pix_fmt = ff_get_format(avctx, pix_fmts);
if (pix_fmt == AV_PIX_FMT_MEDIACODEC) {
AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
if (device_ctx && device_ctx->type == AV_HWDEVICE_TYPE_MEDIACODEC && device_ctx->hwctx) {
s->color_format = COLOR_FormatAndroidOpaque;
}
}
ff_AMediaFormat_setInt32(format, "color-format", s->color_format);
s->codec = ff_AMediaCodec_createCodecByName(s->codec_name);
if (!s->codec) {
av_log(avctx, AV_LOG_ERROR, "Failed to create media decoder for type %s and name %s\n", mime, s->codec_name);
ret = AVERROR_EXTERNAL;
goto fail;
}
status = ff_AMediaCodec_configure(s->codec, format, NULL, NULL, 1);
if (status < 0) {
char *desc = ff_AMediaFormat_toString(format);
av_log(avctx, AV_LOG_ERROR,
"Failed to configure codec %s (status = %d) with format %s\n",
s->codec_name, status, desc);
av_freep(&desc);
ret = AVERROR_EXTERNAL;
goto fail;
}
if (s->color_format == COLOR_FormatAndroidOpaque) {
AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
AVMediaCodecDeviceContext *mediacodec_ctx = (AVMediaCodecDeviceContext *)device_ctx->hwctx;
if (mediacodec_ctx->surface == NULL) {
//save surface in the MediaCodecContext so it can be released codec is being closed.
s->surface = mediacodec_ctx->surface = ff_AMediaCodec_createInputSurface(s->codec);
av_log(avctx, AV_LOG_INFO, "Creating surface %p\n", s->surface);
} else {
ff_AMediaCodec_setInputSurface(s->codec, mediacodec_ctx->surface);
av_log(avctx, AV_LOG_INFO, "Setting surface %p\n", s->surface);
}
}
status = ff_AMediaCodec_start(s->codec);
if (status < 0) {
char *desc = ff_AMediaFormat_toString(format);
av_log(avctx, AV_LOG_ERROR,
"Failed to start codec %s (status = %d) with format %s\n",
s->codec_name, status, desc);
av_freep(&desc);
ret = AVERROR_EXTERNAL;
goto fail;
}
s->format = ff_AMediaCodec_getOutputFormat(s->codec);
if (s->format) {
if ((ret = mediacodec_enc_parse_format(avctx, s)) < 0) {
av_log(avctx, AV_LOG_ERROR,