| INCLUDE FILES |
=======================================================================================*/
#include <gst/allocators/gsttizenmemory.h>
-#include <gst/video/cameracontrol.h>
#include <gst/app/gstappsrc.h>
#include "mm_camcorder_internal.h"
#include "mm_camcorder_videorec.h"
| LOCAL FUNCTION PROTOTYPES: |
---------------------------------------------------------------------------------------*/
/* STATIC INTERNAL FUNCTION */
-static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
+static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
static GstPadProbeReturn __mmcamcorder_video_dataprobe_encoded(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
/*---------------------------------------------------------------------------------------
| GLOBAL FUNCTION DEFINITIONS: |
---------------------------------------------------------------------------------------*/
-gboolean _mmcamcorder_video_push_buffer(void *handle, GstBuffer *buffer)
+gboolean _mmcamcorder_video_push_buffer(void *handle, GstSample *sample)
{
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
_MMCamcorderSubContext *sc = NULL;
_MMCamcorderVideoInfo *info_video = NULL;
_MMCamcorderGstElement *element = NULL;
GstClockTime current_ts = 0; /* nsec */
+ GstBuffer *buffer = NULL;
mmf_return_val_if_fail(hcamcorder, FALSE);
mmf_return_val_if_fail(MMF_CAMCORDER_SUBCONTEXT(hcamcorder), FALSE);
+ buffer = gst_sample_get_buffer(sample);
+
mmf_return_val_if_fail(buffer, FALSE);
mmf_return_val_if_fail(gst_buffer_n_memory(buffer), FALSE);
int ret = 0;
GstClock *clock = NULL;
- MMCAM_LOG_VERBOSE("GST_BUFFER_FLAG_DELTA_UNIT is set : %d",
- GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT));
+ MMCAM_LOG_VERBOSE("buffer[%p] - delta flag[%d]",
+ buffer, GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT));
current_ts = GST_BUFFER_PTS(buffer);
if (info_video->is_first_frame) {
/* check first I frame for H.264 stream */
- if (info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
- if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
- MMCAM_LOG_WARNING("NOT I frame.. skip this buffer");
+ if (_mmcamcorder_is_encoded_preview_pixel_format(info_image->preview_format)) {
+ if (!GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_HEADER)) {
+ MMCAM_LOG_WARNING("No header in buffer");
return TRUE;
- } else {
- MMCAM_LOG_WARNING("[H.264] first I frame");
}
+
+ MMCAM_LOG_WARNING("Got buffer with header");
}
/* set base timestamp */
}
} else {
/* for image capture with encodebin and v4l2src */
- if (sc->bencbin_capture && info_image->capturing) {
+ if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_ENCODEBIN && info_image->capturing) {
g_mutex_lock(&hcamcorder->task_thread_lock);
MMCAM_LOG_INFO("send signal for sound play");
hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_SOUND_SOLO_PLAY_START;
info_video->base_video_ts = current_ts;
}
} else {
- if (_mmcamcorder_invoke_video_stream_cb(handle, buffer, FALSE) == FALSE) {
+ if (_mmcamcorder_invoke_video_stream_cb(handle, sample, FALSE, -1) == FALSE) {
/* increase base video timestamp by frame duration,
it will remove delay of dropped buffer when play recorded file. */
info_video->base_video_ts += current_ts - info_video->last_video_ts;
GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer) = current_ts - info_video->base_video_ts;
- MMCAM_LOG_DEBUG("buffer %p, timestamp %"GST_TIME_FORMAT,
+ MMCAM_LOG_DEBUG("buffer[%p] - timestamp[%"GST_TIME_FORMAT"]",
buffer, GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));
- if (info_video->record_dual_stream) {
- /* It will NOT INCREASE reference count of buffer */
- ret = gst_app_src_push_buffer((GstAppSrc *)element[_MMCAMCORDER_ENCSINK_SRC].gst, buffer);
- } else {
- /* It will INCREASE reference count of buffer */
- g_signal_emit_by_name(element[_MMCAMCORDER_ENCSINK_SRC].gst, "push-buffer", buffer, &ret);
- }
+ /* It will INCREASE reference count of buffer */
+ g_signal_emit_by_name(element[_MMCAMCORDER_ENCSINK_SRC].gst, "push-buffer", buffer, &ret);
MMCAM_LOG_VERBOSE("push buffer result : 0x%x", ret);
}
-static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
+static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
{
- return _mmcamcorder_video_push_buffer(u_data, gst_sample_get_buffer(sample));
+ mmf_return_if_fail(sample);
+
+ /* no need to check return value here */
+ _mmcamcorder_video_push_buffer(u_data, sample);
+
+ gst_sample_unref(sample);
}
MMCAM_LOG_INFO("MMCAM_AUDIO_DISABLE %d, is_modified_rate %d, ved_cb %p",
sc->audio_disable, sc->is_modified_rate, hcamcorder->vedecision_cb);
- if (sc->is_modified_rate || hcamcorder->vedecision_cb)
+ if (sc->is_modified_rate || hcamcorder->vedecision_cb) {
+ MMCAM_LOG_INFO("audio disabled[prev:%d]", sc->audio_disable);
sc->audio_disable = TRUE;
+ }
if (sc->audio_disable == FALSE) {
/* create audiosrc bin */
if (sc->info_video->use_videoscale) {
gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst,
- sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst,
+ sc->encode_element[_MMCAMCORDER_ENCSINK_CAPS].gst,
sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE].gst,
- sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_FILT].gst,
+ sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_CAPS].gst,
sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
NULL);
} else {
gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst,
- sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst,
+ sc->encode_element[_MMCAMCORDER_ENCSINK_CAPS].gst,
sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
NULL);
}
/* Link each element : appsrc - capsfilter - encodesink bin */
srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "src");
- sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "sink");
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_CAPS].gst, "sink");
_MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
- srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src");
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_CAPS].gst, "src");
if (sc->info_video->use_videoscale) {
sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE].gst, "sink");
_MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE].gst, "src");
- sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_FILT].gst, "sink");
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_CAPS].gst, "sink");
_MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
- srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_FILT].gst, "src");
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_CAPS].gst, "src");
}
sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
_MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
__mmcamcorder_audioque_dataprobe, hcamcorder);
gst_object_unref(sinkpad);
- sinkpad = NULL;
/* for voice mute */
srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
__mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
gst_object_unref(srcpad);
- srcpad = NULL;
if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
__mmcamcorder_eventprobe_monitor, hcamcorder);
gst_object_unref(srcpad);
- srcpad = NULL;
}
}
MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
__mmcamcorder_eventprobe_monitor, hcamcorder);
gst_object_unref(srcpad);
- srcpad = NULL;
}
if (sc->audio_disable) {
MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
__mmcamcorder_video_dataprobe_audio_disable, hcamcorder);
gst_object_unref(sinkpad);
- sinkpad = NULL;
}
if (!strcmp(gst_element_rsink_name, "filesink")) {
MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
__mmcamcorder_video_dataprobe_encoded, hcamcorder);
gst_object_unref(srcpad);
- srcpad = NULL;
- srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
- MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_audio_dataprobe_check, hcamcorder);
- gst_object_unref(srcpad);
- srcpad = NULL;
+ if (sc->audio_disable == FALSE) {
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
+ MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_audio_dataprobe_check, hcamcorder);
+ gst_object_unref(srcpad);
+ }
}
sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "sink");
MMCAMCORDER_ADD_EVENT_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
__mmcamcorder_eventprobe_monitor, hcamcorder);
gst_object_unref(sinkpad);
- sinkpad = NULL;
bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
- /* register pipeline message callback */
- hcamcorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
-
/* set sync handler */
gst_bus_set_sync_handler(bus, _mmcamcorder_encode_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL);
gst_object_unref(bus);
- bus = NULL;
return MM_ERROR_NONE;
This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
It's because the pipeline of audio recording destroys at the same time,
- and '_mmcamcorder_element_release_noti' will perfom removing handle.
+ and '_mmcamcorder_element_release_noti' will perform removing handle.
*/
_mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_VOL);
GstPad *reqpad = NULL;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
_MMCamcorderSubContext *sc = NULL;
-#ifdef _MMCAMCORDER_MM_RM_SUPPORT
- int ret = MM_ERROR_NONE;
-#endif /* _MMCAMCORDER_MM_RM_SUPPORT */
mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
if (reqpad) {
gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
gst_object_unref(reqpad);
- reqpad = NULL;
}
reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
if (reqpad) {
gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
gst_object_unref(reqpad);
- reqpad = NULL;
}
/* release encode main pipeline */
This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
It's because the pipeline of audio recording destroys at the same time,
- and '_mmcamcorder_element_release_noti' will perfom removing handle.
+ and '_mmcamcorder_element_release_noti' will perform removing handle.
*/
/* _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element,
_MMCAMCORDER_ENCODE_MAIN_PIPE, _MMCAMCORDER_ENCSINK_SINK); */
MMCAM_LOG_WARNING("Encoder pipeline removed");
-
-#ifdef _MMCAMCORDER_MM_RM_SUPPORT
- _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
-
- MMCAM_LOG_WARNING("lock resource - cb calling %d", hcamcorder->is_release_cb_calling);
-
- if (hcamcorder->is_release_cb_calling == FALSE) {
- /* release resource */
- ret = mm_resource_manager_mark_for_release(hcamcorder->resource_manager,
- hcamcorder->video_encoder_resource);
- if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
- hcamcorder->video_encoder_resource = NULL;
-
- MMCAM_LOG_WARNING("mark resource for release 0x%x", ret);
-
- ret = mm_resource_manager_commit(hcamcorder->resource_manager);
-
- MMCAM_LOG_WARNING("commit resource release 0x%x", ret);
- }
-
- _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
-
- MMCAM_LOG_WARNING("unlock resource");
-#endif /* _MMCAMCORDER_MM_RM_SUPPORT */
}
return MM_ERROR_NONE;
return ret;
}
- /* Remove pipeline message callback */
- if (hcamcorder->encode_pipeline_cb_event_id != 0) {
- g_source_remove(hcamcorder->encode_pipeline_cb_event_id);
- hcamcorder->encode_pipeline_cb_event_id = 0;
- }
-
/* Remove remained message */
if (bus) {
GstMessage *gst_msg = NULL;
while ((gst_msg = gst_bus_pop(bus)) != NULL) {
_mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
gst_message_unref(gst_msg);
- gst_msg = NULL;
}
gst_object_unref(bus);
- bus = NULL;
}
MMCAM_LOG_INFO("done");
/* Recording */
MMCAM_LOG_INFO("Record Start - dual stream %d", info->support_dual_stream);
-#ifdef _MMCAMCORDER_MM_RM_SUPPORT
- _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
-
- /* prepare resource manager for H/W encoder */
- if (hcamcorder->video_encoder_resource == NULL) {
- ret = mm_resource_manager_mark_for_acquire(hcamcorder->resource_manager,
- MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_ENCODER,
- MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
- &hcamcorder->video_encoder_resource);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- MMCAM_LOG_ERROR("could not prepare for encoder resource");
- ret = MM_ERROR_RESOURCE_INTERNAL;
- _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
- goto _ERR_CAMCORDER_VIDEO_COMMAND;
- }
- } else {
- MMCAM_LOG_INFO("encoder already acquired");
- }
-
- /* acquire resources */
- ret = mm_resource_manager_commit(hcamcorder->resource_manager);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- MMCAM_LOG_ERROR("could not acquire resources");
- ret = MM_ERROR_RESOURCE_INTERNAL;
- _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
- goto _ERR_CAMCORDER_VIDEO_COMMAND;
- }
-
- _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
-#endif /* _MMCAMCORDER_MM_RM_SUPPORT */
-
/* init record_dual_stream */
info->record_dual_stream = FALSE;
MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
- } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
+ } else if (_mmcamcorder_is_encoded_preview_pixel_format(sc->info_image->preview_format) &&
info->preview_width == info->video_width &&
info->preview_height == info->video_height) {
- MMCAM_LOG_INFO("H264 preview mode and same resolution");
-
+ MMCAM_LOG_INFO("Encoded[%d] preview mode and same resolution", sc->info_image->preview_format);
/* No need to restart preview */
info->restart_preview = FALSE;
} else if (info->use_videoscale &&
"PassFirstVideoFrame",
&(sc->pass_first_vframe));
- MMCAM_LOG_INFO("Drop video frame count[%d], Pass fisrt video frame count[%d]",
+ MMCAM_LOG_INFO("Drop video frame count[%d], Pass first video frame count[%d]",
sc->drop_vframe, sc->pass_first_vframe);
info->record_drop_count = (guint)motion_rate;
return GST_PAD_PROBE_DROP;
}
- gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
+ if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
+ MMCAM_LOG_WARNING("map failed : buffer[%p]", buffer);
+ return GST_PAD_PROBE_OK;
+ }
+
+
buffer_size = mapinfo.size;
gst_buffer_unmap(buffer, &mapinfo);
{
guint64 trailer_size = 0;
guint64 rec_pipe_time = 0;
- unsigned int remained_time = 0;
+ unsigned long long remained_time = 0;
GstClockTime b_time;
long double max_size = (long double)videoinfo->max_size;
long double current_size = (long double)(videoinfo->filesize + trailer_size);
- remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
+ remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
}
msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
_MMCamcorderSubContext *sc = NULL;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
_MMCamcorderVideoInfo *videoinfo = NULL;
- unsigned int remained_time = 0;
+ unsigned long long remained_time = 0;
GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
if (err != MM_ERROR_NONE) {
MMCAM_LOG_WARNING("Get attrs fail. (%s:%x)", err_name, err);
SAFE_FREE(err_name);
- return err;
+ return GST_PAD_PROBE_OK;
}
memset(&mapinfo, 0x0, sizeof(GstMapInfo));
- gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
+ if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE)) {
+ MMCAM_LOG_WARNING("map failed : buffer[%p]", buffer);
+ return GST_PAD_PROBE_OK;
+ }
/* Set audio stream NULL */
if (volume == 0.0)
GST_TIME_ARGS(GST_BUFFER_PTS(buffer)), hcamcorder->astream_cb, format, channel, mapinfo.size);
/* CALL audio stream callback */
- if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
+ if (hcamcorder->astream_cb) {
MMCamcorderAudioStreamDataType stream;
if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
stream.data = (void *)mapinfo.data;
stream.format = format;
stream.channel = channel;
- stream.length = mapinfo.size;
+ stream.length = (unsigned int)mapinfo.size;
stream.timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer)));
_MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);