Lost video

Ian Davidson id012c3076 at blueyonder.co.uk
Mon Jan 14 06:56:27 PST 2013


My program now works - for very short videos (up to 1 second and 2 
frames duration!)

I have been testing my program and thought it was almost working - until 
I discovered a problem.  I had been testing with a video camera pointing 
nowhere in particular and all seemed well, but then, when I waved to the 
camera, I noticed that the video did not include me waving.  I 
transferred the video to another machine and noticed that while the 
audio continued as expected, the video stopped after about 1 second and 
2 frames.  I tested with the following gst-launch but it seems to work OK.

gst-launch-1.0 -e --gst-debug-level=6 v4l2src norm=PAL ! 
'video/x-raw,format=(string)I420,width=320,height=240,framerate=(fraction)25/1' 
! queue ! mux. alsasrc ! audioconvert ! 
'audio/x-raw,rate=44100,channels=2' ! queue ! mux. avimux name=mux ! 
filesink location=test.avi

The program is intended to be functionally the same - the only 
'embellishment' is that this test version is set to stop recording after 
1 minute (the live version will have a 40 minute cutoff). The program 
also supports Ctrl-C to stop recording.  I have (I hope) attached a zip 
file of the debug output (the middle 56 seconds have been removed).  I 
can see that the debug shows

  * at 0:00:00.343548749, the pipeline is 'Playing' - so what went
    before is configuration and establishment.
  * it appears to be reporting that both pads have data, repeatedly
    throughout the session
  * there is activity after 1 minute when the EOS gets sent

but I have not noticed anything reporting problems after 1 second when 
the video content stops recording.

I have also tested using gst_parse_launch (instead of constructing the 
pipeline 'by hand') and I get the same problem with the video stopping 
after a second.

Can anyone see what might be going wrong?

Ian

#include <gst/gst.h>
#include <glib.h>
#include <signal.h>
#include <string.h>

static GstElement *pipeline;
   gulong timeout_id;

static gboolean
bus_call (GstBus     *bus,
           GstMessage *msg,
           gpointer    data)
{
   GMainLoop *loop = (GMainLoop *) data;
   switch (GST_MESSAGE_TYPE (msg)) {

     case GST_MESSAGE_EOS:
       g_print ("End of stream\n");
       g_main_loop_quit (loop);
       break;

     case GST_MESSAGE_ERROR: {
       gchar  *debug;
       GError *error;

       gst_message_parse_error (msg, &error, &debug);
       g_free (debug);

       g_printerr ("Error: %s\n", error->message);
       g_error_free (error);

       g_main_loop_quit (loop);
       break;
     }

       case GST_MESSAGE_APPLICATION:{
         const GstStructure *s;

         s = gst_message_get_structure (msg);

         if (gst_structure_has_name (s, "GstLaunchInterrupt")) {
           /* this application message is posted when we caught an 
interrupt and
            * we need to stop the pipeline. */
           g_print ("Interrupt: Stopping pipeline ...\n");
           gst_element_send_event (pipeline, gst_event_new_eos ());
         }
         break;
       }

     default:
       break;
   }

   return TRUE;
}




static void
sigint_restore (void)
{
   struct sigaction action;

   memset (&action, 0, sizeof (action));
   action.sa_handler = SIG_DFL;

   sigaction (SIGINT, &action, NULL);
}


static void
sigint_handler_sighandler (int signum)
{
   g_print ("Caught interrupt -- ");

   gst_element_send_event (pipeline, gst_event_new_eos ());
   sigint_restore ();
}


static void
sigint_setup (void)
{
   struct sigaction action;

   memset (&action, 0, sizeof (action));
   action.sa_handler = sigint_handler_sighandler;

   sigaction (SIGINT, &action, NULL);
}

/* is called every 40 minutes.
  * I will send an EOS to the pipeline. */
static gboolean
times_up (GstElement * pipeline)
{
   gst_element_send_event (pipeline, gst_event_new_eos ());
   sigint_restore ();
   return FALSE;
}



int
main (int   argc,
       char *argv[])
{
   GMainLoop *loop;

   GstElement *vsource, *vcapsfilter, *vidrate, *queue1;
   GstElement *asource, *aconv, *audrate, *acapsfilter, *queue2;
   GstElement *mux, *sink;
   GstBus *bus;
   guint bus_watch_id;

   GstCaps *caps;

   /* Initialisation */
   gst_init (&argc, &argv);

   loop = g_main_loop_new (NULL, FALSE);


   /* Check input arguments */
   if (argc != 2) {
     g_printerr ("Usage: %s <AVI filename>\n", argv[0]);
     return -1;
   }


   /* Create gstreamer elements */
   pipeline     = gst_pipeline_new ("av-recorder");
   vsource      = gst_element_factory_make ("v4l2src", "vid-source");
   vcapsfilter  = gst_element_factory_make ("capsfilter", "vid-caps");
   vidrate      = gst_element_factory_make ("videorate", "vidrate");
   queue1       = gst_element_factory_make ("queue", "queue1");
   asource      = gst_element_factory_make ("alsasrc", "alsa-source");
   aconv        = gst_element_factory_make ("audioconvert", "audio-conv");
   acapsfilter  = gst_element_factory_make ("capsfilter", "audio-caps");
   audrate      = gst_element_factory_make ("audiorate", "audrate");
   queue2       = gst_element_factory_make ("queue", "queue2");
   mux          = gst_element_factory_make ("avimux", "avi-mux");
   sink         = gst_element_factory_make ("filesink", "file-output");

   if (!pipeline || !vsource || !vcapsfilter || !vidrate || !queue1 || 
!asource || !aconv || !audrate || !acapsfilter || !queue2 || !mux || 
!sink) {
     g_printerr ("One element could not be created. Exiting.\n");
     return -1;
   }

   /* Set up the pipeline */

   /* we set the output filename to the sink element */
   g_object_set (G_OBJECT (sink), "location", argv[1], NULL);

   /* we set the video capabilities on the vidcaps element */
   caps = 
gst_caps_from_string("video/x-raw,format=(string)I420,width=320,height=240,framerate=(fraction)25/1");
   g_object_set (G_OBJECT (vcapsfilter), "caps", caps, NULL);
   gst_caps_unref (caps);

   /* we set the audio capabilities on the audiocaps element */
   caps = gst_caps_from_string("audio/x-raw,rate=44100,channels=2");
   g_object_set (G_OBJECT (acapsfilter), "caps", caps, NULL);
   gst_caps_unref (caps);

   g_object_set (G_OBJECT (vsource), "norm", 255, NULL);

   /* we add a message handler */
   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
   bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
   gst_object_unref (bus);

   /* we add all elements into the pipeline */
   /*      vsource, vcapsfilter, vidrate, queue1,
           asource, aconv, acapsfilter, queue2,
           mux, sink */
   gst_bin_add_many (GST_BIN (pipeline),
                         vsource,  vcapsfilter, queue1,
/*                        vsource, vidrate, vcapsfilter, queue1,*/
                         asource, aconv,  acapsfilter, queue2,
/*                        asource, aconv, audrate, acapsfilter, queue2,*/
                         mux, sink, NULL);

   /* we link the elements together */
   /*      vsource -> vcapsfilter -> vidrate -> queue1 -> avimux
           asource -> aconv -> acapsfilter -> queue2 -> avimux
           mux -> sink */
   gst_element_link_many (vsource, vcapsfilter,  queue1, mux, NULL);
/*  gst_element_link_many (vsource, vcapsfilter, vidrate, queue1, mux, 
NULL);*/
   gst_element_link_many (asource, aconv,  acapsfilter, queue2, mux, NULL);
/*  gst_element_link_many (asource, aconv, audrate, acapsfilter, queue2, 
mux, NULL);*/
   gst_element_link_many (mux, sink, NULL);


   /* Set the pipeline to "playing" state*/
   g_print ("Now recording: %s\n", argv[1]);
   gst_element_set_state (pipeline, GST_STATE_PLAYING);

   sigint_setup ();
/*  timeout_id = g_timeout_add (40 * 60000, (GSourceFunc) times_up, 
pipeline);     */
   timeout_id = g_timeout_add (1 * 60000, (GSourceFunc) times_up, 
pipeline);


   /* Iterate */
   g_print ("Recording (or not!)...\n");
   g_main_loop_run (loop);


   /* Out of the main loop, clean up nicely */
   g_print ("Returned, stopping recording\n");
   gst_element_set_state (pipeline, GST_STATE_NULL);

   g_print ("Deleting pipeline\n");
   gst_object_unref (GST_OBJECT (pipeline));
   g_source_remove (bus_watch_id);
   g_main_loop_unref (loop);

   return 0;
}


-- 
Ian Davidson
-- 
Facts used in this message may or may not reflect an underlying 
objective reality. Facts are supplied for personal use only.
Recipients quoting supplied information do so at their own risk. Facts 
supplied may vary in whole or part from widely accepted standards.
While painstakingly researched, facts may or may not be indicative of 
actually occurring events or natural phenomena.
The author accepts no responsibility for personal loss or injury 
resulting from memorisation and subsequent use.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20130114/113adb75/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fr1trim2chop.zip
Type: application/x-zip-compressed
Size: 843011 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20130114/113adb75/attachment-0001.bin>


More information about the gstreamer-devel mailing list