static mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core);
static void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data);
static int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data);
-static int _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer* buff, bool codec_config);
+static int _mc_gst_update_caps(mc_gst_core_t *core, GstMCBuffer *buff, bool codec_config);
static gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h fmt);
static GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet_h pkt, bool codec_config);
static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *buff);
static gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data);
static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data);
static MMVideoBuffer *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, media_packet_h pkt);
-static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t* core, media_packet_h pkt, uint64_t size);
+static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h pkt, uint64_t size);
static void gst_mediacodec_buffer_finalize(GstMCBuffer *buffer);
-static int __mc_set_caps_streamheader(mc_gst_core_t *core, GstMCBuffer*buff, guint streamheader_size);
-static int __mc_set_caps_codecdata(mc_gst_core_t *core, GstMCBuffer*buff, guint codecdata_size);
+static int __mc_set_caps_streamheader(mc_gst_core_t *core, GstMCBuffer *buff, guint streamheader_size);
+static int __mc_set_caps_codecdata(mc_gst_core_t *core, GstMCBuffer *buff, guint codecdata_size);
static void __mc_push_output_to_queue(mc_gst_core_t *core, media_packet_h out_pkt);
static int __mc_gst_create_eos_packet(media_format_h fmt, media_packet_h *out_pkt);
+static void _mc_gst_handle_input_buffer_used(mc_gst_core_t *core, media_packet_h pkt);
static gint __gst_handle_stream_error(mc_gst_core_t *core, GError *error, GstMessage *message);
static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage *message, GError *error);
ret = media_packet_get_buffer_data_ptr(pkt, &buf_data);
if (ret != MEDIA_PACKET_ERROR_NONE) {
- LOGW("buffer size get fail");
+ LOGW("buffer data get fail");
return MC_ERROR;
}
ret = media_packet_get_buffer_data_ptr(pkt, &buf_data);
if (ret != MEDIA_PACKET_ERROR_NONE) {
- LOGW("buffer size get fail");
+ LOGW("buffer data get fail");
return MC_ERROR;
}
ret = media_packet_get_buffer_data_ptr(buff->pkt, &buf_data);
if (ret != MEDIA_PACKET_ERROR_NONE) {
- LOGW("buffer size get fail");
+ LOGW("buffer data get fail");
return ret;
}
return is_updated;
}
-static int _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer* buff, bool codec_config)
+static int _mc_gst_update_caps(mc_gst_core_t *core, GstMCBuffer *buff, bool codec_config)
{
MEDIACODEC_FENTER();
g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
+ g_return_val_if_fail(buff != NULL, MC_PARAM_ERROR);
int ret = MC_ERROR_NONE;
if (core->encoder) {
mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info;
- core->format = __mc_get_gst_input_format(pkt, core->is_hw);
+ core->format = __mc_get_gst_input_format(buff->pkt, core->is_hw);
gst_caps_set_simple(core->caps,
"format", G_TYPE_STRING, core->format,
"width", G_TYPE_INT, enc_info->width,
g_object_set(GST_OBJECT(core->codec), "bitrate", enc_info->bitrate, NULL);
else
g_object_set(GST_OBJECT(core->codec), "target-bitrate", enc_info->bitrate, NULL);
-
+ LOGD("set bitrate = %d.", enc_info->bitrate);
} else {
mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info;
while (g_atomic_int_get(&core->available_queue->running)) {
LOGD("waiting for next input....");
in_buf = _mc_get_input_buffer(core);
-
if (!in_buf)
goto LEAVE;
LOGE("media_packet_is_end_of_stream failed");
goto ERROR;
}
+ /*
+ * receive an eos packet. For decoder + encoder case, encoder always get tbm surface plane first from input data,
+ * but eos packet only has flag not valid data, so we don't put it to downstream.
+ */
+ if (eos) {
+ LOGD("end of stream");
+ gst_app_src_end_of_stream(GST_APP_SRC(core->appsrc));
+ _mc_wait_for_eos(core);
+ initiative = true;
+
+ _mc_gst_handle_input_buffer_used(core, in_buf);
+ goto LEAVE;
+ }
buff = _mc_gst_media_packet_to_gstbuffer(core, in_buf, codec_config);
if (!buff) {
LOGW("gstbuffer can't make");
goto ERROR;
}
+ /* buff took the ownership of the in_buf, so set in_buf to NULL to aviod double unref */
+ in_buf = NULL;
if (codec_config)
initiative = TRUE;
if (initiative) {
GstPad *pad;
- ret = _mc_gst_update_caps(core, in_buf, buff, codec_config);
+ ret = _mc_gst_update_caps(core, buff, codec_config);
if (ret != MC_ERROR_NONE) {
LOGE("failed to update caps");
+ /* unref buff->buffer will invoke the finalize() of GstMcBuffer */
+ gst_buffer_unref(buff->buffer);
goto ERROR;
}
initiative = false;
- if (eos) {
- LOGD("end of stream");
- gst_app_src_end_of_stream(GST_APP_SRC(core->appsrc));
- _mc_wait_for_eos(core);
- initiative = true;
- }
-
-
continue;
ERROR:
+ if (in_buf)
+ _mc_gst_handle_input_buffer_used(core, in_buf);
+
_mc_gst_set_flush_input(core);
if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) {
GstBuffer *buffer = NULL;
media_packet_get_extra(out_pkt, (void**)&buffer);
if (buffer) {
- LOGD("dq : %d TIMESTAMP = %"GST_TIME_FORMAT " DURATION = %"GST_TIME_FORMAT,
+ LOGD("dq : v(%d)e(%d) %d TIMESTAMP = %"GST_TIME_FORMAT " DURATION = %"GST_TIME_FORMAT, core->video, core->encoder,
core->ftb_count, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)), GST_TIME_ARGS(GST_BUFFER_DURATION(buffer)));
} else {
- LOGD("dq : %d ", core->ftb_count);
+ LOGD("dq : v(%d)e(%d) %d ", core->video, core->encoder, core->ftb_count);
}
g_mutex_unlock(&core->ports[1]->mutex);
return format;
}
-GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t* core, media_packet_h pkt, bool codec_config)
+GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet_h pkt, bool codec_config)
{
int ret = MEDIA_PACKET_ERROR_NONE;
GstMCBuffer *mc_buffer = NULL;
ret = media_packet_get_buffer_data_ptr(pkt, &buf_data);
if (ret != MEDIA_PACKET_ERROR_NONE) {
- LOGW("buffer size get fail");
+ LOGW("buffer data get fail");
return NULL;
}
return NULL;
}
- LOGD("pkt : %p, buf_size : %d", pkt, (int)buf_size);
+ LOGD("pkt :v(%d)e(%d) %p, buf_size : %d", core->video, core->encoder, pkt, (int)buf_size);
ret = __mc_fill_input_buffer(core, pkt, mc_buffer);
if (ret != MC_ERROR_NONE) {
LOGW("failed to fill inbuf: %s (ox%08x)", _mc_error_to_string(ret), ret);
+ /*
+ * if __mc_fill_input_buffer() failed, no memory appended to mc_buffer->buffer, so gst_mediacodec_buffer_finalize()
+ * will not be invoked
+ */
+ gst_buffer_unref(mc_buffer->buffer);
+ free(mc_buffer);
return NULL;
}
int ret = MC_ERROR_NONE;
MEDIACODEC_FENTER();
- if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
+ if (media_packet_create(fmt, NULL, NULL, &mediabuf)) {
LOGE("media_packet_create_alloc failed\n");
ret = MC_ERROR;
goto ERROR;
return ret;
}
+void _mc_gst_handle_input_buffer_used(mc_gst_core_t *core, media_packet_h pkt)
+{
+ g_atomic_int_dec_and_test(&core->etb_count);
+
+ if (core && core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) {
+ ((mc_empty_buffer_cb)core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER])
+ (pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]);
+ }
+
+ if (core)
+ LOGD("@v(%d)e(%d) input port emptied buffer(%d): %p", core->video, core->encoder, core->etb_count, pkt);
+}
+
gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data)
{
int ret = MC_ERROR_NONE;
return reply;
}
-static MMVideoBuffer *__mc_gst_make_tbm_buffer(mc_gst_core_t* core, media_packet_h pkt)
+static MMVideoBuffer *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, media_packet_h pkt)
{
int i;
int num_bos;
mc_gst_core_t *core = (mc_gst_core_t *)mc_buffer->core;
- g_atomic_int_dec_and_test(&core->etb_count);
- if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) {
- ((mc_empty_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER])
- (mc_buffer->pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]);
- }
+ _mc_gst_handle_input_buffer_used(core, mc_buffer->pkt);
- LOGD("@v(%d)e(%d)input port emptied buffer(%d): %p", core->video, core->encoder, core->etb_count, mc_buffer->pkt);
free(mc_buffer);
mc_buffer = NULL;
return;
}
-static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t* core, media_packet_h pkt, uint64_t size)
+static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h pkt, uint64_t size)
{
GstMCBuffer *mc_buffer = NULL;
return trans_err;
}
-static gint __gst_handle_stream_error(mc_gst_core_t *core, GError* error, GstMessage * message)
+static gint __gst_handle_stream_error(mc_gst_core_t *core, GError *error, GstMessage *message)
{
gint trans_err = MEDIACODEC_ERROR_NONE;
return trans_err;
}
-static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage * message, GError* error)
+static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage *message, GError *error)
{
gchar *src_element_name = NULL;
GstElement *src_element = NULL;
g_atomic_int_dec_and_test(&core->etb_count);
LOGD("%p poped(%d)", pkt, core->etb_count);
- if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) {
- ((mc_empty_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER])
- (pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]);
- }
+ _mc_gst_handle_input_buffer_used(core, pkt);
}
mc_async_queue_flush(core->available_queue->input);