Commit 207f4001 authored by Thomas Guillem's avatar Thomas Guillem

mediacodec: split mc_api functions

Split put_in into dequeue_in and queue_in.
Split get_out into dequeue_out and get_out
parent 894650f7
......@@ -757,10 +757,16 @@ static int PutInput(decoder_t *p_dec, block_t *p_block, mtime_t timeout)
i_ts = p_block->i_dts;
}
i_ret = p_sys->api->put_in(p_sys->api, p_buf, i_size, i_ts, b_config,
timeout);
if (i_ret != 1)
return i_ret;
i_ret = p_sys->api->dequeue_in(p_sys->api, timeout);
if (i_ret == MC_API_INFO_TRYAGAIN)
return 0;
else if (i_ret < 0)
return -1;
i_ret = p_sys->api->queue_in(p_sys->api, i_ret, p_buf, i_size, i_ts,
b_config);
if (i_ret != 0)
return -1;
if (p_sys->i_csd_send < p_sys->i_csd_count)
{
......@@ -786,7 +792,7 @@ static int Video_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
decoder_sys_t *p_sys = p_dec->p_sys;
mc_api_out out;
picture_t *p_pic = NULL;
int i_ret;
int i_ret = 0, i_index;
assert(pp_out_pic && !pp_out_block);
......@@ -818,7 +824,15 @@ static int Video_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
}
}
i_ret = p_sys->api->get_out(p_sys->api, &out, i_timeout);
i_index = p_sys->api->dequeue_out(p_sys->api, i_timeout);
if (i_index >= 0 || i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED
|| i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
i_ret = p_sys->api->get_out(p_sys->api, i_index, &out);
else if (i_index == MC_API_INFO_TRYAGAIN)
i_ret = 0;
else
i_ret = -1;
if (i_ret != 1)
goto end;
......@@ -955,12 +969,21 @@ static int Audio_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
{
decoder_sys_t *p_sys = p_dec->p_sys;
mc_api_out out;
int i_ret;
int i_ret, i_index;
(void) p_abort;
assert(!pp_out_pic && pp_out_block);
i_ret = p_sys->api->get_out(p_sys->api, &out, i_timeout);
i_index = p_sys->api->dequeue_out(p_sys->api, i_timeout);
if (i_index >= 0 || i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED
|| i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
i_ret = p_sys->api->get_out(p_sys->api, i_index, &out);
else if (i_index == MC_API_INFO_TRYAGAIN)
i_ret = 0;
else
i_ret = -1;
if (i_ret != 1)
return i_ret;
......
......@@ -35,6 +35,11 @@ char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
int MediaCodecJni_Init(mc_api*);
int MediaCodecNdk_Init(mc_api*);
#define MC_API_ERROR (-1)
#define MC_API_INFO_TRYAGAIN (-11)
#define MC_API_INFO_OUTPUT_FORMAT_CHANGED (-12)
#define MC_API_INFO_OUTPUT_BUFFERS_CHANGED (-13)
struct mc_api_out
{
enum {
......@@ -105,9 +110,27 @@ struct mc_api
union mc_api_args *p_args);
int (*stop)(mc_api *);
int (*flush)(mc_api *);
int (*put_in)(mc_api *, const void *p_buf, size_t i_size,
mtime_t i_ts, bool b_config, mtime_t i_timeout);
int (*get_out)(mc_api *, mc_api_out *p_out, mtime_t i_timeout);
/* The Dequeue functions return:
* - The index of the input or output buffer if >= 0,
* - MC_API_INFO_TRYAGAIN if no buffers where dequeued during i_timeout,
* - MC_API_INFO_OUTPUT_FORMAT_CHANGED if output format changed
* - MC_API_INFO_OUTPUT_BUFFERS_CHANGED if buffers changed
* - MC_API_ERROR in case of error. */
int (*dequeue_in)(mc_api *, mtime_t i_timeout);
int (*dequeue_out)(mc_api *, mtime_t i_timeout);
/* i_index is the index returned by dequeue_in and should be >= 0
* Returns 0 if buffer is successfully queued, or MC_API_ERROR */
int (*queue_in)(mc_api *, int i_index, const void *p_buf, size_t i_size,
mtime_t i_ts, bool b_config);
/* i_index is the index returned by dequeue_out and should be >= 0,
* MC_API_INFO_OUTPUT_FORMAT_CHANGED, or MC_API_INFO_OUTPUT_BUFFERS_CHANGED.
* Returns 1 if p_out if valid, 0 if p_out is unchanged or MC_API_ERROR */
int (*get_out)(mc_api *, int i_index, mc_api_out *p_out);
/* i_index is the index returned by dequeue_out and should be >= 0 */
int (*release_out)(mc_api *, int i_index, bool b_render);
};
......
......@@ -165,7 +165,7 @@ static inline bool check_exception(JNIEnv *env)
return false;
}
#define CHECK_EXCEPTION() check_exception( env )
#define GET_ENV() if (!(env = android_getEnv(api->p_obj, THREAD_NAME))) return VLC_EGENERIC;
#define GET_ENV() if (!(env = android_getEnv(api->p_obj, THREAD_NAME))) return MC_API_ERROR;
static inline int get_integer(JNIEnv *env, jobject obj, const char *psz_name)
{
......@@ -461,7 +461,7 @@ static int Stop(mc_api *api)
p_sys->buffer_info = NULL;
}
msg_Dbg(api->p_obj, "MediaCodec via JNI closed");
return VLC_SUCCESS;
return 0;
}
/*****************************************************************************
......@@ -472,7 +472,7 @@ static int Start(mc_api *api, const char *psz_name, const char *psz_mime,
{
mc_api_sys *p_sys = api->p_sys;
JNIEnv* env = NULL;
int i_ret = VLC_EGENERIC;
int i_ret = MC_API_ERROR;
bool b_direct_rendering = false;
jstring jmime = NULL;
jstring jcodec_name = NULL;
......@@ -600,7 +600,7 @@ static int Start(mc_api *api, const char *psz_name, const char *psz_mime,
p_sys->buffer_info = (*env)->NewGlobalRef(env, jbuffer_info);
api->b_direct_rendering = b_direct_rendering;
i_ret = VLC_SUCCESS;
i_ret = 0;
msg_Dbg(api->p_obj, "MediaCodec via JNI opened");
error:
......@@ -621,7 +621,7 @@ error:
if (jbuffer_info)
(*env)->DeleteLocalRef(env, jbuffer_info);
if (i_ret != VLC_SUCCESS)
if (i_ret != 0)
Stop(api);
return i_ret;
}
......@@ -640,48 +640,64 @@ static int Flush(mc_api *api)
if (CHECK_EXCEPTION())
{
msg_Warn(api->p_obj, "Exception occurred in MediaCodec.flush");
return VLC_EGENERIC;
return MC_API_ERROR;
}
return VLC_SUCCESS;
return 0;
}
/*****************************************************************************
* PutInput
* DequeueInput
*****************************************************************************/
static int PutInput(mc_api *api, const void *p_buf, size_t i_size,
mtime_t i_ts, bool b_config, mtime_t i_timeout)
static int DequeueInput(mc_api *api, mtime_t i_timeout)
{
mc_api_sys *p_sys = api->p_sys;
JNIEnv *env;
int index;
uint8_t *p_mc_buf;
jobject j_mc_buf;
jsize j_mc_size;
jint jflags = b_config ? BUFFER_FLAG_CODEC_CONFIG : 0;
int i_index;
GET_ENV();
index = (*env)->CallIntMethod(env, p_sys->codec,
jfields.dequeue_input_buffer, i_timeout);
i_index = (*env)->CallIntMethod(env, p_sys->codec,
jfields.dequeue_input_buffer, i_timeout);
if (CHECK_EXCEPTION())
{
msg_Err(api->p_obj, "Exception occurred in MediaCodec.dequeueInputBuffer");
return VLC_EGENERIC;
return MC_API_ERROR;
}
if (index < 0)
return 0;
if (i_index >= 0)
return i_index;
else
return MC_API_INFO_TRYAGAIN;
}
/*****************************************************************************
* QueueInput
*****************************************************************************/
static int QueueInput(mc_api *api, int i_index, const void *p_buf,
size_t i_size, mtime_t i_ts, bool b_config)
{
mc_api_sys *p_sys = api->p_sys;
JNIEnv *env;
uint8_t *p_mc_buf;
jobject j_mc_buf;
jsize j_mc_size;
jint jflags = b_config ? BUFFER_FLAG_CODEC_CONFIG : 0;
assert(i_index >= 0);
GET_ENV();
if (jfields.get_input_buffers)
j_mc_buf = (*env)->GetObjectArrayElement(env, p_sys->input_buffers,
index);
i_index);
else
{
j_mc_buf = (*env)->CallObjectMethod(env, p_sys->codec,
jfields.get_input_buffer, index);
jfields.get_input_buffer, i_index);
if (CHECK_EXCEPTION())
{
msg_Err(api->p_obj, "Exception in MediaCodec.getInputBuffer");
return VLC_EGENERIC;
return MC_API_ERROR;
}
}
j_mc_size = (*env)->GetDirectBufferCapacity(env, j_mc_buf);
......@@ -690,28 +706,28 @@ static int PutInput(mc_api *api, const void *p_buf, size_t i_size,
{
msg_Err(api->p_obj, "Java buffer has invalid size");
(*env)->DeleteLocalRef(env, j_mc_buf);
return VLC_EGENERIC;
return MC_API_ERROR;
}
if ((size_t) j_mc_size > i_size)
j_mc_size = i_size;
memcpy(p_mc_buf, p_buf, j_mc_size);
(*env)->CallVoidMethod(env, p_sys->codec, jfields.queue_input_buffer,
index, 0, j_mc_size, i_ts, jflags);
i_index, 0, j_mc_size, i_ts, jflags);
(*env)->DeleteLocalRef(env, j_mc_buf);
if (CHECK_EXCEPTION())
{
msg_Err(api->p_obj, "Exception in MediaCodec.queueInputBuffer");
return VLC_EGENERIC;
return MC_API_ERROR;
}
return 1;
return 0;
}
/*****************************************************************************
* GetOutput
* DequeueOutput
*****************************************************************************/
static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
static int DequeueOutput(mc_api *api, mtime_t i_timeout)
{
mc_api_sys *p_sys = api->p_sys;
JNIEnv *env;
......@@ -724,8 +740,27 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
if (CHECK_EXCEPTION())
{
msg_Err(api->p_obj, "Exception in MediaCodec.dequeueOutputBuffer");
return VLC_EGENERIC;
return MC_API_ERROR;
}
if (i_index >= 0)
return i_index;
else if (i_index == INFO_OUTPUT_FORMAT_CHANGED)
return MC_API_INFO_OUTPUT_FORMAT_CHANGED;
else if (i_index == INFO_OUTPUT_BUFFERS_CHANGED)
return MC_API_INFO_OUTPUT_BUFFERS_CHANGED;
else
return MC_API_INFO_TRYAGAIN;
}
/*****************************************************************************
* GetOutput
*****************************************************************************/
static int GetOutput(mc_api *api, int i_index, mc_api_out *p_out)
{
mc_api_sys *p_sys = api->p_sys;
JNIEnv *env;
GET_ENV();
if (i_index >= 0)
{
......@@ -756,7 +791,7 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
if (CHECK_EXCEPTION())
{
msg_Err(api->p_obj, "Exception in MediaCodec.getOutputBuffer");
return VLC_EGENERIC;
return MC_API_ERROR;
}
}
//jsize buf_size = (*env)->GetDirectBufferCapacity(env, buf);
......@@ -770,8 +805,7 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
(*env)->DeleteLocalRef(env, buf);
}
return 1;
}
else if (i_index == INFO_OUTPUT_FORMAT_CHANGED)
} else if (i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED)
{
jobject format = NULL;
jobject format_string = NULL;
......@@ -783,7 +817,7 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
if (CHECK_EXCEPTION())
{
msg_Err(api->p_obj, "Exception in MediaCodec.getOutputFormat");
return VLC_EGENERIC;
return MC_API_ERROR;
}
format_string = (*env)->CallObjectMethod(env, format, jfields.tostring);
......@@ -817,7 +851,7 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
(*env)->DeleteLocalRef(env, format);
return 1;
}
else if (i_index == INFO_OUTPUT_BUFFERS_CHANGED)
else if (i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
{
jobject joutput_buffers;
......@@ -832,7 +866,7 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
{
msg_Err(api->p_obj, "Exception in MediaCodec.getOutputBuffer");
p_sys->output_buffers = NULL;
return VLC_EGENERIC;
return MC_API_ERROR;
}
p_sys->output_buffers = (*env)->NewGlobalRef(env, joutput_buffers);
(*env)->DeleteLocalRef(env, joutput_buffers);
......@@ -848,6 +882,8 @@ static int ReleaseOutput(mc_api *api, int i_index, bool b_render)
mc_api_sys *p_sys = api->p_sys;
JNIEnv *env;
assert(i_index >= 0);
GET_ENV();
(*env)->CallVoidMethod(env, p_sys->codec, jfields.release_output_buffer,
......@@ -855,9 +891,9 @@ static int ReleaseOutput(mc_api *api, int i_index, bool b_render)
if (CHECK_EXCEPTION())
{
msg_Err(api->p_obj, "Exception in MediaCodec.releaseOutputBuffer");
return VLC_EGENERIC;
return MC_API_ERROR;
}
return VLC_SUCCESS;
return 0;
}
/*****************************************************************************
......@@ -878,22 +914,24 @@ int MediaCodecJni_Init(mc_api *api)
GET_ENV();
if (!InitJNIFields(api->p_obj, env))
return VLC_EGENERIC;
return MC_API_ERROR;
api->p_sys = calloc(1, sizeof(mc_api_sys));
if (!api->p_sys)
return VLC_EGENERIC;
return MC_API_ERROR;
api->clean = Clean;
api->start = Start;
api->stop = Stop;
api->flush = Flush;
api->put_in = PutInput;
api->dequeue_in = DequeueInput;
api->queue_in = QueueInput;
api->dequeue_out = DequeueOutput;
api->get_out = GetOutput;
api->release_out = ReleaseOutput;
/* Allow interlaced picture only after API 21 */
api->b_support_interlaced = jfields.get_input_buffer
&& jfields.get_output_buffer;
return VLC_SUCCESS;
return 0;
}
......@@ -262,6 +262,7 @@ struct mc_api_sys
{
AMediaCodec* p_codec;
AMediaFormat* p_format;
AMediaCodecBufferInfo info;
};
/*****************************************************************************
......@@ -290,7 +291,7 @@ static int Stop(mc_api *api)
}
msg_Dbg(api->p_obj, "MediaCodec via NDK closed");
return VLC_SUCCESS;
return 0;
}
/*****************************************************************************
......@@ -300,7 +301,7 @@ static int Start(mc_api *api, const char *psz_name, const char *psz_mime,
union mc_api_args *p_args)
{
mc_api_sys *p_sys = api->p_sys;
int i_ret = VLC_EGENERIC;
int i_ret = MC_API_ERROR;
ANativeWindow *p_anw = NULL;
p_sys->p_codec = syms.AMediaCodec.createCodecByName(psz_name);
......@@ -348,11 +349,11 @@ static int Start(mc_api *api, const char *psz_name, const char *psz_mime,
api->b_started = true;
api->b_direct_rendering = !!p_anw;
i_ret = VLC_SUCCESS;
i_ret = 0;
msg_Dbg(api->p_obj, "MediaCodec via NDK opened");
error:
if (i_ret != VLC_SUCCESS)
if (i_ret != 0)
Stop(api);
return i_ret;
}
......@@ -365,39 +366,48 @@ static int Flush(mc_api *api)
mc_api_sys *p_sys = api->p_sys;
if (syms.AMediaCodec.flush(p_sys->p_codec) == AMEDIA_OK)
return VLC_SUCCESS;
return 0;
else
return VLC_EGENERIC;
return MC_API_ERROR;
}
/*****************************************************************************
* PutInput
* DequeueInput
*****************************************************************************/
static int PutInput(mc_api *api, const void *p_buf, size_t i_size,
mtime_t i_ts, bool b_config, mtime_t i_timeout)
static int DequeueInput(mc_api *api, mtime_t i_timeout)
{
mc_api_sys *p_sys = api->p_sys;
ssize_t i_index;
uint8_t *p_mc_buf;
size_t i_mc_size;
int i_flags = b_config ? AMEDIACODEC_FLAG_CODEC_CONFIG : 0;
i_index = syms.AMediaCodec.dequeueInputBuffer(p_sys->p_codec, i_timeout);
if (i_index < 0)
if (i_index >= 0)
return i_index;
else if (i_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
return MC_API_INFO_TRYAGAIN;
else
{
if (i_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
return 0;
else
{
msg_Err(api->p_obj, "AMediaCodec.dequeueInputBuffer failed");
return VLC_EGENERIC;
}
msg_Err(api->p_obj, "AMediaCodec.dequeueInputBuffer failed");
return MC_API_ERROR;
}
}
/*****************************************************************************
* QueueInput
*****************************************************************************/
static int QueueInput(mc_api *api, int i_index, const void *p_buf,
size_t i_size, mtime_t i_ts, bool b_config)
{
mc_api_sys *p_sys = api->p_sys;
uint8_t *p_mc_buf;
size_t i_mc_size;
int i_flags = b_config ? AMEDIACODEC_FLAG_CODEC_CONFIG : 0;
assert(i_index >= 0);
p_mc_buf = syms.AMediaCodec.getInputBuffer(p_sys->p_codec,
i_index, &i_mc_size);
if (!p_mc_buf)
return VLC_EGENERIC;
return MC_API_ERROR;
if (i_mc_size > i_size)
i_mc_size = i_size;
......@@ -405,11 +415,11 @@ static int PutInput(mc_api *api, const void *p_buf, size_t i_size,
if (syms.AMediaCodec.queueInputBuffer(p_sys->p_codec, i_index, 0, i_mc_size,
i_ts, i_flags) == AMEDIA_OK)
return 1;
return 0;
else
{
msg_Err(api->p_obj, "AMediaCodec.queueInputBuffer failed");
return VLC_EGENERIC;
return MC_API_ERROR;
}
}
......@@ -421,22 +431,44 @@ static int32_t GetFormatInteger(AMediaFormat *p_format, const char *psz_name)
}
/*****************************************************************************
* GetOutput
* DequeueOutput
*****************************************************************************/
static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
static int DequeueOutput(mc_api *api, mtime_t i_timeout)
{
mc_api_sys *p_sys = api->p_sys;
AMediaCodecBufferInfo info;
ssize_t i_index;
i_index = syms.AMediaCodec.dequeueOutputBuffer(p_sys->p_codec, &info,
i_index = syms.AMediaCodec.dequeueOutputBuffer(p_sys->p_codec, &p_sys->info,
i_timeout);
if (i_index >= 0)
return i_index;
else if (i_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
return MC_API_INFO_TRYAGAIN;
else if (i_index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)
return MC_API_INFO_OUTPUT_BUFFERS_CHANGED;
else if (i_index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
return MC_API_INFO_OUTPUT_FORMAT_CHANGED;
else
{
msg_Err(api->p_obj, "AMediaCodec.dequeueOutputBuffer failed");
return MC_API_ERROR;
}
}
/*****************************************************************************
* GetOutput
*****************************************************************************/
static int GetOutput(mc_api *api, int i_index, mc_api_out *p_out)
{
mc_api_sys *p_sys = api->p_sys;
if (i_index >= 0)
{
p_out->type = MC_OUT_TYPE_BUF;
p_out->u.buf.i_index = i_index;
p_out->u.buf.i_ts = info.presentationTimeUs;
p_out->u.buf.i_ts = p_sys->info.presentationTimeUs;
if (api->b_direct_rendering)
{
......@@ -452,14 +484,14 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
if (!p_mc_buf)
{
msg_Err(api->p_obj, "AMediaCodec.getOutputBuffer failed");
return VLC_EGENERIC;
return MC_API_ERROR;
}
p_out->u.buf.p_ptr = p_mc_buf + info.offset;
p_out->u.buf.i_size = info.size;
p_out->u.buf.p_ptr = p_mc_buf + p_sys->info.offset;
p_out->u.buf.i_size = p_sys->info.size;
}
return 1;
}
else if (i_index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
else if (i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED)
{
AMediaFormat *format = syms.AMediaCodec.getOutputFormat(p_sys->p_codec);
......@@ -484,16 +516,7 @@ static int GetOutput(mc_api *api, mc_api_out *p_out, mtime_t i_timeout)
}
return 1;
}
else if (i_index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED
|| i_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
{
return 0;
}
else
{
msg_Err(api->p_obj, "AMediaCodec.dequeueOutputBuffer failed");
return VLC_EGENERIC;
}
return 0;
}
/*****************************************************************************
......@@ -503,11 +526,12 @@ static int ReleaseOutput(mc_api *api, int i_index, bool b_render)
{
mc_api_sys *p_sys = api->p_sys;
assert(i_index >= 0);
if (syms.AMediaCodec.releaseOutputBuffer(p_sys->p_codec, i_index, b_render)
== AMEDIA_OK)
return VLC_SUCCESS;
return 0;
else
return VLC_EGENERIC;
return MC_API_ERROR;
}
......@@ -525,20 +549,22 @@ static void Clean(mc_api *api)
int MediaCodecNdk_Init(mc_api *api)
{
if (!InitSymbols(api))
return VLC_EGENERIC;
return MC_API_ERROR;
api->p_sys = calloc(1, sizeof(mc_api_sys));
if (!api->p_sys)
return VLC_EGENERIC;