[longomatch: 4/5] WIP



commit 63d5fc89c0cc7d5a088d1a3496fd0df82eb9e4af
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Tue Oct 2 16:39:14 2012 +0200

    WIP

 libcesarplayer/gst-camera-capturer.c |  113 +++++++++++++++++++++++-----------
 libcesarplayer/main.c                |    4 +
 2 files changed, 80 insertions(+), 37 deletions(-)
---
diff --git a/libcesarplayer/gst-camera-capturer.c b/libcesarplayer/gst-camera-capturer.c
index 2fd5227..d1dc27b 100644
--- a/libcesarplayer/gst-camera-capturer.c
+++ b/libcesarplayer/gst-camera-capturer.c
@@ -141,6 +141,8 @@ struct GstCameraCapturerPrivate
   /* Recording */
   gboolean is_recording;
   gboolean closing_recording;
+  gboolean video_needs_keyframe_sync;
+  gboolean video_synced;
   GstClockTime accum_recorded_ts;
   GstClockTime last_accum_recorded_ts;
   GstClockTime current_recording_start_ts;
@@ -208,6 +210,7 @@ gst_camera_capturer_init (GstCameraCapturer * object)
   priv->last_accum_recorded_ts = GST_CLOCK_TIME_NONE;
   priv->is_recording = FALSE;
   priv->recording_lock = g_mutex_new();
+  //priv->audio_enabled = TRUE;
 
   priv->lock = g_mutex_new ();
 }
@@ -258,7 +261,6 @@ gst_camera_capturer_finalize (GObject * object)
 
   if (gcc->priv->main_pipeline != NULL
       && GST_IS_ELEMENT (gcc->priv->main_pipeline)) {
-    gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
     gst_object_unref (gcc->priv->main_pipeline);
     gcc->priv->main_pipeline = NULL;
   }
@@ -917,11 +919,6 @@ gst_camera_capture_videosrc_buffer_probe (GstPad * pad, GstBuffer * buf,
   return TRUE;
 }
 
-static void dump (GstCameraCapturer *gcc)
-{
-  GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(gcc->priv->main_pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "academor");
-}
-
 void
 gst_camera_capturer_run (GstCameraCapturer * gcc)
 {
@@ -929,7 +926,6 @@ gst_camera_capturer_run (GstCameraCapturer * gcc)
   g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
 
   gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_PLAYING);
-  g_timeout_add_seconds(5, (GSourceFunc)dump, gcc);
 }
 
 void
@@ -969,6 +965,7 @@ gst_camera_capturer_toggle_pause (GstCameraCapturer * gcc)
     gcc->priv->is_recording = TRUE;
   } else {
     gcc->priv->is_recording = FALSE;
+    gcc->priv->video_synced = FALSE;
   }
   g_mutex_unlock(gcc->priv->recording_lock);
 
@@ -1099,24 +1096,30 @@ static void
 gst_camera_capturer_create_remuxer_bin (GstCameraCapturer *gcc)
 {
   GstElement *muxer;
-  GstPad *a_sink_pad, *v_sink_pad, *src_pad;
+  GstPad *v_sink_pad;
 
   GST_INFO_OBJECT (gcc, "Creating remuxer bin");
   gcc->priv->encoder_bin = gst_bin_new ("encoder_bin");
   muxer = gst_element_factory_make("qtmux", NULL);
+  gcc->priv->filesink = gst_element_factory_make("filesink", NULL);
+  g_object_set (gcc->priv->filesink, "location", gcc->priv->output_file, NULL);
 
-  gst_bin_add(GST_BIN(gcc->priv->encoder_bin), muxer);
+  gst_bin_add_many(GST_BIN(gcc->priv->encoder_bin), muxer, gcc->priv->filesink, NULL);
+  gst_element_link(muxer, gcc->priv->filesink);
 
   /* Create ghost pads */
   v_sink_pad = gst_element_get_request_pad (muxer, "video_%d");
   gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("video", v_sink_pad));
-  gst_object_unref (GST_OBJECT (v_sink_pad));
-  a_sink_pad = gst_element_get_request_pad (muxer, "audio_%d");
-  gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("audio", a_sink_pad));
-  gst_object_unref (GST_OBJECT (v_sink_pad));
-  src_pad = gst_element_get_static_pad (muxer, "src");
-  gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("src", src_pad));
-  gst_object_unref (GST_OBJECT (src_pad));
+  gst_object_unref (v_sink_pad);
+
+  if (gcc->priv->audio_enabled) {
+    GstPad *a_sink_pad;
+
+    /* Create ghost pads */
+    a_sink_pad = gst_element_get_request_pad (muxer, "audio_%d");
+    gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("audio", a_sink_pad));
+    gst_object_unref (GST_OBJECT (v_sink_pad));
+  }
 }
 
 static GstElement *
@@ -1127,6 +1130,8 @@ gst_camera_capturer_prepare_raw_source (GstCameraCapturer *gcc)
 
   GST_INFO_OBJECT (gcc, "Creating raw source");
 
+  gcc->priv->video_needs_keyframe_sync = FALSE;
+
   gcc->priv->source_decoder_bin = gst_bin_new ("decoder");
   bin = gcc->priv->source_decoder_bin;
   v_identity = gst_element_factory_make ("identity", NULL);
@@ -1149,29 +1154,42 @@ gst_camera_capturer_prepare_raw_source (GstCameraCapturer *gcc)
 static GstElement *
 gst_camera_capturer_prepare_dv_source (GstCameraCapturer *gcc)
 {
-  GstElement *bin, *decodebin, *deinterlacer, *audio;
-  GstPad *audio_pad, *video_pad, *src_pad;
+  GstElement *bin, *decodebin, *deinterlacer;
+  GstPad *video_pad, *src_pad;
 
   GST_INFO_OBJECT (gcc, "Creating dv source");
+
+  gcc->priv->video_needs_keyframe_sync = FALSE;
+
   gcc->priv->source_decoder_bin = gst_bin_new ("decoder");
   bin = gcc->priv->source_decoder_bin;
   decodebin = gst_element_factory_make ("decodebin2", NULL);
   deinterlacer = gst_element_factory_make ("ffdeinterlace", "video-pad");
-  audio = gst_element_factory_make ("identity", "audio-pad");
 
-  gst_bin_add_many (GST_BIN (bin), decodebin, deinterlacer, audio, NULL);
+  gst_bin_add_many (GST_BIN (bin), decodebin, deinterlacer, NULL);
 
   /* add ghostpad */
   video_pad = gst_element_get_static_pad (deinterlacer, "src");
   gst_element_add_pad (bin, gst_ghost_pad_new ("video", video_pad));
   gst_object_unref (GST_OBJECT (video_pad));
-  audio_pad = gst_element_get_static_pad (audio, "src");
-  gst_element_add_pad (bin, gst_ghost_pad_new ("audio", audio_pad));
-  gst_object_unref (GST_OBJECT (audio_pad));
   src_pad = gst_element_get_static_pad (decodebin, "sink");
   gst_element_add_pad (bin, gst_ghost_pad_new ("sink", src_pad));
   gst_object_unref (GST_OBJECT (src_pad));
 
+  if (gcc->priv->audio_enabled) {
+    GstElement *audio;
+    GstPad *audio_pad;
+
+    audio = gst_element_factory_make ("identity", "audio-pad");
+
+    gst_bin_add_many (GST_BIN (bin), audio, NULL);
+
+    /* add ghostpad */
+    audio_pad = gst_element_get_static_pad (audio, "src");
+    gst_element_add_pad (bin, gst_ghost_pad_new ("audio", audio_pad));
+    gst_object_unref (GST_OBJECT (audio_pad));
+  }
+
   g_signal_connect (decodebin, "pad-added", G_CALLBACK (cb_new_pad), gcc);
 
   gst_camera_capturer_create_encoder_bin(gcc);
@@ -1182,18 +1200,24 @@ gst_camera_capturer_prepare_dv_source (GstCameraCapturer *gcc)
 static GstElement *
 gst_camera_capturer_prepare_mpegts_source (GstCameraCapturer *gcc)
 {
-  GstElement *bin, *demuxer,  *video;
+  GstElement *bin, *demuxer,  *video, *video_parser;
   GstPad *video_pad, *src_pad;
 
   GST_INFO_OBJECT (gcc, "Creating mpegts source");
 
+  gcc->priv->video_needs_keyframe_sync = TRUE;
+  gcc->priv->video_synced = FALSE;
+
   /* We don't want to reencode, only remux */
   gcc->priv->source_decoder_bin = gst_bin_new ("decoder");
   bin = gcc->priv->source_decoder_bin;
   demuxer = gst_element_factory_make ("mpegtsdemux", NULL);
-  video = gst_element_factory_make ("identity", "video-pad");
+  video_parser = gst_element_factory_make ("h264parse", "video-pad");
+  video = gst_element_factory_make ("capsfilter", NULL);
+  g_object_set(video, "caps", gst_caps_from_string("video/x-h264, stream-format=avc, alignment=au"), NULL);
 
-  gst_bin_add_many (GST_BIN (bin), demuxer, video, NULL);
+  gst_bin_add_many (GST_BIN (bin), demuxer, video_parser, video, NULL);
+  gst_element_link(video_parser, video);
 
   /* add ghostpad */
   video_pad = gst_element_get_static_pad (video, "src");
@@ -1262,6 +1286,16 @@ gst_camera_capturer_encoding_retimestamper (GstCameraCapturer *gcc,
     } else {
       GstClockTime duration;
 
+      if (gcc->priv->video_needs_keyframe_sync && !gcc->priv->video_synced) {
+        if (is_video && !GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
+          gcc->priv->video_synced = TRUE;
+        } else {
+          GST_LOG_OBJECT (gcc, "Waitin for a keyframe, dropping buffer on %s pad", is_video ? "video": "audio");
+          ret = FALSE;
+          goto done;
+        }
+      }
+
       buf_ts = GST_BUFFER_TIMESTAMP(buf);
       duration = GST_BUFFER_DURATION(buf);
       if (duration == GST_CLOCK_TIME_NONE)
@@ -1279,13 +1313,19 @@ gst_camera_capturer_encoding_retimestamper (GstCameraCapturer *gcc,
         goto done;
       }
 
-      new_buf_ts = buf_ts - gcc->priv->current_recording_start_ts + gcc->priv->last_accum_recorded_ts;
-      //buf = gst_buffer_make_metadata_writable(buf);
-      GST_BUFFER_TIMESTAMP(buf) = new_buf_ts;
-      if (new_buf_ts + duration > gcc->priv->accum_recorded_ts)
-      {
-        gcc->priv->accum_recorded_ts = new_buf_ts + duration;
+      if (buf_ts != GST_CLOCK_TIME_NONE) {
+        new_buf_ts = buf_ts - gcc->priv->current_recording_start_ts + gcc->priv->last_accum_recorded_ts;
+        if (new_buf_ts + duration > gcc->priv->accum_recorded_ts)
+        {
+          gcc->priv->accum_recorded_ts = new_buf_ts + duration;
+          gcc->priv->accum_recorded_ts = new_buf_ts;
+        }
+      } else {
+        /* h264parse only sets the timestamp on the first buffer */
+        new_buf_ts = gcc->priv->accum_recorded_ts;
       }
+      GST_BUFFER_TIMESTAMP(buf) = new_buf_ts;
+
       GST_LOG_OBJECT(gcc, "Pushing %s frame to the encoder in ts:% " GST_TIME_FORMAT
           " out ts: %" GST_TIME_FORMAT, is_video ? "video": "audio",
           GST_TIME_ARGS(buf_ts), GST_TIME_ARGS(new_buf_ts));
@@ -1430,8 +1470,6 @@ gst_camera_capturer_link_encoder_bin (GstCameraCapturer *gcc)
   if (gcc->priv->audio_enabled) {
     GstPad *a_dec_pad, *a_enc_pad;
 
-    gst_bin_add(GST_BIN(gcc->priv->main_pipeline), gcc->priv->encoder_bin);
-
     a_dec_pad = gst_element_get_static_pad(gcc->priv->decoder_bin, "audio");
     a_enc_pad = gst_element_get_static_pad(gcc->priv->encoder_bin, "audio");
     gst_pad_link(a_dec_pad, a_enc_pad);
@@ -1472,7 +1510,6 @@ gst_camera_capturer_link_preview (GstCameraCapturer *gcc)
     gst_object_unref(a_dec_prev_pad);
     gst_object_unref(a_prev_pad);
   }
-
   gst_element_set_state(gcc->priv->decoder_bin, GST_STATE_PLAYING);
 }
 
@@ -1537,9 +1574,11 @@ gst_camera_capturer_source_pad_probe (GstPad *pad, GstBuffer *buf, GstCameraCapt
   GstElement *decoder_bin = NULL;
 
   src_caps = gst_buffer_get_caps(buf);
+  GST_INFO_OBJECT (gcc, "Got first buffer from the source with caps %s", gst_caps_to_string(src_caps));
 
   /* Check for DV streams */
   media_caps = gst_caps_from_string("video/x-dv, systemstream=true");
+
   if (gst_caps_can_intersect(src_caps, media_caps)) {
     decoder_bin = gst_camera_capturer_prepare_dv_source(gcc);
     gst_caps_unref(media_caps);
@@ -1553,8 +1592,7 @@ gst_camera_capturer_source_pad_probe (GstPad *pad, GstBuffer *buf, GstCameraCapt
   }
 
   /* Check for Raw streams */
-  media_caps = gst_caps_from_string ("video/x-dv, systemstream=true;"
-      "video/x-raw-rgb; video/x-raw-yuv");
+  media_caps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
   if (gst_caps_can_intersect(src_caps, media_caps)) {
     gcc->priv->audio_enabled = FALSE;
     decoder_bin = gst_camera_capturer_prepare_raw_source(gcc);
@@ -1595,6 +1633,7 @@ gst_camera_capturer_create_video_source (GstCameraCapturer * gcc,
       GST_INFO_OBJECT(gcc, "Creating system video source");
       gcc->priv->source =
           gst_element_factory_make (SYSVIDEOSRC, "source");
+      //gcc->priv->source = gst_parse_bin_from_description("filesrc location=/home/andoni/test.dv ! typefind", TRUE, NULL);
       name = SYSVIDEOSRC;
       break;
     default:
diff --git a/libcesarplayer/main.c b/libcesarplayer/main.c
index 6e956db..4eaabda 100644
--- a/libcesarplayer/main.c
+++ b/libcesarplayer/main.c
@@ -39,6 +39,10 @@ window_state_event (GtkWidget * widget, GdkEventWindowState * event,
 
   }
   if (i == 5)
+    gst_camera_capturer_toggle_pause (GST_CAMERA_CAPTURER (gvc));
+  if (i == 6)
+    gst_camera_capturer_toggle_pause (GST_CAMERA_CAPTURER (gvc));
+  if (i == 7)
     gst_camera_capturer_stop (GST_CAMERA_CAPTURER (gvc));
   return TRUE;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]