+gboolean _mmcamcorder_video_push_buffer(void *handle, GstSample *sample)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderImageInfo *info_image = 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);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+
+ mmf_return_val_if_fail(sc->info_image, FALSE);
+ mmf_return_val_if_fail(sc->info_video, FALSE);
+ mmf_return_val_if_fail(sc->encode_element, FALSE);
+
+ info_image = sc->info_image;
+ info_video = sc->info_video;
+ element = sc->encode_element;
+
+ if (info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_RUN &&
+ element[_MMCAMCORDER_ENCSINK_SRC].gst) {
+ int ret = 0;
+ GstClock *clock = NULL;
+
+ 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 (_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;
+ }
+
+ MMCAM_LOG_WARNING("Got buffer with header");
+ }
+
+ /* set base timestamp */
+ if (element[_MMCAMCORDER_AUDIOSRC_SRC].gst) {
+ clock = GST_ELEMENT_CLOCK(element[_MMCAMCORDER_AUDIOSRC_SRC].gst);
+ if (clock) {
+ gst_object_ref(clock);
+ info_video->base_video_ts = current_ts - (gst_clock_get_time(clock) - \
+ GST_ELEMENT(element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time);
+ gst_object_unref(clock);
+ }
+ } else {
+ /* for image capture with encodebin and v4l2src */
+ 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;
+ g_cond_signal(&hcamcorder->task_thread_cond);
+ g_mutex_unlock(&hcamcorder->task_thread_lock);
+ }
+ info_video->base_video_ts = current_ts;
+ }
+ } else {
+ 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;
+ MMCAM_LOG_DEBUG("do not push buffer to encode by app's return value");
+ goto _VIDEO_PUSH_BUFFER_DONE;
+ }
+ }
+
+ GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer) = current_ts - info_video->base_video_ts;
+
+ MMCAM_LOG_DEBUG("buffer[%p] - timestamp[%"GST_TIME_FORMAT"]",
+ buffer, GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));
+
+ /* 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);
+
+_VIDEO_PUSH_BUFFER_DONE:
+ info_video->last_video_ts = current_ts;
+
+ if (info_video->is_first_frame) {
+ info_video->is_first_frame = FALSE;
+
+ /* drop buffer if it's from tizen allocator */
+ if (gst_is_tizen_memory(gst_buffer_peek_memory(buffer, 0))) {
+ MMCAM_LOG_WARNING("drop first buffer from tizen allocator to avoid copy in basesrc");
+ return FALSE;
+ }
+ }
+ }
+
+ /* skip display if too fast FPS */
+ if (info_video->record_dual_stream == FALSE &&
+ info_video->fps > _MMCAMCORDER_FRAME_PASS_MIN_FPS) {
+ if (info_video->prev_preview_ts != 0) {
+ if (GST_BUFFER_PTS(buffer) - info_video->prev_preview_ts < _MMCAMCORDER_MIN_TIME_TO_PASS_FRAME) {
+ MMCAM_LOG_VERBOSE("it's too fast. drop frame...");
+ return FALSE;
+ }
+ }
+
+ MMCAM_LOG_VERBOSE("display buffer [%p]", buffer);
+
+ info_video->prev_preview_ts = GST_BUFFER_PTS(buffer);
+ }
+
+ return TRUE;
+}
+
+
+static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)