mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
androidmedia: Conditionally use get_{input,output}_buffer() Android 21 APIs
Also properly set limit/position on byte buffer, some codecs prefer to have correct values there.
This commit is contained in:
parent
360f0be2a8
commit
a6fb482247
10 changed files with 623 additions and 316 deletions
|
@ -72,7 +72,9 @@ static struct
|
|||
jmethodID dequeue_output_buffer;
|
||||
jmethodID flush;
|
||||
jmethodID get_input_buffers;
|
||||
jmethodID get_input_buffer;
|
||||
jmethodID get_output_buffers;
|
||||
jmethodID get_output_buffer;
|
||||
jmethodID get_output_format;
|
||||
jmethodID queue_input_buffer;
|
||||
jmethodID release;
|
||||
|
@ -106,6 +108,11 @@ static struct
|
|||
jmethodID set_byte_buffer;
|
||||
} media_format;
|
||||
|
||||
static GstAmcBuffer *gst_amc_codec_get_input_buffers (GstAmcCodec * codec,
|
||||
gsize * n_buffers, GError ** err);
|
||||
static GstAmcBuffer *gst_amc_codec_get_output_buffers (GstAmcCodec * codec,
|
||||
gsize * n_buffers, GError ** err);
|
||||
|
||||
GstAmcCodec *
|
||||
gst_amc_codec_new (const gchar * name, GError ** err)
|
||||
{
|
||||
|
@ -160,6 +167,19 @@ gst_amc_codec_free (GstAmcCodec * codec)
|
|||
g_return_if_fail (codec != NULL);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (codec->input_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->input_buffers,
|
||||
codec->n_input_buffers);
|
||||
codec->input_buffers = NULL;
|
||||
codec->n_input_buffers = 0;
|
||||
|
||||
if (codec->output_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->output_buffers,
|
||||
codec->n_output_buffers);
|
||||
codec->output_buffers = NULL;
|
||||
codec->n_output_buffers = 0;
|
||||
|
||||
gst_amc_jni_object_unref (env, codec->object);
|
||||
g_slice_free (GstAmcCodec, codec);
|
||||
}
|
||||
|
@ -212,12 +232,29 @@ gboolean
|
|||
gst_amc_codec_start (GstAmcCodec * codec, GError ** err)
|
||||
{
|
||||
JNIEnv *env;
|
||||
gboolean ret;
|
||||
|
||||
g_return_val_if_fail (codec != NULL, FALSE);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
return gst_amc_jni_call_void_method (env, err, codec->object,
|
||||
ret = gst_amc_jni_call_void_method (env, err, codec->object,
|
||||
media_codec.start);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
if (!media_codec.get_input_buffer) {
|
||||
if (codec->input_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->input_buffers,
|
||||
codec->n_input_buffers);
|
||||
codec->input_buffers =
|
||||
gst_amc_codec_get_input_buffers (codec, &codec->n_input_buffers, err);
|
||||
if (!codec->input_buffers) {
|
||||
gst_amc_codec_stop (codec, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -228,6 +265,19 @@ gst_amc_codec_stop (GstAmcCodec * codec, GError ** err)
|
|||
g_return_val_if_fail (codec != NULL, FALSE);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (codec->input_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->input_buffers,
|
||||
codec->n_input_buffers);
|
||||
codec->input_buffers = NULL;
|
||||
codec->n_input_buffers = 0;
|
||||
|
||||
if (codec->output_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->output_buffers,
|
||||
codec->n_output_buffers);
|
||||
codec->output_buffers = NULL;
|
||||
codec->n_output_buffers = 0;
|
||||
|
||||
return gst_amc_jni_call_void_method (env, err, codec->object,
|
||||
media_codec.stop);
|
||||
}
|
||||
|
@ -252,11 +302,24 @@ gst_amc_codec_release (GstAmcCodec * codec, GError ** err)
|
|||
g_return_val_if_fail (codec != NULL, FALSE);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (codec->input_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->input_buffers,
|
||||
codec->n_input_buffers);
|
||||
codec->input_buffers = NULL;
|
||||
codec->n_input_buffers = 0;
|
||||
|
||||
if (codec->output_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->output_buffers,
|
||||
codec->n_output_buffers);
|
||||
codec->output_buffers = NULL;
|
||||
codec->n_output_buffers = 0;
|
||||
|
||||
return gst_amc_jni_call_void_method (env, err, codec->object,
|
||||
media_codec.release);
|
||||
}
|
||||
|
||||
GstAmcBuffer *
|
||||
static GstAmcBuffer *
|
||||
gst_amc_codec_get_output_buffers (GstAmcCodec * codec, gsize * n_buffers,
|
||||
GError ** err)
|
||||
{
|
||||
|
@ -284,6 +347,55 @@ done:
|
|||
}
|
||||
|
||||
GstAmcBuffer *
|
||||
gst_amc_codec_get_output_buffer (GstAmcCodec * codec, gint index, GError ** err)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jobject buffer = NULL;
|
||||
GstAmcBuffer *ret = NULL;
|
||||
|
||||
g_return_val_if_fail (codec != NULL, NULL);
|
||||
g_return_val_if_fail (index >= 0, NULL);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (!media_codec.get_output_buffer) {
|
||||
g_return_val_if_fail (index < codec->n_output_buffers && index >= 0, NULL);
|
||||
return gst_amc_buffer_copy (&codec->output_buffers[index]);
|
||||
}
|
||||
|
||||
if (!gst_amc_jni_call_object_method (env, err, codec->object,
|
||||
media_codec.get_output_buffer, &buffer, index))
|
||||
goto done;
|
||||
|
||||
ret = g_new0 (GstAmcBuffer, 1);
|
||||
ret->object = gst_amc_jni_object_make_global (env, buffer);
|
||||
if (!ret->object) {
|
||||
gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
|
||||
GST_LIBRARY_ERROR_FAILED, "Failed to create global buffer reference");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret->data = (*env)->GetDirectBufferAddress (env, ret->object);
|
||||
if (!ret->data) {
|
||||
gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
|
||||
GST_LIBRARY_ERROR_FAILED, "Failed to get buffer address");
|
||||
goto error;
|
||||
}
|
||||
ret->size = (*env)->GetDirectBufferCapacity (env, ret->object);
|
||||
|
||||
done:
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
if (ret->object)
|
||||
gst_amc_jni_object_unref (env, ret->object);
|
||||
g_free (ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GstAmcBuffer *
|
||||
gst_amc_codec_get_input_buffers (GstAmcCodec * codec, gsize * n_buffers,
|
||||
GError ** err)
|
||||
{
|
||||
|
@ -310,13 +422,53 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
gst_amc_codec_free_buffers (GstAmcBuffer * buffers, gsize n_buffers)
|
||||
GstAmcBuffer *
|
||||
gst_amc_codec_get_input_buffer (GstAmcCodec * codec, gint index, GError ** err)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jobject buffer = NULL;
|
||||
GstAmcBuffer *ret = NULL;
|
||||
|
||||
g_return_val_if_fail (codec != NULL, NULL);
|
||||
g_return_val_if_fail (index >= 0, NULL);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
gst_amc_jni_free_buffer_array (env, buffers, n_buffers);
|
||||
|
||||
if (!media_codec.get_input_buffer) {
|
||||
g_return_val_if_fail (index < codec->n_input_buffers && index >= 0, NULL);
|
||||
return gst_amc_buffer_copy (&codec->input_buffers[index]);
|
||||
}
|
||||
|
||||
if (!gst_amc_jni_call_object_method (env, err, codec->object,
|
||||
media_codec.get_input_buffer, &buffer, index))
|
||||
goto done;
|
||||
|
||||
ret = g_new0 (GstAmcBuffer, 1);
|
||||
ret->object = gst_amc_jni_object_make_global (env, buffer);
|
||||
if (!ret->object) {
|
||||
gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
|
||||
GST_LIBRARY_ERROR_FAILED, "Failed to create global buffer reference");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret->data = (*env)->GetDirectBufferAddress (env, ret->object);
|
||||
if (!ret->data) {
|
||||
gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
|
||||
GST_LIBRARY_ERROR_FAILED, "Failed to get buffer address");
|
||||
goto error;
|
||||
}
|
||||
ret->size = (*env)->GetDirectBufferCapacity (env, ret->object);
|
||||
|
||||
done:
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
if (ret->object)
|
||||
gst_amc_jni_object_unref (env, ret->object);
|
||||
g_free (ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
|
@ -386,7 +538,30 @@ gst_amc_codec_dequeue_output_buffer (GstAmcCodec * codec,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (!gst_amc_codec_fill_buffer_info (env, info_o, info, err)) {
|
||||
if (ret == INFO_OUTPUT_BUFFERS_CHANGED || ret == INFO_OUTPUT_FORMAT_CHANGED
|
||||
|| (ret >= 0 && !codec->output_buffers
|
||||
&& !media_codec.get_output_buffer)) {
|
||||
if (!media_codec.get_output_buffer) {
|
||||
if (codec->output_buffers)
|
||||
gst_amc_jni_free_buffer_array (env, codec->output_buffers,
|
||||
codec->n_output_buffers);
|
||||
codec->output_buffers =
|
||||
gst_amc_codec_get_output_buffers (codec,
|
||||
&codec->n_output_buffers, err);
|
||||
if (!codec->output_buffers) {
|
||||
ret = G_MININT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (ret == INFO_OUTPUT_BUFFERS_CHANGED) {
|
||||
gst_amc_jni_object_local_unref (env, info_o);
|
||||
return gst_amc_codec_dequeue_output_buffer (codec, info, timeoutUs, err);
|
||||
}
|
||||
} else if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret >= 0 && !gst_amc_codec_fill_buffer_info (env, info_o, info, err)) {
|
||||
ret = G_MININT;
|
||||
goto done;
|
||||
}
|
||||
|
@ -766,6 +941,8 @@ gst_amc_format_get_buffer (GstAmcFormat * format, const gchar * key,
|
|||
gboolean ret = FALSE;
|
||||
jstring key_str = NULL;
|
||||
jobject v = NULL;
|
||||
GstAmcBuffer buf = { 0, };
|
||||
gint position = 0, limit = 0;
|
||||
|
||||
g_return_val_if_fail (format != NULL, FALSE);
|
||||
g_return_val_if_fail (key != NULL, FALSE);
|
||||
|
@ -791,7 +968,14 @@ gst_amc_format_get_buffer (GstAmcFormat * format, const gchar * key,
|
|||
goto done;
|
||||
}
|
||||
*size = (*env)->GetDirectBufferCapacity (env, v);
|
||||
*data = g_memdup (*data, *size);
|
||||
|
||||
buf.object = v;
|
||||
buf.data = *data;
|
||||
buf.size = *size;
|
||||
gst_amc_buffer_get_position_and_limit (&buf, NULL, &position, &limit);
|
||||
*size = limit;
|
||||
|
||||
*data = g_memdup (*data + position, limit);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
|
@ -812,6 +996,7 @@ gst_amc_format_set_buffer (GstAmcFormat * format, const gchar * key,
|
|||
jstring key_str = NULL;
|
||||
jobject v = NULL;
|
||||
gboolean ret = FALSE;
|
||||
GstAmcBuffer buf = { 0, };
|
||||
|
||||
g_return_val_if_fail (format != NULL, FALSE);
|
||||
g_return_val_if_fail (key != NULL, FALSE);
|
||||
|
@ -831,6 +1016,12 @@ gst_amc_format_set_buffer (GstAmcFormat * format, const gchar * key,
|
|||
goto done;
|
||||
}
|
||||
|
||||
buf.object = v;
|
||||
buf.data = data;
|
||||
buf.size = size;
|
||||
|
||||
gst_amc_buffer_set_position_and_limit (&buf, NULL, 0, size);
|
||||
|
||||
if (!gst_amc_jni_call_void_method (env, err, format->object,
|
||||
media_format.set_byte_buffer, key_str, v))
|
||||
goto done;
|
||||
|
@ -972,6 +1163,20 @@ get_java_classes (void)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Android >= 21 */
|
||||
media_codec.get_output_buffer =
|
||||
(*env)->GetMethodID (env, media_codec.klass, "getOutputBuffer",
|
||||
"(I)Ljava/nio/ByteBuffer;");
|
||||
if ((*env)->ExceptionCheck (env))
|
||||
(*env)->ExceptionClear (env);
|
||||
|
||||
/* Android >= 21 */
|
||||
media_codec.get_input_buffer =
|
||||
(*env)->GetMethodID (env, media_codec.klass, "getInputBuffer",
|
||||
"(I)Ljava/nio/ByteBuffer;");
|
||||
if ((*env)->ExceptionCheck (env))
|
||||
(*env)->ExceptionClear (env);
|
||||
|
||||
tmp = (*env)->FindClass (env, "android/media/MediaCodec$BufferInfo");
|
||||
if (!tmp) {
|
||||
ret = FALSE;
|
||||
|
|
|
@ -65,6 +65,9 @@ struct _GstAmcFormat {
|
|||
struct _GstAmcCodec {
|
||||
/* < private > */
|
||||
jobject object; /* global reference */
|
||||
|
||||
GstAmcBuffer *input_buffers, *output_buffers;
|
||||
gsize n_input_buffers, n_output_buffers;
|
||||
};
|
||||
|
||||
struct _GstAmcBufferInfo {
|
||||
|
@ -87,9 +90,8 @@ gboolean gst_amc_codec_stop (GstAmcCodec * codec, GError **err);
|
|||
gboolean gst_amc_codec_flush (GstAmcCodec * codec, GError **err);
|
||||
gboolean gst_amc_codec_release (GstAmcCodec * codec, GError **err);
|
||||
|
||||
GstAmcBuffer * gst_amc_codec_get_output_buffers (GstAmcCodec * codec, gsize * n_buffers, GError **err);
|
||||
GstAmcBuffer * gst_amc_codec_get_input_buffers (GstAmcCodec * codec, gsize * n_buffers, GError **err);
|
||||
void gst_amc_codec_free_buffers (GstAmcBuffer * buffers, gsize n_buffers);
|
||||
GstAmcBuffer * gst_amc_codec_get_output_buffer (GstAmcCodec * codec, gint index, GError **err);
|
||||
GstAmcBuffer * gst_amc_codec_get_input_buffer (GstAmcCodec * codec, gint index, GError **err);
|
||||
|
||||
gint gst_amc_codec_dequeue_input_buffer (GstAmcCodec * codec, gint64 timeoutUs, GError **err);
|
||||
gint gst_amc_codec_dequeue_output_buffer (GstAmcCodec * codec, GstAmcBufferInfo *info, gint64 timeoutUs, GError **err);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Copyright (C) 2012, Collabora Ltd.
|
||||
* Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
*
|
||||
* Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation
|
||||
|
@ -408,6 +410,7 @@ gst_amc_audio_dec_loop (GstAmcAudioDec * self)
|
|||
{
|
||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||
gboolean is_eos;
|
||||
GstAmcBuffer *buf;
|
||||
GstAmcBufferInfo buffer_info;
|
||||
gint idx;
|
||||
GError *err = NULL;
|
||||
|
@ -435,18 +438,10 @@ retry:
|
|||
}
|
||||
|
||||
switch (idx) {
|
||||
case INFO_OUTPUT_BUFFERS_CHANGED:{
|
||||
GST_DEBUG_OBJECT (self, "Output buffers have changed");
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers,
|
||||
self->n_output_buffers);
|
||||
self->output_buffers =
|
||||
gst_amc_codec_get_output_buffers (self->codec,
|
||||
&self->n_output_buffers, &err);
|
||||
if (!self->output_buffers)
|
||||
goto get_output_buffers_error;
|
||||
case INFO_OUTPUT_BUFFERS_CHANGED:
|
||||
/* Handled internally */
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
case INFO_OUTPUT_FORMAT_CHANGED:{
|
||||
GstAmcFormat *format;
|
||||
gchar *format_string;
|
||||
|
@ -471,15 +466,6 @@ retry:
|
|||
}
|
||||
gst_amc_format_free (format);
|
||||
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers,
|
||||
self->n_output_buffers);
|
||||
self->output_buffers =
|
||||
gst_amc_codec_get_output_buffers (self->codec,
|
||||
&self->n_output_buffers, &err);
|
||||
if (!self->output_buffers)
|
||||
goto get_output_buffers_error;
|
||||
|
||||
goto retry;
|
||||
|
||||
}
|
||||
|
@ -500,23 +486,24 @@ retry:
|
|||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Got output buffer at index %d: size %d time %" G_GINT64_FORMAT
|
||||
" flags 0x%08x", idx, buffer_info.size, buffer_info.presentation_time_us,
|
||||
buffer_info.flags);
|
||||
"Got output buffer at index %d: offset %d size %d time %" G_GINT64_FORMAT
|
||||
" flags 0x%08x", idx, buffer_info.offset, buffer_info.size,
|
||||
buffer_info.presentation_time_us, buffer_info.flags);
|
||||
|
||||
is_eos = ! !(buffer_info.flags & BUFFER_FLAG_END_OF_STREAM);
|
||||
|
||||
buf = gst_amc_codec_get_output_buffer (self->codec, idx, &err);
|
||||
if (!buf)
|
||||
goto failed_to_get_output_buffer;
|
||||
|
||||
if (buffer_info.size > 0) {
|
||||
GstBuffer *outbuf;
|
||||
GstAmcBuffer *buf;
|
||||
GstMapInfo minfo;
|
||||
|
||||
/* This sometimes happens at EOS or if the input is not properly framed,
|
||||
* let's handle it gracefully by allocating a new buffer for the current
|
||||
* caps and filling it
|
||||
*/
|
||||
if (idx >= self->n_output_buffers)
|
||||
goto invalid_buffer_index;
|
||||
|
||||
if (buffer_info.size % self->info.bpf != 0)
|
||||
goto invalid_buffer_size;
|
||||
|
@ -528,7 +515,6 @@ retry:
|
|||
goto failed_allocate;
|
||||
|
||||
gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
|
||||
buf = &self->output_buffers[idx];
|
||||
if (self->needs_reorder) {
|
||||
gint i, n_samples, c, n_channels;
|
||||
gint *reorder_map = self->reorder_map;
|
||||
|
@ -557,6 +543,9 @@ retry:
|
|||
}
|
||||
}
|
||||
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
if (self->spf != -1) {
|
||||
GstBuffer *outbuf;
|
||||
guint avail = gst_adapter_available (self->output_adapter);
|
||||
|
@ -632,20 +621,6 @@ dequeue_error:
|
|||
return;
|
||||
}
|
||||
|
||||
get_output_buffers_error:
|
||||
{
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
|
||||
gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
|
||||
self->downstream_flow_ret = GST_FLOW_ERROR;
|
||||
GST_AUDIO_DECODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = FALSE;
|
||||
g_cond_broadcast (&self->drain_cond);
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
format_error:
|
||||
{
|
||||
if (err)
|
||||
|
@ -711,10 +686,9 @@ flow_error:
|
|||
return;
|
||||
}
|
||||
|
||||
invalid_buffer_index:
|
||||
failed_to_get_output_buffer:
|
||||
{
|
||||
GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
|
||||
("Invalid input buffer index %d of %d", idx, self->n_input_buffers));
|
||||
GST_AUDIO_DECODER_ERROR_FROM_ERROR (self, err);
|
||||
gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
|
||||
gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
|
||||
self->downstream_flow_ret = GST_FLOW_ERROR;
|
||||
|
@ -796,12 +770,6 @@ gst_amc_audio_dec_stop (GstAudioDecoder * decoder)
|
|||
if (err)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
self->started = FALSE;
|
||||
if (self->input_buffers)
|
||||
gst_amc_codec_free_buffers (self->input_buffers, self->n_input_buffers);
|
||||
self->input_buffers = NULL;
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers, self->n_output_buffers);
|
||||
self->output_buffers = NULL;
|
||||
}
|
||||
gst_pad_stop_task (GST_AUDIO_DECODER_SRC_PAD (decoder));
|
||||
|
||||
|
@ -973,17 +941,6 @@ gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->input_buffers)
|
||||
gst_amc_codec_free_buffers (self->input_buffers, self->n_input_buffers);
|
||||
self->input_buffers =
|
||||
gst_amc_codec_get_input_buffers (self->codec, &self->n_input_buffers,
|
||||
&err);
|
||||
if (!self->input_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get input buffers");
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->spf = -1;
|
||||
/* TODO: Implement for other codecs too */
|
||||
if (gst_structure_has_name (s, "audio/mpeg")) {
|
||||
|
@ -1133,9 +1090,6 @@ gst_amc_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (idx >= self->n_input_buffers)
|
||||
goto invalid_buffer_index;
|
||||
|
||||
if (self->flushing) {
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, NULL);
|
||||
|
@ -1155,14 +1109,21 @@ gst_amc_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
|
|||
|
||||
/* Copy the buffer content in chunks of size as requested
|
||||
* by the port */
|
||||
buf = &self->input_buffers[idx];
|
||||
buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
|
||||
if (!buf)
|
||||
goto failed_to_get_input_buffer;
|
||||
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.offset = 0;
|
||||
buffer_info.size = MIN (minfo.size - offset, buf->size);
|
||||
gst_amc_buffer_set_position_and_limit (buf, NULL, buffer_info.offset,
|
||||
buffer_info.size);
|
||||
|
||||
orc_memcpy (buf->data, minfo.data + offset, buffer_info.size);
|
||||
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
/* Interpolate timestamps if we're passing the buffer
|
||||
* in multiple chunks */
|
||||
if (offset != 0 && duration != GST_CLOCK_TIME_NONE) {
|
||||
|
@ -1212,10 +1173,9 @@ downstream_error:
|
|||
gst_buffer_unref (inbuf);
|
||||
return self->downstream_flow_ret;
|
||||
}
|
||||
invalid_buffer_index:
|
||||
failed_to_get_input_buffer:
|
||||
{
|
||||
GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
|
||||
("Invalid input buffer index %d of %d", idx, self->n_input_buffers));
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
if (minfo.data)
|
||||
gst_buffer_unmap (inbuf, &minfo);
|
||||
if (inbuf)
|
||||
|
@ -1281,43 +1241,53 @@ gst_amc_audio_dec_drain (GstAmcAudioDec * self)
|
|||
idx = gst_amc_codec_dequeue_input_buffer (self->codec, 500000, &err);
|
||||
GST_AUDIO_DECODER_STREAM_LOCK (self);
|
||||
|
||||
if (idx >= 0 && idx < self->n_input_buffers) {
|
||||
if (idx >= 0) {
|
||||
GstAmcBuffer *buf;
|
||||
GstAmcBufferInfo buffer_info;
|
||||
|
||||
GST_AUDIO_DECODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = TRUE;
|
||||
buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
|
||||
if (buf) {
|
||||
GST_AUDIO_DECODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = TRUE;
|
||||
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.size = 0;
|
||||
buffer_info.presentation_time_us =
|
||||
gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
|
||||
buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.size = 0;
|
||||
buffer_info.presentation_time_us =
|
||||
gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
|
||||
buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
|
||||
|
||||
if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err)) {
|
||||
GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
|
||||
g_cond_wait (&self->drain_cond, &self->drain_lock);
|
||||
GST_DEBUG_OBJECT (self, "Drained codec");
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to queue input buffer");
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
gst_amc_buffer_set_position_and_limit (buf, NULL, 0, 0);
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info,
|
||||
&err)) {
|
||||
GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
|
||||
g_cond_wait (&self->drain_cond, &self->drain_lock);
|
||||
GST_DEBUG_OBJECT (self, "Drained codec");
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_ERROR_OBJECT (self, "Failed to queue input buffer");
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
} else {
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->drained = TRUE;
|
||||
self->draining = FALSE;
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
GST_AUDIO_DECODER_STREAM_LOCK (self);
|
||||
} else if (idx >= self->n_input_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Invalid input buffer index %d of %d",
|
||||
idx, self->n_input_buffers);
|
||||
ret = GST_FLOW_ERROR;
|
||||
self->drained = TRUE;
|
||||
self->draining = FALSE;
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
GST_AUDIO_DECODER_STREAM_LOCK (self);
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to get buffer for EOS: %d", idx);
|
||||
if (err)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
}
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to acquire buffer for EOS: %d", idx);
|
||||
if (err)
|
||||
|
|
|
@ -51,8 +51,6 @@ struct _GstAmcAudioDec
|
|||
|
||||
/* < private > */
|
||||
GstAmcCodec *codec;
|
||||
GstAmcBuffer *input_buffers, *output_buffers;
|
||||
gsize n_input_buffers, n_output_buffers;
|
||||
|
||||
GstCaps *input_caps;
|
||||
GList *codec_datas;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
*
|
||||
* Copyright (C) 2012, Rafaël Carré <funman@videolanorg>
|
||||
*
|
||||
* Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation
|
||||
|
@ -557,27 +559,18 @@ gst_amc_video_dec_set_src_caps (GstAmcVideoDec * self, GstAmcFormat * format)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
|
||||
gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, GstAmcBuffer * buf,
|
||||
const GstAmcBufferInfo * buffer_info, GstBuffer * outbuf)
|
||||
{
|
||||
GstAmcBuffer *buf;
|
||||
GstVideoCodecState *state =
|
||||
gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
|
||||
GstVideoInfo *info = &state->info;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (idx >= self->n_output_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Invalid output buffer index %d of %d",
|
||||
idx, self->n_output_buffers);
|
||||
goto done;
|
||||
}
|
||||
buf = &self->output_buffers[idx];
|
||||
|
||||
ret =
|
||||
gst_amc_color_format_copy (&self->color_format_info, buf, buffer_info,
|
||||
info, outbuf, COLOR_FORMAT_COPY_OUT);
|
||||
|
||||
done:
|
||||
gst_video_codec_state_unref (state);
|
||||
return ret;
|
||||
}
|
||||
|
@ -589,6 +582,7 @@ gst_amc_video_dec_loop (GstAmcVideoDec * self)
|
|||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||
GstClockTimeDiff deadline;
|
||||
gboolean is_eos;
|
||||
GstAmcBuffer *buf;
|
||||
GstAmcBufferInfo buffer_info;
|
||||
gint idx;
|
||||
GError *err = NULL;
|
||||
|
@ -616,18 +610,10 @@ retry:
|
|||
}
|
||||
|
||||
switch (idx) {
|
||||
case INFO_OUTPUT_BUFFERS_CHANGED:{
|
||||
GST_DEBUG_OBJECT (self, "Output buffers have changed");
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers,
|
||||
self->n_output_buffers);
|
||||
self->output_buffers =
|
||||
gst_amc_codec_get_output_buffers (self->codec,
|
||||
&self->n_output_buffers, &err);
|
||||
if (!self->output_buffers)
|
||||
goto get_output_buffers_error;
|
||||
case INFO_OUTPUT_BUFFERS_CHANGED:
|
||||
/* Handled internally */
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
case INFO_OUTPUT_FORMAT_CHANGED:{
|
||||
GstAmcFormat *format;
|
||||
gchar *format_string;
|
||||
|
@ -652,15 +638,6 @@ retry:
|
|||
}
|
||||
gst_amc_format_free (format);
|
||||
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers,
|
||||
self->n_output_buffers);
|
||||
self->output_buffers =
|
||||
gst_amc_codec_get_output_buffers (self->codec,
|
||||
&self->n_output_buffers, &err);
|
||||
if (!self->output_buffers)
|
||||
goto get_output_buffers_error;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
case INFO_TRY_AGAIN_LATER:
|
||||
|
@ -678,9 +655,9 @@ retry:
|
|||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Got output buffer at index %d: size %d time %" G_GINT64_FORMAT
|
||||
" flags 0x%08x", idx, buffer_info.size, buffer_info.presentation_time_us,
|
||||
buffer_info.flags);
|
||||
"Got output buffer at index %d: offset %d size %d time %" G_GINT64_FORMAT
|
||||
" flags 0x%08x", idx, buffer_info.offset, buffer_info.size,
|
||||
buffer_info.presentation_time_us, buffer_info.flags);
|
||||
|
||||
frame =
|
||||
_find_nearest_frame (self,
|
||||
|
@ -688,6 +665,10 @@ retry:
|
|||
|
||||
is_eos = ! !(buffer_info.flags & BUFFER_FLAG_END_OF_STREAM);
|
||||
|
||||
buf = gst_amc_codec_get_output_buffer (self->codec, idx, &err);
|
||||
if (!buf)
|
||||
goto failed_to_get_output_buffer;
|
||||
|
||||
if (frame
|
||||
&& (deadline =
|
||||
gst_video_decoder_get_max_decode_time (GST_VIDEO_DECODER (self),
|
||||
|
@ -708,7 +689,7 @@ retry:
|
|||
outbuf =
|
||||
gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
|
||||
|
||||
if (!gst_amc_video_dec_fill_buffer (self, idx, &buffer_info, outbuf)) {
|
||||
if (!gst_amc_video_dec_fill_buffer (self, buf, &buffer_info, outbuf)) {
|
||||
gst_buffer_unref (outbuf);
|
||||
if (!gst_amc_codec_release_output_buffer (self->codec, idx, &err))
|
||||
GST_ERROR_OBJECT (self, "Failed to release output buffer index %d",
|
||||
|
@ -716,6 +697,8 @@ retry:
|
|||
if (err && !self->flushing)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
g_clear_error (&err);
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
goto invalid_buffer;
|
||||
}
|
||||
|
||||
|
@ -733,10 +716,12 @@ retry:
|
|||
if (err && !self->flushing)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
g_clear_error (&err);
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
goto flow_error;
|
||||
}
|
||||
|
||||
if (!gst_amc_video_dec_fill_buffer (self, idx, &buffer_info,
|
||||
if (!gst_amc_video_dec_fill_buffer (self, buf, &buffer_info,
|
||||
frame->output_buffer)) {
|
||||
gst_buffer_replace (&frame->output_buffer, NULL);
|
||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||
|
@ -746,6 +731,8 @@ retry:
|
|||
if (err && !self->flushing)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
g_clear_error (&err);
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
goto invalid_buffer;
|
||||
}
|
||||
|
||||
|
@ -754,6 +741,9 @@ retry:
|
|||
flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||
}
|
||||
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
if (!gst_amc_codec_release_output_buffer (self->codec, idx, &err)) {
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
|
@ -802,20 +792,6 @@ dequeue_error:
|
|||
return;
|
||||
}
|
||||
|
||||
get_output_buffers_error:
|
||||
{
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
|
||||
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
|
||||
self->downstream_flow_ret = GST_FLOW_ERROR;
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = FALSE;
|
||||
g_cond_broadcast (&self->drain_cond);
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
format_error:
|
||||
{
|
||||
if (err)
|
||||
|
@ -881,6 +857,20 @@ flow_error:
|
|||
return;
|
||||
}
|
||||
|
||||
failed_to_get_output_buffer:
|
||||
{
|
||||
GST_VIDEO_DECODER_ERROR_FROM_ERROR (self, err);
|
||||
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
|
||||
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
|
||||
self->downstream_flow_ret = GST_FLOW_ERROR;
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = FALSE;
|
||||
g_cond_broadcast (&self->drain_cond);
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
invalid_buffer:
|
||||
{
|
||||
GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
|
||||
|
@ -929,12 +919,6 @@ gst_amc_video_dec_stop (GstVideoDecoder * decoder)
|
|||
if (err)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
self->started = FALSE;
|
||||
if (self->input_buffers)
|
||||
gst_amc_codec_free_buffers (self->input_buffers, self->n_input_buffers);
|
||||
self->input_buffers = NULL;
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers, self->n_output_buffers);
|
||||
self->output_buffers = NULL;
|
||||
}
|
||||
gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
|
||||
|
||||
|
@ -1080,17 +1064,6 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->input_buffers)
|
||||
gst_amc_codec_free_buffers (self->input_buffers, self->n_input_buffers);
|
||||
self->input_buffers =
|
||||
gst_amc_codec_get_input_buffers (self->codec, &self->n_input_buffers,
|
||||
&err);
|
||||
if (!self->input_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get input buffers");
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->started = TRUE;
|
||||
self->input_state = gst_video_codec_state_ref (state);
|
||||
self->input_state_changed = TRUE;
|
||||
|
@ -1212,9 +1185,6 @@ gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (idx >= self->n_input_buffers)
|
||||
goto invalid_buffer_index;
|
||||
|
||||
if (self->flushing) {
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, NULL);
|
||||
|
@ -1234,14 +1204,21 @@ gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
|
|||
|
||||
/* Copy the buffer content in chunks of size as requested
|
||||
* by the port */
|
||||
buf = &self->input_buffers[idx];
|
||||
buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
|
||||
if (!buf)
|
||||
goto failed_to_get_input_buffer;
|
||||
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.offset = 0;
|
||||
buffer_info.size = MIN (minfo.size - offset, buf->size);
|
||||
gst_amc_buffer_set_position_and_limit (buf, NULL, buffer_info.offset,
|
||||
buffer_info.size);
|
||||
|
||||
orc_memcpy (buf->data, minfo.data + offset, buffer_info.size);
|
||||
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
/* Interpolate timestamps if we're passing the buffer
|
||||
* in multiple chunks */
|
||||
if (offset != 0 && duration != GST_CLOCK_TIME_NONE) {
|
||||
|
@ -1295,10 +1272,9 @@ downstream_error:
|
|||
gst_video_codec_frame_unref (frame);
|
||||
return self->downstream_flow_ret;
|
||||
}
|
||||
invalid_buffer_index:
|
||||
failed_to_get_input_buffer:
|
||||
{
|
||||
GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
|
||||
("Invalid input buffer index %d of %d", idx, self->n_input_buffers));
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
if (minfo.data)
|
||||
gst_buffer_unmap (frame->input_buffer, &minfo);
|
||||
gst_video_codec_frame_unref (frame);
|
||||
|
@ -1370,43 +1346,53 @@ gst_amc_video_dec_drain (GstAmcVideoDec * self)
|
|||
idx = gst_amc_codec_dequeue_input_buffer (self->codec, 500000, &err);
|
||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||
|
||||
if (idx >= 0 && idx < self->n_input_buffers) {
|
||||
if (idx >= 0) {
|
||||
GstAmcBuffer *buf;
|
||||
GstAmcBufferInfo buffer_info;
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = TRUE;
|
||||
buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
|
||||
if (buf) {
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = TRUE;
|
||||
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.size = 0;
|
||||
buffer_info.presentation_time_us =
|
||||
gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
|
||||
buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.size = 0;
|
||||
buffer_info.presentation_time_us =
|
||||
gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
|
||||
buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
|
||||
|
||||
if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err)) {
|
||||
GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
|
||||
g_cond_wait (&self->drain_cond, &self->drain_lock);
|
||||
GST_DEBUG_OBJECT (self, "Drained codec");
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to queue input buffer");
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
gst_amc_buffer_set_position_and_limit (buf, NULL, 0, 0);
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info,
|
||||
&err)) {
|
||||
GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
|
||||
g_cond_wait (&self->drain_cond, &self->drain_lock);
|
||||
GST_DEBUG_OBJECT (self, "Drained codec");
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_ERROR_OBJECT (self, "Failed to queue input buffer");
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
} else {
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->drained = TRUE;
|
||||
self->draining = FALSE;
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||
} else if (idx >= self->n_input_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Invalid input buffer index %d of %d",
|
||||
idx, self->n_input_buffers);
|
||||
ret = GST_FLOW_ERROR;
|
||||
self->drained = TRUE;
|
||||
self->draining = FALSE;
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to get buffer for EOS: %d", idx);
|
||||
if (err)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
}
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to acquire buffer for EOS: %d", idx);
|
||||
if (err)
|
||||
|
|
|
@ -51,8 +51,6 @@ struct _GstAmcVideoDec
|
|||
|
||||
/* < private > */
|
||||
GstAmcCodec *codec;
|
||||
GstAmcBuffer *input_buffers, *output_buffers;
|
||||
gsize n_input_buffers, n_output_buffers;
|
||||
|
||||
GstVideoCodecState *input_state;
|
||||
gboolean input_state_changed;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
* Copyright (C) 2013, Lemote Ltd.
|
||||
* Author: Chen Jie <chenj@lemote.com>
|
||||
*
|
||||
* Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation
|
||||
|
@ -982,15 +984,6 @@ retry:
|
|||
|
||||
gst_amc_format_free (format);
|
||||
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers,
|
||||
self->n_output_buffers);
|
||||
self->output_buffers =
|
||||
gst_amc_codec_get_output_buffers (self->codec,
|
||||
&self->n_output_buffers, &err);
|
||||
if (!self->output_buffers)
|
||||
goto get_output_buffers_error;
|
||||
|
||||
if (idx >= 0)
|
||||
goto process_buffer;
|
||||
|
||||
|
@ -998,18 +991,10 @@ retry:
|
|||
}
|
||||
|
||||
switch (idx) {
|
||||
case INFO_OUTPUT_BUFFERS_CHANGED:{
|
||||
GST_DEBUG_OBJECT (self, "Output buffers have changed");
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers,
|
||||
self->n_output_buffers);
|
||||
self->output_buffers =
|
||||
gst_amc_codec_get_output_buffers (self->codec,
|
||||
&self->n_output_buffers, &err);
|
||||
if (!self->output_buffers)
|
||||
goto get_output_buffers_error;
|
||||
case INFO_OUTPUT_BUFFERS_CHANGED:
|
||||
/* Handled internally */
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
case INFO_TRY_AGAIN_LATER:
|
||||
GST_DEBUG_OBJECT (self, "Dequeueing output buffer timed out");
|
||||
goto retry;
|
||||
|
@ -1038,17 +1023,16 @@ process_buffer:
|
|||
|
||||
is_eos = ! !(buffer_info.flags & BUFFER_FLAG_END_OF_STREAM);
|
||||
|
||||
if (idx >= self->n_output_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Invalid output buffer index %d of %d",
|
||||
idx, self->n_output_buffers);
|
||||
|
||||
goto invalid_buffer;
|
||||
}
|
||||
buf = &self->output_buffers[idx];
|
||||
buf = gst_amc_codec_get_output_buffer (self->codec, idx, &err);
|
||||
if (!buf)
|
||||
goto failed_to_get_output_buffer;
|
||||
|
||||
flow_ret =
|
||||
gst_amc_video_enc_handle_output_frame (self, buf, &buffer_info, frame);
|
||||
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
if (!gst_amc_codec_release_output_buffer (self->codec, idx, &err)) {
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
|
@ -1097,20 +1081,6 @@ dequeue_error:
|
|||
return;
|
||||
}
|
||||
|
||||
get_output_buffers_error:
|
||||
{
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
|
||||
gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
|
||||
self->downstream_flow_ret = GST_FLOW_ERROR;
|
||||
GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = FALSE;
|
||||
g_cond_broadcast (&self->drain_cond);
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
format_error:
|
||||
{
|
||||
if (err)
|
||||
|
@ -1173,10 +1143,9 @@ flow_error:
|
|||
return;
|
||||
}
|
||||
|
||||
invalid_buffer:
|
||||
failed_to_get_output_buffer:
|
||||
{
|
||||
GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
|
||||
("Invalid sized input buffer"));
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
|
||||
gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
|
||||
self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
|
||||
|
@ -1221,12 +1190,6 @@ gst_amc_video_enc_stop (GstVideoEncoder * encoder)
|
|||
if (err)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
self->started = FALSE;
|
||||
if (self->input_buffers)
|
||||
gst_amc_codec_free_buffers (self->input_buffers, self->n_input_buffers);
|
||||
self->input_buffers = NULL;
|
||||
if (self->output_buffers)
|
||||
gst_amc_codec_free_buffers (self->output_buffers, self->n_output_buffers);
|
||||
self->output_buffers = NULL;
|
||||
}
|
||||
gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder));
|
||||
|
||||
|
@ -1341,17 +1304,6 @@ gst_amc_video_enc_set_format (GstVideoEncoder * encoder,
|
|||
goto quit;
|
||||
}
|
||||
|
||||
if (self->input_buffers)
|
||||
gst_amc_codec_free_buffers (self->input_buffers, self->n_input_buffers);
|
||||
self->input_buffers =
|
||||
gst_amc_codec_get_input_buffers (self->codec, &self->n_input_buffers,
|
||||
&err);
|
||||
if (!self->input_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get input buffers");
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
self->amc_format = format;
|
||||
format = NULL;
|
||||
|
||||
|
@ -1481,9 +1433,6 @@ again:
|
|||
goto again;
|
||||
}
|
||||
|
||||
if (idx >= self->n_input_buffers)
|
||||
goto invalid_buffer_index;
|
||||
|
||||
if (self->flushing) {
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, NULL);
|
||||
|
@ -1503,11 +1452,15 @@ again:
|
|||
|
||||
/* Copy the buffer content in chunks of size as requested
|
||||
* by the port */
|
||||
buf = &self->input_buffers[idx];
|
||||
buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
|
||||
if (!buf)
|
||||
goto failed_to_get_input_buffer;
|
||||
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.offset = 0;
|
||||
buffer_info.size = MIN (self->color_format_info.frame_size, buf->size);
|
||||
gst_amc_buffer_set_position_and_limit (buf, NULL, buffer_info.offset,
|
||||
buffer_info.size);
|
||||
|
||||
if (!gst_amc_video_enc_fill_buffer (self, frame->input_buffer, buf,
|
||||
&buffer_info)) {
|
||||
|
@ -1516,9 +1469,14 @@ again:
|
|||
if (err && !self->flushing)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
g_clear_error (&err);
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
goto buffer_fill_error;
|
||||
}
|
||||
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
if (timestamp != GST_CLOCK_TIME_NONE) {
|
||||
buffer_info.presentation_time_us =
|
||||
gst_util_uint64_scale (timestamp + timestamp_offset, 1, GST_USECOND);
|
||||
|
@ -1559,10 +1517,9 @@ downstream_error:
|
|||
gst_video_codec_frame_unref (frame);
|
||||
return self->downstream_flow_ret;
|
||||
}
|
||||
invalid_buffer_index:
|
||||
failed_to_get_input_buffer:
|
||||
{
|
||||
GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
|
||||
("Invalid input buffer index %d of %d", idx, self->n_input_buffers));
|
||||
GST_ELEMENT_ERROR_FROM_ERROR (self, err);
|
||||
gst_video_codec_frame_unref (frame);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
@ -1634,43 +1591,53 @@ gst_amc_video_enc_drain (GstAmcVideoEnc * self)
|
|||
idx = gst_amc_codec_dequeue_input_buffer (self->codec, 500000, &err);
|
||||
GST_VIDEO_ENCODER_STREAM_LOCK (self);
|
||||
|
||||
if (idx >= 0 && idx < self->n_input_buffers) {
|
||||
if (idx >= 0) {
|
||||
GstAmcBuffer *buf;
|
||||
GstAmcBufferInfo buffer_info;
|
||||
|
||||
GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = TRUE;
|
||||
buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
|
||||
if (buf) {
|
||||
GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
|
||||
g_mutex_lock (&self->drain_lock);
|
||||
self->draining = TRUE;
|
||||
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.size = 0;
|
||||
buffer_info.presentation_time_us =
|
||||
gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
|
||||
buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
|
||||
memset (&buffer_info, 0, sizeof (buffer_info));
|
||||
buffer_info.size = 0;
|
||||
buffer_info.presentation_time_us =
|
||||
gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
|
||||
buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
|
||||
|
||||
if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err)) {
|
||||
GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
|
||||
g_cond_wait (&self->drain_cond, &self->drain_lock);
|
||||
GST_DEBUG_OBJECT (self, "Drained codec");
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to queue input buffer");
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
gst_amc_buffer_set_position_and_limit (buf, NULL, 0, 0);
|
||||
gst_amc_buffer_free (buf);
|
||||
buf = NULL;
|
||||
|
||||
if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info,
|
||||
&err)) {
|
||||
GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
|
||||
g_cond_wait (&self->drain_cond, &self->drain_lock);
|
||||
GST_DEBUG_OBJECT (self, "Drained codec");
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_ERROR_OBJECT (self, "Failed to queue input buffer");
|
||||
if (self->flushing) {
|
||||
g_clear_error (&err);
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
} else {
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->drained = TRUE;
|
||||
self->draining = FALSE;
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
GST_VIDEO_ENCODER_STREAM_LOCK (self);
|
||||
} else if (idx >= self->n_input_buffers) {
|
||||
GST_ERROR_OBJECT (self, "Invalid input buffer index %d of %d",
|
||||
idx, self->n_input_buffers);
|
||||
ret = GST_FLOW_ERROR;
|
||||
self->drained = TRUE;
|
||||
self->draining = FALSE;
|
||||
g_mutex_unlock (&self->drain_lock);
|
||||
GST_VIDEO_ENCODER_STREAM_LOCK (self);
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to get buffer for EOS: %d", idx);
|
||||
if (err)
|
||||
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
}
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to acquire buffer for EOS: %d", idx);
|
||||
if (err)
|
||||
|
|
|
@ -53,8 +53,6 @@ struct _GstAmcVideoEnc
|
|||
|
||||
/* < private > */
|
||||
GstAmcCodec *codec;
|
||||
GstAmcBuffer *input_buffers, *output_buffers;
|
||||
gsize n_input_buffers, n_output_buffers;
|
||||
GstAmcFormat *amc_format;
|
||||
|
||||
GstVideoCodecState *input_state;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
|
||||
* Copyright (C) 2014, Collabora Ltd.
|
||||
* Author: Matthieu Bouron <matthieu.bouron@collabora.com>
|
||||
* Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -41,6 +42,14 @@ static JavaVM *java_vm;
|
|||
static gboolean started_java_vm = FALSE;
|
||||
static pthread_key_t current_jni_env;
|
||||
|
||||
static struct
|
||||
{
|
||||
jclass klass;
|
||||
jmethodID get_limit, get_position;
|
||||
jmethodID set_limit, set_position;
|
||||
jmethodID clear;
|
||||
} java_nio_buffer;
|
||||
|
||||
jclass
|
||||
gst_amc_jni_get_class (JNIEnv * env, GError ** err, const gchar * name)
|
||||
{
|
||||
|
@ -547,6 +556,69 @@ symbol_error:
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
initialize_classes (void)
|
||||
{
|
||||
JNIEnv *env;
|
||||
GError *err = NULL;
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
java_nio_buffer.klass = gst_amc_jni_get_class (env, &err, "java/nio/Buffer");
|
||||
if (!java_nio_buffer.klass) {
|
||||
GST_ERROR ("Failed to get java.nio.Buffer class: %s", err->message);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
java_nio_buffer.get_limit =
|
||||
gst_amc_jni_get_method_id (env, &err, java_nio_buffer.klass, "limit",
|
||||
"()I");
|
||||
if (!java_nio_buffer.get_limit) {
|
||||
GST_ERROR ("Failed to get java.nio.Buffer limit(): %s", err->message);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
java_nio_buffer.get_position =
|
||||
gst_amc_jni_get_method_id (env, &err, java_nio_buffer.klass, "position",
|
||||
"()I");
|
||||
if (!java_nio_buffer.get_position) {
|
||||
GST_ERROR ("Failed to get java.nio.Buffer position(): %s", err->message);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
java_nio_buffer.set_limit =
|
||||
gst_amc_jni_get_method_id (env, &err, java_nio_buffer.klass, "limit",
|
||||
"(I)Ljava/nio/Buffer;");
|
||||
if (!java_nio_buffer.set_limit) {
|
||||
GST_ERROR ("Failed to get java.nio.Buffer limit(): %s", err->message);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
java_nio_buffer.set_position =
|
||||
gst_amc_jni_get_method_id (env, &err, java_nio_buffer.klass, "position",
|
||||
"(I)Ljava/nio/Buffer;");
|
||||
if (!java_nio_buffer.set_position) {
|
||||
GST_ERROR ("Failed to get java.nio.Buffer position(): %s", err->message);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
java_nio_buffer.clear =
|
||||
gst_amc_jni_get_method_id (env, &err, java_nio_buffer.klass, "clear",
|
||||
"()Ljava/nio/Buffer;");
|
||||
if (!java_nio_buffer.clear) {
|
||||
GST_ERROR ("Failed to get java.nio.Buffer clear(): %s", err->message);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_amc_jni_initialize_java_vm (void)
|
||||
{
|
||||
|
@ -599,7 +671,10 @@ gst_amc_jni_initialize_java_vm (void)
|
|||
started_java_vm = TRUE;
|
||||
}
|
||||
|
||||
return java_vm != NULL;
|
||||
if (java_vm == NULL)
|
||||
return FALSE;
|
||||
|
||||
return initialize_classes ();
|
||||
|
||||
get_created_failed:
|
||||
{
|
||||
|
@ -902,3 +977,105 @@ gst_amc_jni_free_buffer_array (JNIEnv * env, GstAmcBuffer * buffers,
|
|||
}
|
||||
g_free (buffers);
|
||||
}
|
||||
|
||||
void
|
||||
gst_amc_buffer_free (GstAmcBuffer * buffer)
|
||||
{
|
||||
JNIEnv *env;
|
||||
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (buffer->object)
|
||||
gst_amc_jni_object_unref (env, buffer->object);
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
GstAmcBuffer *
|
||||
gst_amc_buffer_copy (GstAmcBuffer * buffer)
|
||||
{
|
||||
JNIEnv *env;
|
||||
GstAmcBuffer *ret;
|
||||
|
||||
g_return_val_if_fail (buffer != NULL, NULL);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
ret = g_new0 (GstAmcBuffer, 1);
|
||||
|
||||
ret->object = gst_amc_jni_object_ref (env, buffer->object);
|
||||
ret->data = buffer->data;
|
||||
ret->size = buffer->size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_amc_buffer_get_position_and_limit (GstAmcBuffer * buffer, GError ** err,
|
||||
gint * position, gint * limit)
|
||||
{
|
||||
JNIEnv *env;
|
||||
|
||||
g_return_val_if_fail (buffer != NULL, FALSE);
|
||||
g_return_val_if_fail (buffer->object != NULL, FALSE);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (!gst_amc_jni_call_int_method (env, err, buffer->object,
|
||||
java_nio_buffer.get_position, position))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_amc_jni_call_int_method (env, err, buffer->object,
|
||||
java_nio_buffer.get_limit, limit))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_amc_buffer_set_position_and_limit (GstAmcBuffer * buffer, GError ** err,
|
||||
gint position, gint limit)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jobject tmp;
|
||||
|
||||
g_return_val_if_fail (buffer != NULL, FALSE);
|
||||
g_return_val_if_fail (buffer->object != NULL, FALSE);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (!gst_amc_jni_call_object_method (env, err, buffer->object,
|
||||
java_nio_buffer.set_limit, &tmp, limit))
|
||||
return FALSE;
|
||||
|
||||
gst_amc_jni_object_local_unref (env, tmp);
|
||||
|
||||
if (!gst_amc_jni_call_object_method (env, err, buffer->object,
|
||||
java_nio_buffer.set_position, &tmp, position))
|
||||
return FALSE;
|
||||
|
||||
gst_amc_jni_object_local_unref (env, tmp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_amc_buffer_clear (GstAmcBuffer * buffer, GError ** err)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jobject tmp;
|
||||
|
||||
g_return_val_if_fail (buffer != NULL, FALSE);
|
||||
g_return_val_if_fail (buffer->object != NULL, FALSE);
|
||||
|
||||
env = gst_amc_jni_get_env ();
|
||||
|
||||
if (!gst_amc_jni_call_object_method (env, err, buffer->object,
|
||||
java_nio_buffer.clear, &tmp))
|
||||
return FALSE;
|
||||
|
||||
gst_amc_jni_object_local_unref (env, tmp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -175,6 +175,12 @@ struct _GstAmcBuffer {
|
|||
gsize size;
|
||||
};
|
||||
|
||||
gboolean gst_amc_buffer_get_position_and_limit (GstAmcBuffer * buffer, GError ** err, gint * position, gint * limit);
|
||||
gboolean gst_amc_buffer_set_position_and_limit (GstAmcBuffer * buffer, GError ** err, gint position, gint limit);
|
||||
gboolean gst_amc_buffer_clear (GstAmcBuffer * buffer, GError ** err);
|
||||
GstAmcBuffer * gst_amc_buffer_copy (GstAmcBuffer * buffer);
|
||||
void gst_amc_buffer_free (GstAmcBuffer * buffer);
|
||||
|
||||
gboolean gst_amc_jni_get_buffer_array (JNIEnv * env, GError ** err, jobject array, GstAmcBuffer ** buffers, gsize * n_buffers);
|
||||
void gst_amc_jni_free_buffer_array (JNIEnv * env, GstAmcBuffer * buffers, gsize n_buffers);
|
||||
|
||||
|
|
Loading…
Reference in a new issue