Commit 3a4fb831 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"
......@@ -3252,6 +3255,7 @@ vc1_qsv_decoder_select="qsvdec"
vc1_v4l2m2m_decoder_deps="v4l2_m2m vc1_v4l2_m2m"
vp8_cuvid_decoder_deps="cuvid"
vp8_mediacodec_decoder_deps="mediacodec"
vp8_mediacodec_encoder_deps="mediacodec"
vp8_qsv_decoder_select="qsvdec"
vp8_rkmpp_decoder_deps="rkmpp"
vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8"
......@@ -3260,6 +3264,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"
......
......@@ -122,7 +122,7 @@ OBJS-$(CONFIG_LSP) += lsp.o
OBJS-$(CONFIG_LZF) += lzf.o
OBJS-$(CONFIG_MDCT) += mdct_float.o mdct_fixed_32.o
OBJS-$(CONFIG_ME_CMP) += me_cmp.o
OBJS-$(CONFIG_MEDIACODEC) += mediacodecdec_common.o mediacodec_surface.o mediacodec_wrapper.o mediacodec_sw_buffer.o
OBJS-$(CONFIG_MEDIACODEC) += mediacodec_common.o mediacodec_surface.o mediacodec_wrapper.o mediacodec_sw_buffer.o
OBJS-$(CONFIG_MPEG_ER) += mpeg_er.o
OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodec_common.o \
mpegaudiodata.o
......@@ -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
......@@ -745,6 +748,7 @@ OBJS-$(CONFIG_VP7_DECODER) += vp8.o vpx_rac.o
OBJS-$(CONFIG_VP8_DECODER) += vp8.o vpx_rac.o
OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_VP8_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec.o
OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o
OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o
......@@ -755,6 +759,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
......@@ -1249,7 +1254,7 @@ SKIPHEADERS-$(CONFIG_LIBAOM) += libaom.h
SKIPHEADERS-$(CONFIG_LIBJXL) += libjxl.h
SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h
SKIPHEADERS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.h
SKIPHEADERS-$(CONFIG_MEDIACODEC) += mediacodecdec_common.h mediacodec_surface.h mediacodec_wrapper.h mediacodec_sw_buffer.h
SKIPHEADERS-$(CONFIG_MEDIACODEC) += mediacodec_common.h mediacodec_surface.h mediacodec_wrapper.h mediacodec_sw_buffer.h
SKIPHEADERS-$(CONFIG_MEDIAFOUNDATION) += mf_utils.h
SKIPHEADERS-$(CONFIG_NVDEC) += nvdec.h
SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h
......
......@@ -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;
......@@ -866,11 +869,13 @@ extern const FFCodec ff_prores_videotoolbox_encoder;
extern const FFCodec ff_vc1_cuvid_decoder;
extern const FFCodec ff_vp8_cuvid_decoder;
extern const FFCodec ff_vp8_mediacodec_decoder;
extern const FFCodec ff_vp8_mediacodec_encoder;
extern const FFCodec ff_vp8_qsv_decoder;
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;
......
......@@ -34,7 +34,7 @@
#include "libavutil/mem.h"
#include "ffjni.h"
#include "mediacodecdec_common.h"
#include "mediacodec_common.h"
AVMediaCodecContext *av_mediacodec_alloc_context(void)
{
......@@ -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))) {
......
/*
* Android MediaCodec decoder
* Android MediaCodec decoder / encoder
*
* Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
*
......@@ -33,12 +33,13 @@
#include "avcodec.h"
#include "decode.h"
#include "encode.h"
#include "mediacodec.h"
#include "mediacodec_surface.h"
#include "mediacodec_sw_buffer.h"
#include "mediacodec_wrapper.h"
#include "mediacodecdec_common.h"
#include "mediacodec_common.h"
/**
* OMX.k3.video.decoder.avc, OMX.NVIDIA.* OMX.SEC.avc.dec and OMX.google
......@@ -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,13 @@ 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 +323,8 @@ static int mediacodec_wrap_hw_buffer(AVCodecContext *avctx,
buffer->ctx = s;
buffer->serial = atomic_load(&s->serial);
ff_mediacodec_dec_ref(s);
if (s->delay_flush)
ff_mediacodec_context_ref(s);
buffer->index = index;
buffer->pts = info->presentationTimeUs;
......@@ -346,7 +350,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 +438,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 +531,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 +554,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 +655,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 +749,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 +860,309 @@ 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;
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) {
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) {
AVMediaCodecContext *user_ctx = avctx->hwaccel_context;
if (avctx->hw_device_ctx) {
AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
if (device_ctx->type == AV_HWDEVICE_TYPE_MEDIACODEC && device_ctx->hwctx) {
AVMediaCodecDeviceContext *mediacodec_ctx = (AVMediaCodecDeviceContext *)device_ctx->hwctx;
if (mediacodec_ctx->surface) {
s->surface = ff_mediacodec_surface_ref(mediacodec_ctx->surface, avctx);
ff_AMediaCodec_setInputSurface(s->codec, mediacodec_ctx->surface);
av_log(avctx, AV_LOG_INFO, "Setting surface %p\n", mediacodec_ctx->surface);
}
}
}
if (!s->surface && user_ctx && user_ctx->surface) {
s->surface = ff_mediacodec_surface_ref(user_ctx->surface, avctx);
ff_AMediaCodec_setInputSurface(s->codec, user_ctx->surface);
av_log(avctx, AV_LOG_INFO, "Setting surface %p\n", user_ctx->surface);
}
if (!s->surface) {
av_log(avctx, AV_LOG_ERROR, "No input surface provided\n");
ret = AVERROR_EXTERNAL;
goto fail;
}
}
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,
"Failed to configure context\n");
goto fail;
}
}
av_log(avctx, AV_LOG_DEBUG, "MediaCodec %p started successfully\n", s->codec);
return 0;
fail:
av_log(avctx, AV_LOG_ERROR, "MediaCodec %p failed to start\n", s->codec);
ff_mediacodec_enc_close(avctx, s);
return ret;
}
int ff_mediacodec_enc_send(AVCodecContext *avctx,
MediaCodecContext *s,
const AVFrame* frame)
{
size_t bufsize;
ssize_t index;
if (s->color_format == COLOR_FormatAndroidOpaque) {
return 0;
}
index = ff_AMediaCodec_dequeueInputBuffer(s->codec, INPUT_DEQUEUE_TIMEOUT_US);
if (index >= 0) {
size_t insize = (avctx->width * avctx->height) * 3 / 2;
uint8_t *buf = ff_AMediaCodec_getInputBuffer(s->codec, index, &bufsize);
if(buf) {
ff_mediacodec_copy_yuv420_semi_planar_to_semi_planar(avctx, s, frame, buf);
} else {
av_log(avctx, AV_LOG_TRACE, "ff_AMediaCodec_getInputBuffer returned NULL for index: %zd.\n", index);
}
ff_AMediaCodec_queueInputBuffer(s->codec, index, 0, insize, frame->pts, 0);
} else {
if (ff_AMediaCodec_infoTryAgainLater(s->codec, index)) {
av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n");
return AVERROR(EAGAIN);
} else {
av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index);
return AVERROR_EXTERNAL;
}
}
return 0;
}
int ff_mediacodec_enc_receive(AVCodecContext* avctx,
MediaCodecContext *s,
AVPacket* pkt,
int *got_packet)
{
uint8_t *buf = NULL;
size_t bufsize;
FFAMediaCodecBufferInfo info;
int status = 0;
int ret;
ssize_t index = ff_AMediaCodec_dequeueOutputBuffer(s->codec, &info, OUTPUT_DEQUEUE_TIMEOUT_US);
if (ff_AMediaCodec_infoOutputFormatChanged(s->codec, index)) {
char *format = NULL;
if (s->format) {
status = ff_AMediaFormat_delete(s->format);
if (status < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to delete MediaFormat %p\n", s->format);
}
}
s->format = ff_AMediaCodec_getOutputFormat(s->codec);
if (!s->format) {
av_log(avctx, AV_LOG_ERROR, "Failed to get output format\n");
return AVERROR_EXTERNAL;
}
format = ff_AMediaFormat_toString(s->format);
if (!format) {
return AVERROR_EXTERNAL;
}
av_log(avctx, AV_LOG_INFO, "Output MediaFormat changed to %s\n", format);
av_freep(&format);
if ((ret = mediacodec_enc_parse_format(avctx, s)) < 0) {
return ret;
}
} else if (ff_AMediaCodec_infoOutputBuffersChanged(s->codec, index)) {
av_log(avctx, AV_LOG_INFO, "media codec info output buffers changed\n");
ff_AMediaCodec_cleanOutputBuffers(s->codec);
} else if (ff_AMediaCodec_infoTryAgainLater(s->codec, index)) {
av_log(avctx, AV_LOG_TRACE, "No output buffer available, try again later\n");
} else if (index < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to dequeue output buffer (status=%zd)\n", index);
return AVERROR_EXTERNAL;
}
while (index >= 0) {
av_log(avctx, AV_LOG_TRACE, "Got output buffer %zd"
" offset=%" PRIi32 " size=%" PRIi32 " ts=%" PRIi64
" flags=%" PRIu32 "\n", index, info.offset, info.size,
info.presentationTimeUs, info.flags);
buf = ff_AMediaCodec_getOutputBuffer(s->codec, index, &bufsize);
if (info.flags & ff_AMediaCodec_getBufferFlagCodecConfig(s->codec)) {
av_log(avctx, AV_LOG_INFO, "codec config data: %d\n", info.size);
if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
if (!avctx->extradata) {
avctx->extradata = av_memdup(buf, info.size);
if (!avctx->extradata) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for codec config\n");
ff_AMediaCodec_releaseOutputBuffer(s->codec, index, false);
return AVERROR(ENOMEM);
}
avctx->extradata_size = info.size;
}
if (avctx->codec_id == AV_CODEC_ID_H264 ||
avctx->codec_id == AV_CODEC_ID_HEVC) {
s->extradata = av_memdup(buf, info.size);
if (!s->extradata) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for codec config\n");
ff_AMediaCodec_releaseOutputBuffer(s->codec, index, false);
return AVERROR(ENOMEM);
}
s->extradata_size = info.size;
}
}
} else {
int ret = ff_get_encode_buffer(avctx, pkt, info.size + s->extradata_size, 0);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "ff_get_encode_buffer failed with error: %d\n", ret);
ff_AMediaCodec_releaseOutputBuffer(s->codec, index, false);
return ret;
}
if (s->extradata) {
memcpy(pkt->data, s->extradata, s->extradata_size);
memcpy(pkt->data + s->extradata_size, buf, info.size);
s->extradata_size = 0;
av_freep(&s->extradata);
} else {
memcpy(pkt->data, buf, info.size);
}
if (s->color_format == COLOR_FormatAndroidOpaque) {
int64_t pts;
AVRational time_base = (AVRational){1, 1000000};
if (s->initial_pts == -1) {
s->initial_pts = info.presentationTimeUs;
}
pts = info.presentationTimeUs - s->initial_pts;
pkt->pts = pkt->dts = av_rescale_q(pts, time_base, avctx->time_base);
} else {
pkt->pts = pkt->dts = info.presentationTimeUs;
}
pkt->flags = (info.flags & ff_AMediaCodec_getBufferFlagKeyFrame(s->codec)) ? AV_PKT_FLAG_KEY : 0;
*got_packet = 1;
ff_AMediaCodec_releaseOutputBuffer(s->codec, index, false);
return 0;
}
index = ff_AMediaCodec_dequeueOutputBuffer(s->codec, &info, OUTPUT_DEQUEUE_TIMEOUT_US);
}
return AVERROR(EAGAIN);
}
int ff_mediacodec_enc_close(AVCodecContext *avctx, MediaCodecContext *s)
{
ff_mediacodec_context_unref(s);
return 0;
}
/*
* ff_mediacodec_dec_flush returns 0 if the flush cannot be performed on
* the codec (because the user retains frames). The codec stays in the
......@@ -868,7 +1175,7 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s,
* ff_mediacodec_dec_flush returns a negative value if an error has
* occurred.
*/
int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s)
int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecContext *s)
{
if (!s->surface || !s->delay_flush || atomic_load(&s->refcount) == 1) {